@mailwoman/codex 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/out/ca/index.d.ts +12 -0
  2. package/out/ca/index.d.ts.map +1 -0
  3. package/out/ca/index.js +12 -0
  4. package/out/ca/index.js.map +1 -0
  5. package/out/ca/postal-code.d.ts +74 -0
  6. package/out/ca/postal-code.d.ts.map +1 -0
  7. package/out/ca/postal-code.js +100 -0
  8. package/out/ca/postal-code.js.map +1 -0
  9. package/out/ca/province.d.ts +114 -0
  10. package/out/ca/province.d.ts.map +1 -0
  11. package/out/ca/province.js +79 -0
  12. package/out/ca/province.js.map +1 -0
  13. package/out/ca/street-type.d.ts +57 -0
  14. package/out/ca/street-type.d.ts.map +1 -0
  15. package/out/ca/street-type.js +156 -0
  16. package/out/ca/street-type.js.map +1 -0
  17. package/out/de/bundesland.d.ts +124 -0
  18. package/out/de/bundesland.d.ts.map +1 -0
  19. package/out/de/bundesland.js +81 -0
  20. package/out/de/bundesland.js.map +1 -0
  21. package/out/de/index.d.ts +12 -0
  22. package/out/de/index.d.ts.map +1 -0
  23. package/out/de/index.js +12 -0
  24. package/out/de/index.js.map +1 -0
  25. package/out/de/postleitzahl.d.ts +108 -0
  26. package/out/de/postleitzahl.d.ts.map +1 -0
  27. package/out/de/postleitzahl.js +63 -0
  28. package/out/de/postleitzahl.js.map +1 -0
  29. package/out/de/street-type.d.ts +58 -0
  30. package/out/de/street-type.d.ts.map +1 -0
  31. package/out/de/street-type.js +79 -0
  32. package/out/de/street-type.js.map +1 -0
  33. package/out/fr/code-postal.d.ts +68 -0
  34. package/out/fr/code-postal.d.ts.map +1 -0
  35. package/out/fr/code-postal.js +84 -0
  36. package/out/fr/code-postal.js.map +1 -0
  37. package/out/fr/departement.d.ts +538 -0
  38. package/out/fr/departement.d.ts.map +1 -0
  39. package/out/fr/departement.js +127 -0
  40. package/out/fr/departement.js.map +1 -0
  41. package/out/fr/index.d.ts +13 -0
  42. package/out/fr/index.d.ts.map +1 -0
  43. package/out/fr/index.js +13 -0
  44. package/out/fr/index.js.map +1 -0
  45. package/out/fr/region.d.ts +113 -0
  46. package/out/fr/region.d.ts.map +1 -0
  47. package/out/fr/region.js +76 -0
  48. package/out/fr/region.js.map +1 -0
  49. package/out/fr/voie.d.ts +64 -0
  50. package/out/fr/voie.d.ts.map +1 -0
  51. package/out/fr/voie.js +88 -0
  52. package/out/fr/voie.js.map +1 -0
  53. package/out/gb/country.d.ts +51 -0
  54. package/out/gb/country.d.ts.map +1 -0
  55. package/out/gb/country.js +56 -0
  56. package/out/gb/country.js.map +1 -0
  57. package/out/gb/index.d.ts +14 -0
  58. package/out/gb/index.d.ts.map +1 -0
  59. package/out/gb/index.js +14 -0
  60. package/out/gb/index.js.map +1 -0
  61. package/out/gb/postcode-area.d.ts +46 -0
  62. package/out/gb/postcode-area.d.ts.map +1 -0
  63. package/out/gb/postcode-area.js +101 -0
  64. package/out/gb/postcode-area.js.map +1 -0
  65. package/out/gb/postcode.d.ts +73 -0
  66. package/out/gb/postcode.d.ts.map +1 -0
  67. package/out/gb/postcode.js +88 -0
  68. package/out/gb/postcode.js.map +1 -0
  69. package/out/gb/street-type.d.ts +36 -0
  70. package/out/gb/street-type.d.ts.map +1 -0
  71. package/out/gb/street-type.js +86 -0
  72. package/out/gb/street-type.js.map +1 -0
  73. package/out/index.d.ts +27 -0
  74. package/out/index.d.ts.map +1 -0
  75. package/out/index.js +27 -0
  76. package/out/index.js.map +1 -0
  77. package/out/jp/address-unit.d.ts +72 -0
  78. package/out/jp/address-unit.d.ts.map +1 -0
  79. package/out/jp/address-unit.js +78 -0
  80. package/out/jp/address-unit.js.map +1 -0
  81. package/out/jp/index.d.ts +13 -0
  82. package/out/jp/index.d.ts.map +1 -0
  83. package/out/jp/index.js +13 -0
  84. package/out/jp/index.js.map +1 -0
  85. package/out/jp/postal-code.d.ts +63 -0
  86. package/out/jp/postal-code.d.ts.map +1 -0
  87. package/out/jp/postal-code.js +77 -0
  88. package/out/jp/postal-code.js.map +1 -0
  89. package/out/jp/prefecture.d.ts +347 -0
  90. package/out/jp/prefecture.d.ts.map +1 -0
  91. package/out/jp/prefecture.js +147 -0
  92. package/out/jp/prefecture.js.map +1 -0
  93. package/out/postcode-systems.d.ts +31 -0
  94. package/out/postcode-systems.d.ts.map +1 -0
  95. package/out/postcode-systems.js +58 -0
  96. package/out/postcode-systems.js.map +1 -0
  97. package/out/us/index.d.ts +12 -0
  98. package/out/us/index.d.ts.map +1 -0
  99. package/out/us/index.js +12 -0
  100. package/out/us/index.js.map +1 -0
  101. package/out/us/state.d.ts +26 -0
  102. package/out/us/state.d.ts.map +1 -0
  103. package/out/us/state.js +84 -0
  104. package/out/us/state.js.map +1 -0
  105. package/out/us/street-suffix.d.ts +499 -0
  106. package/out/us/street-suffix.d.ts.map +1 -0
  107. package/out/us/street-suffix.js +313 -0
  108. package/out/us/street-suffix.js.map +1 -0
  109. package/out/us/zipcode.d.ts +184 -0
  110. package/out/us/zipcode.d.ts.map +1 -0
  111. package/out/us/zipcode.js +127 -0
  112. package/out/us/zipcode.js.map +1 -0
  113. package/package.json +34 -0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The Canadian address system (Canada Post / ISO 3166-2:CA): bilingual street types, alphanumeric
7
+ * postal codes, and the provinces and territories.
8
+ */
9
+ export * from "./postal-code.js";
10
+ export * from "./province.js";
11
+ export * from "./street-type.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../ca/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The Canadian address system (Canada Post / ISO 3166-2:CA): bilingual street types, alphanumeric
7
+ * postal codes, and the provinces and territories.
8
+ */
9
+ export * from "./postal-code.js";
10
+ export * from "./province.js";
11
+ export * from "./street-type.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../ca/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Canadian postal codes: the branded type, the shape, normalization, and the FSA-letter →
7
+ * province/territory prior — the only ALPHANUMERIC postcode of the systems the codex models.
8
+ *
9
+ * The informative contrast across `us/zipcode.ts`, `de/postleitzahl.ts`, `fr/code-postal.ts`, and
10
+ * here:
11
+ *
12
+ * - A US ZIP is numeric; its first digit maps to a loose BAND of states.
13
+ * - A German PLZ is numeric; its first digit maps to a Leitzone that CROSSES Bundesland borders.
14
+ * - A French code postal is numeric; its first TWO digits ARE the département.
15
+ * - A Canadian postal code is `A1A 1A1` — Letter Digit Letter, then Digit Letter Digit — and its
16
+ * first LETTER pins the province or territory directly (`M` → Ontario, `H` → Quebec, `V` →
17
+ * British Columbia). So like the French prefix it is a clean admin prior, but it does the job
18
+ * with a single ALPHA character rather than digits.
19
+ *
20
+ * The clean rule has two wrinkles worth knowing. `X` is SHARED by the Northwest Territories and
21
+ * Nunavut (no single letter splits them), so `provinceOfPostalCode` returns an array there. And
22
+ * the large provinces span SEVERAL letters: Ontario alone owns `K L M N P`, Quebec owns `G H J`.
23
+ * The first three characters form the FSA (Forward Sortation Area); the last three are the LDU
24
+ * (Local Delivery Unit). A FSA whose SECOND character (the first digit) is `0` is a RURAL area —
25
+ * the bridge to the wider, lower-density delivery zones.
26
+ */
27
+ import type { Tagged } from "type-fest";
28
+ import type { CanadianProvinceCode } from "./province.js";
29
+ /**
30
+ * A Canadian postal code: `A1A 1A1`. Six alphanumeric characters in a strict
31
+ * Letter-Digit-Letter-Digit-Letter-Digit pattern, conventionally written with a single space after
32
+ * the third. Unlike the other systems' bare five digits, the shape alone already says "Canada".
33
+ *
34
+ * @category Postal
35
+ * @type string
36
+ * @title Postal Code
37
+ * @pattern ^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z] ?\d[ABCEGHJ-NPRSTV-Z]\d$
38
+ */
39
+ export type PostalCode = Tagged<string, "CaPostalCode">;
40
+ /**
41
+ * The Canadian postal-code shape. The valid FIRST letters exclude `D F I O Q U W Z` (never used to
42
+ * open a postcode); the interior letters additionally exclude `D F I O Q U` (the visually ambiguous
43
+ * ones). The space between FSA and LDU is optional in the raw form.
44
+ */
45
+ export declare const CA_POSTAL_CODE_PATTERN: RegExp;
46
+ /**
47
+ * Normalize a postal-code surface form to canonical `A1A 1A1`: uppercase and ensure exactly one
48
+ * space between the FSA (first three chars) and the LDU (last three) — `K1A0B1` → `K1A 0B1`, `k1a
49
+ * 0b1` → `K1A 0B1`. Returns null if the input is not a valid Canadian postal code.
50
+ */
51
+ export declare function normalizeCaPostalCode(raw: unknown): PostalCode | null;
52
+ /** Type-predicate for a Canadian postal code (accepts the spaced or unspaced surface form). */
53
+ export declare function isCaPostalCode(input: unknown): input is PostalCode;
54
+ /**
55
+ * FSA first letter → province/territory. Clean (one province per letter) except `X`, shared by the
56
+ * Northwest Territories and Nunavut, and the large provinces that span several letters: Ontario
57
+ * owns `K L M N P` and Quebec owns `G H J`. Letters `D F I O Q U W Z` never open a Canadian
58
+ * postcode and so do not appear here.
59
+ */
60
+ export declare const FSA_LETTER_TO_PROVINCE: Record<string, CanadianProvinceCode | CanadianProvinceCode[]>;
61
+ /**
62
+ * The province/territory a postal code belongs to, via its FSA first letter. Returns the single
63
+ * code for the clean letters, the `["NT", "NU"]` pair for the shared `X`, and null if the input is
64
+ * not a valid Canadian postal code (or its first letter has no province, which the pattern already
65
+ * forbids).
66
+ */
67
+ export declare function provinceOfPostalCode(postalCode: unknown): CanadianProvinceCode | CanadianProvinceCode[] | null;
68
+ /**
69
+ * True when a postal code is RURAL: its SECOND character (the FSA's first digit) is `0`. Canada
70
+ * Post uses a `0` in that position to mark the lower-density delivery zones (rural routes, small
71
+ * communities) — the contrast with the urban `1`–`9` FSAs. Returns false for a non-code.
72
+ */
73
+ export declare function isRuralPostalCode(pc: unknown): boolean;
74
+ //# sourceMappingURL=postal-code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postal-code.d.ts","sourceRoot":"","sources":["../../ca/postal-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;AAEvD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAsE,CAAA;AAEzG;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAMrE;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAElE;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,CAmBhG,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,OAAO,GAAG,oBAAoB,GAAG,oBAAoB,EAAE,GAAG,IAAI,CAI9G;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAItD"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Canadian postal codes: the branded type, the shape, normalization, and the FSA-letter →
7
+ * province/territory prior — the only ALPHANUMERIC postcode of the systems the codex models.
8
+ *
9
+ * The informative contrast across `us/zipcode.ts`, `de/postleitzahl.ts`, `fr/code-postal.ts`, and
10
+ * here:
11
+ *
12
+ * - A US ZIP is numeric; its first digit maps to a loose BAND of states.
13
+ * - A German PLZ is numeric; its first digit maps to a Leitzone that CROSSES Bundesland borders.
14
+ * - A French code postal is numeric; its first TWO digits ARE the département.
15
+ * - A Canadian postal code is `A1A 1A1` — Letter Digit Letter, then Digit Letter Digit — and its
16
+ * first LETTER pins the province or territory directly (`M` → Ontario, `H` → Quebec, `V` →
17
+ * British Columbia). So like the French prefix it is a clean admin prior, but it does the job
18
+ * with a single ALPHA character rather than digits.
19
+ *
20
+ * The clean rule has two wrinkles worth knowing. `X` is SHARED by the Northwest Territories and
21
+ * Nunavut (no single letter splits them), so `provinceOfPostalCode` returns an array there. And
22
+ * the large provinces span SEVERAL letters: Ontario alone owns `K L M N P`, Quebec owns `G H J`.
23
+ * The first three characters form the FSA (Forward Sortation Area); the last three are the LDU
24
+ * (Local Delivery Unit). A FSA whose SECOND character (the first digit) is `0` is a RURAL area —
25
+ * the bridge to the wider, lower-density delivery zones.
26
+ */
27
+ /**
28
+ * The Canadian postal-code shape. The valid FIRST letters exclude `D F I O Q U W Z` (never used to
29
+ * open a postcode); the interior letters additionally exclude `D F I O Q U` (the visually ambiguous
30
+ * ones). The space between FSA and LDU is optional in the raw form.
31
+ */
32
+ export const CA_POSTAL_CODE_PATTERN = /^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z] ?\d[ABCEGHJ-NPRSTV-Z]\d$/i;
33
+ /**
34
+ * Normalize a postal-code surface form to canonical `A1A 1A1`: uppercase and ensure exactly one
35
+ * space between the FSA (first three chars) and the LDU (last three) — `K1A0B1` → `K1A 0B1`, `k1a
36
+ * 0b1` → `K1A 0B1`. Returns null if the input is not a valid Canadian postal code.
37
+ */
38
+ export function normalizeCaPostalCode(raw) {
39
+ if (typeof raw !== "string")
40
+ return null;
41
+ const compact = raw.trim().toUpperCase().replace(/\s+/g, "");
42
+ if (compact.length !== 6)
43
+ return null;
44
+ const spaced = `${compact.slice(0, 3)} ${compact.slice(3)}`;
45
+ return CA_POSTAL_CODE_PATTERN.test(spaced) ? spaced : null;
46
+ }
47
+ /** Type-predicate for a Canadian postal code (accepts the spaced or unspaced surface form). */
48
+ export function isCaPostalCode(input) {
49
+ return typeof input === "string" && CA_POSTAL_CODE_PATTERN.test(input);
50
+ }
51
+ /**
52
+ * FSA first letter → province/territory. Clean (one province per letter) except `X`, shared by the
53
+ * Northwest Territories and Nunavut, and the large provinces that span several letters: Ontario
54
+ * owns `K L M N P` and Quebec owns `G H J`. Letters `D F I O Q U W Z` never open a Canadian
55
+ * postcode and so do not appear here.
56
+ */
57
+ export const FSA_LETTER_TO_PROVINCE = {
58
+ A: "NL",
59
+ B: "NS",
60
+ C: "PE",
61
+ E: "NB",
62
+ G: "QC",
63
+ H: "QC",
64
+ J: "QC",
65
+ K: "ON",
66
+ L: "ON",
67
+ M: "ON",
68
+ N: "ON",
69
+ P: "ON",
70
+ R: "MB",
71
+ S: "SK",
72
+ T: "AB",
73
+ V: "BC",
74
+ X: ["NT", "NU"],
75
+ Y: "YT",
76
+ };
77
+ /**
78
+ * The province/territory a postal code belongs to, via its FSA first letter. Returns the single
79
+ * code for the clean letters, the `["NT", "NU"]` pair for the shared `X`, and null if the input is
80
+ * not a valid Canadian postal code (or its first letter has no province, which the pattern already
81
+ * forbids).
82
+ */
83
+ export function provinceOfPostalCode(postalCode) {
84
+ const normalized = normalizeCaPostalCode(postalCode);
85
+ if (!normalized)
86
+ return null;
87
+ return FSA_LETTER_TO_PROVINCE[normalized[0]] ?? null;
88
+ }
89
+ /**
90
+ * True when a postal code is RURAL: its SECOND character (the FSA's first digit) is `0`. Canada
91
+ * Post uses a `0` in that position to mark the lower-density delivery zones (rural routes, small
92
+ * communities) — the contrast with the urban `1`–`9` FSAs. Returns false for a non-code.
93
+ */
94
+ export function isRuralPostalCode(pc) {
95
+ const normalized = normalizeCaPostalCode(pc);
96
+ if (!normalized)
97
+ return false;
98
+ return normalized[1] === "0";
99
+ }
100
+ //# sourceMappingURL=postal-code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postal-code.js","sourceRoot":"","sources":["../../ca/postal-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAiBH;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,mEAAmE,CAAA;AAEzG;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAY;IACjD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3D,OAAO,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAqB,CAAC,CAAC,CAAC,IAAI,CAAA;AAC3E,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,cAAc,CAAC,KAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACvE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkE;IACpG,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACf,CAAC,EAAE,IAAI;CACP,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAmB;IACvD,MAAM,UAAU,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACpD,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAC5B,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC,IAAI,IAAI,CAAA;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAW;IAC5C,MAAM,UAAU,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAAA;IAC5C,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAC7B,OAAO,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The 13 Canadian provinces and territories (10 provinces + 3 territories), keyed by their ISO
7
+ * 3166-2:CA code.
8
+ *
9
+ * The informative contrast with `de/bundesland.ts` and `us/state.ts`: a Canadian subdivision is
10
+ * officially BILINGUAL, so each unit carries two equally-canonical names — an English one and a
11
+ * French one — and the gap between them is wide (`Nova Scotia` / `Nouvelle-Écosse`, `British
12
+ * Columbia` / `Colombie-Britannique`). That mirrors the German English-exonym pattern (`Bavaria`
13
+ * / `Bayern`), except here the French name is not a foreign exonym but a co-official form a real
14
+ * address can be written in. And like a US two-letter state code, the ISO code (`ON`, `QC`, `BC`)
15
+ * is the abbreviation people actually write on the address line — so unlike German or French
16
+ * regions, the Canadian code IS a surface form, not just a resolver key.
17
+ */
18
+ /** Per-province record: ISO 3166-2:CA code, English name, and the co-official French name. */
19
+ export interface CanadianProvinceInfo {
20
+ /** ISO 3166-2:CA subdivision code without the `CA-` prefix (e.g. `ON` for `CA-ON`). */
21
+ code: string;
22
+ /** English name (e.g. `Quebec`). */
23
+ name: string;
24
+ /** Co-official French name (e.g. `Québec`). */
25
+ french: string;
26
+ }
27
+ /**
28
+ * ISO 3166-2:CA code → province/territory info, for all 13 subdivisions (10 provinces + 3
29
+ * territories). Codes are the official subdivision codes minus the `CA-` prefix.
30
+ */
31
+ export declare const CA_PROVINCES: {
32
+ readonly AB: {
33
+ readonly code: "AB";
34
+ readonly name: "Alberta";
35
+ readonly french: "Alberta";
36
+ };
37
+ readonly BC: {
38
+ readonly code: "BC";
39
+ readonly name: "British Columbia";
40
+ readonly french: "Colombie-Britannique";
41
+ };
42
+ readonly MB: {
43
+ readonly code: "MB";
44
+ readonly name: "Manitoba";
45
+ readonly french: "Manitoba";
46
+ };
47
+ readonly NB: {
48
+ readonly code: "NB";
49
+ readonly name: "New Brunswick";
50
+ readonly french: "Nouveau-Brunswick";
51
+ };
52
+ readonly NL: {
53
+ readonly code: "NL";
54
+ readonly name: "Newfoundland and Labrador";
55
+ readonly french: "Terre-Neuve-et-Labrador";
56
+ };
57
+ readonly NS: {
58
+ readonly code: "NS";
59
+ readonly name: "Nova Scotia";
60
+ readonly french: "Nouvelle-Écosse";
61
+ };
62
+ readonly NT: {
63
+ readonly code: "NT";
64
+ readonly name: "Northwest Territories";
65
+ readonly french: "Territoires du Nord-Ouest";
66
+ };
67
+ readonly NU: {
68
+ readonly code: "NU";
69
+ readonly name: "Nunavut";
70
+ readonly french: "Nunavut";
71
+ };
72
+ readonly ON: {
73
+ readonly code: "ON";
74
+ readonly name: "Ontario";
75
+ readonly french: "Ontario";
76
+ };
77
+ readonly PE: {
78
+ readonly code: "PE";
79
+ readonly name: "Prince Edward Island";
80
+ readonly french: "Île-du-Prince-Édouard";
81
+ };
82
+ readonly QC: {
83
+ readonly code: "QC";
84
+ readonly name: "Quebec";
85
+ readonly french: "Québec";
86
+ };
87
+ readonly SK: {
88
+ readonly code: "SK";
89
+ readonly name: "Saskatchewan";
90
+ readonly french: "Saskatchewan";
91
+ };
92
+ readonly YT: {
93
+ readonly code: "YT";
94
+ readonly name: "Yukon";
95
+ readonly french: "Yukon";
96
+ };
97
+ };
98
+ /** An ISO 3166-2:CA province/territory code (`AB`, `ON`, `QC`, …). */
99
+ export type CanadianProvinceCode = keyof typeof CA_PROVINCES;
100
+ /** Type-predicate for an ISO 3166-2:CA province/territory code. Case-insensitive. */
101
+ export declare function isCanadianProvinceCode(input: unknown): input is CanadianProvinceCode;
102
+ /**
103
+ * Folded province name (English or French) / code → ISO 3166-2:CA code. Built diacritic-insensitive
104
+ * so both co-official names map regardless of accents: `Québec`, `Quebec`, and an unaccented
105
+ * `Nouvelle-Ecosse` all resolve. The two-name design is the Canadian wrinkle — unlike the German
106
+ * lookup's English exonym, the French form here is a name a real address may legitimately use.
107
+ */
108
+ export declare const CA_PROVINCE_NAME_TO_CODE: ReadonlyMap<string, CanadianProvinceCode>;
109
+ /**
110
+ * Resolve a Canadian province/territory surface form (ISO code, English name, or French name,
111
+ * accents optional) to its ISO code; null if unknown.
112
+ */
113
+ export declare function lookupCanadianProvince(input: string | null | undefined): CanadianProvinceCode | null;
114
+ //# sourceMappingURL=province.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"province.d.ts","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,8FAA8F;AAC9F,MAAM,WAAW,oBAAoB;IACpC,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAA;IACZ,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcgC,CAAA;AAEzD,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,YAAY,CAAA;AAI5D,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAYD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAS3E,CAAA;AAEJ;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,oBAAoB,GAAG,IAAI,CAKpG"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The 13 Canadian provinces and territories (10 provinces + 3 territories), keyed by their ISO
7
+ * 3166-2:CA code.
8
+ *
9
+ * The informative contrast with `de/bundesland.ts` and `us/state.ts`: a Canadian subdivision is
10
+ * officially BILINGUAL, so each unit carries two equally-canonical names — an English one and a
11
+ * French one — and the gap between them is wide (`Nova Scotia` / `Nouvelle-Écosse`, `British
12
+ * Columbia` / `Colombie-Britannique`). That mirrors the German English-exonym pattern (`Bavaria`
13
+ * / `Bayern`), except here the French name is not a foreign exonym but a co-official form a real
14
+ * address can be written in. And like a US two-letter state code, the ISO code (`ON`, `QC`, `BC`)
15
+ * is the abbreviation people actually write on the address line — so unlike German or French
16
+ * regions, the Canadian code IS a surface form, not just a resolver key.
17
+ */
18
+ /**
19
+ * ISO 3166-2:CA code → province/territory info, for all 13 subdivisions (10 provinces + 3
20
+ * territories). Codes are the official subdivision codes minus the `CA-` prefix.
21
+ */
22
+ export const CA_PROVINCES = {
23
+ AB: { code: "AB", name: "Alberta", french: "Alberta" },
24
+ BC: { code: "BC", name: "British Columbia", french: "Colombie-Britannique" },
25
+ MB: { code: "MB", name: "Manitoba", french: "Manitoba" },
26
+ NB: { code: "NB", name: "New Brunswick", french: "Nouveau-Brunswick" },
27
+ NL: { code: "NL", name: "Newfoundland and Labrador", french: "Terre-Neuve-et-Labrador" },
28
+ NS: { code: "NS", name: "Nova Scotia", french: "Nouvelle-Écosse" },
29
+ NT: { code: "NT", name: "Northwest Territories", french: "Territoires du Nord-Ouest" },
30
+ NU: { code: "NU", name: "Nunavut", french: "Nunavut" },
31
+ ON: { code: "ON", name: "Ontario", french: "Ontario" },
32
+ PE: { code: "PE", name: "Prince Edward Island", french: "Île-du-Prince-Édouard" },
33
+ QC: { code: "QC", name: "Quebec", french: "Québec" },
34
+ SK: { code: "SK", name: "Saskatchewan", french: "Saskatchewan" },
35
+ YT: { code: "YT", name: "Yukon", french: "Yukon" },
36
+ };
37
+ const PROVINCE_CODE_SET = new Set(Object.keys(CA_PROVINCES));
38
+ /** Type-predicate for an ISO 3166-2:CA province/territory code. Case-insensitive. */
39
+ export function isCanadianProvinceCode(input) {
40
+ return typeof input === "string" && PROVINCE_CODE_SET.has(input.toUpperCase());
41
+ }
42
+ /** Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike. */
43
+ function foldName(s) {
44
+ return s
45
+ .toLowerCase()
46
+ .normalize("NFD")
47
+ .replace(/[\u0300-\u036f]/g, "")
48
+ .replace(/[^a-z0-9]+/g, " ")
49
+ .trim();
50
+ }
51
+ /**
52
+ * Folded province name (English or French) / code → ISO 3166-2:CA code. Built diacritic-insensitive
53
+ * so both co-official names map regardless of accents: `Québec`, `Quebec`, and an unaccented
54
+ * `Nouvelle-Ecosse` all resolve. The two-name design is the Canadian wrinkle — unlike the German
55
+ * lookup's English exonym, the French form here is a name a real address may legitimately use.
56
+ */
57
+ export const CA_PROVINCE_NAME_TO_CODE = (() => {
58
+ const out = new Map();
59
+ for (const code of Object.keys(CA_PROVINCES)) {
60
+ const info = CA_PROVINCES[code];
61
+ out.set(foldName(info.name), code);
62
+ out.set(foldName(info.french), code);
63
+ out.set(code.toLowerCase(), code);
64
+ }
65
+ return out;
66
+ })();
67
+ /**
68
+ * Resolve a Canadian province/territory surface form (ISO code, English name, or French name,
69
+ * accents optional) to its ISO code; null if unknown.
70
+ */
71
+ export function lookupCanadianProvince(input) {
72
+ if (!input || typeof input !== "string")
73
+ return null;
74
+ const upper = input.trim().toUpperCase();
75
+ if (PROVINCE_CODE_SET.has(upper))
76
+ return upper;
77
+ return CA_PROVINCE_NAME_TO_CODE.get(foldName(input)) ?? null;
78
+ }
79
+ //# sourceMappingURL=province.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"province.js","sourceRoot":"","sources":["../../ca/province.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Canadian street types and directionals — BILINGUAL, because Canada Post recognizes both English
7
+ * and French forms on the same national network.
8
+ *
9
+ * The informative contrast with `us/street-suffix.ts`, `de/street-type.ts`, and `fr/voie.ts`:
10
+ *
11
+ * - US — a trailing word with a USPS-standardized abbreviation (`Main Street` → `ST`).
12
+ * - German — a fused TRAILING suffix (`Hauptstraße`).
13
+ * - French — a LEADING standalone word (`Rue de la Paix`).
14
+ * - Canadian — BOTH at once. An English street puts the type LAST (`Maple Avenue`, `Sunset
15
+ * Crescent`); a French street puts it FIRST (`Rue Sainte-Catherine`, `Boulevard
16
+ * René-Lévesque`). So {@link isCanadianStreetWord} matches a whole token against EITHER
17
+ * vocabulary and stays position-agnostic — it cannot assume a side the way the
18
+ * single-language files do.
19
+ *
20
+ * The directionals carry the same bilingual twist, and one trap inside it: French `Ouest`
21
+ * abbreviates to `O`, not `W`. A naive English-only matcher reading `Rue Sherbrooke O` would miss
22
+ * the quadrant entirely. {@link CA_DIRECTIONALS} spells out the French abbreviations so `O` =
23
+ * Ouest = West is recognized.
24
+ */
25
+ /**
26
+ * English Canadian street-type words (Canada Post's recognized set, lowercase). Appear as the
27
+ * TRAILING token of an English street name (`Maple Avenue`, `Sunset Crescent`).
28
+ */
29
+ export declare const CA_STREET_TYPES_EN: ReadonlySet<string>;
30
+ /**
31
+ * French Canadian street-type words (Canada Post's recognized set, lowercase, accent-bearing).
32
+ * Appear as the LEADING token of a French street name (`Rue Sainte-Catherine`, `Chemin du Roy`).
33
+ * Folded for matching in {@link isCanadianStreetWord}, so `Côte`/`cote` and `Allée`/`allee` key
34
+ * alike.
35
+ */
36
+ export declare const CA_STREET_TYPES_FR: ReadonlySet<string>;
37
+ /**
38
+ * True when a token is a Canadian street-type word in EITHER language (case- and
39
+ * accent-insensitive) — `Street`, `Crescent`, `Rue`, `Chemin`, `Côte`. Position-agnostic, because
40
+ * an English type trails the name and a French type leads it; the matcher cannot lean on a side.
41
+ */
42
+ export declare function isCanadianStreetWord(token: unknown): boolean;
43
+ /**
44
+ * Bilingual directional words → canonical compass letter. Covers the bare letters (`N S E W`), the
45
+ * full English words (`North`/`South`/`East`/`West`), and the full French words
46
+ * (`Nord`/`Sud`/`Est`/`Ouest`). The bilingual twist is `O`: French `Ouest` abbreviates to `O`, NOT
47
+ * `W`, so an English-only matcher silently drops the quadrant on a French address line. Keys are
48
+ * folded (lowercase, accent-free); values are the English compass letter.
49
+ */
50
+ export declare const CA_DIRECTIONALS: Record<string, "N" | "S" | "E" | "W">;
51
+ /**
52
+ * True when a token is a Canadian directional in either language (case- and accent-insensitive) —
53
+ * `N`, `NW`, `Nord`, `Ouest`, `O`. Compound English quadrants (`NW`, `SE`) are accepted by
54
+ * decomposing into their single-letter halves; the lone French `O` resolves to West.
55
+ */
56
+ export declare function isCanadianDirectional(token: unknown): boolean;
57
+ //# sourceMappingURL=street-type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"street-type.d.ts","sourceRoot":"","sources":["../../ca/street-type.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CA8BjD,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAmBjD,CAAA;AAmBF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI5D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAcjE,CAAA;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAW7D"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Canadian street types and directionals — BILINGUAL, because Canada Post recognizes both English
7
+ * and French forms on the same national network.
8
+ *
9
+ * The informative contrast with `us/street-suffix.ts`, `de/street-type.ts`, and `fr/voie.ts`:
10
+ *
11
+ * - US — a trailing word with a USPS-standardized abbreviation (`Main Street` → `ST`).
12
+ * - German — a fused TRAILING suffix (`Hauptstraße`).
13
+ * - French — a LEADING standalone word (`Rue de la Paix`).
14
+ * - Canadian — BOTH at once. An English street puts the type LAST (`Maple Avenue`, `Sunset
15
+ * Crescent`); a French street puts it FIRST (`Rue Sainte-Catherine`, `Boulevard
16
+ * René-Lévesque`). So {@link isCanadianStreetWord} matches a whole token against EITHER
17
+ * vocabulary and stays position-agnostic — it cannot assume a side the way the
18
+ * single-language files do.
19
+ *
20
+ * The directionals carry the same bilingual twist, and one trap inside it: French `Ouest`
21
+ * abbreviates to `O`, not `W`. A naive English-only matcher reading `Rue Sherbrooke O` would miss
22
+ * the quadrant entirely. {@link CA_DIRECTIONALS} spells out the French abbreviations so `O` =
23
+ * Ouest = West is recognized.
24
+ */
25
+ /**
26
+ * English Canadian street-type words (Canada Post's recognized set, lowercase). Appear as the
27
+ * TRAILING token of an English street name (`Maple Avenue`, `Sunset Crescent`).
28
+ */
29
+ export const CA_STREET_TYPES_EN = new Set([
30
+ "street",
31
+ "avenue",
32
+ "boulevard",
33
+ "drive",
34
+ "road",
35
+ "crescent",
36
+ "court",
37
+ "place",
38
+ "lane",
39
+ "way",
40
+ "trail",
41
+ "terrace",
42
+ "close",
43
+ "circle",
44
+ "square",
45
+ "heights",
46
+ "grove",
47
+ "gardens",
48
+ "hill",
49
+ "park",
50
+ "row",
51
+ "walk",
52
+ "green",
53
+ "bay",
54
+ "cove",
55
+ "gate",
56
+ "point",
57
+ "ridge",
58
+ "view",
59
+ ]);
60
+ /**
61
+ * French Canadian street-type words (Canada Post's recognized set, lowercase, accent-bearing).
62
+ * Appear as the LEADING token of a French street name (`Rue Sainte-Catherine`, `Chemin du Roy`).
63
+ * Folded for matching in {@link isCanadianStreetWord}, so `Côte`/`cote` and `Allée`/`allee` key
64
+ * alike.
65
+ */
66
+ export const CA_STREET_TYPES_FR = new Set([
67
+ "rue",
68
+ "avenue",
69
+ "boulevard",
70
+ "chemin",
71
+ "côte",
72
+ "place",
73
+ "impasse",
74
+ "allée",
75
+ "croissant",
76
+ "montée",
77
+ "rang",
78
+ "ruelle",
79
+ "voie",
80
+ "passage",
81
+ "carré",
82
+ "terrasse",
83
+ "promenade",
84
+ "sentier",
85
+ ]);
86
+ /** Strip diacritics + lowercase so `Côte`/`cote`, `Allée`/`allee`, `Crescent`/`crescent` key alike. */
87
+ function foldToken(s) {
88
+ return s
89
+ .toLowerCase()
90
+ .normalize("NFD")
91
+ .replace(/[\u0300-\u036f]/g, "")
92
+ .replace(/[^a-z]/g, "");
93
+ }
94
+ /** The English + French street-type vocabularies, both folded, for one position-agnostic lookup. */
95
+ const STREET_WORD_SET = (() => {
96
+ const out = new Set();
97
+ for (const w of CA_STREET_TYPES_EN)
98
+ out.add(foldToken(w));
99
+ for (const w of CA_STREET_TYPES_FR)
100
+ out.add(foldToken(w));
101
+ return out;
102
+ })();
103
+ /**
104
+ * True when a token is a Canadian street-type word in EITHER language (case- and
105
+ * accent-insensitive) — `Street`, `Crescent`, `Rue`, `Chemin`, `Côte`. Position-agnostic, because
106
+ * an English type trails the name and a French type leads it; the matcher cannot lean on a side.
107
+ */
108
+ export function isCanadianStreetWord(token) {
109
+ if (typeof token !== "string")
110
+ return false;
111
+ const t = foldToken(token);
112
+ return t.length > 0 && STREET_WORD_SET.has(t);
113
+ }
114
+ /**
115
+ * Bilingual directional words → canonical compass letter. Covers the bare letters (`N S E W`), the
116
+ * full English words (`North`/`South`/`East`/`West`), and the full French words
117
+ * (`Nord`/`Sud`/`Est`/`Ouest`). The bilingual twist is `O`: French `Ouest` abbreviates to `O`, NOT
118
+ * `W`, so an English-only matcher silently drops the quadrant on a French address line. Keys are
119
+ * folded (lowercase, accent-free); values are the English compass letter.
120
+ */
121
+ export const CA_DIRECTIONALS = {
122
+ n: "N",
123
+ north: "N",
124
+ nord: "N",
125
+ s: "S",
126
+ south: "S",
127
+ sud: "S",
128
+ e: "E",
129
+ east: "E",
130
+ est: "E",
131
+ w: "W",
132
+ west: "W",
133
+ ouest: "W",
134
+ o: "W", // French Ouest abbreviates to O, not W — the bilingual trap.
135
+ };
136
+ /**
137
+ * True when a token is a Canadian directional in either language (case- and accent-insensitive) —
138
+ * `N`, `NW`, `Nord`, `Ouest`, `O`. Compound English quadrants (`NW`, `SE`) are accepted by
139
+ * decomposing into their single-letter halves; the lone French `O` resolves to West.
140
+ */
141
+ export function isCanadianDirectional(token) {
142
+ if (typeof token !== "string")
143
+ return false;
144
+ const t = foldToken(token);
145
+ if (t.length === 0)
146
+ return false;
147
+ if (t in CA_DIRECTIONALS)
148
+ return true;
149
+ // Compound English quadrants like NW / SE / NE / SW: each half must be a single-letter directional.
150
+ if (t.length === 2) {
151
+ const isLetter = (h) => h === "n" || h === "s" || h === "e" || h === "w";
152
+ return isLetter(t[0]) && isLetter(t[1]);
153
+ }
154
+ return false;
155
+ }
156
+ //# sourceMappingURL=street-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"street-type.js","sourceRoot":"","sources":["../../ca/street-type.ts"],"names":[],"mappings":"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"}