@mailwoman/codex 7.2.1 → 7.4.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.
- package/country/index.ts +1 -0
- package/country/subdivision.ts +93 -0
- package/out/country/index.d.ts +1 -0
- package/out/country/index.d.ts.map +1 -1
- package/out/country/index.js +1 -0
- package/out/country/index.js.map +1 -1
- package/out/country/subdivision.d.ts +44 -0
- package/out/country/subdivision.d.ts.map +1 -0
- package/out/country/subdivision.js +76 -0
- package/out/country/subdivision.js.map +1 -0
- package/package.json +2 -2
package/country/index.ts
CHANGED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* ISO 3166-2 subdivision → country reference, the cross-country complement to `country.ts`'s
|
|
7
|
+
* ISO 3166-1 `matchCountry`. A subdivision token ("QC", "Ontario", "Illinois") names a first-level
|
|
8
|
+
* admin unit whose COUNTRY is the piece the resolver needs when a region qualifier is the only
|
|
9
|
+
* signal that the locale-inferred default country is wrong ("Montreal QC" under a US locale).
|
|
10
|
+
*
|
|
11
|
+
* Scope is deliberately minimal: the two subdivision systems whose two-letter codes people write
|
|
12
|
+
* ON THE ADDRESS LINE and whose homonymous localities collide across the border — US states
|
|
13
|
+
* (`us/state.ts`) and Canadian provinces (`ca/province.ts`). Both directions are covered: the ISO
|
|
14
|
+
* code (`QC` → Quebec) and the full name (`Quebec` / `Québec` → the `QC` record), so a resolver
|
|
15
|
+
* can expand the abbreviation the gazetteer FTS index lacks ("QC" is not an alt-name of Québec)
|
|
16
|
+
* into the full name it does carry. This is a soft prior, not a routing decision — the gazetteer
|
|
17
|
+
* still does the geographic confirmation (per the registry-backed-soft-prior doctrine).
|
|
18
|
+
*
|
|
19
|
+
* The US and Canadian code sets are disjoint (no two-letter code, and no full name, collides
|
|
20
|
+
* between the two), so the combined lookup below is unambiguous. `CA` resolves to California the
|
|
21
|
+
* US state (Canada's provinces carry no `CA` subdivision code), never to Canada the country —
|
|
22
|
+
* country recognition stays with `matchCountry`.
|
|
23
|
+
*
|
|
24
|
+
* Source: the underlying `US_STATE_BY_ABBREVIATION` (USPS Publication 28, Appendix B) and
|
|
25
|
+
* `CA_PROVINCES` (ISO 3166-2:CA) tables. No new provenance is introduced here — this module only
|
|
26
|
+
* re-keys those two existing tables into one subdivision→country view.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { CA_PROVINCES } from "../ca/province.ts"
|
|
30
|
+
import { US_STATE_BY_ABBREVIATION } from "../us/state.ts"
|
|
31
|
+
|
|
32
|
+
/** A resolved subdivision: its ISO 3166-2 code (sans country prefix), canonical English name, and ISO 3166-1 country. */
|
|
33
|
+
export interface SubdivisionMatch {
|
|
34
|
+
/** ISO 3166-2 subdivision code without the country prefix (e.g. `QC` for `CA-QC`, `IL` for `US-IL`). */
|
|
35
|
+
code: string
|
|
36
|
+
/** Canonical English name (e.g. `Quebec`, `Illinois`). */
|
|
37
|
+
name: string
|
|
38
|
+
/** ISO 3166-1 alpha-2 country the subdivision belongs to (`CA`, `US`). */
|
|
39
|
+
country: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike (mirrors `ca/province.ts`). */
|
|
43
|
+
function foldName(s: string): string {
|
|
44
|
+
return s
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.normalize("NFD")
|
|
47
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
48
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
49
|
+
.trim()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Folded surface form (ISO code, English name, or — for CA — co-official French name) → subdivision. Built once. US
|
|
54
|
+
* states are inserted first and never overwritten, so on the (currently empty) event of a future code/name collision
|
|
55
|
+
* the US entry wins deterministically; today the two sets are disjoint.
|
|
56
|
+
*/
|
|
57
|
+
const SUBDIVISION_LOOKUP: ReadonlyMap<string, SubdivisionMatch> = (() => {
|
|
58
|
+
const out = new Map<string, SubdivisionMatch>()
|
|
59
|
+
const put = (key: string, match: SubdivisionMatch): void => {
|
|
60
|
+
const folded = foldName(key)
|
|
61
|
+
|
|
62
|
+
if (folded.length > 0 && !out.has(folded)) {
|
|
63
|
+
out.set(folded, match)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const [code, name] of Object.entries(US_STATE_BY_ABBREVIATION)) {
|
|
68
|
+
const match: SubdivisionMatch = { code, name, country: "US" }
|
|
69
|
+
put(code, match)
|
|
70
|
+
put(name, match)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (const info of Object.values(CA_PROVINCES)) {
|
|
74
|
+
const match: SubdivisionMatch = { code: info.code, name: info.name, country: "CA" }
|
|
75
|
+
put(info.code, match)
|
|
76
|
+
put(info.name, match)
|
|
77
|
+
put(info.french, match)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return out
|
|
81
|
+
})()
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Resolve a first-level subdivision surface form (ISO 3166-2 code, English name, or co-official French name for CA;
|
|
85
|
+
* accents optional) to its `{ code, name, country }`. Case- and diacritic-insensitive. Returns null for anything that
|
|
86
|
+
* isn't a US state or Canadian province/territory — including bare country tokens (use {@link matchCountry} for
|
|
87
|
+
* those).
|
|
88
|
+
*/
|
|
89
|
+
export function matchSubdivision(token: string | null | undefined): SubdivisionMatch | null {
|
|
90
|
+
if (!token || typeof token !== "string") return null
|
|
91
|
+
|
|
92
|
+
return SUBDIVISION_LOOKUP.get(foldName(token)) ?? null
|
|
93
|
+
}
|
package/out/country/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../country/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../country/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA"}
|
package/out/country/index.js
CHANGED
package/out/country/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../country/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../country/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* ISO 3166-2 subdivision → country reference, the cross-country complement to `country.ts`'s
|
|
7
|
+
* ISO 3166-1 `matchCountry`. A subdivision token ("QC", "Ontario", "Illinois") names a first-level
|
|
8
|
+
* admin unit whose COUNTRY is the piece the resolver needs when a region qualifier is the only
|
|
9
|
+
* signal that the locale-inferred default country is wrong ("Montreal QC" under a US locale).
|
|
10
|
+
*
|
|
11
|
+
* Scope is deliberately minimal: the two subdivision systems whose two-letter codes people write
|
|
12
|
+
* ON THE ADDRESS LINE and whose homonymous localities collide across the border — US states
|
|
13
|
+
* (`us/state.ts`) and Canadian provinces (`ca/province.ts`). Both directions are covered: the ISO
|
|
14
|
+
* code (`QC` → Quebec) and the full name (`Quebec` / `Québec` → the `QC` record), so a resolver
|
|
15
|
+
* can expand the abbreviation the gazetteer FTS index lacks ("QC" is not an alt-name of Québec)
|
|
16
|
+
* into the full name it does carry. This is a soft prior, not a routing decision — the gazetteer
|
|
17
|
+
* still does the geographic confirmation (per the registry-backed-soft-prior doctrine).
|
|
18
|
+
*
|
|
19
|
+
* The US and Canadian code sets are disjoint (no two-letter code, and no full name, collides
|
|
20
|
+
* between the two), so the combined lookup below is unambiguous. `CA` resolves to California the
|
|
21
|
+
* US state (Canada's provinces carry no `CA` subdivision code), never to Canada the country —
|
|
22
|
+
* country recognition stays with `matchCountry`.
|
|
23
|
+
*
|
|
24
|
+
* Source: the underlying `US_STATE_BY_ABBREVIATION` (USPS Publication 28, Appendix B) and
|
|
25
|
+
* `CA_PROVINCES` (ISO 3166-2:CA) tables. No new provenance is introduced here — this module only
|
|
26
|
+
* re-keys those two existing tables into one subdivision→country view.
|
|
27
|
+
*/
|
|
28
|
+
/** A resolved subdivision: its ISO 3166-2 code (sans country prefix), canonical English name, and ISO 3166-1 country. */
|
|
29
|
+
export interface SubdivisionMatch {
|
|
30
|
+
/** ISO 3166-2 subdivision code without the country prefix (e.g. `QC` for `CA-QC`, `IL` for `US-IL`). */
|
|
31
|
+
code: string;
|
|
32
|
+
/** Canonical English name (e.g. `Quebec`, `Illinois`). */
|
|
33
|
+
name: string;
|
|
34
|
+
/** ISO 3166-1 alpha-2 country the subdivision belongs to (`CA`, `US`). */
|
|
35
|
+
country: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Resolve a first-level subdivision surface form (ISO 3166-2 code, English name, or co-official French name for CA;
|
|
39
|
+
* accents optional) to its `{ code, name, country }`. Case- and diacritic-insensitive. Returns null for anything that
|
|
40
|
+
* isn't a US state or Canadian province/territory — including bare country tokens (use {@link matchCountry} for
|
|
41
|
+
* those).
|
|
42
|
+
*/
|
|
43
|
+
export declare function matchSubdivision(token: string | null | undefined): SubdivisionMatch | null;
|
|
44
|
+
//# sourceMappingURL=subdivision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subdivision.d.ts","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH,yHAAyH;AACzH,MAAM,WAAW,gBAAgB;IAChC,wGAAwG;IACxG,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;CACf;AA2CD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAI1F"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* ISO 3166-2 subdivision → country reference, the cross-country complement to `country.ts`'s
|
|
7
|
+
* ISO 3166-1 `matchCountry`. A subdivision token ("QC", "Ontario", "Illinois") names a first-level
|
|
8
|
+
* admin unit whose COUNTRY is the piece the resolver needs when a region qualifier is the only
|
|
9
|
+
* signal that the locale-inferred default country is wrong ("Montreal QC" under a US locale).
|
|
10
|
+
*
|
|
11
|
+
* Scope is deliberately minimal: the two subdivision systems whose two-letter codes people write
|
|
12
|
+
* ON THE ADDRESS LINE and whose homonymous localities collide across the border — US states
|
|
13
|
+
* (`us/state.ts`) and Canadian provinces (`ca/province.ts`). Both directions are covered: the ISO
|
|
14
|
+
* code (`QC` → Quebec) and the full name (`Quebec` / `Québec` → the `QC` record), so a resolver
|
|
15
|
+
* can expand the abbreviation the gazetteer FTS index lacks ("QC" is not an alt-name of Québec)
|
|
16
|
+
* into the full name it does carry. This is a soft prior, not a routing decision — the gazetteer
|
|
17
|
+
* still does the geographic confirmation (per the registry-backed-soft-prior doctrine).
|
|
18
|
+
*
|
|
19
|
+
* The US and Canadian code sets are disjoint (no two-letter code, and no full name, collides
|
|
20
|
+
* between the two), so the combined lookup below is unambiguous. `CA` resolves to California the
|
|
21
|
+
* US state (Canada's provinces carry no `CA` subdivision code), never to Canada the country —
|
|
22
|
+
* country recognition stays with `matchCountry`.
|
|
23
|
+
*
|
|
24
|
+
* Source: the underlying `US_STATE_BY_ABBREVIATION` (USPS Publication 28, Appendix B) and
|
|
25
|
+
* `CA_PROVINCES` (ISO 3166-2:CA) tables. No new provenance is introduced here — this module only
|
|
26
|
+
* re-keys those two existing tables into one subdivision→country view.
|
|
27
|
+
*/
|
|
28
|
+
import { CA_PROVINCES } from "../ca/province.js";
|
|
29
|
+
import { US_STATE_BY_ABBREVIATION } from "../us/state.js";
|
|
30
|
+
/** Strip diacritics + lowercase so `Québec`, `Quebec`, and `quebec` all key alike (mirrors `ca/province.ts`). */
|
|
31
|
+
function foldName(s) {
|
|
32
|
+
return s
|
|
33
|
+
.toLowerCase()
|
|
34
|
+
.normalize("NFD")
|
|
35
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
36
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
37
|
+
.trim();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Folded surface form (ISO code, English name, or — for CA — co-official French name) → subdivision. Built once. US
|
|
41
|
+
* states are inserted first and never overwritten, so on the (currently empty) event of a future code/name collision
|
|
42
|
+
* the US entry wins deterministically; today the two sets are disjoint.
|
|
43
|
+
*/
|
|
44
|
+
const SUBDIVISION_LOOKUP = (() => {
|
|
45
|
+
const out = new Map();
|
|
46
|
+
const put = (key, match) => {
|
|
47
|
+
const folded = foldName(key);
|
|
48
|
+
if (folded.length > 0 && !out.has(folded)) {
|
|
49
|
+
out.set(folded, match);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
for (const [code, name] of Object.entries(US_STATE_BY_ABBREVIATION)) {
|
|
53
|
+
const match = { code, name, country: "US" };
|
|
54
|
+
put(code, match);
|
|
55
|
+
put(name, match);
|
|
56
|
+
}
|
|
57
|
+
for (const info of Object.values(CA_PROVINCES)) {
|
|
58
|
+
const match = { code: info.code, name: info.name, country: "CA" };
|
|
59
|
+
put(info.code, match);
|
|
60
|
+
put(info.name, match);
|
|
61
|
+
put(info.french, match);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
})();
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a first-level subdivision surface form (ISO 3166-2 code, English name, or co-official French name for CA;
|
|
67
|
+
* accents optional) to its `{ code, name, country }`. Case- and diacritic-insensitive. Returns null for anything that
|
|
68
|
+
* isn't a US state or Canadian province/territory — including bare country tokens (use {@link matchCountry} for
|
|
69
|
+
* those).
|
|
70
|
+
*/
|
|
71
|
+
export function matchSubdivision(token) {
|
|
72
|
+
if (!token || typeof token !== "string")
|
|
73
|
+
return null;
|
|
74
|
+
return SUBDIVISION_LOOKUP.get(foldName(token)) ?? null;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=subdivision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subdivision.js","sourceRoot":"","sources":["../../country/subdivision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAYzD,iHAAiH;AACjH,SAAS,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC;SACN,WAAW,EAAE;SACb,SAAS,CAAC,KAAK,CAAC;SAChB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,IAAI,EAAE,CAAA;AACT,CAAC;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAA0C,CAAC,GAAG,EAAE;IACvE,MAAM,GAAG,GAAG,IAAI,GAAG,EAA4B,CAAA;IAC/C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,KAAuB,EAAQ,EAAE;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;QAE5B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACvB,CAAC;IACF,CAAC,CAAA;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,CAAC;QACrE,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAC7D,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAChB,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACjB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAChD,MAAM,KAAK,GAAqB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QACnF,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACrB,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,GAAG,CAAA;AACX,CAAC,CAAC,EAAE,CAAA;AAEJ;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAgC;IAChE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEpD,OAAO,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAA;AACvD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/codex",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "Per-address-system postal reference data + branded types (USPS street suffixes, US ZIP codes). Pure, zero-runtime-dep — the shared canonical home for postal-system primitives the parser, resolver, and synthesis layers all reach for.",
|
|
5
5
|
"license": "AGPL-3.0-only OR LicenseRef-Commercial",
|
|
6
6
|
"repository": {
|
|
@@ -124,6 +124,6 @@
|
|
|
124
124
|
"type-fest": "^5.8.0"
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
|
-
"@mailwoman/annotations": "7.
|
|
127
|
+
"@mailwoman/annotations": "7.4.0"
|
|
128
128
|
}
|
|
129
129
|
}
|