@jordanmgsoftware/postcode-nl-validator
v1.0.1
Published
Zero-setup Dutch postcode validator. Bundled JSON data, no SQLite, works on Vercel / AWS Lambda / local Node.
Readme
@jordanmgsoftware/postcode-nl-validator
Zero-setup Dutch postcode validator. Ships the data inside the package, so npm install is enough — no database to build, no environment variables, no network calls at runtime. Works identically on local Node, Vercel / AWS Lambda serverless, and any Node 20+ environment.
import { PostcodeValidator } from '@jordanmgsoftware/postcode-nl-validator';
const v = new PostcodeValidator();
v.validate('1011 ab');
// {
// valid: true,
// normalizedPostcode: '1011AB',
// reason: 'ok',
// matches: [{
// postcode: '1011AB',
// straat: 'De Ruijterkade',
// woonplaats: 'Amsterdam',
// gemeente: 'Amsterdam',
// provincie: 'Noord-Holland',
// }],
// }Install
npm install @jordanmgsoftware/postcode-nl-validatorThat's it. No post-install step, no native modules, no environment variables.
Scope
This package performs postcode-level validation:
- Checks that a Dutch postcode has valid PostNL format (e.g. rejects
0123AB,1011SA). - Resolves a postcode to its
straat,woonplaats,gemeente,provincie.
It does not validate individual house numbers. The full BAG per-address dataset is ~10 M rows (~1 GB) and cannot be shipped inside an npm package. For most address forms, postcode-level validation is enough: once you know the postcode is real and belongs to a given street, the user's huisnummer is accepted as-is.
API
new PostcodeValidator(options?)
interface ValidatorOptions {
/** Override the bundled data directory. Tests/forks only. */
dataDir?: string;
}Methods
| Method | Returns | Notes |
|---|---|---|
| validate(postcode, huisnummer?) | ValidationResult | huisnummer is accepted for back-compat but ignored |
| lookup(postcode) | Address[] | 0 or 1 entries |
| findExact(postcode) | Address \| null | single entry or null |
| exists(postcode) | boolean | cheap existence check |
| count() | number | total postcodes in the bundled dataset |
| dataVersion() | string \| null | version of the bundled dataset |
| close() | void | no-op, kept for API compatibility |
Types
interface Address {
postcode: string; // canonical '1234AB'
straat: string;
woonplaats: string;
gemeente: string;
provincie: string;
}
interface ValidationResult {
valid: boolean;
normalizedPostcode: string | null;
matches: Address[];
reason?: 'invalid_format' | 'invalid_huisnummer' | 'postcode_not_found' | 'ok';
}Standalone helpers
No instance required, no data loaded:
import {
isValidPostcodeFormat,
normalizePostcode,
parseHuisnummer,
} from '@jordanmgsoftware/postcode-nl-validator';
isValidPostcodeFormat('1011 ab'); // true
normalizePostcode(' 1011 ab '); // '1011AB'
parseHuisnummer('42'); // 42How it works
- At build time, the Dutch address dataset is collapsed to one record per unique postcode and sharded by the two-letter suffix (
AA..ZZ) into ~500 small JSON files underdata/. - At runtime,
PostcodeValidatorreads only the shard a request touches (typically ~100 KB, parsed in under a millisecond) and caches it in memory. - No SQLite, no native modules, no network. The whole package is pure JavaScript.
Runtime footprint
- Tarball: ~10-15 MB gzipped on npm.
- Per lookup: one
readFileSyncon cold shard (sub-ms),Map.geton warm shard. - Memory: only shards that have been queried are kept in memory.
Vercel / serverless
Works on Vercel's Node runtime out of the box. No extra configuration, no environment variables, no external calls. The JSON shards are included in the deployed function bundle because they live inside node_modules/@jordanmgsoftware/postcode-nl-validator/data/.
On AWS Lambda and similar platforms, the same applies.
Data updates
The dataset is pinned to the package version. To pick up a refreshed dataset, run npm update @jordanmgsoftware/postcode-nl-validator like you would with any dependency. You can inspect the current version at runtime via validator.dataVersion().
Migration from v0.x
v0.x required you to build a local SQLite database and pass dbPath or set POSTCODE_NL_DB. v1.x removes both:
new PostcodeValidator()— no options required.validate(postcode, huisnummer)still compiles;huisnummeris now ignored.- The CLI, HTTP server, and
postcode-nl buildcommand have been removed. POSTCODE_NL_DBis a no-op and can be dropped from your env.Addressno longer includeshuisnummer,huisletter,huisnummertoevoeging,lat,lon.
Maintainers: regenerating the bundled data
npm install
npm run build:data -- --input ../Nederland.csv.zst
npm run build
npm publishbuild:data streams the upstream Nederland.csv.zst, dedupes to postcode-level, and regenerates data/*.json plus data/manifest.json.
