Skip to content
Devix Open Source
UI component v1.0.0 MIT Stable

Validators

ID and tax number validation that tells you why — and admits when there was nothing to check.

npm install @devix-labs/validators
Vanilla JS TypeScript
Try any number Open

IBAN for every country in the registry, European VAT with fifteen verified check digits, and the numbers this region actually collects: Emirates ID, UAE TRN, Saudi ID and VAT, Qatar ID, Kuwait Civil ID, Bahrain CPR, Oman civil number, CNIC, NTN, PAN and GSTIN. Every answer carries a reason code you can turn into a message, and says whether a check digit was verified or only the shape. Formatting, input masks and test-data generators included. The PHP twin answers identically — 224 shared vectors keep them honest.

What you get

A reason, not a boolean

too-short, bad-structure, bad-checksum, unknown-country — so the message can say what to fix instead of “invalid”.

Honest about the check

Every result says checked: 'checksum' or 'structure'. A UAE TRN has no public check digit, and this will never pretend it does.

This region, properly

Emirates ID, TRN, Saudi ID and VAT, QID, Civil ID, CPR, CNIC, NTN, PAN, GSTIN — with real check digits where they exist. No mainstream library has them.

IBAN done carefully

All 78 registry countries: length, MOD 97-10, and the BBAN pattern plus bank code for the sixty whose structure is published here.

The same answers in PHP

224 shared vectors assert that the Laravel package agrees with the browser, down to the reason code and the formatting.

5.1 KB, tree-shakable

validator.js is 35.4 KB for its bundle and its most-reacted issue is about tree shaking. Import one validator and ship one validator.

Validators — overview

Why it exists

Three things are wrong with how identifiers get validated today. Libraries answer true or false, so nobody can tell a person what to fix. They quietly claim to have checked numbers that have nothing to check. And the regional numbers a business in Dubai, Riyadh, Karachi or Bengaluru actually collects are missing entirely, so everyone writes their own regular expression.

What it does differently

  • Reason codes. Every answer says why, in a vocabulary you can turn into a message.
  • Honesty about the check. checked: 'checksum' or 'structure' — a number with no published check digit never pretends to have passed one.
  • This region, properly. Emirates ID, TRN, Saudi ID and VAT, QID, Civil ID, CPR, CNIC, NTN, PAN, GSTIN, with real check digits where they exist.
  • One set of rules, two languages. 224 shared vectors assert that the PHP package answers exactly as the JavaScript one does.
  • 5.1 kB, tree-shakable, no dependencies.

Shape of the package

Export What
validate(kind, value, options?) the one way in
iban, vat, emiratesId, cnic, gstin, … each validator on its own
format, mask, generate, kinds writing, typing and test data
luhn, mod97, luhn36, weightedMod11 the primitives, for your own numbers

Not in 1.0

Live lookups — VIES for VAT, the FTA's TRN service, bank names from an IBAN — are the Pro edition's shape, because they need a network and a subscription. This package never makes a request.

How it compares

Questions

Why does “valid” sometimes mean less than it sounds?

Because some numbers have nothing to verify. A UAE TRN and a Pakistani CNIC carry no published check digit, so the most anyone can check is the shape. Every result says which happened in its `checked` field — treat 'structure' as “looks right”, not “is real”.

Which VAT numbers have their check digit verified?

AT, BE, DE, DK, FI, FR, GB, IE, IT, LU, NL, PL, PT, SE and SK. The other thirteen countries have their shape checked, and the result says so. Only VIES can tell you a number is actually registered.

Does it agree with the server?

That is the point. devix/laravel-validators is the same rules in PHP, and 224 shared vectors — real published numbers, generated ones and awkward input — assert both sides return the same reason code, the same cleaned value and the same formatting.

Can I use it for test data?

Yes. generate('emirates-id') returns a number that passes its own check digit and belongs to nobody; pass a seed for a fixture that stays stable between runs.

What about Arabic numerals and pasted spaces?

Handled. Arabic-Indic, Persian, Devanagari, Bengali and full-width digits are read as digits, and separators plus the invisible marks that come with a copy and paste are removed before anything is checked.

Does it make any network requests?

Never. Lookups against VIES, the FTA's TRN service or a bank directory need a network and a subscription; those are the Pro edition's shape.