Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,26 @@ jobs:
- run: bun install --frozen-lockfile
- run: bun test

build:
name: Build
if: >-
always()
&& (github.event_name != 'pull_request'
|| needs.trust-check.outputs.trusted == 'true')
needs: [trust-check]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun run build
- run: bun run sync-exports:check

publish:
name: Publish
if: startsWith(github.ref, 'refs/tags/v')
needs: [test, lint]
needs: [test, lint, build]
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
2 changes: 1 addition & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"no-shadow": "error",
"require-await": "error",
"no-useless-catch": "error",
"no-non-null-assertion": "error",
"no-non-null-assertion": "off",
"typescript/no-explicit-any": "error",
"typescript/no-dynamic-delete": "error",
"typescript/consistent-type-definitions": [
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ a pull request.
```bash
# Prerequisites: Bun
bun install
bun run typecheck # type-check source
bun test # run tests
bun run lint # oxlint
bun run format # oxfmt
Expand All @@ -25,7 +26,7 @@ bun run format # oxfmt
1. Create `src/{cc}/{id}.ts` implementing the
`Validator` type from `src/types.ts`.
2. Export from `src/{cc}/mod.ts`.
3. Add an entry point in `package.json` exports.
3. Run `bun run sync-exports`.
4. Write tests in `__test__/{cc}.test.ts`.
5. Update `src/types.ts` if the country is new
(add to `CountryCode` union).
Expand All @@ -41,7 +42,7 @@ Each validator must export:

- One logical change per PR.
- Include tests for all validators.
- Run `bun test && bun run lint && bun run format`
- Run `bun run typecheck && bun test && bun run lint && bun run format`
before submitting.
- Use [Conventional Commits](https://www.conventionalcommits.org/):
`feat:`, `fix:`, `chore:`, `docs:`.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ handled automatically.

```bash
bun install
bun test # 4,185 tests
bun run typecheck
bun test
bun run lint # oxlint
bun run format # oxfmt
```
Expand Down
8 changes: 8 additions & 0 deletions __test__/cz.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ describe("cz.rc", () => {
expect(r.valid).toBe(true);
});

test("rejects 9-digit numbers using modern +20 month overflow", () => {
const r = cz.rc.validate("913216323");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_COMPONENT");
}
});

test("invalid component (bad date)", () => {
const r = cz.rc.validate("1103492745");
expect(r.valid).toBe(false);
Expand Down
8 changes: 8 additions & 0 deletions __test__/ee.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ describe("ee.ik", () => {
}
});

test("rejects 7/8 century digits not used by the official format", () => {
const r = ee.ik.validate("76805280109");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_COMPONENT");
}
});

test("metadata", () => {
expect(ee.ik.country).toBe("EE");
expect(ee.ik.entityType).toBe("person");
Expand Down
21 changes: 21 additions & 0 deletions __test__/lv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ describe("lv.vat", () => {
expect(r.valid).toBe(true);
});

test("valid Latvian new-format personal VAT", () => {
const r = lv.vat.validate("LV32999999999");
expect(r.valid).toBe(true);
});

test("invalid checksum (legal)", () => {
const r = lv.vat.validate("LV40003521601");
expect(r.valid).toBe(false);
Expand All @@ -29,6 +34,22 @@ describe("lv.vat", () => {
}
});

test("new-format personal VAT must use second digit 2-9", () => {
const r = lv.vat.validate("LV31000000000");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_COMPONENT");
}
});

test("old personal VAT must use century digit 0, 1 or 2", () => {
const r = lv.vat.validate("LV28190736398");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_COMPONENT");
}
});

test("metadata", () => {
expect(lv.vat.country).toBe("LV");
});
Expand Down
21 changes: 13 additions & 8 deletions __test__/nl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@ import { describe, expect, test } from "bun:test";
import { nl } from "../src";

describe("nl.vat", () => {
test("valid Dutch VAT", () => {
const r = nl.vat.validate("NL123456789B13");
test("valid Dutch VAT ID from official example", () => {
const r = nl.vat.validate("NL000099998B57");
expect(r.valid).toBe(true);
});

test("invalid checksum", () => {
const r = nl.vat.validate("NL123456789B14");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_CHECKSUM");
}
test("accepts leading zeros in the 9-digit section", () => {
const r = nl.vat.validate("NL001234567B01");
expect(r.valid).toBe(true);
});

test("missing B", () => {
Expand All @@ -32,6 +29,14 @@ describe("nl.vat", () => {
}
});

test("rejects non-digit suffix", () => {
const r = nl.vat.validate("NL000099998BA7");
expect(r.valid).toBe(false);
if (!r.valid) {
expect(r.error.code).toBe("INVALID_FORMAT");
}
});

test("metadata", () => {
expect(nl.vat.country).toBe("NL");
});
Expand Down
Loading
Loading