@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
@@ -45,14 +45,12 @@
45
45
  * nothing.
46
46
  */
47
47
 
48
- import { readdirSync } from "node:fs"
49
- import type { DatabaseSync } from "node:sqlite"
50
-
51
- import { DatabaseClient } from "@mailwoman/core/kysley/client"
48
+ import { readDirectoryEntries } from "@mailwoman/core/fs/readers"
52
49
  import { readWOFFeature } from "@mailwoman/core/resources/whosonfirst"
53
- import { join } from "path-ts"
50
+ import type { DatabaseClient } from "@mailwoman/sqlite/client"
51
+ import { join, resolvePath, type PathBuilderLike } from "path-ts"
54
52
 
55
- import type { WOFDatabase } from "./schema.ts"
53
+ import type { WOFDatabase } from "#schema"
56
54
 
57
55
  /**
58
56
  * Genuinely top-level placetypes — they never have (or need) an ancestor, so skip them.
@@ -76,23 +74,21 @@ export interface AncestryBackfillResult {
76
74
  }
77
75
 
78
76
  /**
79
- * Discover the `data` directories under a WOF repos root that hold sharded geojson, e.g.
77
+ * Discover the `data` directories under a WOF repos root that hold attached geojson, e.g.
80
78
  * `<root>/whosonfirst-data/whosonfirst-data-admin-us/data`. Resolves an id to its geojson via these roots. Accepts both
81
79
  * the nested lab layout (a `whosonfirst-data` group dir holding the admin repos) and a flat layout (admin repos
82
80
  * directly under the root); searches at most two directory levels deep.
83
81
  */
84
- export function discoverAdminDataRoots(reposRoot: string): string[] {
82
+ export async function discoverAdminDataRoots(reposRoot: PathBuilderLike): Promise<string[]> {
85
83
  const roots: string[] = []
86
84
 
87
- const visit = (dir: string, depth: number): void => {
85
+ const visit = async (dir: string, depth: number): Promise<void> => {
88
86
  if (depth > 2) return
89
87
 
90
88
  let names: string[]
91
89
 
92
90
  try {
93
- names = readdirSync(dir, { withFileTypes: true })
94
- .filter((e) => e.isDirectory())
95
- .map((e) => e.name)
91
+ names = (await readDirectoryEntries(dir)).filter((e) => e.isDirectory()).map((e) => e.name)
96
92
  } catch {
97
93
  return
98
94
  }
@@ -103,12 +99,12 @@ export function discoverAdminDataRoots(reposRoot: string): string[] {
103
99
  if (name === "data") {
104
100
  roots.push(child)
105
101
  } else if (name.startsWith("whosonfirst-data")) {
106
- visit(child, depth + 1)
102
+ await visit(child, depth + 1)
107
103
  }
108
104
  }
109
105
  }
110
106
 
111
- visit(reposRoot, 0)
107
+ await visit(resolvePath(reposRoot), 0)
112
108
 
113
109
  return roots
114
110
  }
@@ -136,18 +132,17 @@ function placetypeFromKey(key: string): string | null {
136
132
  * skipped rows would have `noGeojson`-skipped anyway. Omit `maxID` (default) for the legacy WOF-only DBs.
137
133
  */
138
134
  export async function backfillAncestorsFromHierarchy(
139
- db: DatabaseSync,
135
+ db: DatabaseClient<WOFDatabase>,
140
136
  geojsonRoots: readonly string[],
141
137
  opts: { maxID?: number } = {}
142
138
  ): Promise<AncestryBackfillResult> {
143
139
  const maxID = opts.maxID ?? Number.MAX_SAFE_INTEGER
144
- const kdb = new DatabaseClient<WOFDatabase>({ database: db })
145
140
 
146
141
  // "No country-tier ancestor" is the dead-end signal at any depth — see the module docstring. The
147
142
  // earlier "<= 1 ancestor row" test only caught the dead end's origin, never the children that
148
143
  // inherit it (a child of a repaired -4 place has two rows: itself and that parent) (#1445).
149
144
  // The id bound is stated first so SQLite prunes by the PK index before the NOT EXISTS runs at all.
150
- const candidateBase = kdb
145
+ const candidateBase = db
151
146
  .selectFrom("spr")
152
147
  .where("id", "<", maxID)
153
148
  .where((eb) =>
@@ -172,7 +167,7 @@ export async function backfillAncestorsFromHierarchy(
172
167
  // (measured 2026-08-04).
173
168
  const alreadyPresent = new Map<number, Set<number>>()
174
169
 
175
- for (const row of await kdb
170
+ for (const row of await db
176
171
  .selectFrom("ancestors")
177
172
  .select(["id", "ancestor_id"])
178
173
  .where("id", "in", candidateBase.select("spr.id"))
@@ -198,7 +193,7 @@ export async function backfillAncestorsFromHierarchy(
198
193
 
199
194
  for (const { id, placetype } of candidates) {
200
195
  if (placetype && TOP_PLACETYPES.has(placetype)) continue
201
- const gj = readWOFFeature(id, geojsonRoots)
196
+ const gj = await readWOFFeature(id, geojsonRoots)
202
197
  const hierarchy = gj?.properties?.["wof:hierarchy"]
203
198
 
204
199
  if (!hierarchy || !hierarchy.length) {
@@ -15,9 +15,8 @@
15
15
  * geocoding always does).
16
16
  */
17
17
 
18
- import type { DatabaseSync } from "node:sqlite"
19
-
20
- import { allRows } from "./sqlite-utils.ts"
18
+ import { allRows } from "@mailwoman/core/utils"
19
+ import type { DatabaseClient } from "@mailwoman/sqlite/client"
21
20
 
22
21
  /**
23
22
  * WOF placetype → containment depth, coarsest = 1. Higher = finer. Placetypes we never resolve (continent, empire, …)
@@ -61,7 +60,7 @@ export interface AncestorPlaceRow {
61
60
  * The ancestor lineage of `id` — self excluded, nearest-first. Returns `[]` when the place has no recorded ancestry.
62
61
  * NOT memoized here; `WOFSQLitePlaceLookup` keeps its own per-id cache.
63
62
  */
64
- export function ancestorLineage(db: DatabaseSync, id: number, schemaName = "main"): AncestorPlaceRow[] {
63
+ export function ancestorLineage<DB>(db: DatabaseClient<DB>, id: number, schemaName = "main"): AncestorPlaceRow[] {
65
64
  const rows = allRows<AncestorPlaceRow>(
66
65
  db.prepare(
67
66
  `SELECT a.ancestor_id AS id, a.ancestor_placetype AS placetype, s.name AS name,
@@ -76,3 +75,5 @@ export function ancestorLineage(db: DatabaseSync, id: number, schemaName = "main
76
75
 
77
76
  return rows
78
77
  }
78
+
79
+ export * from "#ancestry/backfill"
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * The name_key normalizer is the SHARED {@link normalizeLocalityForKey} — the query side (the demo
24
24
  * resolver {@link WOFCandidateTableLookup}) MUST use the same function, the one-normalizer
25
- * discipline the address-point shard uses, so build/query stay consistent by construction.
25
+ * discipline the address-point extract uses, so build/query stay consistent by construction.
26
26
  *
27
27
  * Measured (2026-06-20, vs the 2.6 GB full-DB FTS): ~5 M rows; ~12 range fetches per 8-query
28
28
  * session (the full DB needs 243); US locality 96.8% (region bbox), EU coord parity 88.6%.
@@ -39,36 +39,36 @@
39
39
  * `candidate-ancestors-schema.ts` owns the encoding decision and the DAG/absence semantics.
40
40
  */
41
41
 
42
- import { existsSync, rmSync } from "node:fs"
43
- import { DatabaseSync } from "node:sqlite"
44
-
45
42
  import { COUNTRY_POPULATION } from "@mailwoman/codex/country"
46
- import { DatabaseClient } from "@mailwoman/core/kysley/client"
43
+ import { pathExists } from "@mailwoman/core/fs/readers"
44
+ import { removePath } from "@mailwoman/core/fs/writers"
45
+ import { DatabaseClient } from "@mailwoman/sqlite/client"
47
46
 
48
- import { createCandidateFTS } from "./candidate-fts.ts"
49
- import { IMPORTANCE_JOIN_GATE_KM, loadImportanceIndex } from "./candidate-importance.ts"
47
+ import { createCandidateFTS } from "#candidate-fts"
48
+ import { IMPORTANCE_JOIN_RADIUS_KM, loadImportanceIndex } from "#candidate-importance"
50
49
  import {
51
50
  CANDIDATE_COLUMNS,
52
51
  createCandidateStagingTables,
53
52
  createCandidateTable,
54
53
  type CandidateDatabase,
55
- } from "./candidate-schema.ts"
56
- import { explodeAliasBags } from "./candidate/alias-bags.ts"
57
- import { buildAncestorsSidecar } from "./candidate/ancestors-sidecar.ts"
58
- import { stageCountryDisplayNames } from "./candidate/country-display-names.ts"
59
- import { GLOSS_KEY_THRESHOLD, stampNameRoles } from "./candidate/name-roles.ts"
60
- import type { PlaceAttrs } from "./candidate/place-attrs.ts"
61
- import { foldShard } from "./candidate/shard-fold.ts"
62
- import { createCapitalTable } from "./capital-schema.ts"
63
- import type { CapitalPoint } from "./capitals.ts"
64
- import { resurrectCurrencyHoles } from "./currency-backfill.ts"
65
- import { normalizeLocalityForKey } from "./street-normalize.ts"
54
+ } from "#candidate-schema"
55
+ import { explodeAliasBags } from "#candidate/alias-bags"
56
+ import { buildAncestorsSidecar } from "#candidate/ancestors-sidecar"
57
+ import { stageCountryDisplayNames } from "#candidate/country-display-names"
58
+ import { foldExtract } from "#candidate/extract-fold"
59
+ import { GLOSS_KEY_THRESHOLD, stampNameRoles } from "#candidate/name-roles"
60
+ import type { PlaceAttrs } from "#candidate/place-attrs"
61
+ import { createCapitalTable } from "#capital-schema"
62
+ import type { CapitalPoint } from "#capitals"
63
+ import { resurrectCurrencyHoles } from "#currency-backfill"
64
+ import type { WOFDatabase } from "#schema"
65
+ import { normalizeLocalityForKey } from "#street/normalize"
66
66
 
67
67
  // The build's contract is this module path; the passes behind it live in `./candidate/`. Re-exported
68
68
  // here so a consumer never has to know which pass owns which name.
69
- export { stageCountryDisplayNames } from "./candidate/country-display-names.ts"
70
- export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "./candidate/name-roles.ts"
71
- export type { PlaceAttrs } from "./candidate/place-attrs.ts"
69
+ export { stageCountryDisplayNames } from "#candidate/country-display-names"
70
+ export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "#candidate/name-roles"
71
+ export type { PlaceAttrs } from "#candidate/place-attrs"
72
72
 
73
73
  export interface BuildCandidateOptions {
74
74
  /**
@@ -86,20 +86,22 @@ export interface BuildCandidateOptions {
86
86
  */
87
87
  capitals?: readonly CapitalPoint[]
88
88
  /**
89
- * Optional postcode shards (`spr` rows with `placetype='postalcode'` + real coords, e.g. postalcode-us.db) — folded
89
+ * Optional postcode extracts (`spr` rows with `placetype='postalcode'` + real coords, e.g. postalcode-us.db) — folded
90
90
  * in as `postalcode` candidate rows so `findPlace(postalcode)` resolves a ZIP directly (the demo's primary postcode
91
91
  * path; the postcode-*.bin anchor stays the fallback). Matches the slim wof-hot.db, which took one such postcode DB.
92
92
  *
93
- * Each shard's `names` table is folded in too (#1495) — that's where the GeoNames delivery-city names live
93
+ * Each extract's `names` table is folded in too (#1495) — that's where the GeoNames delivery-city names live
94
94
  * ("Brooklyn" for 11201), and they were previously reachable only through FTS.
95
95
  */
96
96
  postcodes?: string[]
97
97
  /**
98
- * Optional LOCALITY shards (`spr` rows with `placetype='locality'` + real coords, e.g. localities-nz-linz.db — the
99
- * #1564 NZ suburb tier) — folded through the same shard loop as the postcode shards, staged as `locality` candidate
100
- * rows with no region scope and UNMEASURED population (`neg_rank 0`: a shard row ranks behind any populated namesake
101
- * and wins only where its key is the answer). Each shard's `names` table folds as aliases, `is_primary = 0`, same as
102
- * the delivery-city pass.
98
+ * Optional LOCALITY extracts (`spr` rows with `placetype='locality'` + real coords, e.g. localities-nz-linz.db — the
99
+ * #1564 NZ suburb tier) — folded through the same extract loop as the postcode extracts, staged as `locality`
100
+ * candidate rows with UNMEASURED population (`neg_rank 0`: a extract row ranks behind any populated namesake and wins
101
+ * only where its key is the answer). Each extract's `names` table folds as aliases, `is_primary = 0`, same as the
102
+ * delivery-city pass. An extract whose `ancestors` table names an admin region for a row gives that row the region's
103
+ * scope (`region_id`) plus closure rows for the region and the region's own chain above it; an extract without one
104
+ * stays unscoped, as before.
103
105
  */
104
106
  localities?: string[]
105
107
  /**
@@ -118,21 +120,30 @@ export interface BuildCandidateOptions {
118
120
  * Cross-source currency backfill (#1737). WOF carries deprecated-with-no-successor records for real, populated
119
121
  * settlements (Rochester Kent, Aldershot, Telford — 120 GB localities alone), and the currency filter correctly drops
120
122
  * them, leaving holes no ranking can fill. When this option is set, pass 1c resurrects a dead locality ONLY under
121
- * three gates, positive evidence throughout: no live same-name row of any placetype near the dead record (a distant
122
- * same-name row is a NAMESAKE and does not block — Rochester, Northumberland pop 318 must not veto Rochester, Kent);
123
- * an independent GeoNames P-class attestation of the same folded name within {@link CURRENCY_BACKFILL_RADIUS_KM}; and
124
- * the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged row keeps the real WOF id, name, centroid
125
- * and bbox — GeoNames only ATTESTS the place and supplies the population that lets it stand in prominence races.
126
- * `countries` are judged only where `<cc>.txt` exists under `geonamesDir`; absent dumps are skipped loudly.
123
+ * three conditions, positive evidence throughout: no live same-name row of any placetype near the dead record (a
124
+ * distant same-name row is a NAMESAKE and does not block — Rochester, Northumberland pop 318 must not veto Rochester,
125
+ * Kent); an independent GeoNames P-class attestation of the same folded name within
126
+ * {@link CURRENCY_BACKFILL_RADIUS_KM}; and the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged
127
+ * row keeps the real WOF id, name, centroid and bbox — GeoNames only ATTESTS the place and supplies the population
128
+ * that lets it stand in prominence races. `countries` are judged only where `<cc>.txt` exists under `geonamesDir`;
129
+ * absent dumps are skipped loudly.
127
130
  */
128
- currencyBackfill?: { geonamesDir: string; countries: readonly string[] }
131
+ currencyBackfill?: {
132
+ geonamesDir: string
133
+ countries: readonly string[]
134
+ /**
135
+ * The dead placetypes the resurrection judges; `resurrectCurrencyHoles`'s default (`locality`) when absent. The
136
+ * `localadmin` widening #1746 named is admitted here once its census is read.
137
+ */
138
+ deadPlacetypes?: readonly string[]
139
+ }
129
140
  /**
130
141
  * Optional progress callback for CLI / test introspection.
131
142
  */
132
143
  onProgress?: (phase: string, message: string) => void
133
144
  /**
134
145
  * Key-count threshold for the gloss anomaly detector — {@link GLOSS_KEY_THRESHOLD} unless a test passes a
135
- * fixture-scale value. The production number is the #1730 sweep's own cut (4,000 places at >= 50 keys).
146
+ * fixture-scale value. The production number is the #1730 sweep's own threshold (4,000 places at >= 50 keys).
136
147
  */
137
148
  glossKeyThreshold?: number
138
149
  }
@@ -145,8 +156,8 @@ export interface BuildCandidateResult {
145
156
  abbrevs: number
146
157
  postcodes: number
147
158
  /**
148
- * Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the shards
149
- * carried no alias names, NOT that the pass was skipped: a shard with no `names` table reports that separately
159
+ * Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the extracts
160
+ * carried no alias names, NOT that the pass was skipped: a extract with no `names` table reports that separately
150
161
  * through `onProgress`.
151
162
  */
152
163
  postcodeAliases: number
@@ -161,7 +172,7 @@ export interface BuildCandidateResult {
161
172
  ancestorPlaces: number
162
173
  /**
163
174
  * Places that received a pre/post interval label — the canonical-parent forest's node count. Places outside it (no
164
- * recorded ancestry, shard rows, cycle-skipped) have NO label: containment against them is unverifiable, never
175
+ * recorded ancestry, extract rows, cycle-skipped) have NO label: containment against them is unverifiable, never
165
176
  * false.
166
177
  */
167
178
  intervalPlaces: number
@@ -174,12 +185,12 @@ export interface BuildCandidateResult {
174
185
  importanceScored?: number
175
186
  /**
176
187
  * Places whose `(name_key, country, placetype)` matched a scored group but whose nearest scored centroid was outside
177
- * {@link IMPORTANCE_JOIN_GATE_KM} — a different town wearing the same name, refused rather than scored.
188
+ * {@link IMPORTANCE_JOIN_RADIUS_KM} — a different town wearing the same name, refused rather than scored.
178
189
  *
179
190
  * Worth watching across rebuilds: a jump here means the score source and the admin source have drifted apart, and the
180
191
  * join is being asked to guess.
181
192
  */
182
- importanceGated?: number
193
+ importanceFiltered?: number
183
194
  /**
184
195
  * Alias rows stamped `name_role = 'gloss'` — the anomaly detector's certain core (#1730).
185
196
  */
@@ -202,16 +213,16 @@ export interface BuildCandidateResult {
202
213
  export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<BuildCandidateResult> {
203
214
  const progress = opts.onProgress ?? (() => {})
204
215
 
205
- if (existsSync(opts.output)) {
206
- rmSync(opts.output)
216
+ if (await pathExists(opts.output)) {
217
+ await removePath(opts.output)
207
218
  }
208
219
 
209
- const src = new DatabaseSync(opts.input, { readOnly: true })
210
- const out = new DatabaseSync(opts.output)
220
+ using src = new DatabaseClient<WOFDatabase>(opts.input, { readOnly: true })
221
+ await using kdb = new DatabaseClient<CandidateDatabase>(opts.output)
211
222
  // Build-tuning pragmas (raw — Kysely doesn't model PRAGMA). The code dictionaries + the transient
212
223
  // staging table come from the SHARED schema DDL, so they can't drift from {@link CandidateDatabase}.
213
- out.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
214
- const kdb = new DatabaseClient<CandidateDatabase>({ database: out })
224
+ kdb.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
225
+
215
226
  await createCandidateStagingTables(kdb)
216
227
 
217
228
  // --- compact code maps (country/placetype → small int, shrinks the clustered key). The ids are
@@ -296,13 +307,13 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
296
307
  // The hot path — millions of clustered rows. Kept a single positional prepared statement (the fastest
297
308
  // node:sqlite insert) rather than a per-row query builder. Placeholders come from CANDIDATE_COLUMNS so
298
309
  // the column COUNT can't drift; the positional run() args below MUST stay in CANDIDATE_COLUMNS order.
299
- const insStage = out.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
310
+ const insStage = kdb.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
300
311
 
301
312
  // --- pass 1: primaries (and the per-place attrs the alias/abbrev passes reuse) ---
302
313
  progress("primaries", "indexing place names")
303
314
  const attrs = new Map<number, PlaceAttrs>()
304
315
  let nPrim = 0
305
- out.exec("BEGIN")
316
+ kdb.exec("BEGIN")
306
317
 
307
318
  for (const r of src
308
319
  .prepare(
@@ -374,14 +385,14 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
374
385
  }
375
386
  }
376
387
 
377
- out.exec("COMMIT")
388
+ kdb.exec("COMMIT")
378
389
  progress("primaries", `${nPrim.toLocaleString()} primaries; ${attrs.size.toLocaleString()} places`)
379
390
 
380
391
  if (importance) {
381
392
  progress(
382
393
  "importance",
383
394
  `${importance.matched.toLocaleString()} places scored; ` +
384
- `${importance.gated.toLocaleString()} refused (nearest same-name place > ${IMPORTANCE_JOIN_GATE_KM} km away)`
395
+ `${importance.refused.toLocaleString()} refused (nearest same-name place > ${IMPORTANCE_JOIN_RADIUS_KM} km away)`
385
396
  )
386
397
  }
387
398
 
@@ -417,18 +428,19 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
417
428
  iso2ByID: new Map([...ccodes].map(([code, id]) => [id, code])),
418
429
  countryPtID: ptID("country"),
419
430
  stageRow,
420
- tx: out,
431
+ tx: kdb,
421
432
  }).toLocaleString()} country surfaces`
422
433
  )
423
434
 
424
- // --- pass 1c: cross-source currency backfill (#1737 — resurrectCurrencyHoles owns the gates). Runs BEFORE
435
+ // --- pass 1c: cross-source currency backfill (#1737 — resurrectCurrencyHoles owns the checks). Runs BEFORE
425
436
  // the alias pass so a resurrected place's alt names explode like any primary's. ---
426
437
  if (opts.currencyBackfill) {
427
438
  const nBackfill = await resurrectCurrencyHoles({
428
439
  src,
429
- tx: out,
440
+ tx: kdb,
430
441
  geonamesDir: opts.currencyBackfill.geonamesDir,
431
442
  countries: opts.currencyBackfill.countries,
443
+ ...(opts.currencyBackfill.deadPlacetypes ? { deadPlacetypes: opts.currencyBackfill.deadPlacetypes } : {}),
432
444
  attrs,
433
445
  ccID,
434
446
  ptID,
@@ -447,12 +459,12 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
447
459
 
448
460
  // --- pass 2: distinct normalized aliases from place_search.alt_names (explodeAliasBags owns the loop) ---
449
461
  progress("aliases", "exploding alias bags")
450
- const { nAlias, keyCounts } = explodeAliasBags(src, out, attrs, stageRow)
462
+ const { nAlias, keyCounts } = explodeAliasBags(src, kdb, attrs, stageRow)
451
463
  progress("aliases", `${nAlias.toLocaleString()} aliases`)
452
464
 
453
465
  // --- pass 3: region abbreviations (place_abbr) ---
454
466
  let nAbbr = 0
455
- out.exec("BEGIN")
467
+ kdb.exec("BEGIN")
456
468
 
457
469
  for (const r of src.prepare("SELECT id, abbr FROM place_abbr").iterate()) {
458
470
  const a = attrs.get(Number(r.id))
@@ -466,7 +478,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
466
478
  nAbbr++
467
479
  }
468
480
 
469
- out.exec("COMMIT")
481
+ kdb.exec("COMMIT")
470
482
  progress("abbrevs", `${nAbbr.toLocaleString()} abbrevs`)
471
483
 
472
484
  // --- pass 3b: name roles (#1730 prototype — stampNameRoles owns the detectors) ---
@@ -474,7 +486,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
474
486
  // interval tables, and neither reads the other's output. Ordered by label only.
475
487
  const roles = stampNameRoles({
476
488
  src,
477
- out,
489
+ out: kdb,
478
490
  attrs,
479
491
  keyCounts,
480
492
  glossThreshold: opts.glossKeyThreshold ?? GLOSS_KEY_THRESHOLD,
@@ -484,17 +496,17 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
484
496
  })
485
497
 
486
498
  // --- pass 3c: the ancestors sidecar (candidate-ancestors-schema.ts owns the encoding decision) ---
487
- const sidecar = await buildAncestorsSidecar({ src, out, kdb, attrs, ptID, progress })
499
+ const sidecar = await buildAncestorsSidecar({ src, out: kdb, attrs, ptID, progress })
488
500
 
489
- // --- pass 4 + 4b: postcode and locality shards (foldShard owns the per-shard loop) ---
501
+ // --- pass 4 + 4b: postcode and locality extracts (foldExtract owns the per-extract loop) ---
490
502
  let nPostcode = 0
491
503
  let nPostcodeAlias = 0
492
504
 
493
505
  for (const pcDB of opts.postcodes ?? []) {
494
- const folded = foldShard({
495
- out,
496
- shardPath: pcDB,
497
- shardPlacetype: "postalcode",
506
+ const folded = foldExtract({
507
+ out: kdb,
508
+ extractPath: pcDB,
509
+ extractPlacetype: "postalcode",
498
510
  ccID,
499
511
  ptID,
500
512
  stageRow,
@@ -510,23 +522,34 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
510
522
  }
511
523
 
512
524
  let nLocality = 0
525
+ let nLocalityScoped = 0
526
+ let nLocalityAncestor = 0
513
527
 
514
528
  for (const locDB of opts.localities ?? []) {
515
- const folded = foldShard({
516
- out,
517
- shardPath: locDB,
518
- shardPlacetype: "locality",
529
+ const folded = foldExtract({
530
+ out: kdb,
531
+ extractPath: locDB,
532
+ extractPlacetype: "locality",
519
533
  ccID,
520
534
  ptID,
521
535
  stageRow,
536
+ attrs,
522
537
  progress,
523
538
  })
524
539
 
525
540
  nLocality += folded.primaries
541
+ nLocalityScoped += folded.scoped
542
+ nLocalityAncestor += folded.ancestorRows
526
543
  }
527
544
 
528
545
  if (nLocality > 0) {
529
- progress("localities", `${nLocality.toLocaleString()} shard localities folded`)
546
+ progress(
547
+ "localities",
548
+ `${nLocality.toLocaleString()} extract localities folded` +
549
+ (nLocalityScoped
550
+ ? `; ${nLocalityScoped.toLocaleString()} carry a region scope (${nLocalityAncestor.toLocaleString()} closure rows)`
551
+ : "")
552
+ )
530
553
  }
531
554
 
532
555
  // --- code dictionaries: typed batch inserts via kdb (a few hundred rows — Kysely is clean here) ---
@@ -574,26 +597,23 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
574
597
  await createCandidateTable(kdb)
575
598
  // OR IGNORE: an abbrev/alias can normalize to a place's primary key (same place, same rank) → any one
576
599
  // row. The bulk sorted INSERT…SELECT (clustered materialization) stays raw — a single hot bulk statement.
577
- out.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
600
+ kdb.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
578
601
  await kdb.schema.dropTable("cand_stage").execute()
579
602
  // Typo-tolerant fallback index (the unified gazetteer's second mode): the exact name_key probe can't
580
603
  // recover misspellings, so FTS5-trigram over `name` lets the reader fuzzy-match on an exact+strip miss.
581
604
  progress("fts", "building FTS5-trigram fuzzy index")
582
- createCandidateFTS(out)
605
+ createCandidateFTS(kdb)
583
606
  // page_size MUST be set right before VACUUM: node:sqlite initializes the file at the 4096 default on
584
607
  // `new DatabaseSync`, so the creation-time pragma is a no-op — only a VACUUM rebuilds at the new size.
585
608
  // 8192 matches the sql.js-httpvfs 64 KiB request chunk cleanly (8 pages) and shallows the B-tree.
586
- out.exec("PRAGMA page_size=8192")
587
- out.exec("VACUUM")
609
+ kdb.exec("PRAGMA page_size=8192")
610
+ kdb.exec("VACUUM")
588
611
 
589
612
  const { n: rows } = await kdb
590
613
  .selectFrom("candidate")
591
614
  .select((eb) => eb.fn.countAll<number>().as("n"))
592
615
  .executeTakeFirstOrThrow()
593
616
 
594
- src.close()
595
- await kdb.destroy()
596
-
597
617
  // closes the underlying `out` connection
598
618
  return {
599
619
  rows,
@@ -603,10 +623,10 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
603
623
  abbrevs: nAbbr,
604
624
  postcodes: nPostcode,
605
625
  postcodeAliases: nPostcodeAlias,
606
- ancestorRows: sidecar.ancestorRows,
607
- ancestorPlaces: sidecar.ancestorPlaces,
626
+ ancestorRows: sidecar.ancestorRows + nLocalityAncestor,
627
+ ancestorPlaces: sidecar.ancestorPlaces + nLocalityScoped,
608
628
  intervalPlaces: sidecar.intervalPlaces,
609
629
  ...roles,
610
- ...(importance ? { importanceScored: importance.matched, importanceGated: importance.gated } : {}),
630
+ ...(importance ? { importanceScored: importance.matched, importanceFiltered: importance.refused } : {}),
611
631
  }
612
632
  }