@mailwoman/resolver-wof-sqlite 9.2.0 → 9.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.
Files changed (493) hide show
  1. package/README.md +16 -19
  2. package/lib/address/index.ts +9 -0
  3. package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +25 -24
  4. package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
  5. package/lib/address/point.ts +328 -0
  6. package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
  7. package/{ancestry.ts → lib/ancestry/index.ts} +5 -4
  8. package/{build-candidate.ts → lib/build-candidate.ts} +99 -79
  9. package/{build-slim.ts → lib/build-slim.ts} +150 -165
  10. package/{candidate → lib/candidate}/alias-bags.ts +8 -6
  11. package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
  12. package/{candidate → lib/candidate}/country-display-names.ts +2 -2
  13. package/lib/candidate/extract-fold.ts +219 -0
  14. package/{candidate → lib/candidate}/name-roles.ts +17 -16
  15. package/{candidate → lib/candidate}/own-name.ts +2 -1
  16. package/{candidate → lib/candidate}/place-attrs.ts +3 -3
  17. package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
  18. package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
  19. package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
  20. package/{candidate-lookup.ts → lib/candidate-lookup.ts} +84 -80
  21. package/{candidate-schema.ts → lib/candidate-schema.ts} +6 -6
  22. package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
  23. package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
  24. package/{capitals.ts → lib/capitals.ts} +2 -2
  25. package/{coincident-roles.ts → lib/coincident-roles.ts} +9 -13
  26. package/{convention.ts → lib/convention/index.ts} +3 -3
  27. package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
  28. package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +10 -10
  29. package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
  30. package/lib/env.ts +50 -0
  31. package/{exact-match.ts → lib/exact-match.ts} +23 -14
  32. package/{sharding.ts → lib/extracts.ts} +61 -58
  33. package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
  34. package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
  35. package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
  36. package/lib/fst/format.ts +106 -0
  37. package/{fst-freshness.ts → lib/fst/freshness.ts} +40 -74
  38. package/lib/fst/index.ts +14 -0
  39. package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
  40. package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
  41. package/{fst-types.ts → lib/fst/types.ts} +4 -2
  42. package/{fts.ts → lib/fts/index.ts} +24 -19
  43. package/{fts-query.ts → lib/fts/query.ts} +1 -1
  44. package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
  45. package/lib/geonames/index.ts +8 -0
  46. package/{geonames-postal.ts → lib/geonames/postal.ts} +14 -13
  47. package/{index.ts → lib/index.ts} +37 -37
  48. package/{interpolation.ts → lib/interpolation.ts} +28 -26
  49. package/{lookup.ts → lib/lookup.ts} +130 -142
  50. package/lib/nsul/index.ts +8 -0
  51. package/lib/nsul/lookup.ts +144 -0
  52. package/lib/nsul/schema.ts +130 -0
  53. package/{place-importance-schema.ts → lib/place-importance-schema.ts} +7 -16
  54. package/lib/poi/index.ts +8 -0
  55. package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -29
  56. package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
  57. package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
  58. package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
  59. package/lib/postal/index.ts +9 -0
  60. package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
  61. package/{primary-preference.ts → lib/primary-preference.ts} +43 -14
  62. package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
  63. package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
  64. package/{region-keys.ts → lib/region-keys.ts} +9 -9
  65. package/{reverse.ts → lib/reverse.ts} +34 -47
  66. package/{schema.ts → lib/schema.ts} +10 -0
  67. package/{search-fetch.ts → lib/search-fetch.ts} +29 -29
  68. package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
  69. package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -19
  70. package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
  71. package/{street-centroid.ts → lib/street/centroid.ts} +15 -22
  72. package/lib/street/index.ts +13 -0
  73. package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
  74. package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
  75. package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
  76. package/{street-normalize.ts → lib/street/normalize.ts} +86 -20
  77. package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
  78. package/{types.ts → lib/types.ts} +18 -12
  79. package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
  80. package/lib/uprn/existence.ts +84 -0
  81. package/lib/uprn/index.ts +9 -0
  82. package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -19
  83. package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
  84. package/lib/weights-overlay-linker.ts +879 -0
  85. package/out/address/index.d.ts +9 -0
  86. package/out/address/index.d.ts.map +1 -0
  87. package/out/address/index.js +9 -0
  88. package/out/address/index.js.map +1 -0
  89. package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +12 -11
  90. package/out/address/point-interpolation.d.ts.map +1 -0
  91. package/out/{address-point-interpolation.js → address/point-interpolation.js} +18 -18
  92. package/out/address/point-interpolation.js.map +1 -0
  93. package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
  94. package/out/address/point-schema.d.ts.map +1 -0
  95. package/out/{address-point-schema.js → address/point-schema.js} +7 -3
  96. package/out/address/point-schema.js.map +1 -0
  97. package/out/{address-point.d.ts → address/point.d.ts} +19 -9
  98. package/out/address/point.d.ts.map +1 -0
  99. package/out/address/point.js +222 -0
  100. package/out/address/point.js.map +1 -0
  101. package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
  102. package/out/ancestry/backfill.d.ts.map +1 -0
  103. package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
  104. package/out/ancestry/backfill.js.map +1 -0
  105. package/out/{ancestry.d.ts → ancestry/index.d.ts} +4 -3
  106. package/out/ancestry/index.d.ts.map +1 -0
  107. package/out/{ancestry.js → ancestry/index.js} +3 -2
  108. package/out/ancestry/index.js.map +1 -0
  109. package/out/build-candidate.d.ts +32 -24
  110. package/out/build-candidate.d.ts.map +1 -1
  111. package/out/build-candidate.js +60 -54
  112. package/out/build-candidate.js.map +1 -1
  113. package/out/build-slim.d.ts +4 -4
  114. package/out/build-slim.d.ts.map +1 -1
  115. package/out/build-slim.js +124 -139
  116. package/out/build-slim.js.map +1 -1
  117. package/out/candidate/alias-bags.d.ts +5 -3
  118. package/out/candidate/alias-bags.d.ts.map +1 -1
  119. package/out/candidate/alias-bags.js +2 -2
  120. package/out/candidate/alias-bags.js.map +1 -1
  121. package/out/candidate/ancestors-sidecar.d.ts +9 -10
  122. package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
  123. package/out/candidate/ancestors-sidecar.js +7 -7
  124. package/out/candidate/ancestors-sidecar.js.map +1 -1
  125. package/out/candidate/country-display-names.d.ts +1 -1
  126. package/out/candidate/country-display-names.d.ts.map +1 -1
  127. package/out/candidate/country-display-names.js +1 -1
  128. package/out/candidate/country-display-names.js.map +1 -1
  129. package/out/candidate/extract-fold.d.ts +41 -0
  130. package/out/candidate/extract-fold.d.ts.map +1 -0
  131. package/out/candidate/extract-fold.js +153 -0
  132. package/out/candidate/extract-fold.js.map +1 -0
  133. package/out/candidate/name-roles.d.ts +13 -11
  134. package/out/candidate/name-roles.d.ts.map +1 -1
  135. package/out/candidate/name-roles.js +11 -10
  136. package/out/candidate/name-roles.js.map +1 -1
  137. package/out/candidate/own-name.d.ts +1 -1
  138. package/out/candidate/own-name.d.ts.map +1 -1
  139. package/out/candidate/own-name.js +2 -1
  140. package/out/candidate/own-name.js.map +1 -1
  141. package/out/candidate/place-attrs.d.ts +3 -3
  142. package/out/candidate/place-attrs.d.ts.map +1 -1
  143. package/out/candidate/place-attrs.js +1 -1
  144. package/out/candidate/place-attrs.js.map +1 -1
  145. package/out/candidate-ancestors-schema.d.ts +4 -4
  146. package/out/candidate-ancestors-schema.d.ts.map +1 -1
  147. package/out/candidate-ancestors-schema.js +2 -2
  148. package/out/candidate-ancestors-schema.js.map +1 -1
  149. package/out/candidate-fts.d.ts +3 -3
  150. package/out/candidate-fts.d.ts.map +1 -1
  151. package/out/candidate-fts.js +1 -1
  152. package/out/candidate-fts.js.map +1 -1
  153. package/out/candidate-importance.d.ts +16 -16
  154. package/out/candidate-importance.d.ts.map +1 -1
  155. package/out/candidate-importance.js +46 -51
  156. package/out/candidate-importance.js.map +1 -1
  157. package/out/candidate-lookup.d.ts +16 -14
  158. package/out/candidate-lookup.d.ts.map +1 -1
  159. package/out/candidate-lookup.js +67 -63
  160. package/out/candidate-lookup.js.map +1 -1
  161. package/out/candidate-schema.d.ts +6 -6
  162. package/out/candidate-schema.d.ts.map +1 -1
  163. package/out/candidate-schema.js +1 -1
  164. package/out/candidate-schema.js.map +1 -1
  165. package/out/candidate-scoring.d.ts +7 -7
  166. package/out/candidate-scoring.d.ts.map +1 -1
  167. package/out/candidate-scoring.js +10 -14
  168. package/out/candidate-scoring.js.map +1 -1
  169. package/out/capital-schema.d.ts +3 -3
  170. package/out/capital-schema.d.ts.map +1 -1
  171. package/out/capital-schema.js +2 -2
  172. package/out/capital-schema.js.map +1 -1
  173. package/out/capitals.d.ts +1 -1
  174. package/out/capitals.d.ts.map +1 -1
  175. package/out/capitals.js +2 -2
  176. package/out/capitals.js.map +1 -1
  177. package/out/coincident-roles.d.ts +7 -6
  178. package/out/coincident-roles.d.ts.map +1 -1
  179. package/out/coincident-roles.js +2 -4
  180. package/out/coincident-roles.js.map +1 -1
  181. package/out/{convention.d.ts → convention/index.d.ts} +4 -4
  182. package/out/convention/index.d.ts.map +1 -0
  183. package/out/{convention.js → convention/index.js} +2 -2
  184. package/out/convention/index.js.map +1 -0
  185. package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
  186. package/out/convention/schema.d.ts.map +1 -0
  187. package/out/{convention-schema.js → convention/schema.js} +3 -3
  188. package/out/convention/schema.js.map +1 -0
  189. package/out/coverage-manifest-schema.d.ts +8 -8
  190. package/out/coverage-manifest-schema.d.ts.map +1 -1
  191. package/out/coverage-manifest-schema.js +5 -4
  192. package/out/coverage-manifest-schema.js.map +1 -1
  193. package/out/currency-backfill.d.ts +51 -7
  194. package/out/currency-backfill.d.ts.map +1 -1
  195. package/out/currency-backfill.js +65 -49
  196. package/out/currency-backfill.js.map +1 -1
  197. package/out/env.d.ts +43 -0
  198. package/out/env.d.ts.map +1 -0
  199. package/out/env.js +48 -0
  200. package/out/env.js.map +1 -0
  201. package/out/exact-match.d.ts +5 -5
  202. package/out/exact-match.d.ts.map +1 -1
  203. package/out/exact-match.js +10 -11
  204. package/out/exact-match.js.map +1 -1
  205. package/out/extracts.d.ts +114 -0
  206. package/out/extracts.d.ts.map +1 -0
  207. package/out/{sharding.js → extracts.js} +38 -38
  208. package/out/extracts.js.map +1 -0
  209. package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +2 -2
  210. package/out/fst/autocomplete.d.ts.map +1 -0
  211. package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
  212. package/out/fst/autocomplete.js.map +1 -0
  213. package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
  214. package/out/fst/builder.d.ts.map +1 -0
  215. package/out/{fst-builder.js → fst/builder.js} +14 -13
  216. package/out/fst/builder.js.map +1 -0
  217. package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
  218. package/out/fst/deserialize-web.d.ts.map +1 -0
  219. package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
  220. package/out/fst/deserialize-web.js.map +1 -0
  221. package/out/fst/format.d.ts +80 -0
  222. package/out/fst/format.d.ts.map +1 -0
  223. package/out/fst/format.js +91 -0
  224. package/out/fst/format.js.map +1 -0
  225. package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +9 -13
  226. package/out/fst/freshness.d.ts.map +1 -0
  227. package/out/{fst-freshness.js → fst/freshness.js} +40 -73
  228. package/out/fst/freshness.js.map +1 -0
  229. package/out/fst/index.d.ts +14 -0
  230. package/out/fst/index.d.ts.map +1 -0
  231. package/out/fst/index.js +14 -0
  232. package/out/fst/index.js.map +1 -0
  233. package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
  234. package/out/fst/matcher.d.ts.map +1 -0
  235. package/out/{fst-matcher.js → fst/matcher.js} +1 -1
  236. package/out/fst/matcher.js.map +1 -0
  237. package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
  238. package/out/fst/serialize.d.ts.map +1 -0
  239. package/out/{fst-serialize.js → fst/serialize.js} +18 -98
  240. package/out/fst/serialize.js.map +1 -0
  241. package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
  242. package/out/fst/types.d.ts.map +1 -0
  243. package/out/{fst-types.js → fst/types.js} +1 -1
  244. package/out/fst/types.js.map +1 -0
  245. package/out/{fts.d.ts → fts/index.d.ts} +16 -9
  246. package/out/fts/index.d.ts.map +1 -0
  247. package/out/{fts.js → fts/index.js} +16 -11
  248. package/out/fts/index.js.map +1 -0
  249. package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
  250. package/out/fts/query.d.ts.map +1 -0
  251. package/out/{fts-query.js → fts/query.js} +1 -1
  252. package/out/fts/query.js.map +1 -0
  253. package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
  254. package/out/geonames/aliases.d.ts.map +1 -0
  255. package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
  256. package/out/geonames/aliases.js.map +1 -0
  257. package/out/geonames/index.d.ts +8 -0
  258. package/out/geonames/index.d.ts.map +1 -0
  259. package/out/geonames/index.js +8 -0
  260. package/out/geonames/index.js.map +1 -0
  261. package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +10 -8
  262. package/out/geonames/postal.d.ts.map +1 -0
  263. package/out/{geonames-postal.js → geonames/postal.js} +9 -9
  264. package/out/geonames/postal.js.map +1 -0
  265. package/out/index.d.ts +32 -32
  266. package/out/index.d.ts.map +1 -1
  267. package/out/index.js +24 -24
  268. package/out/index.js.map +1 -1
  269. package/out/interpolation.d.ts +11 -10
  270. package/out/interpolation.d.ts.map +1 -1
  271. package/out/interpolation.js +20 -20
  272. package/out/interpolation.js.map +1 -1
  273. package/out/lookup.d.ts +22 -21
  274. package/out/lookup.d.ts.map +1 -1
  275. package/out/lookup.js +103 -113
  276. package/out/lookup.js.map +1 -1
  277. package/out/name-score.d.ts.map +1 -1
  278. package/out/name-score.js.map +1 -1
  279. package/out/nsul/index.d.ts +8 -0
  280. package/out/nsul/index.d.ts.map +1 -0
  281. package/out/nsul/index.js +8 -0
  282. package/out/nsul/index.js.map +1 -0
  283. package/out/nsul/lookup.d.ts +83 -0
  284. package/out/nsul/lookup.d.ts.map +1 -0
  285. package/out/nsul/lookup.js +80 -0
  286. package/out/nsul/lookup.js.map +1 -0
  287. package/out/nsul/schema.d.ts +100 -0
  288. package/out/nsul/schema.d.ts.map +1 -0
  289. package/out/nsul/schema.js +78 -0
  290. package/out/nsul/schema.js.map +1 -0
  291. package/out/place-importance-schema.d.ts +5 -6
  292. package/out/place-importance-schema.d.ts.map +1 -1
  293. package/out/place-importance-schema.js +3 -4
  294. package/out/place-importance-schema.js.map +1 -1
  295. package/out/poi/index.d.ts +8 -0
  296. package/out/poi/index.d.ts.map +1 -0
  297. package/out/poi/index.js +8 -0
  298. package/out/poi/index.js.map +1 -0
  299. package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
  300. package/out/poi/lookup.d.ts.map +1 -0
  301. package/out/{poi-lookup.js → poi/lookup.js} +14 -18
  302. package/out/poi/lookup.js.map +1 -0
  303. package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
  304. package/out/poi/schema.d.ts.map +1 -0
  305. package/out/{poi-schema.js → poi/schema.js} +1 -1
  306. package/out/poi/schema.js.map +1 -0
  307. package/out/polygon-schema.d.ts.map +1 -1
  308. package/out/polygon-schema.js.map +1 -1
  309. package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
  310. package/out/postal/city-alias-lookup.d.ts.map +1 -0
  311. package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
  312. package/out/postal/city-alias-lookup.js.map +1 -0
  313. package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
  314. package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
  315. package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
  316. package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
  317. package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +3 -3
  318. package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
  319. package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
  320. package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
  321. package/out/postal/index.d.ts +9 -0
  322. package/out/postal/index.d.ts.map +1 -0
  323. package/out/postal/index.js +9 -0
  324. package/out/postal/index.js.map +1 -0
  325. package/out/postcode-point-lookup.d.ts +10 -10
  326. package/out/postcode-point-lookup.d.ts.map +1 -1
  327. package/out/postcode-point-lookup.js +13 -13
  328. package/out/postcode-point-lookup.js.map +1 -1
  329. package/out/primary-preference.d.ts +15 -7
  330. package/out/primary-preference.d.ts.map +1 -1
  331. package/out/primary-preference.js +28 -12
  332. package/out/primary-preference.js.map +1 -1
  333. package/out/proximity-rerank.d.ts +2 -2
  334. package/out/proximity-rerank.d.ts.map +1 -1
  335. package/out/proximity-rerank.js +2 -2
  336. package/out/proximity-rerank.js.map +1 -1
  337. package/out/ranking-weights.d.ts +15 -3
  338. package/out/ranking-weights.d.ts.map +1 -1
  339. package/out/ranking-weights.js +21 -3
  340. package/out/ranking-weights.js.map +1 -1
  341. package/out/region-keys.d.ts +8 -8
  342. package/out/region-keys.d.ts.map +1 -1
  343. package/out/region-keys.js +9 -9
  344. package/out/region-keys.js.map +1 -1
  345. package/out/reverse.d.ts +6 -6
  346. package/out/reverse.d.ts.map +1 -1
  347. package/out/reverse.js +20 -29
  348. package/out/reverse.js.map +1 -1
  349. package/out/schema.d.ts +9 -0
  350. package/out/schema.d.ts.map +1 -1
  351. package/out/schema.js.map +1 -1
  352. package/out/search-fetch.d.ts +12 -10
  353. package/out/search-fetch.d.ts.map +1 -1
  354. package/out/search-fetch.js +21 -20
  355. package/out/search-fetch.js.map +1 -1
  356. package/out/sqlite-convention-source.d.ts +7 -7
  357. package/out/sqlite-convention-source.d.ts.map +1 -1
  358. package/out/sqlite-convention-source.js +5 -5
  359. package/out/sqlite-convention-source.js.map +1 -1
  360. package/out/sqlite-utils.d.ts +8 -9
  361. package/out/sqlite-utils.d.ts.map +1 -1
  362. package/out/sqlite-utils.js +6 -10
  363. package/out/sqlite-utils.js.map +1 -1
  364. package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
  365. package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
  366. package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
  367. package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
  368. package/out/{street-centroid.d.ts → street/centroid.d.ts} +7 -7
  369. package/out/street/centroid.d.ts.map +1 -0
  370. package/out/{street-centroid.js → street/centroid.js} +13 -19
  371. package/out/street/centroid.js.map +1 -0
  372. package/out/street/index.d.ts +13 -0
  373. package/out/street/index.d.ts.map +1 -0
  374. package/out/street/index.js +13 -0
  375. package/out/street/index.js.map +1 -0
  376. package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
  377. package/out/street/morphology-fst-builder.d.ts.map +1 -0
  378. package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
  379. package/out/street/morphology-fst-builder.js.map +1 -0
  380. package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
  381. package/out/street/morphology-fst-loader.d.ts.map +1 -0
  382. package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
  383. package/out/street/morphology-fst-loader.js.map +1 -0
  384. package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
  385. package/out/street/name-lookup.d.ts.map +1 -0
  386. package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
  387. package/out/street/name-lookup.js.map +1 -0
  388. package/out/{street-normalize.d.ts → street/normalize.d.ts} +38 -15
  389. package/out/street/normalize.d.ts.map +1 -0
  390. package/out/{street-normalize.js → street/normalize.js} +73 -17
  391. package/out/street/normalize.js.map +1 -0
  392. package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
  393. package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
  394. package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
  395. package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
  396. package/out/types.d.ts +18 -12
  397. package/out/types.d.ts.map +1 -1
  398. package/out/types.js.map +1 -1
  399. package/out/unified-schema.d.ts +5 -4
  400. package/out/unified-schema.d.ts.map +1 -1
  401. package/out/unified-schema.js +15 -18
  402. package/out/unified-schema.js.map +1 -1
  403. package/out/uprn/existence.d.ts +53 -0
  404. package/out/uprn/existence.d.ts.map +1 -0
  405. package/out/uprn/existence.js +61 -0
  406. package/out/uprn/existence.js.map +1 -0
  407. package/out/uprn/index.d.ts +9 -0
  408. package/out/uprn/index.d.ts.map +1 -0
  409. package/out/uprn/index.js +9 -0
  410. package/out/uprn/index.js.map +1 -0
  411. package/out/{uprn-lookup.d.ts → uprn/lookup.d.ts} +4 -4
  412. package/out/uprn/lookup.d.ts.map +1 -0
  413. package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
  414. package/out/uprn/lookup.js.map +1 -0
  415. package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
  416. package/out/uprn/schema.d.ts.map +1 -0
  417. package/out/{uprn-schema.js → uprn/schema.js} +4 -4
  418. package/out/uprn/schema.js.map +1 -0
  419. package/out/weights-overlay-linker.d.ts +184 -26
  420. package/out/weights-overlay-linker.d.ts.map +1 -1
  421. package/out/weights-overlay-linker.js +339 -86
  422. package/out/weights-overlay-linker.js.map +1 -1
  423. package/package.json +465 -269
  424. package/address-point.ts +0 -218
  425. package/candidate/shard-fold.ts +0 -137
  426. package/out/address-point-interpolation.d.ts.map +0 -1
  427. package/out/address-point-interpolation.js.map +0 -1
  428. package/out/address-point-schema.d.ts.map +0 -1
  429. package/out/address-point-schema.js.map +0 -1
  430. package/out/address-point.d.ts.map +0 -1
  431. package/out/address-point.js +0 -140
  432. package/out/address-point.js.map +0 -1
  433. package/out/ancestry-backfill.d.ts.map +0 -1
  434. package/out/ancestry-backfill.js.map +0 -1
  435. package/out/ancestry.d.ts.map +0 -1
  436. package/out/ancestry.js.map +0 -1
  437. package/out/candidate/shard-fold.d.ts +0 -31
  438. package/out/candidate/shard-fold.d.ts.map +0 -1
  439. package/out/candidate/shard-fold.js +0 -104
  440. package/out/candidate/shard-fold.js.map +0 -1
  441. package/out/convention-schema.d.ts.map +0 -1
  442. package/out/convention-schema.js.map +0 -1
  443. package/out/convention.d.ts.map +0 -1
  444. package/out/convention.js.map +0 -1
  445. package/out/fst-autocomplete.d.ts.map +0 -1
  446. package/out/fst-autocomplete.js.map +0 -1
  447. package/out/fst-builder.d.ts.map +0 -1
  448. package/out/fst-builder.js.map +0 -1
  449. package/out/fst-deserialize-web.d.ts.map +0 -1
  450. package/out/fst-deserialize-web.js.map +0 -1
  451. package/out/fst-freshness.d.ts.map +0 -1
  452. package/out/fst-freshness.js.map +0 -1
  453. package/out/fst-matcher.d.ts.map +0 -1
  454. package/out/fst-matcher.js.map +0 -1
  455. package/out/fst-serialize.d.ts.map +0 -1
  456. package/out/fst-serialize.js.map +0 -1
  457. package/out/fst-types.d.ts.map +0 -1
  458. package/out/fst-types.js.map +0 -1
  459. package/out/fts-query.d.ts.map +0 -1
  460. package/out/fts-query.js.map +0 -1
  461. package/out/fts.d.ts.map +0 -1
  462. package/out/fts.js.map +0 -1
  463. package/out/geonames-aliases.d.ts.map +0 -1
  464. package/out/geonames-aliases.js.map +0 -1
  465. package/out/geonames-postal.d.ts.map +0 -1
  466. package/out/geonames-postal.js.map +0 -1
  467. package/out/poi-lookup.d.ts.map +0 -1
  468. package/out/poi-lookup.js.map +0 -1
  469. package/out/poi-schema.d.ts.map +0 -1
  470. package/out/poi-schema.js.map +0 -1
  471. package/out/postal-city-alias-lookup.d.ts.map +0 -1
  472. package/out/postal-city-alias-lookup.js.map +0 -1
  473. package/out/sharding.d.ts +0 -114
  474. package/out/sharding.d.ts.map +0 -1
  475. package/out/sharding.js.map +0 -1
  476. package/out/street-centroid.d.ts.map +0 -1
  477. package/out/street-centroid.js.map +0 -1
  478. package/out/street-morphology-fst-builder.d.ts.map +0 -1
  479. package/out/street-morphology-fst-builder.js.map +0 -1
  480. package/out/street-morphology-fst-loader.d.ts.map +0 -1
  481. package/out/street-morphology-fst-loader.js.map +0 -1
  482. package/out/street-name-lookup.d.ts.map +0 -1
  483. package/out/street-name-lookup.js.map +0 -1
  484. package/out/street-normalize.d.ts.map +0 -1
  485. package/out/street-normalize.js.map +0 -1
  486. package/out/uprn-lookup.d.ts.map +0 -1
  487. package/out/uprn-lookup.js.map +0 -1
  488. package/out/uprn-schema.d.ts.map +0 -1
  489. package/out/uprn-schema.js.map +0 -1
  490. package/weights-overlay-linker.ts +0 -377
  491. /package/{name-score.ts → lib/name-score.ts} +0 -0
  492. /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
  493. /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
@@ -6,13 +6,12 @@
6
6
  * Small shared helpers for the SQLite-backed lookups.
7
7
  */
8
8
 
9
- import type { DatabaseSync, SQLInputValue } from "node:sqlite"
10
-
11
9
  import { allRows, getRow } from "@mailwoman/core/utils"
10
+ import type { DatabaseClient, SQLInputValue } from "@mailwoman/sqlite/client"
11
+ import { hasColumn as columnExists, tableExists } from "@mailwoman/sqlite/introspection"
12
12
 
13
13
  // The row-shape assertion itself lives in `core` so the readers that cannot depend on this package reach the same
14
- // seam; re-exported here because this module is where this package's readers already look for it.
15
- export { allRows, getRow } from "@mailwoman/core/utils"
14
+ // helper; re-exported here because this module is where this package's readers already look for it.
16
15
 
17
16
  /**
18
17
  * A prepared single-row query whose parameter tuple remains visible to TypeScript. `StatementSync` accepts only the
@@ -23,8 +22,8 @@ export type PreparedGet<Parameters extends SQLInputValue[], Row> = (...parameter
23
22
  /**
24
23
  * Prepare a single-row query while preserving its exact parameter tuple at every call site.
25
24
  */
26
- export function prepareGet<Parameters extends SQLInputValue[], Row>(
27
- db: DatabaseSync,
25
+ export function prepareGet<Parameters extends SQLInputValue[], Row, DB>(
26
+ db: DatabaseClient<DB>,
28
27
  sql: string
29
28
  ): PreparedGet<Parameters, Row> {
30
29
  const statement = db.prepare(sql)
@@ -40,8 +39,8 @@ export type PreparedAll<Parameters extends SQLInputValue[], Row> = (...parameter
40
39
  /**
41
40
  * Prepare a multi-row query while preserving its exact parameter tuple at every call site.
42
41
  */
43
- export function prepareAll<Parameters extends SQLInputValue[], Row>(
44
- db: DatabaseSync,
42
+ export function prepareAll<Parameters extends SQLInputValue[], Row, DB>(
43
+ db: DatabaseClient<DB>,
45
44
  sql: string
46
45
  ): PreparedAll<Parameters, Row> {
47
46
  const statement = db.prepare(sql)
@@ -51,15 +50,13 @@ export function prepareAll<Parameters extends SQLInputValue[], Row>(
51
50
 
52
51
  /**
53
52
  * True when `name` is a table in the open database. The street-level lookups use this to degrade gracefully on an
54
- * empty/tableless shard — an interrupted `build-*-shard.ts`, or a stray 0-byte file (e.g. `sqlite3 <missing>.db "…"`
55
- * CREATES one) — rather than throwing `no such table` at construction and taking down a whole state's geocode (#568). A
56
- * missing table makes the lookup a no-op miss.
53
+ * empty/tableless extract — an interrupted `build-*-extract.ts`, or a stray 0-byte file (e.g. `sqlite3 <missing>.db
54
+ * "…"` CREATES one) — rather than throwing `no such table` at construction and taking down a whole state's geocode
55
+ * (#568). A missing table makes the lookup a no-op miss.
57
56
  */
58
- export function hasTable(db: DatabaseSync, name: string): boolean {
57
+ export function hasTable<DB>(db: DatabaseClient<DB>, name: string): boolean {
59
58
  try {
60
- const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1").get(name)
61
-
62
- return row !== undefined
59
+ return tableExists(db, name)
63
60
  } catch {
64
61
  return false
65
62
  }
@@ -76,11 +73,9 @@ export function hasTable(db: DatabaseSync, name: string): boolean {
76
73
  * Note the interpolation: PRAGMA does not take bound parameters, so `table` is spliced. Every caller passes a
77
74
  * module-level constant; never pass user input.
78
75
  */
79
- export function hasColumn(db: DatabaseSync, table: string, column: string): boolean {
76
+ export function hasColumn<DB>(db: DatabaseClient<DB>, table: string, column: string): boolean {
80
77
  try {
81
- const rows = allRows<{ name: string }>(db.prepare(`PRAGMA table_info(${table})`))
82
-
83
- return rows.some((r) => String(r.name) === column)
78
+ return columnExists(db, table, column)
84
79
  } catch {
85
80
  return false
86
81
  }
@@ -3,10 +3,10 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Typed schema for the DERIVED STREET-CENTROID shard (`street-centroids-<cc>.db`, built by
7
- * `ban/scripts/build-street-centroid-shard.ts` — the #1042 street-level tier behind "street-only
8
- * FR queries deserve a street-level answer"). The shard is a `GROUP BY street` roll-up of the
9
- * sealed rooftop address-point shard: one row per (street, postcode, commune) carrying the street's
6
+ * Typed schema for the DERIVED STREET-CENTROID extract (`street-centroids-<cc>.db`, built by
7
+ * `ban/scripts/build-street-centroid-extract.ts` — the #1042 street-level tier behind "street-only
8
+ * FR queries deserve a street-level answer"). The extract is a `GROUP BY street` roll-up of the
9
+ * sealed rooftop address-point extract: one row per (street, postcode, commune) carrying the street's
10
10
  * CENTROID + bounding-box EXTENT + member-point count. No new data source — a derived artifact.
11
11
  *
12
12
  * Single source of truth for the columns shared by the BUILDER (a positional prepared INSERT for
@@ -22,7 +22,7 @@
22
22
 
23
23
  import type { Kysely } from "kysely"
24
24
 
25
- import type { NameKey, StreetKey } from "./street-normalize.ts"
25
+ import type { NameKey, StreetKey } from "#street/normalize"
26
26
 
27
27
  /**
28
28
  * One street roll-up. `(street_norm, postcode, locality_base)` is unique. `lat`/`lon` are the UNWEIGHTED mean of the
@@ -8,7 +8,7 @@
8
8
  * number) plus a postcode/commune scope, it returns the street's CENTROID + an honest extent-derived
9
9
  * uncertainty from the derived `street-centroids-<cc>.db` roll-up.
10
10
  *
11
- * Query-side normalization is THE shared normalizer (`street-normalize.ts`), selected per the shard's
11
+ * Query-side normalization is THE shared normalizer (`street-normalize.ts`), selected per the extract's
12
12
  * `streetLocale`, so build-side and probe-side keys agree by construction. The commune scope folds
13
13
  * through `normalizeLocalityForKey` + `stripArrondissement` (BAN names Paris/Lyon/Marseille per
14
14
  * arrondissement; a query names the base commune).
@@ -19,11 +19,12 @@
19
19
  * exact-after-normalization only (no fuzzy street matching in this tier).
20
20
  */
21
21
 
22
- import { DatabaseSync } from "node:sqlite"
22
+ import type { StreetCentroidHit, StreetCentroidLookup } from "@mailwoman/core/resolver"
23
+ import { haversineKm } from "@mailwoman/spatial"
24
+ import { DatabaseClient } from "@mailwoman/sqlite/client"
23
25
 
24
- import type { StreetCentroidHit, StreetCentroidLookup } from "@mailwoman/resolver"
25
-
26
- import { hasTable, prepareGet, type PreparedGet } from "./sqlite-utils.ts"
26
+ import { hasTable, prepareGet, type PreparedGet } from "#sqlite-utils"
27
+ import type { StreetCentroidDatabase } from "#street/centroid-schema"
27
28
  import {
28
29
  normalizeLocalityForKey,
29
30
  normalizeStreetForKeyLocale,
@@ -32,7 +33,7 @@ import {
32
33
  streetLocaleForSurface,
33
34
  type StreetLocale,
34
35
  stripArrondissement,
35
- } from "./street-normalize.ts"
36
+ } from "#street/normalize"
36
37
 
37
38
  /**
38
39
  * The weighted-centroid + extent + provenance an aggregate probe projects. `lat` is null when nothing matched.
@@ -61,33 +62,25 @@ const AGG_SELECT =
61
62
  * Half the bbox diagonal, in METERS — an honest coarse radius for a street centroid.
62
63
  */
63
64
  function extentRadiusM(minLat: number, maxLat: number, minLon: number, maxLon: number): number {
64
- const R = 6_371_000
65
- const toRad = (d: number): number => (d * Math.PI) / 180
66
- const dLat = toRad(maxLat - minLat)
67
- const dLon = toRad(maxLon - minLon)
68
- const midLat = toRad((minLat + maxLat) / 2)
69
- const a = Math.sin(dLat / 2) ** 2 + Math.cos(midLat) ** 2 * Math.sin(dLon / 2) ** 2
70
- const diag = 2 * R * Math.asin(Math.min(1, Math.sqrt(a)))
71
-
72
- return Math.round(diag / 2)
65
+ return Math.round(haversineKm(minLat, minLon, maxLat, maxLon) * 500)
73
66
  }
74
67
 
75
68
  export class StreetCentroidSqliteLookup implements StreetCentroidLookup {
76
- readonly #db: DatabaseSync
69
+ readonly #db: DatabaseClient<StreetCentroidDatabase>
77
70
  readonly #locale: StreetLocale
78
71
  readonly #byPostcode: PreparedGet<[postcode: string, street: StreetKey], AggRow> | undefined
79
72
  readonly #byLocality: PreparedGet<[locality: NameKey, street: StreetKey], AggRow> | undefined
80
73
 
81
74
  /**
82
- * @param dbPath Shard path.
83
- * @param opts.streetLocale The street-normalization locale this shard was BUILT with — must match, or every key
75
+ * @param dbPath Extract path.
76
+ * @param opts.streetLocale The street-normalization locale this extract was BUILT with — must match, or every key
84
77
  * misses. Defaults to `"fr"` (BAN is the French national register; the tier is FR-only today).
85
78
  */
86
79
  constructor(dbPath: string, opts: { streetLocale?: StreetLocale } = {}) {
87
- this.#db = new DatabaseSync(dbPath, { readOnly: true })
80
+ this.#db = new DatabaseClient<StreetCentroidDatabase>(dbPath, { readOnly: true })
88
81
  this.#locale = opts.streetLocale ?? "fr"
89
82
 
90
- // Degrade gracefully on an empty/tableless shard (interrupted build, stray 0-byte file): with no
83
+ // Degrade gracefully on an empty/tableless extract (interrupted build, stray 0-byte file): with no
91
84
  // `street_centroid` table this lookup is a no-op miss, not a crash (mirrors the address-point reader).
92
85
  if (hasTable(this.#db, "street_centroid")) {
93
86
  this.#byPostcode = prepareGet(
@@ -130,7 +123,7 @@ export class StreetCentroidSqliteLookup implements StreetCentroidLookup {
130
123
  }
131
124
  }
132
125
 
133
- close(): void {
134
- this.#db.close()
126
+ [Symbol.dispose](): void {
127
+ this.#db[Symbol.dispose]()
135
128
  }
136
129
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+
7
+ export * from "#street/centroid"
8
+ export * from "#street/centroid-schema"
9
+ export * from "#street/morphology-fst-builder"
10
+ export * from "#street/morphology-fst-loader"
11
+ export * from "#street/name-lookup"
12
+ export * from "#street/normalize"
13
+ export * from "#street/segment-schema"
@@ -23,14 +23,13 @@
23
23
  * `fst-street-morphology.bin`.
24
24
  */
25
25
 
26
- import { readdirSync, readFileSync, statSync } from "node:fs"
27
- import { join } from "node:path"
28
-
26
+ import { isDirectory, readDirectory, readLocalTextFile, statPath } from "@mailwoman/core/fs/readers"
27
+ import { join } from "path-ts"
29
28
  import { TextSpliterator } from "spliterator"
30
29
 
31
- import type { FSTNode } from "./fst-matcher.ts"
32
- import { FSTMatcher, normalizeTokens } from "./fst-matcher.ts"
33
- import type { FSTProvenance, PlaceEntry } from "./fst-types.ts"
30
+ import type { FSTNode } from "#fst/matcher"
31
+ import { FSTMatcher, normalizeTokens } from "#fst/matcher"
32
+ import type { FSTProvenance, PlaceEntry } from "#fst/types"
34
33
 
35
34
  /**
36
35
  * Reserved synthetic wofID base for street-morphology entries. 32-bit unsigned, well above any realistic WOF
@@ -96,7 +95,9 @@ function parseLine(line: string): { canonical: string; variants: string[] } | nu
96
95
  return { canonical: parts[0]!, variants: parts }
97
96
  }
98
97
 
99
- export function buildStreetMorphologyFST(opts: BuildStreetMorphologyFSTOpts): BuildStreetMorphologyFSTResult {
98
+ export async function buildStreetMorphologyFST(
99
+ opts: BuildStreetMorphologyFSTOpts
100
+ ): Promise<BuildStreetMorphologyFSTResult> {
100
101
  const progress = opts.onProgress ?? (() => {})
101
102
  const minVariantLength = opts.minVariantLength ?? 3
102
103
 
@@ -107,19 +108,28 @@ export function buildStreetMorphologyFST(opts: BuildStreetMorphologyFSTOpts): Bu
107
108
  if (opts.locales && opts.locales.length) {
108
109
  locales = opts.locales
109
110
  } else {
110
- locales = readdirSync(opts.dictionariesDir).filter((entry) => {
111
+ const entries = await readDirectory(opts.dictionariesDir)
112
+ const localeProbes: Array<[string, boolean]> = []
113
+
114
+ for (const entry of entries) {
111
115
  const localePath = join(opts.dictionariesDir, entry)
112
116
 
113
- if (!statSync(localePath).isDirectory()) return false
117
+ if (!(await isDirectory(localePath))) {
118
+ localeProbes.push([entry, false])
119
+
120
+ continue
121
+ }
114
122
 
115
123
  try {
116
- statSync(join(localePath, STREET_TYPES_FILENAME))
124
+ await statPath(join(localePath, STREET_TYPES_FILENAME))
117
125
 
118
- return true
126
+ localeProbes.push([entry, true])
119
127
  } catch {
120
- return false
128
+ localeProbes.push([entry, false])
121
129
  }
122
- })
130
+ }
131
+
132
+ locales = localeProbes.filter(([, hasFile]) => hasFile).map(([entry]) => entry)
123
133
  }
124
134
 
125
135
  progress("discover", `Found ${locales.length} locales with ${STREET_TYPES_FILENAME}`)
@@ -130,7 +140,7 @@ export function buildStreetMorphologyFST(opts: BuildStreetMorphologyFSTOpts): Bu
130
140
 
131
141
  for (const locale of locales) {
132
142
  const filePath = join(opts.dictionariesDir, locale, STREET_TYPES_FILENAME)
133
- const content = readFileSync(filePath, "utf8")
143
+ const content = await readLocalTextFile(filePath)
134
144
 
135
145
  for (const line of TextSpliterator.from(content)) {
136
146
  const parsed = parseLine(line)
@@ -3,7 +3,7 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * Unified runtime loader for the street-morphology FST — the #1315 street-context gate's signal
6
+ * Unified runtime loader for the street-morphology FST — the #1315 street-context check's signal
7
7
  * source, previously rebuilt from the libpostal dictionaries per process at three duplicate call
8
8
  * sites (runtime pipeline / parity eval / neural harness). The sealed artifact
9
9
  * (`fst-street-morphology.bin`, built by `mailwoman gazetteer build street-morphology`) replaces
@@ -21,14 +21,14 @@
21
21
  * `fst-deserialize-web.ts` (see the docs demo loader).
22
22
  */
23
23
 
24
- import { existsSync, readFileSync } from "node:fs"
24
+ import { dataRootPath } from "@mailwoman/core/data-root"
25
+ import { pathExists, readLocalBuffer } from "@mailwoman/core/fs/readers"
26
+ import { resourceDictionaryPath } from "@mailwoman/core/paths"
25
27
 
26
- import { dataRootPath, resourceDictionaryPath } from "@mailwoman/core/utils"
27
-
28
- import type { FSTMatcher } from "./fst-matcher.ts"
29
- import { deserializeFST, readFSTProvenance } from "./fst-serialize.ts"
30
- import type { FSTProvenance } from "./fst-types.ts"
31
- import { buildStreetMorphologyFST } from "./street-morphology-fst-builder.ts"
28
+ import type { FSTMatcher } from "#fst/matcher"
29
+ import { deserializeFST, readFSTProvenance } from "#fst/serialize"
30
+ import type { FSTProvenance } from "#fst/types"
31
+ import { buildStreetMorphologyFST } from "#street/morphology-fst-builder"
32
32
 
33
33
  /**
34
34
  * The sealed artifact's canonical filename — identical in the data-root staging dir and as a weights-package sibling.
@@ -77,13 +77,15 @@ export interface LoadedStreetMorphologyFST {
77
77
  /**
78
78
  * Load the street-morphology matcher: sealed artifact first, per-process dictionary build as the degrade path.
79
79
  */
80
- export function loadStreetMorphologyFST(opts: LoadStreetMorphologyFSTOpts = {}): LoadedStreetMorphologyFST {
80
+ export async function loadStreetMorphologyFST(
81
+ opts: LoadStreetMorphologyFSTOpts = {}
82
+ ): Promise<LoadedStreetMorphologyFST> {
81
83
  const warn = opts.onWarn ?? (() => {})
82
84
  const artifactPath = opts.artifactPath ?? defaultStreetMorphologyArtifactPath()
83
85
 
84
- if (existsSync(artifactPath)) {
86
+ if (await pathExists(artifactPath)) {
85
87
  try {
86
- const buf = readFileSync(artifactPath)
88
+ const buf = await readLocalBuffer(artifactPath)
87
89
  const matcher = deserializeFST(buf)
88
90
  const provenance = readFSTProvenance(buf)
89
91
 
@@ -95,7 +97,7 @@ export function loadStreetMorphologyFST(opts: LoadStreetMorphologyFSTOpts = {}):
95
97
  }
96
98
  }
97
99
 
98
- const built = buildStreetMorphologyFST({
100
+ const built = await buildStreetMorphologyFST({
99
101
  dictionariesDir: opts.dictionariesDir ?? resourceDictionaryPath("libpostal"),
100
102
  })
101
103
 
@@ -8,7 +8,7 @@
8
8
  * Reads a street-name index (the FR instance = BAN `street-centroids-fr.db`, a `street_centroid`
9
9
  * table of `street_norm × locality_base × postcode` rows) and answers "does this street surface
10
10
  * exist as a name" for the k-best rerank. Sync-by-interface, `readOnly`, prepared statements,
11
- * graceful-degrade on a tableless shard — the same reader discipline as `AddressPointSqliteLookup`.
11
+ * graceful-degrade on a tableless extract — the same reader discipline as `AddressPointSqliteLookup`.
12
12
  *
13
13
  * THE FOLD CONTRACT: the surface is folded with {@link foldStreetSurface} (the shared function),
14
14
  * and the DB's `street_norm` column MUST have been built with that SAME fold or every hyphenated /
@@ -19,24 +19,11 @@
19
19
  * the production rebuild is a tracked BAN-sdk follow-up.
20
20
  */
21
21
 
22
- import { DatabaseSync } from "node:sqlite"
23
-
24
22
  import { foldStreetSurface, type StreetEvidenceScope, type StreetLocalityEvidence } from "@mailwoman/resolver"
23
+ import { DatabaseClient } from "@mailwoman/sqlite/client"
25
24
 
26
- function hasTable(db: DatabaseSync, table: string): boolean {
27
- const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1").get(table)
28
-
29
- return row !== undefined
30
- }
31
-
32
- function hasColumn(db: DatabaseSync, table: string, column: string): boolean {
33
- // `table` is a caller-controlled identifier (default `street_centroid`), not user input — safe to interpolate.
34
- for (const row of db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>) {
35
- if (row.name === column) return true
36
- }
37
-
38
- return false
39
- }
25
+ import type { WOFDatabase } from "#schema"
26
+ import { hasColumn, hasTable } from "#sqlite-utils"
40
27
 
41
28
  export interface SQLiteStreetNameLookupOpts {
42
29
  /**
@@ -53,22 +40,22 @@ export interface SQLiteStreetNameLookupOpts {
53
40
  * A {@link StreetLocalityEvidence} backed by a street-name SQLite index. Positive evidence only: any doubt (missing
54
41
  * table, read miss) returns `false`, so the rerank fails open to the model's ranking.
55
42
  */
56
- export class SQLiteStreetNameLookup implements StreetLocalityEvidence {
43
+ export class SQLiteStreetNameLookup implements StreetLocalityEvidence, Disposable {
57
44
  readonly countries: ReadonlySet<string>
58
- readonly #db: DatabaseSync
59
- readonly #byName: ReturnType<DatabaseSync["prepare"]> | undefined
60
- readonly #byNameLocality: ReturnType<DatabaseSync["prepare"]> | undefined
61
- readonly #byNamePostcode: ReturnType<DatabaseSync["prepare"]> | undefined
45
+ readonly #db: DatabaseClient<WOFDatabase>
46
+ readonly #byName: ReturnType<DatabaseClient["prepare"]> | undefined
47
+ readonly #byNameLocality: ReturnType<DatabaseClient["prepare"]> | undefined
48
+ readonly #byNamePostcode: ReturnType<DatabaseClient["prepare"]> | undefined
62
49
 
63
50
  constructor(dbPath: string, opts: SQLiteStreetNameLookupOpts = {}) {
64
51
  this.countries = new Set([...(opts.countries ?? ["FR"])].map((c) => c.toUpperCase()))
65
- this.#db = new DatabaseSync(dbPath, { readOnly: true })
52
+ this.#db = new DatabaseClient<WOFDatabase>(dbPath, { readOnly: true })
66
53
  const table = opts.table ?? "street_centroid"
67
54
 
68
- // Degrade gracefully on an empty/tableless shard — a no-op miss, never a crash (#568 discipline).
55
+ // Degrade gracefully on an empty/tableless extract — a no-op miss, never a crash (#568 discipline).
69
56
  if (hasTable(this.#db, table)) {
70
57
  // Prefer the #727 phase-4c `name_key` column (foldStreetSurface, indexed by `idx_sc_name` for a direct seek);
71
- // fall back to `street_norm` on a pre-rebuild shard (a skip-scan, but correct). The fold used to build
58
+ // fall back to `street_norm` on a pre-rebuild extract (a skip-scan, but correct). The fold used to build
72
59
  // `name_key` MUST match `foldStreetSurface` here (the fold-parity contract).
73
60
  const keyCol = hasColumn(this.#db, table, "name_key") ? "name_key" : "street_norm"
74
61
  this.#byName = this.#db.prepare(`SELECT 1 FROM ${table} WHERE ${keyCol} = ? LIMIT 1`)
@@ -104,10 +91,7 @@ export class SQLiteStreetNameLookup implements StreetLocalityEvidence {
104
91
  return this.#byName.get(norm) !== undefined
105
92
  }
106
93
 
107
- /**
108
- * Close the underlying handle.
109
- */
110
- close(): void {
111
- this.#db.close()
94
+ [Symbol.dispose](): void {
95
+ this.#db[Symbol.dispose]()
112
96
  }
113
97
  }
@@ -3,8 +3,8 @@
3
3
  * @license AGPL-3.0
4
4
  * @author Teffen Ellis, et al.
5
5
  *
6
- * THE street normalizer for the address-point tier (#476). One function, used by BOTH the shard
7
- * builder (`scripts/build-address-point-shard.ts`) and the lookup tier (`address-point.ts`) —
6
+ * THE street normalizer for the address-point tier (#476). One function, used by BOTH the extract
7
+ * builder (`scripts/build-address-point-extract.ts`) and the lookup tier (`address-point.ts`) —
8
8
  * never two implementations (the PLACETYPE_ORDER lesson: parallel copies silently corrupt).
9
9
  *
10
10
  * Normalization contract (deliberately aggressive — both sides apply the same function, so
@@ -27,13 +27,13 @@ import type { Tagged } from "type-fest"
27
27
 
28
28
  /**
29
29
  * A place name folded by {@link normalizeLocalityForKey} — the value stored in, and required to probe, every
30
- * `name_key`-style column: the candidate gazetteer, the postal-city side-index, the street-centroid shard, an ancestor
31
- * chain's `parent_name_key`, and the address-point locality scope.
30
+ * `name_key`-style column: the candidate gazetteer, the postal-city side-index, the street-centroid extract, an
31
+ * ancestor chain's `parent_name_key`, and the address-point locality scope.
32
32
  *
33
33
  * The brand is here because the fold is applied at BUILD time and is therefore mandatory at QUERY time, while a
34
34
  * near-miss approximation of it (`toLowerCase()`, `trim()`) is still a `string`: it binds to the parameter, returns
35
35
  * fewer rows, and the shortfall reads as a coverage gap in the data rather than a defect in the probe. Requiring the
36
- * brand at the seam turns that silent under-match into a compile error. Mint one only by calling the fold.
36
+ * brand at the boundary turns that silent under-match into a compile error. Mint one only by calling the fold.
37
37
  */
38
38
  export type NameKey = Tagged<string, "NameKey">
39
39
 
@@ -64,8 +64,8 @@ const MIN_TOKENS_FOR_TAIL_MERGE = 3
64
64
  /**
65
65
  * Spelled ordinal street names → their digit-ordinal form ("tenth" → "10th"), applied ONLY when a street-type suffix
66
66
  * follows (#723 admin-tail) — so the ordinal cross-streets common in grid cities ("Tenth Street", "Fifth Avenue") match
67
- * the shards' digit keys, WITHOUT rewriting ordinal-WORD names where the next token is not a suffix ("First National
68
- * Bank Rd" stays "first national …"). Digit-source shards are unaffected (a digit token isn't in this map), so the
67
+ * the extracts' digit keys, WITHOUT rewriting ordinal-WORD names where the next token is not a suffix ("First National
68
+ * Bank Rd" stays "first national …"). Digit-source extracts are unaffected (a digit token isn't in this map), so the
69
69
  * existing keys need no rebuild; a future rebuild folds any spelled-source key the same way (the one-function
70
70
  * discipline).
71
71
  */
@@ -123,7 +123,7 @@ export function normalizeStreetForKey(street: string): StreetKey {
123
123
  if (!tokens.length) return "" as StreetKey
124
124
 
125
125
  // Spelled-ordinal street names → digit form when a street suffix follows ("Tenth Street" →
126
- // "10th street", #723). Gated on the next token being a suffix so ordinal-WORD names are untouched.
126
+ // "10th street", #723). Conditioned on the next token being a suffix so ordinal-WORD names are untouched.
127
127
  for (let i = 0; i < tokens.length - 1; i++) {
128
128
  const digit = SPELLED_ORDINAL_TO_DIGIT.get(tokens[i]!)
129
129
 
@@ -193,7 +193,42 @@ export function normalizeStreetForKey(street: string): StreetKey {
193
193
  * article, so no salient-token / multi-key index is built yet (deferred until probing shows the normalizer can't absorb
194
194
  * the false-negatives).
195
195
  */
196
- export type StreetLocale = "us" | "en" | "fr" | "de" | "nl" | "pl" | "vn" | "id"
196
+ export type StreetLocale = "us" | "en" | "fr" | "de" | "nl" | "pl" | "vn" | "id" | "zh"
197
+
198
+ /**
199
+ * The Han fold shared by every `zh` key: NFKC so a full-width digit or letter keys as its ASCII form (the Taiwanese
200
+ * civil-affairs registers write `122`, a person types `122`), 臺 → 台 (the register writes 臺北市, the common hand writes
201
+ * 台北市), and no whitespace at all, because a Han surface carries none and a stray space would split one key into two.
202
+ * Kanji numerals stay as written: the register spells a road section `一段`, and so does a query.
203
+ */
204
+ function foldHan(input: string): string {
205
+ return input.normalize("NFKC").replaceAll("臺", "台").replaceAll(/\s+/g, "").toLowerCase()
206
+ }
207
+
208
+ /**
209
+ * Country → street-locale registry surface for the acquisition SDKs (BAN, OSM). Each SDK keeps its own map — membership
210
+ * is a per-register decision — and this factory owns the lookup discipline: throw for an unsupported country rather
211
+ * than silently folding with the wrong rules, because a extract built with the wrong normalizer keys every street
212
+ * incorrectly and looks fine until a probe misses. `label` is the SDK's own registration instructions, appended to the
213
+ * error verbatim.
214
+ */
215
+ export function createStreetLocaleRegistry(
216
+ registry: ReadonlyMap<string, StreetLocale>,
217
+ label: string
218
+ ): { localeFor: (countryCode: string) => StreetLocale; supported: () => string[] } {
219
+ return {
220
+ localeFor: (countryCode) => {
221
+ const locale = registry.get(countryCode.toLowerCase())
222
+
223
+ if (!locale) {
224
+ throw new Error(`No street-normalization locale registered for country "${countryCode}". ${label}`)
225
+ }
226
+
227
+ return locale
228
+ },
229
+ supported: () => [...registry.keys()],
230
+ }
231
+ }
197
232
 
198
233
  /**
199
234
  * French street-type abbreviations → canonical full form, applied per token after {@link fold}. French address types
@@ -223,7 +258,7 @@ const FR_STREET_ABBREV = new Map<string, string>([
223
258
  ])
224
259
 
225
260
  /**
226
- * Polish leading street-type tokens, STRIPPED rather than expanded. Measured on the 5.56M-row PL OSM shard
261
+ * Polish leading street-type tokens, STRIPPED rather than expanded. Measured on the 5.56M-row PL OSM extract
227
262
  * (2026-08-19): OSM Poland tags `addr:street` BARE — `ulica%` covers 22 rows and `ul.%` eight, so an EXPANSION rule
228
263
  * makes a typed query ("ul. Świętokrzyska" → "ulica swietokrzyska") miss the 3,846 bare "swietokrzyska" rows. Stripping
229
264
  * the leading type on BOTH sides keys typed and bare surfaces identically. The full words are stripped too: the
@@ -255,7 +290,7 @@ const ID_STREET_ABBREV = new Map<string, string>([
255
290
  * {@link PL_LEADING_TYPE} for the measured reason expansion was wrong for this source.
256
291
  * - **vn** — fold + đ→d AND ð→d (both non-decomposing, and OSM mixes the two codepoints inside single values — see the
257
292
  * branch comment). Deliberately NO type-abbreviation map yet: the common abbreviation is the single letter "Đ." for
258
- * Đường, and expanding a bare folded "d" token would rewrite initials — measure the miss rate on the built shard
293
+ * Đường, and expanding a bare folded "d" token would rewrite initials — measure the miss rate on the built extract
259
294
  * before adding anything.
260
295
  * - **id** — fold + expand leading type abbreviations (jl/jln→jalan, gg→gang); Indonesian street surfaces are otherwise
261
296
  * ASCII-clean.
@@ -263,12 +298,16 @@ const ID_STREET_ABBREV = new Map<string, string>([
263
298
  export function normalizeStreetForKeyLocale(street: string, locale: StreetLocale): StreetKey {
264
299
  if (locale === "us" || locale === "en") return normalizeStreetForKey(street)
265
300
 
301
+ // A Han street name has no tokens, no type abbreviation and no diacritics; the Latin pipeline below would only
302
+ // split it on whitespace it never carries. `zh` keys are the Han fold and nothing else.
303
+ if (locale === "zh") return foldHan(street) as StreetKey
304
+
266
305
  // Hyphen → space so a compound name keys the same whether the source or the query writes the
267
306
  // hyphen ("Champs-Élysées", "St-Honoré") or a space — both sides fold identically, so this is pure
268
307
  // robustness. It also splits a hyphenated abbreviation ("St-Honoré" → "st honore") into tokens the
269
308
  // per-locale type/Saint map can see. Letter maps for non-decomposing letters (ß, ł, đ) live in the
270
309
  // per-locale branches, NEVER here: widening the shared pipeline would silently change keys under
271
- // every already-built shard of the other locales.
310
+ // every already-built extract of the other locales.
272
311
  const tokens = fold(street)
273
312
  .replaceAll("ß", "ss")
274
313
  .replaceAll("-", " ")
@@ -317,7 +356,7 @@ export function normalizeStreetForKeyLocale(street: string, locale: StreetLocale
317
356
  break
318
357
  case "vn":
319
358
  // đ (U+0111, d-with-stroke) AND ð (U+00F0, eth): OSM Vietnamese data mixes the two visually
320
- // identical codepoints inside single values — the 2026-08-19 shard measured `Đường Trần Hưng
359
+ // identical codepoints inside single values — the 2026-08-19 extract measured `Đường Trần Hưng
321
360
  // Đạo` carrying d-with-stroke at the front and ETH in `Đạo`, splitting the country's most
322
361
  // common street into two keys with the MAJORITY variant (630 vs 421 rows) unreachable by a
323
362
  // correctly-typed query. No abbreviation map — see the locale table.
@@ -337,6 +376,33 @@ export function normalizeLocalityForKey(locality: string): NameKey {
337
376
  return fold(locality) as NameKey
338
377
  }
339
378
 
379
+ /**
380
+ * The locality key under a street locale: the Han fold for `zh`, {@link normalizeLocalityForKey} for every other.
381
+ * Separate from the shared fold on purpose — the candidate gazetteer's `name_key` column is the shared fold, and a Han
382
+ * rule inside it would re-key every 臺 name under an extract built without the rule.
383
+ */
384
+ export function normalizeLocalityForKeyLocale(locality: string, locale: StreetLocale): NameKey {
385
+ return locale === "zh" ? (foldHan(locality) as NameKey) : normalizeLocalityForKey(locality)
386
+ }
387
+
388
+ /**
389
+ * The house-number key under a street locale. Every Latin register stores a lower-cased, trimmed number and the reader
390
+ * probes the same; `zh` additionally folds width and drops the trailing 號 the Taiwanese registers write on the number
391
+ * itself (`122號`), which a parse also carries on the `house_number` span (`122號`). Both sides key `122`.
392
+ */
393
+ export function normalizeHouseNumberForKey(number: string, locale: StreetLocale): string {
394
+ // The sub-number is written two ways — `30之19號` and `30號之19` — and an attached number a third (`30附40號`,
395
+ // `55之23附1號`); the register stores the base `30` with the rest in `unit`. Every form keys with the 號 dropped and
396
+ // the base number first, which the reader's sub-number rung then falls from.
397
+ if (locale === "zh") {
398
+ return foldHan(number)
399
+ .replace(/^(\d+)號([之附]\d+)$/u, "$1$2")
400
+ .replace(/號$/u, "")
401
+ }
402
+
403
+ return number.trim().toLowerCase()
404
+ }
405
+
340
406
  /**
341
407
  * Leading French street-type token. French types LEAD the name ("avenue du Parc", "boul Saint-Laurent") while English
342
408
  * types TRAIL ("Fifth Avenue", "Grosvenor Place"), so a leading type-token is the discriminating signal — "1 Avenue NE"
@@ -347,7 +413,7 @@ const FRENCH_LEAD_TYPE =
347
413
  /^(?:rue|ruelle|av|ave|avenue|boul|bd|boulevard|ch|che|chemin|all[ée]e|imp|impasse|mont[ée]e|c[ôo]te|pl|place|prom|promenade|rang|rte|route|autoroute|carr[eé]|croissant|terrasse|sentier)(?=[\s.-]|$)/i
348
414
 
349
415
  /**
350
- * Surface-driven street-locale ROUTER for bilingual shards — the Québec finishing move on the CA rooftop shard.
416
+ * Surface-driven street-locale ROUTER for bilingual extracts — the Québec finishing move on the CA rooftop extract.
351
417
  *
352
418
  * A country registers ONE street locale, but Canada's street surfaces are two languages: under the `en` rules a French
353
419
  * surface passes through mostly unchanged (both sides fold identically, so those rows stay reachable), and what breaks
@@ -355,11 +421,11 @@ const FRENCH_LEAD_TYPE =
355
421
  * misses a full-word row and vice versa. Routing on the SURFACE (not the province) also carries bilingual NB and the
356
422
  * French street names outside Québec for free.
357
423
  *
358
- * ONE function, called by the shard BUILDER and the query PROBE alike — the #861 discipline: routing is part of the
424
+ * ONE function, called by the extract BUILDER and the query PROBE alike — the #861 discipline: routing is part of the
359
425
  * fold contract, and two transcriptions of this predicate would diverge exactly where it matters. Only an `en` base
360
- * re-routes: a `fr`/`de`/`nl` shard already speaks its own rules, and the US pipeline stays untouched.
426
+ * re-routes: a `fr`/`de`/`nl` extract already speaks its own rules, and the US pipeline stays untouched.
361
427
  *
362
- * Measured basis (CA shard, 2026-08-19): 183,963 distinct surfaces, 43,762 French-lead; 29,682 fold differently under
428
+ * Measured basis (CA extract, 2026-08-19): 183,963 distinct surfaces, 43,762 French-lead; 29,682 fold differently under
363
429
  * fr-vs-en (888,265 rows), and the non-French half of those are English surfaces this router keeps on `en` unchanged.
364
430
  */
365
431
  export function streetLocaleForSurface(street: string, base: StreetLocale): StreetLocale {
@@ -453,9 +519,9 @@ export function stripLocalityQualifier(locality: string): string {
453
519
  * (the state abbreviation form) fold to `state route N…`. Only digit-leading route numbers fold — `State Street` and
454
520
  * friends never match.
455
521
  *
456
- * Used by BOTH the segment-shard builder (`scripts/build-interpolation-shard.ts`) and the interpolation lookup — same
457
- * one-function discipline as {@link normalizeStreetForKey}. The address-point tier (#476) does NOT apply it yet:
458
- * adopting it there requires a shard rebuild (noted on #483).
522
+ * Used by BOTH the segment-extract builder (`scripts/build-interpolation-extract.ts`) and the interpolation lookup —
523
+ * same one-function discipline as {@link normalizeStreetForKey}. The address-point tier (#476) does NOT apply it yet:
524
+ * adopting it there requires a extract rebuild (noted on #483).
459
525
  *
460
526
  * A same-numbered US and state route stay DISTINCT keys (`us route 5` vs `state route 5`); only the BARE `route N` form
461
527
  * is ambiguous (designator unknown) and it stays unfolded — a bare-route query therefore misses rather than guessing a