@mailwoman/codex 8.1.0 → 8.3.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 (210) hide show
  1. package/address-system-conventions.ts +7 -1
  2. package/au/delivery-service.ts +34 -12
  3. package/au/level-designator.ts +38 -14
  4. package/au/postcode.ts +9 -3
  5. package/au/state.ts +9 -3
  6. package/ca/postal-code.ts +10 -3
  7. package/ca/province.ts +23 -9
  8. package/ca/street-type.ts +9 -5
  9. package/country/country.ts +14 -8
  10. package/country/official-languages.ts +12 -4
  11. package/country/reference-data.ts +7 -3
  12. package/country/reference.ts +1 -1
  13. package/country/subdivision.ts +19 -8
  14. package/de/bundesland.ts +19 -6
  15. package/de/postleitzahl.ts +21 -7
  16. package/de/street-type.ts +14 -3
  17. package/fr/cedex.ts +15 -5
  18. package/fr/code-postal.ts +17 -4
  19. package/fr/departement.ts +18 -6
  20. package/fr/region.ts +23 -9
  21. package/fr/voie.ts +8 -4
  22. package/gb/country.ts +25 -9
  23. package/gb/postcode-area.ts +6 -2
  24. package/gb/postcode.ts +10 -3
  25. package/gb/street-type.ts +4 -2
  26. package/index.ts +1 -0
  27. package/jp/address-unit.ts +8 -4
  28. package/jp/postal-code.ts +7 -3
  29. package/jp/prefecture.ts +27 -10
  30. package/level-semantics.ts +55 -19
  31. package/nz/delivery-service.ts +43 -15
  32. package/nz/postcode.ts +9 -3
  33. package/out/address-system-conventions.d.ts +7 -1
  34. package/out/address-system-conventions.d.ts.map +1 -1
  35. package/out/address-system-conventions.js +7 -1
  36. package/out/address-system-conventions.js.map +1 -1
  37. package/out/au/delivery-service.d.ts +30 -10
  38. package/out/au/delivery-service.d.ts.map +1 -1
  39. package/out/au/delivery-service.js +7 -3
  40. package/out/au/delivery-service.js.map +1 -1
  41. package/out/au/level-designator.d.ts +27 -9
  42. package/out/au/level-designator.d.ts.map +1 -1
  43. package/out/au/level-designator.js +10 -6
  44. package/out/au/level-designator.js.map +1 -1
  45. package/out/au/postcode.d.ts +9 -3
  46. package/out/au/postcode.d.ts.map +1 -1
  47. package/out/au/postcode.js +9 -3
  48. package/out/au/postcode.js.map +1 -1
  49. package/out/au/state.d.ts +9 -3
  50. package/out/au/state.d.ts.map +1 -1
  51. package/out/au/state.js +6 -2
  52. package/out/au/state.js.map +1 -1
  53. package/out/ca/postal-code.d.ts +3 -1
  54. package/out/ca/postal-code.d.ts.map +1 -1
  55. package/out/ca/postal-code.js +9 -3
  56. package/out/ca/postal-code.js.map +1 -1
  57. package/out/ca/province.d.ts +18 -6
  58. package/out/ca/province.d.ts.map +1 -1
  59. package/out/ca/province.js +8 -4
  60. package/out/ca/province.js.map +1 -1
  61. package/out/ca/street-type.d.ts.map +1 -1
  62. package/out/ca/street-type.js +9 -5
  63. package/out/ca/street-type.js.map +1 -1
  64. package/out/country/country.d.ts +11 -7
  65. package/out/country/country.d.ts.map +1 -1
  66. package/out/country/country.js +7 -4
  67. package/out/country/country.js.map +1 -1
  68. package/out/country/official-languages.d.ts +12 -4
  69. package/out/country/official-languages.d.ts.map +1 -1
  70. package/out/country/official-languages.js +3 -1
  71. package/out/country/official-languages.js.map +1 -1
  72. package/out/country/reference-data.d.ts +6 -2
  73. package/out/country/reference-data.d.ts.map +1 -1
  74. package/out/country/reference-data.js +4 -2
  75. package/out/country/reference-data.js.map +1 -1
  76. package/out/country/reference.js +1 -1
  77. package/out/country/reference.js.map +1 -1
  78. package/out/country/subdivision.d.ts +12 -4
  79. package/out/country/subdivision.d.ts.map +1 -1
  80. package/out/country/subdivision.js +6 -4
  81. package/out/country/subdivision.js.map +1 -1
  82. package/out/de/bundesland.d.ts +18 -6
  83. package/out/de/bundesland.d.ts.map +1 -1
  84. package/out/de/bundesland.js +3 -1
  85. package/out/de/bundesland.js.map +1 -1
  86. package/out/de/postleitzahl.d.ts +21 -7
  87. package/out/de/postleitzahl.d.ts.map +1 -1
  88. package/out/de/postleitzahl.js +9 -3
  89. package/out/de/postleitzahl.js.map +1 -1
  90. package/out/de/street-type.d.ts +5 -4
  91. package/out/de/street-type.d.ts.map +1 -1
  92. package/out/de/street-type.js +10 -2
  93. package/out/de/street-type.js.map +1 -1
  94. package/out/fr/cedex.d.ts +15 -5
  95. package/out/fr/cedex.d.ts.map +1 -1
  96. package/out/fr/cedex.js +6 -2
  97. package/out/fr/cedex.js.map +1 -1
  98. package/out/fr/code-postal.d.ts +8 -11
  99. package/out/fr/code-postal.d.ts.map +1 -1
  100. package/out/fr/code-postal.js +24 -4
  101. package/out/fr/code-postal.js.map +1 -1
  102. package/out/fr/departement.d.ts +18 -6
  103. package/out/fr/departement.d.ts.map +1 -1
  104. package/out/fr/departement.js +3 -1
  105. package/out/fr/departement.js.map +1 -1
  106. package/out/fr/region.d.ts +18 -6
  107. package/out/fr/region.d.ts.map +1 -1
  108. package/out/fr/region.js +11 -5
  109. package/out/fr/region.js.map +1 -1
  110. package/out/fr/voie.d.ts +3 -1
  111. package/out/fr/voie.d.ts.map +1 -1
  112. package/out/fr/voie.js +3 -3
  113. package/out/fr/voie.js.map +1 -1
  114. package/out/gb/country.d.ts +18 -6
  115. package/out/gb/country.d.ts.map +1 -1
  116. package/out/gb/country.js +13 -5
  117. package/out/gb/country.js.map +1 -1
  118. package/out/gb/postcode-area.d.ts.map +1 -1
  119. package/out/gb/postcode-area.js +6 -2
  120. package/out/gb/postcode-area.js.map +1 -1
  121. package/out/gb/postcode.d.ts +3 -11
  122. package/out/gb/postcode.d.ts.map +1 -1
  123. package/out/gb/postcode.js +19 -3
  124. package/out/gb/postcode.js.map +1 -1
  125. package/out/gb/street-type.d.ts +3 -1
  126. package/out/gb/street-type.d.ts.map +1 -1
  127. package/out/gb/street-type.js +1 -1
  128. package/out/gb/street-type.js.map +1 -1
  129. package/out/index.d.ts.map +1 -1
  130. package/out/index.js.map +1 -1
  131. package/out/jp/address-unit.d.ts +6 -2
  132. package/out/jp/address-unit.d.ts.map +1 -1
  133. package/out/jp/address-unit.js +2 -2
  134. package/out/jp/address-unit.js.map +1 -1
  135. package/out/jp/postal-code.d.ts +6 -2
  136. package/out/jp/postal-code.d.ts.map +1 -1
  137. package/out/jp/postal-code.js +7 -3
  138. package/out/jp/postal-code.js.map +1 -1
  139. package/out/jp/prefecture.d.ts +24 -8
  140. package/out/jp/prefecture.d.ts.map +1 -1
  141. package/out/jp/prefecture.js +5 -3
  142. package/out/jp/prefecture.js.map +1 -1
  143. package/out/level-semantics.d.ts +48 -16
  144. package/out/level-semantics.d.ts.map +1 -1
  145. package/out/level-semantics.js +34 -12
  146. package/out/level-semantics.js.map +1 -1
  147. package/out/nz/delivery-service.d.ts +39 -13
  148. package/out/nz/delivery-service.d.ts.map +1 -1
  149. package/out/nz/delivery-service.js +16 -6
  150. package/out/nz/delivery-service.js.map +1 -1
  151. package/out/nz/postcode.d.ts +9 -3
  152. package/out/nz/postcode.d.ts.map +1 -1
  153. package/out/nz/postcode.js +9 -3
  154. package/out/nz/postcode.js.map +1 -1
  155. package/out/postcode-systems.d.ts +3 -1
  156. package/out/postcode-systems.d.ts.map +1 -1
  157. package/out/postcode-systems.js +1 -1
  158. package/out/postcode-systems.js.map +1 -1
  159. package/out/tools/build-country-surface-lexicon.js +26 -12
  160. package/out/tools/build-country-surface-lexicon.js.map +1 -1
  161. package/out/tools/export-country-surfaces.js.map +1 -1
  162. package/out/tools/generate-country-reference.d.ts +12 -4
  163. package/out/tools/generate-country-reference.d.ts.map +1 -1
  164. package/out/tools/generate-country-reference.js +10 -8
  165. package/out/tools/generate-country-reference.js.map +1 -1
  166. package/out/tools/generate-official-languages.d.ts +18 -6
  167. package/out/tools/generate-official-languages.d.ts.map +1 -1
  168. package/out/tools/generate-official-languages.js +9 -7
  169. package/out/tools/generate-official-languages.js.map +1 -1
  170. package/out/us/floor-designator.d.ts +15 -5
  171. package/out/us/floor-designator.d.ts.map +1 -1
  172. package/out/us/floor-designator.js +3 -1
  173. package/out/us/floor-designator.js.map +1 -1
  174. package/out/us/military-address.d.ts +36 -12
  175. package/out/us/military-address.d.ts.map +1 -1
  176. package/out/us/military-address.js +26 -15
  177. package/out/us/military-address.js.map +1 -1
  178. package/out/us/po-box.d.ts +9 -3
  179. package/out/us/po-box.d.ts.map +1 -1
  180. package/out/us/po-box.js +4 -2
  181. package/out/us/po-box.js.map +1 -1
  182. package/out/us/state.d.ts +6 -2
  183. package/out/us/state.d.ts.map +1 -1
  184. package/out/us/state.js +3 -1
  185. package/out/us/state.js.map +1 -1
  186. package/out/us/street-directional.d.ts +12 -3
  187. package/out/us/street-directional.d.ts.map +1 -1
  188. package/out/us/street-directional.js +8 -3
  189. package/out/us/street-directional.js.map +1 -1
  190. package/out/us/street-suffix.d.ts +24 -8
  191. package/out/us/street-suffix.d.ts.map +1 -1
  192. package/out/us/street-suffix.js +7 -3
  193. package/out/us/street-suffix.js.map +1 -1
  194. package/out/us/unit-designator.d.ts +24 -8
  195. package/out/us/unit-designator.d.ts.map +1 -1
  196. package/out/us/unit-designator.js +3 -1
  197. package/out/us/unit-designator.js.map +1 -1
  198. package/package.json +2 -2
  199. package/postcode-systems.ts +4 -2
  200. package/tools/build-country-surface-lexicon.ts +30 -12
  201. package/tools/export-country-surfaces.ts +2 -0
  202. package/tools/generate-country-reference.ts +27 -13
  203. package/tools/generate-official-languages.ts +27 -12
  204. package/us/floor-designator.ts +15 -5
  205. package/us/military-address.ts +53 -24
  206. package/us/po-box.ts +13 -5
  207. package/us/state.ts +6 -2
  208. package/us/street-directional.ts +14 -5
  209. package/us/street-suffix.ts +27 -9
  210. package/us/unit-designator.ts +25 -8
@@ -33,16 +33,22 @@
33
33
  * @see {@link https://pe.usps.com/text/pub28/28apb_001.htm USPS Pub 28 Appendix B — Armed Forces Addresses}
34
34
  */
35
35
 
36
- /** USPS military / diplomatic post-office location codes (the "city" substitute on the city line). */
36
+ /**
37
+ * USPS military / diplomatic post-office location codes (the "city" substitute on the city line).
38
+ */
37
39
  export const US_MILITARY_POST_OFFICE_CODES = [
38
40
  /**
39
41
  * Army Post Office — domestic USPS gateway for Army and Air Force overseas mail; also used for some diplomatic
40
42
  * addresses (DPO is preferred for State Dept posts since 2011).
41
43
  */
42
44
  { code: "APO", name: "Army Post Office", armedForces: true },
43
- /** Fleet Post Office — Navy ships and shore installations. */
45
+ /**
46
+ * Fleet Post Office — Navy ships and shore installations.
47
+ */
44
48
  { code: "FPO", name: "Fleet Post Office", armedForces: true },
45
- /** Diplomatic Post Office — US embassies and missions (added 2011). */
49
+ /**
50
+ * Diplomatic Post Office — US embassies and missions (added 2011).
51
+ */
46
52
  { code: "DPO", name: "Diplomatic Post Office", armedForces: false },
47
53
  ] as const
48
54
 
@@ -96,20 +102,32 @@ export const US_MILITARY_UNIT_DESIGNATORS = [
96
102
 
97
103
  export type USMilitaryUnitDesignatorCode = (typeof US_MILITARY_UNIT_DESIGNATORS)[number]["code"]
98
104
 
99
- /** Result of a military address line parse (the unit line: PSC/CMR/UNIT). */
105
+ /**
106
+ * Result of a military address line parse (the unit line: PSC/CMR/UNIT).
107
+ */
100
108
  export interface USMilitaryUnitMatch {
101
- /** The designator as it appeared ("PSC", "CMR", "Unit"). */
109
+ /**
110
+ * The designator as it appeared ("PSC", "CMR", "Unit").
111
+ */
102
112
  matched: string
103
- /** The canonical designator code ("PSC", "CMR", "UNIT"). */
113
+ /**
114
+ * The canonical designator code ("PSC", "CMR", "UNIT").
115
+ */
104
116
  code: USMilitaryUnitDesignatorCode
105
- /** The installation identifier ("1520", "453"). */
117
+ /**
118
+ * The installation identifier ("1520", "453").
119
+ */
106
120
  id: string
107
- /** The box number when present ("4620", "1234A"). */
121
+ /**
122
+ * The box number when present ("4620", "1234A").
123
+ */
108
124
  box?: string
109
125
  }
110
126
 
111
- // Unit-line regex: PSC/CMR/UNIT <id> [BOX <box>]
112
- // Identifiers are numeric; box numbers are alphanumeric. UNIT may stand without BOX.
127
+ /**
128
+ * Unit-line regex: PSC/CMR/UNIT <id> [BOX <box>] Identifiers are numeric; box numbers are alphanumeric. UNIT may stand
129
+ * without BOX.
130
+ */
113
131
  const UNIT_LINE_RE = /^\s*(psc|cmr|unit)\s+(\d+)(?:\s+box\s+([\dA-Za-z]+))?\s*$/i
114
132
 
115
133
  /**
@@ -137,7 +155,9 @@ export function matchMilitaryUnitLine(input: unknown): USMilitaryUnitMatch | nul
137
155
  return { matched: m[1]!, code, id, ...(box ? { box } : {}) }
138
156
  }
139
157
 
140
- /** Type-predicate: does the input look like a USPS military unit line (PSC/CMR/UNIT)? */
158
+ /**
159
+ * Type-predicate: does the input look like a USPS military unit line (PSC/CMR/UNIT)?
160
+ */
141
161
  export function isMilitaryUnitLine(input: unknown): boolean {
142
162
  try {
143
163
  return matchMilitaryUnitLine(input) !== null
@@ -146,13 +166,21 @@ export function isMilitaryUnitLine(input: unknown): boolean {
146
166
  }
147
167
  }
148
168
 
149
- /** Result of a military city-line parse (APO/FPO/DPO + region code + ZIP). */
169
+ /**
170
+ * Result of a military city-line parse (APO/FPO/DPO + region code + ZIP).
171
+ */
150
172
  export interface USMilitaryCityMatch {
151
- /** The post-office code as it appeared ("APO", "FPO", "DPO"). */
173
+ /**
174
+ * The post-office code as it appeared ("APO", "FPO", "DPO").
175
+ */
152
176
  matched: string
153
- /** The canonical post-office code. */
177
+ /**
178
+ * The canonical post-office code.
179
+ */
154
180
  code: USMilitaryPostOfficeCode
155
- /** The Armed Forces region code ("AA", "AE", "AP"). */
181
+ /**
182
+ * The Armed Forces region code ("AA", "AE", "AP").
183
+ */
156
184
  region: USArmedForcesRegionCode
157
185
  /**
158
186
  * The 5-digit or 9-digit ZIP code. Typical ranges per Pub 28: 09xxx (AE), 34xxx (AA), 96xxx (AP) — range validation
@@ -161,14 +189,13 @@ export interface USMilitaryCityMatch {
161
189
  zip: string
162
190
  }
163
191
 
164
- // City-line regex: APO/FPO/DPO <region> <zip>
165
- // USPS military ZIP assignment per Pub 28 and the Armed Forces zip code list:
166
- // - AA (Americas): 340xx range
167
- // - AE (Europe/ME/Africa/Canada): 09xxx range
168
- // - AP (Pacific): 962xx-966xx range
169
- // The regex accepts any 5-digit or 9-digit ZIP code in combination with a valid region code —
170
- // validating the specific numeric range for each region is left to the caller (region+ZIP
171
- // co-validation is operational policy, not structural syntax).
192
+ /**
193
+ * City-line regex: APO/FPO/DPO <region> <zip> USPS military ZIP assignment per Pub 28 and the Armed Forces zip code
194
+ * list: - AA (Americas): 340xx range - AE (Europe/ME/Africa/Canada): 09xxx range - AP (Pacific): 962xx-966xx range The
195
+ * regex accepts any 5-digit or 9-digit ZIP code in combination with a valid region code — validating the specific
196
+ * numeric range for each region is left to the caller (region+ZIP co-validation is operational policy, not structural
197
+ * syntax).
198
+ */
172
199
  const CITY_LINE_RE = /^\s*(apo|fpo|dpo)\s+(aa|ae|ap)\s+(\d{5}(?:-\d{4})?)\s*$/i
173
200
 
174
201
  /**
@@ -193,7 +220,9 @@ export function matchMilitaryCityLine(input: unknown): USMilitaryCityMatch | nul
193
220
  }
194
221
  }
195
222
 
196
- /** Type-predicate: does the input look like a USPS military city line (APO/FPO/DPO + region + ZIP)? */
223
+ /**
224
+ * Type-predicate: does the input look like a USPS military city line (APO/FPO/DPO + region + ZIP)?
225
+ */
197
226
  export function isMilitaryCityLine(input: unknown): boolean {
198
227
  return matchMilitaryCityLine(input) !== null
199
228
  }
package/us/po-box.ts CHANGED
@@ -30,8 +30,10 @@ export const US_PO_BOX_DESIGNATORS = [
30
30
 
31
31
  export type USPoBoxDesignator = (typeof US_PO_BOX_DESIGNATORS)[number]
32
32
 
33
- // Matches a leading PO-box designator + its identifier. Allows "P.O. Box", "PO BOX", "Post Office
34
- // Box", "Box 12-A", etc. The id is alphanumeric with optional dashes (USPS caller/firm ids exist).
33
+ /**
34
+ * Matches a leading PO-box designator + its identifier. Allows "P.O. Box", "PO BOX", "Post Office Box", "Box 12-A",
35
+ * etc. The id is alphanumeric with optional dashes (USPS caller/firm ids exist).
36
+ */
35
37
  const PO_BOX_RE =
36
38
  /^\s*(?:(p\.?\s*o\.?\s*box)|(post\s+office\s+box)|(firm\s+caller)|(caller)|(drawer)|(lockbox)|(box))\s*#?\s*([\dA-Za-z][\dA-Za-z-]*)\s*$/i
37
39
 
@@ -44,11 +46,17 @@ export function isPOBox(input: unknown): boolean {
44
46
  return typeof input === "string" && PO_BOX_RE.test(input)
45
47
  }
46
48
 
47
- /** Result of a PO-box parse: the matched designator phrase and the box identifier. */
49
+ /**
50
+ * Result of a PO-box parse: the matched designator phrase and the box identifier.
51
+ */
48
52
  export interface PoBoxMatch {
49
- /** The designator phrase as it appeared, e.g. "P.O. Box", "Post Office Box". */
53
+ /**
54
+ * The designator phrase as it appeared, e.g. "P.O. Box", "Post Office Box".
55
+ */
50
56
  matched: string
51
- /** The box identifier, e.g. "123", "12-A". */
57
+ /**
58
+ * The box identifier, e.g. "123", "12-A".
59
+ */
52
60
  id: string
53
61
  }
54
62
 
package/us/state.ts CHANGED
@@ -75,7 +75,9 @@ export const US_STATE_ABBREVIATIONS = [
75
75
  "AS",
76
76
  ] as const satisfies readonly string[]
77
77
 
78
- /** A USPS two-letter state-or-territory abbreviation. */
78
+ /**
79
+ * A USPS two-letter state-or-territory abbreviation.
80
+ */
79
81
  export type USStateAbbreviation = (typeof US_STATE_ABBREVIATIONS)[number]
80
82
 
81
83
  const STATE_ABBREVIATION_SET: ReadonlySet<string> = new Set(US_STATE_ABBREVIATIONS)
@@ -152,5 +154,7 @@ export const US_STATE_BY_ABBREVIATION = {
152
154
  AS: "American Samoa",
153
155
  } as const satisfies Record<USStateAbbreviation, string>
154
156
 
155
- /** The full state/territory names, derived from {@link US_STATE_BY_ABBREVIATION}. */
157
+ /**
158
+ * The full state/territory names, derived from {@link US_STATE_BY_ABBREVIATION}.
159
+ */
156
160
  export const US_STATE_NAMES: readonly string[] = Object.values(US_STATE_BY_ABBREVIATION)
@@ -29,7 +29,9 @@ export const DirectionalAbbreviation = {
29
29
 
30
30
  export type DirectionalAbbreviation = (typeof DirectionalAbbreviation)[keyof typeof DirectionalAbbreviation]
31
31
 
32
- /** The 8 directional names accepted by the USPS (intercardinals spaced, per the publication). */
32
+ /**
33
+ * The 8 directional names accepted by the USPS (intercardinals spaced, per the publication).
34
+ */
33
35
  export const DirectionalNames = [
34
36
  "NORTH",
35
37
  "EAST",
@@ -43,6 +45,9 @@ export const DirectionalNames = [
43
45
 
44
46
  export type DirectionalName = (typeof DirectionalNames)[number]
45
47
 
48
+ /**
49
+ * Surface forms a US directional can take (`N`, `N.`, `North`), for both parsing and formatting.
50
+ */
46
51
  export const DirectionalNameVariations = [
47
52
  ...DirectionalNames,
48
53
  // Without spaces (the common US street form: "Northeast Main St")…
@@ -143,7 +148,7 @@ export function lookupDirectionalAbbreviation(input: unknown): DirectionalAbbrev
143
148
 
144
149
  return (
145
150
  DirectionalToAbbreviationMap.get(input) ||
146
- DirectionalToAbbreviationMap.get(input.trim().toUpperCase().replace(/\s+/g, " ")) ||
151
+ DirectionalToAbbreviationMap.get(input.trim().toUpperCase().replaceAll(/\s+/g, " ")) ||
147
152
  null
148
153
  )
149
154
  }
@@ -152,9 +157,13 @@ export function lookupDirectionalAbbreviation(input: unknown): DirectionalAbbrev
152
157
  * Result of a directional lookup: the canonical full name + its preferred abbreviation.
153
158
  */
154
159
  export interface DirectionalMatch {
155
- /** The matched directional name, e.g. "NORTH", "NORTH EAST". */
160
+ /**
161
+ * The matched directional name, e.g. "NORTH", "NORTH EAST".
162
+ */
156
163
  directional: DirectionalName
157
- /** The corresponding USPS abbreviation, e.g. "N", "NE". */
164
+ /**
165
+ * The corresponding USPS abbreviation, e.g. "N", "NE".
166
+ */
158
167
  abbreviation: DirectionalAbbreviation
159
168
  }
160
169
 
@@ -207,7 +216,7 @@ export function renderDirectional(
207
216
  form: "abbr" | "full",
208
217
  reference: string
209
218
  ): string {
210
- const target = form === "abbr" ? match.abbreviation : match.canonical.replace(/\s+/g, "")
219
+ const target = form === "abbr" ? match.abbreviation : match.canonical.replaceAll(/\s+/g, "")
211
220
 
212
221
  return matchCase(target, reference)
213
222
  }
@@ -228,7 +228,9 @@ export const US_STREET_SUFFIX_VARIANTS = {
228
228
  WELLS: ["WLS"],
229
229
  } as const satisfies Record<string, readonly string[]>
230
230
 
231
- /** Canonical USPS suffix (full word, uppercase per the publication). */
231
+ /**
232
+ * Canonical USPS suffix (full word, uppercase per the publication).
233
+ */
232
234
  export type USStreetSuffix = keyof typeof US_STREET_SUFFIX_VARIANTS
233
235
 
234
236
  /**
@@ -254,7 +256,9 @@ export const US_STREET_SUFFIX_LOOKUP: ReadonlyMap<string, USStreetSuffix> = (()
254
256
  return out
255
257
  })()
256
258
 
257
- /** Preferred USPS abbreviation per canonical (`AVENUE → "AVE"`, `STREET → "ST"`). */
259
+ /**
260
+ * Preferred USPS abbreviation per canonical (`AVENUE → "AVE"`, `STREET → "ST"`).
261
+ */
258
262
  export const US_STREET_SUFFIX_PREFERRED_ABBR: Readonly<Record<USStreetSuffix, string>> = Object.fromEntries(
259
263
  (Object.keys(US_STREET_SUFFIX_VARIANTS) as USStreetSuffix[]).map((k) => [k, US_STREET_SUFFIX_VARIANTS[k][0]])
260
264
  ) as Readonly<Record<USStreetSuffix, string>>
@@ -285,7 +289,7 @@ export function matchTrailingSuffix(street: string): { canonical: USStreetSuffix
285
289
 
286
290
  if (!trimmed) return null
287
291
  const parts = trimmed.split(/\s+/)
288
- const last = parts[parts.length - 1]!
292
+ const last = parts.at(-1)!
289
293
  const canonical = US_STREET_SUFFIX_LOOKUP.get(last.toLowerCase())
290
294
 
291
295
  if (!canonical) return null
@@ -297,6 +301,7 @@ export function matchTrailingSuffix(street: string): { canonical: USStreetSuffix
297
301
  * The USPS suffix record, under its original isp-nexus name. Aliases {@link US_STREET_SUFFIX_VARIANTS}.
298
302
  */
299
303
  export const StreetSuffixAbbreviationRecord = US_STREET_SUFFIX_VARIANTS
304
+
300
305
  export type StreetSuffixAbbreviationRecord = typeof US_STREET_SUFFIX_VARIANTS
301
306
 
302
307
  /**
@@ -304,17 +309,27 @@ export type StreetSuffixAbbreviationRecord = typeof US_STREET_SUFFIX_VARIANTS
304
309
  */
305
310
  export type StreetSuffix = USStreetSuffix
306
311
 
307
- /** A standardized USPS street suffix abbreviation (the preferred form), i.e. "ST", "AVE", "BLVD". */
312
+ /**
313
+ * A standardized USPS street suffix abbreviation (the preferred form), i.e. "ST", "AVE", "BLVD".
314
+ */
308
315
  export type USPSStandardSuffixAbbreviation = StreetSuffixAbbreviationRecord[StreetSuffix][0]
309
316
 
310
- /** Any USPS-recognized suffix variant or abbreviation. */
317
+ /**
318
+ * Any USPS-recognized suffix variant or abbreviation.
319
+ */
311
320
  export type StreetSuffixAbbreviation = StreetSuffixAbbreviationRecord[StreetSuffix][number]
312
321
 
313
- /** Result of a successful USPS street suffix lookup. */
322
+ /**
323
+ * Result of a successful USPS street suffix lookup.
324
+ */
314
325
  export interface StreetSuffixMatch<S extends StreetSuffix = StreetSuffix> {
315
- /** The matched canonical USPS street suffix, i.e. "STREET", "AVENUE". */
326
+ /**
327
+ * The matched canonical USPS street suffix, i.e. "STREET", "AVENUE".
328
+ */
316
329
  suffix: S
317
- /** The preferred USPS street suffix abbreviation, i.e. "ST", "AVE". */
330
+ /**
331
+ * The preferred USPS street suffix abbreviation, i.e. "ST", "AVE".
332
+ */
318
333
  abbreviation: StreetSuffixAbbreviationRecord[S][0]
319
334
  }
320
335
 
@@ -323,6 +338,7 @@ export interface StreetSuffixMatch<S extends StreetSuffix = StreetSuffix> {
323
338
  */
324
339
  export function lookupStreetSuffix<S extends StreetSuffix>(suffix: S): StreetSuffixMatch<S>
325
340
  export function lookupStreetSuffix(input: string | null | undefined): StreetSuffixMatch | null
341
+
326
342
  export function lookupStreetSuffix(input: string | null | undefined): StreetSuffixMatch | null {
327
343
  if (!input || typeof input !== "string") return null
328
344
  const suffix = US_STREET_SUFFIX_LOOKUP.get(input.trim().toLowerCase())
@@ -332,7 +348,9 @@ export function lookupStreetSuffix(input: string | null | undefined): StreetSuff
332
348
  return { suffix, abbreviation: US_STREET_SUFFIX_VARIANTS[suffix][0] }
333
349
  }
334
350
 
335
- /** Type-predicate: is the input a canonical USPS street suffix (uppercase full word, e.g. "STREET")? */
351
+ /**
352
+ * Type-predicate: is the input a canonical USPS street suffix (uppercase full word, e.g. "STREET")?
353
+ */
336
354
  export function isStreetSuffix(input: unknown): input is StreetSuffix {
337
355
  return typeof input === "string" && Object.hasOwn(US_STREET_SUFFIX_VARIANTS, input)
338
356
  }
@@ -62,7 +62,9 @@ export const US_UNIT_DESIGNATOR_VARIANTS = {
62
62
  UPPER: ["UPPR"],
63
63
  } as const satisfies Record<string, readonly string[]>
64
64
 
65
- /** Canonical USPS secondary unit designator (full word, uppercase per the publication). */
65
+ /**
66
+ * Canonical USPS secondary unit designator (full word, uppercase per the publication).
67
+ */
66
68
  export type USUnitDesignator = keyof typeof US_UNIT_DESIGNATOR_VARIANTS
67
69
 
68
70
  /**
@@ -86,7 +88,9 @@ export const US_UNIT_DESIGNATOR_LOOKUP: ReadonlyMap<string, USUnitDesignator> =
86
88
  return out
87
89
  })()
88
90
 
89
- /** Approved USPS abbreviation per canonical (`APARTMENT → "APT"`, `SUITE → "STE"`). */
91
+ /**
92
+ * Approved USPS abbreviation per canonical (`APARTMENT → "APT"`, `SUITE → "STE"`).
93
+ */
90
94
  export const US_UNIT_DESIGNATOR_PREFERRED_ABBR: Readonly<Record<USUnitDesignator, string>> = Object.fromEntries(
91
95
  (Object.keys(US_UNIT_DESIGNATOR_VARIANTS) as USUnitDesignator[]).map((k) => [k, US_UNIT_DESIGNATOR_VARIANTS[k][0]])
92
96
  ) as Readonly<Record<USUnitDesignator, string>>
@@ -141,11 +145,17 @@ export function matchLeadingDesignator(unit: string): { canonical: USUnitDesigna
141
145
  return { canonical, matched: first }
142
146
  }
143
147
 
144
- /** Result of {@link matchLeadingDesignatorWithRange}: the leading designator plus its optional secondary range. */
148
+ /**
149
+ * Result of {@link matchLeadingDesignatorWithRange}: the leading designator plus its optional secondary range.
150
+ */
145
151
  export interface UnitDesignatorRangeMatch {
146
- /** The matched canonical designator, i.e. "APARTMENT", "SUITE". */
152
+ /**
153
+ * The matched canonical designator, i.e. "APARTMENT", "SUITE".
154
+ */
147
155
  canonical: USUnitDesignator
148
- /** The designator's own matched surface form, i.e. "Apt". */
156
+ /**
157
+ * The designator's own matched surface form, i.e. "Apt".
158
+ */
149
159
  matched: string
150
160
  /**
151
161
  * The secondary range/identifier token immediately following the designator, i.e. "4B" in "Apt 4B". Undefined when
@@ -183,11 +193,17 @@ export function matchLeadingDesignatorWithRange(unit: string): UnitDesignatorRan
183
193
  }
184
194
  }
185
195
 
186
- /** Result of a successful USPS secondary-unit designator lookup. */
196
+ /**
197
+ * Result of a successful USPS secondary-unit designator lookup.
198
+ */
187
199
  export interface UnitDesignatorMatch<D extends USUnitDesignator = USUnitDesignator> {
188
- /** The matched canonical designator, i.e. "APARTMENT", "SUITE". */
200
+ /**
201
+ * The matched canonical designator, i.e. "APARTMENT", "SUITE".
202
+ */
189
203
  designator: D
190
- /** The approved USPS abbreviation, i.e. "APT", "STE". */
204
+ /**
205
+ * The approved USPS abbreviation, i.e. "APT", "STE".
206
+ */
191
207
  abbreviation: (typeof US_UNIT_DESIGNATOR_VARIANTS)[D][0]
192
208
  }
193
209
 
@@ -197,6 +213,7 @@ export interface UnitDesignatorMatch<D extends USUnitDesignator = USUnitDesignat
197
213
  */
198
214
  export function lookupUnitDesignator<D extends USUnitDesignator>(designator: D): UnitDesignatorMatch<D>
199
215
  export function lookupUnitDesignator(input: string | null | undefined): UnitDesignatorMatch | null
216
+
200
217
  export function lookupUnitDesignator(input: string | null | undefined): UnitDesignatorMatch | null {
201
218
  if (!input || typeof input !== "string") return null
202
219
  const designator = US_UNIT_DESIGNATOR_LOOKUP.get(input.trim().toLowerCase())