@mailwoman/resolver-wof-sqlite 9.1.0 → 9.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (501) hide show
  1. package/README.md +36 -20
  2. package/lib/address/index.ts +9 -0
  3. package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +40 -28
  4. package/{address-point-schema.ts → lib/address/point-schema.ts} +34 -8
  5. package/lib/address/point.ts +280 -0
  6. package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
  7. package/{ancestry.ts → lib/ancestry/index.ts} +13 -8
  8. package/{build-candidate.ts → lib/build-candidate.ts} +243 -199
  9. package/{build-slim.ts → lib/build-slim.ts} +153 -168
  10. package/lib/candidate/alias-bags.ts +56 -0
  11. package/lib/candidate/ancestors-sidecar.ts +204 -0
  12. package/lib/candidate/country-display-names.ts +79 -0
  13. package/lib/candidate/extract-fold.ts +138 -0
  14. package/lib/candidate/name-roles.ts +238 -0
  15. package/lib/candidate/own-name.ts +146 -0
  16. package/lib/candidate/place-attrs.ts +44 -0
  17. package/lib/candidate-ancestors-schema.ts +195 -0
  18. package/{candidate-fts.ts → lib/candidate-fts.ts} +7 -5
  19. package/{candidate-importance.ts → lib/candidate-importance.ts} +54 -57
  20. package/lib/candidate-lookup.ts +976 -0
  21. package/{candidate-schema.ts → lib/candidate-schema.ts} +34 -6
  22. package/lib/candidate-scoring.ts +261 -0
  23. package/lib/capital-schema.ts +89 -0
  24. package/lib/capitals.ts +148 -0
  25. package/{coincident-roles.ts → lib/coincident-roles.ts} +75 -19
  26. package/{convention.ts → lib/convention/index.ts} +5 -5
  27. package/lib/convention/schema.ts +72 -0
  28. package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +15 -16
  29. package/lib/currency-backfill.ts +334 -0
  30. package/lib/env.ts +50 -0
  31. package/lib/exact-match.ts +113 -0
  32. package/{sharding.ts → lib/extracts.ts} +63 -60
  33. package/lib/fst/autocomplete.ts +176 -0
  34. package/{fst-builder.ts → lib/fst/builder.ts} +30 -27
  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} +42 -75
  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} +28 -23
  43. package/{fts-query.ts → lib/fts/query.ts} +2 -2
  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} +16 -15
  47. package/{index.ts → lib/index.ts} +52 -48
  48. package/{interpolation.ts → lib/interpolation.ts} +137 -41
  49. package/lib/lookup.ts +861 -0
  50. package/{name-score.ts → lib/name-score.ts} +6 -4
  51. package/lib/nsul/index.ts +8 -0
  52. package/lib/nsul/lookup.ts +144 -0
  53. package/lib/nsul/schema.ts +130 -0
  54. package/{place-importance-schema.ts → lib/place-importance-schema.ts} +70 -22
  55. package/lib/poi/index.ts +8 -0
  56. package/{poi-lookup.ts → lib/poi/lookup.ts} +32 -39
  57. package/{poi-schema.ts → lib/poi/schema.ts} +10 -6
  58. package/lib/polygon-schema.ts +47 -0
  59. package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +15 -21
  60. package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +4 -2
  61. package/lib/postal/index.ts +9 -0
  62. package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
  63. package/lib/primary-preference.ts +226 -0
  64. package/lib/proximity-rerank.ts +120 -0
  65. package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
  66. package/lib/region-keys.ts +144 -0
  67. package/{reverse.ts → lib/reverse.ts} +45 -56
  68. package/{schema.ts → lib/schema.ts} +11 -1
  69. package/lib/search-fetch.ts +257 -0
  70. package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
  71. package/lib/sqlite-utils.ts +83 -0
  72. package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +12 -6
  73. package/{street-centroid.ts → lib/street/centroid.ts} +26 -28
  74. package/lib/street/index.ts +13 -0
  75. package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
  76. package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
  77. package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
  78. package/lib/street/normalize.ts +572 -0
  79. package/{street-segment-schema.ts → lib/street/segment-schema.ts} +13 -8
  80. package/{types.ts → lib/types.ts} +49 -9
  81. package/{unified-schema.ts → lib/unified-schema.ts} +21 -25
  82. package/lib/uprn/existence.ts +84 -0
  83. package/lib/uprn/index.ts +9 -0
  84. package/lib/uprn/lookup.ts +206 -0
  85. package/lib/uprn/schema.ts +124 -0
  86. package/lib/weights-overlay-linker.ts +878 -0
  87. package/out/address/index.d.ts +9 -0
  88. package/out/address/index.d.ts.map +1 -0
  89. package/out/address/index.js +9 -0
  90. package/out/address/index.js.map +1 -0
  91. package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +11 -10
  92. package/out/address/point-interpolation.d.ts.map +1 -0
  93. package/out/{address-point-interpolation.js → address/point-interpolation.js} +29 -23
  94. package/out/address/point-interpolation.js.map +1 -0
  95. package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +30 -10
  96. package/out/address/point-schema.d.ts.map +1 -0
  97. package/out/{address-point-schema.js → address/point-schema.js} +7 -3
  98. package/out/address/point-schema.js.map +1 -0
  99. package/out/{address-point.d.ts → address/point.d.ts} +16 -8
  100. package/out/address/point.d.ts.map +1 -0
  101. package/out/address/point.js +191 -0
  102. package/out/address/point.js.map +1 -0
  103. package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
  104. package/out/ancestry/backfill.d.ts.map +1 -0
  105. package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
  106. package/out/ancestry/backfill.js.map +1 -0
  107. package/out/{ancestry.d.ts → ancestry/index.d.ts} +6 -5
  108. package/out/ancestry/index.d.ts.map +1 -0
  109. package/out/{ancestry.js → ancestry/index.js} +7 -7
  110. package/out/ancestry/index.js.map +1 -0
  111. package/out/build-candidate.d.ts +88 -7
  112. package/out/build-candidate.d.ts.map +1 -1
  113. package/out/build-candidate.js +145 -149
  114. package/out/build-candidate.js.map +1 -1
  115. package/out/build-slim.d.ts +5 -5
  116. package/out/build-slim.d.ts.map +1 -1
  117. package/out/build-slim.js +127 -142
  118. package/out/build-slim.js.map +1 -1
  119. package/out/candidate/alias-bags.d.ts +19 -0
  120. package/out/candidate/alias-bags.d.ts.map +1 -0
  121. package/out/candidate/alias-bags.js +39 -0
  122. package/out/candidate/alias-bags.js.map +1 -0
  123. package/out/candidate/ancestors-sidecar.d.ts +32 -0
  124. package/out/candidate/ancestors-sidecar.d.ts.map +1 -0
  125. package/out/candidate/ancestors-sidecar.js +140 -0
  126. package/out/candidate/ancestors-sidecar.js.map +1 -0
  127. package/out/candidate/country-display-names.d.ts +35 -0
  128. package/out/candidate/country-display-names.d.ts.map +1 -0
  129. package/out/candidate/country-display-names.js +59 -0
  130. package/out/candidate/country-display-names.js.map +1 -0
  131. package/out/candidate/extract-fold.d.ts +32 -0
  132. package/out/candidate/extract-fold.d.ts.map +1 -0
  133. package/out/candidate/extract-fold.js +104 -0
  134. package/out/candidate/extract-fold.js.map +1 -0
  135. package/out/candidate/name-roles.d.ts +57 -0
  136. package/out/candidate/name-roles.d.ts.map +1 -0
  137. package/out/candidate/name-roles.js +166 -0
  138. package/out/candidate/name-roles.js.map +1 -0
  139. package/out/candidate/own-name.d.ts +50 -0
  140. package/out/candidate/own-name.d.ts.map +1 -0
  141. package/out/candidate/own-name.js +132 -0
  142. package/out/candidate/own-name.js.map +1 -0
  143. package/out/candidate/place-attrs.d.ts +43 -0
  144. package/out/candidate/place-attrs.d.ts.map +1 -0
  145. package/out/candidate/place-attrs.js +15 -0
  146. package/out/candidate/place-attrs.js.map +1 -0
  147. package/out/candidate-ancestors-schema.d.ts +150 -0
  148. package/out/candidate-ancestors-schema.d.ts.map +1 -0
  149. package/out/candidate-ancestors-schema.js +123 -0
  150. package/out/candidate-ancestors-schema.js.map +1 -0
  151. package/out/candidate-fts.d.ts +7 -5
  152. package/out/candidate-fts.d.ts.map +1 -1
  153. package/out/candidate-fts.js +5 -3
  154. package/out/candidate-fts.js.map +1 -1
  155. package/out/candidate-importance.d.ts +16 -16
  156. package/out/candidate-importance.d.ts.map +1 -1
  157. package/out/candidate-importance.js +47 -52
  158. package/out/candidate-importance.js.map +1 -1
  159. package/out/candidate-lookup.d.ts +31 -52
  160. package/out/candidate-lookup.d.ts.map +1 -1
  161. package/out/candidate-lookup.js +380 -172
  162. package/out/candidate-lookup.js.map +1 -1
  163. package/out/candidate-schema.d.ts +31 -7
  164. package/out/candidate-schema.d.ts.map +1 -1
  165. package/out/candidate-schema.js +3 -0
  166. package/out/candidate-schema.js.map +1 -1
  167. package/out/candidate-scoring.d.ts +34 -0
  168. package/out/candidate-scoring.d.ts.map +1 -0
  169. package/out/candidate-scoring.js +196 -0
  170. package/out/candidate-scoring.js.map +1 -0
  171. package/out/capital-schema.d.ts +51 -0
  172. package/out/capital-schema.d.ts.map +1 -0
  173. package/out/capital-schema.js +63 -0
  174. package/out/capital-schema.js.map +1 -0
  175. package/out/capitals.d.ts +69 -0
  176. package/out/capitals.d.ts.map +1 -0
  177. package/out/capitals.js +98 -0
  178. package/out/capitals.js.map +1 -0
  179. package/out/coincident-roles.d.ts +12 -4
  180. package/out/coincident-roles.d.ts.map +1 -1
  181. package/out/coincident-roles.js +43 -11
  182. package/out/coincident-roles.js.map +1 -1
  183. package/out/{convention.d.ts → convention/index.d.ts} +5 -5
  184. package/out/convention/index.d.ts.map +1 -0
  185. package/out/{convention.js → convention/index.js} +4 -4
  186. package/out/convention/index.js.map +1 -0
  187. package/out/convention/schema.d.ts +51 -0
  188. package/out/convention/schema.d.ts.map +1 -0
  189. package/out/convention/schema.js +34 -0
  190. package/out/convention/schema.js.map +1 -0
  191. package/out/coverage-manifest-schema.d.ts +8 -8
  192. package/out/coverage-manifest-schema.d.ts.map +1 -1
  193. package/out/coverage-manifest-schema.js +6 -10
  194. package/out/coverage-manifest-schema.js.map +1 -1
  195. package/out/currency-backfill.d.ts +90 -0
  196. package/out/currency-backfill.d.ts.map +1 -0
  197. package/out/currency-backfill.js +196 -0
  198. package/out/currency-backfill.js.map +1 -0
  199. package/out/env.d.ts +43 -0
  200. package/out/env.d.ts.map +1 -0
  201. package/out/env.js +48 -0
  202. package/out/env.js.map +1 -0
  203. package/out/exact-match.d.ts +25 -0
  204. package/out/exact-match.d.ts.map +1 -0
  205. package/out/exact-match.js +88 -0
  206. package/out/exact-match.js.map +1 -0
  207. package/out/extracts.d.ts +114 -0
  208. package/out/extracts.d.ts.map +1 -0
  209. package/out/{sharding.js → extracts.js} +38 -38
  210. package/out/extracts.js.map +1 -0
  211. package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +13 -13
  212. package/out/fst/autocomplete.d.ts.map +1 -0
  213. package/out/fst/autocomplete.js +113 -0
  214. package/out/fst/autocomplete.js.map +1 -0
  215. package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
  216. package/out/fst/builder.d.ts.map +1 -0
  217. package/out/{fst-builder.js → fst/builder.js} +24 -24
  218. package/out/fst/builder.js.map +1 -0
  219. package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
  220. package/out/fst/deserialize-web.d.ts.map +1 -0
  221. package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
  222. package/out/fst/deserialize-web.js.map +1 -0
  223. package/out/fst/format.d.ts +80 -0
  224. package/out/fst/format.d.ts.map +1 -0
  225. package/out/fst/format.js +91 -0
  226. package/out/fst/format.js.map +1 -0
  227. package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +11 -14
  228. package/out/fst/freshness.d.ts.map +1 -0
  229. package/out/{fst-freshness.js → fst/freshness.js} +42 -74
  230. package/out/fst/freshness.js.map +1 -0
  231. package/out/fst/index.d.ts +14 -0
  232. package/out/fst/index.d.ts.map +1 -0
  233. package/out/fst/index.js +14 -0
  234. package/out/fst/index.js.map +1 -0
  235. package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
  236. package/out/fst/matcher.d.ts.map +1 -0
  237. package/out/{fst-matcher.js → fst/matcher.js} +1 -1
  238. package/out/fst/matcher.js.map +1 -0
  239. package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
  240. package/out/fst/serialize.d.ts.map +1 -0
  241. package/out/{fst-serialize.js → fst/serialize.js} +18 -98
  242. package/out/fst/serialize.js.map +1 -0
  243. package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
  244. package/out/fst/types.d.ts.map +1 -0
  245. package/out/{fst-types.js → fst/types.js} +1 -1
  246. package/out/fst/types.js.map +1 -0
  247. package/out/{fts.d.ts → fts/index.d.ts} +20 -13
  248. package/out/fts/index.d.ts.map +1 -0
  249. package/out/{fts.js → fts/index.js} +20 -15
  250. package/out/fts/index.js.map +1 -0
  251. package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
  252. package/out/fts/query.d.ts.map +1 -0
  253. package/out/{fts-query.js → fts/query.js} +2 -2
  254. package/out/fts/query.js.map +1 -0
  255. package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
  256. package/out/geonames/aliases.d.ts.map +1 -0
  257. package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
  258. package/out/geonames/aliases.js.map +1 -0
  259. package/out/geonames/index.d.ts +8 -0
  260. package/out/geonames/index.d.ts.map +1 -0
  261. package/out/geonames/index.js +8 -0
  262. package/out/geonames/index.js.map +1 -0
  263. package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +12 -10
  264. package/out/geonames/postal.d.ts.map +1 -0
  265. package/out/{geonames-postal.js → geonames/postal.js} +11 -11
  266. package/out/geonames/postal.js.map +1 -0
  267. package/out/index.d.ts +32 -31
  268. package/out/index.d.ts.map +1 -1
  269. package/out/index.js +24 -24
  270. package/out/index.js.map +1 -1
  271. package/out/interpolation.d.ts +18 -9
  272. package/out/interpolation.d.ts.map +1 -1
  273. package/out/interpolation.js +108 -36
  274. package/out/interpolation.js.map +1 -1
  275. package/out/lookup.d.ts +25 -25
  276. package/out/lookup.d.ts.map +1 -1
  277. package/out/lookup.js +174 -558
  278. package/out/lookup.js.map +1 -1
  279. package/out/name-score.d.ts +0 -10
  280. package/out/name-score.d.ts.map +1 -1
  281. package/out/name-score.js +6 -4
  282. package/out/name-score.js.map +1 -1
  283. package/out/nsul/index.d.ts +8 -0
  284. package/out/nsul/index.d.ts.map +1 -0
  285. package/out/nsul/index.js +8 -0
  286. package/out/nsul/index.js.map +1 -0
  287. package/out/nsul/lookup.d.ts +83 -0
  288. package/out/nsul/lookup.d.ts.map +1 -0
  289. package/out/nsul/lookup.js +80 -0
  290. package/out/nsul/lookup.js.map +1 -0
  291. package/out/nsul/schema.d.ts +100 -0
  292. package/out/nsul/schema.d.ts.map +1 -0
  293. package/out/nsul/schema.js +78 -0
  294. package/out/nsul/schema.js.map +1 -0
  295. package/out/place-importance-schema.d.ts +47 -10
  296. package/out/place-importance-schema.d.ts.map +1 -1
  297. package/out/place-importance-schema.js +56 -10
  298. package/out/place-importance-schema.js.map +1 -1
  299. package/out/poi/index.d.ts +8 -0
  300. package/out/poi/index.d.ts.map +1 -0
  301. package/out/poi/index.js +8 -0
  302. package/out/poi/index.js.map +1 -0
  303. package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
  304. package/out/poi/lookup.d.ts.map +1 -0
  305. package/out/{poi-lookup.js → poi/lookup.js} +24 -29
  306. package/out/poi/lookup.js.map +1 -0
  307. package/out/{poi-schema.d.ts → poi/schema.d.ts} +10 -6
  308. package/out/poi/schema.d.ts.map +1 -0
  309. package/out/{poi-schema.js → poi/schema.js} +1 -1
  310. package/out/poi/schema.js.map +1 -0
  311. package/out/polygon-schema.d.ts +37 -0
  312. package/out/polygon-schema.d.ts.map +1 -0
  313. package/out/polygon-schema.js +23 -0
  314. package/out/polygon-schema.js.map +1 -0
  315. package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +7 -6
  316. package/out/postal/city-alias-lookup.d.ts.map +1 -0
  317. package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +12 -16
  318. package/out/postal/city-alias-lookup.js.map +1 -0
  319. package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
  320. package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
  321. package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
  322. package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
  323. package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +4 -3
  324. package/out/postal/city-candidate-schema.d.ts.map +1 -0
  325. package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
  326. package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
  327. package/out/postal/index.d.ts +9 -0
  328. package/out/postal/index.d.ts.map +1 -0
  329. package/out/postal/index.js +9 -0
  330. package/out/postal/index.js.map +1 -0
  331. package/out/postcode-point-lookup.d.ts +10 -10
  332. package/out/postcode-point-lookup.d.ts.map +1 -1
  333. package/out/postcode-point-lookup.js +13 -13
  334. package/out/postcode-point-lookup.js.map +1 -1
  335. package/out/primary-preference.d.ts +133 -0
  336. package/out/primary-preference.d.ts.map +1 -0
  337. package/out/primary-preference.js +146 -0
  338. package/out/primary-preference.js.map +1 -0
  339. package/out/proximity-rerank.d.ts +77 -0
  340. package/out/proximity-rerank.d.ts.map +1 -0
  341. package/out/proximity-rerank.js +86 -0
  342. package/out/proximity-rerank.js.map +1 -0
  343. package/out/ranking-weights.d.ts +15 -3
  344. package/out/ranking-weights.d.ts.map +1 -1
  345. package/out/ranking-weights.js +21 -3
  346. package/out/ranking-weights.js.map +1 -1
  347. package/out/region-keys.d.ts +47 -0
  348. package/out/region-keys.d.ts.map +1 -0
  349. package/out/region-keys.js +121 -0
  350. package/out/region-keys.js.map +1 -0
  351. package/out/reverse.d.ts +6 -6
  352. package/out/reverse.d.ts.map +1 -1
  353. package/out/reverse.js +23 -35
  354. package/out/reverse.js.map +1 -1
  355. package/out/schema.d.ts +10 -1
  356. package/out/schema.d.ts.map +1 -1
  357. package/out/schema.js.map +1 -1
  358. package/out/search-fetch.d.ts +59 -0
  359. package/out/search-fetch.d.ts.map +1 -0
  360. package/out/search-fetch.js +184 -0
  361. package/out/search-fetch.js.map +1 -0
  362. package/out/sqlite-convention-source.d.ts +7 -7
  363. package/out/sqlite-convention-source.d.ts.map +1 -1
  364. package/out/sqlite-convention-source.js +5 -5
  365. package/out/sqlite-convention-source.js.map +1 -1
  366. package/out/sqlite-utils.d.ts +24 -6
  367. package/out/sqlite-utils.d.ts.map +1 -1
  368. package/out/sqlite-utils.js +24 -7
  369. package/out/sqlite-utils.js.map +1 -1
  370. package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +12 -7
  371. package/out/street/centroid-schema.d.ts.map +1 -0
  372. package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
  373. package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
  374. package/out/{street-centroid.d.ts → street/centroid.d.ts} +6 -6
  375. package/out/street/centroid.d.ts.map +1 -0
  376. package/out/{street-centroid.js → street/centroid.js} +18 -24
  377. package/out/street/centroid.js.map +1 -0
  378. package/out/street/index.d.ts +13 -0
  379. package/out/street/index.d.ts.map +1 -0
  380. package/out/street/index.js +13 -0
  381. package/out/street/index.js.map +1 -0
  382. package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
  383. package/out/street/morphology-fst-builder.d.ts.map +1 -0
  384. package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
  385. package/out/street/morphology-fst-builder.js.map +1 -0
  386. package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
  387. package/out/street/morphology-fst-loader.d.ts.map +1 -0
  388. package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
  389. package/out/street/morphology-fst-loader.js.map +1 -0
  390. package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
  391. package/out/street/name-lookup.d.ts.map +1 -0
  392. package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
  393. package/out/street/name-lookup.js.map +1 -0
  394. package/out/street/normalize.d.ts +179 -0
  395. package/out/street/normalize.d.ts.map +1 -0
  396. package/out/street/normalize.js +457 -0
  397. package/out/street/normalize.js.map +1 -0
  398. package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +13 -9
  399. package/out/street/segment-schema.d.ts.map +1 -0
  400. package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
  401. package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
  402. package/out/types.d.ts +49 -9
  403. package/out/types.d.ts.map +1 -1
  404. package/out/types.js.map +1 -1
  405. package/out/unified-schema.d.ts +6 -5
  406. package/out/unified-schema.d.ts.map +1 -1
  407. package/out/unified-schema.js +16 -19
  408. package/out/unified-schema.js.map +1 -1
  409. package/out/uprn/existence.d.ts +53 -0
  410. package/out/uprn/existence.d.ts.map +1 -0
  411. package/out/uprn/existence.js +61 -0
  412. package/out/uprn/existence.js.map +1 -0
  413. package/out/uprn/index.d.ts +9 -0
  414. package/out/uprn/index.d.ts.map +1 -0
  415. package/out/uprn/index.js +9 -0
  416. package/out/uprn/index.js.map +1 -0
  417. package/out/uprn/lookup.d.ts +85 -0
  418. package/out/uprn/lookup.d.ts.map +1 -0
  419. package/out/uprn/lookup.js +149 -0
  420. package/out/uprn/lookup.js.map +1 -0
  421. package/out/uprn/schema.d.ts +93 -0
  422. package/out/uprn/schema.d.ts.map +1 -0
  423. package/out/uprn/schema.js +78 -0
  424. package/out/uprn/schema.js.map +1 -0
  425. package/out/weights-overlay-linker.d.ts +299 -0
  426. package/out/weights-overlay-linker.d.ts.map +1 -0
  427. package/out/weights-overlay-linker.js +511 -0
  428. package/out/weights-overlay-linker.js.map +1 -0
  429. package/package.json +622 -154
  430. package/address-point.ts +0 -125
  431. package/candidate-lookup.ts +0 -720
  432. package/fst-autocomplete.ts +0 -204
  433. package/geo.ts +0 -121
  434. package/lookup.ts +0 -1354
  435. package/out/address-point-interpolation.d.ts.map +0 -1
  436. package/out/address-point-interpolation.js.map +0 -1
  437. package/out/address-point-schema.d.ts.map +0 -1
  438. package/out/address-point-schema.js.map +0 -1
  439. package/out/address-point.d.ts.map +0 -1
  440. package/out/address-point.js +0 -84
  441. package/out/address-point.js.map +0 -1
  442. package/out/ancestry-backfill.d.ts.map +0 -1
  443. package/out/ancestry-backfill.js.map +0 -1
  444. package/out/ancestry.d.ts.map +0 -1
  445. package/out/ancestry.js.map +0 -1
  446. package/out/convention.d.ts.map +0 -1
  447. package/out/convention.js.map +0 -1
  448. package/out/fst-autocomplete.d.ts.map +0 -1
  449. package/out/fst-autocomplete.js +0 -130
  450. package/out/fst-autocomplete.js.map +0 -1
  451. package/out/fst-builder.d.ts.map +0 -1
  452. package/out/fst-builder.js.map +0 -1
  453. package/out/fst-deserialize-web.d.ts.map +0 -1
  454. package/out/fst-deserialize-web.js.map +0 -1
  455. package/out/fst-freshness.d.ts.map +0 -1
  456. package/out/fst-freshness.js.map +0 -1
  457. package/out/fst-matcher.d.ts.map +0 -1
  458. package/out/fst-matcher.js.map +0 -1
  459. package/out/fst-serialize.d.ts.map +0 -1
  460. package/out/fst-serialize.js.map +0 -1
  461. package/out/fst-types.d.ts.map +0 -1
  462. package/out/fst-types.js.map +0 -1
  463. package/out/fts-query.d.ts.map +0 -1
  464. package/out/fts-query.js.map +0 -1
  465. package/out/fts.d.ts.map +0 -1
  466. package/out/fts.js.map +0 -1
  467. package/out/geo.d.ts +0 -74
  468. package/out/geo.d.ts.map +0 -1
  469. package/out/geo.js +0 -71
  470. package/out/geo.js.map +0 -1
  471. package/out/geonames-aliases.d.ts.map +0 -1
  472. package/out/geonames-aliases.js.map +0 -1
  473. package/out/geonames-postal.d.ts.map +0 -1
  474. package/out/geonames-postal.js.map +0 -1
  475. package/out/poi-lookup.d.ts.map +0 -1
  476. package/out/poi-lookup.js.map +0 -1
  477. package/out/poi-schema.d.ts.map +0 -1
  478. package/out/poi-schema.js.map +0 -1
  479. package/out/postal-city-alias-lookup.d.ts.map +0 -1
  480. package/out/postal-city-alias-lookup.js.map +0 -1
  481. package/out/postal-city-candidate-schema.d.ts.map +0 -1
  482. package/out/sharding.d.ts +0 -114
  483. package/out/sharding.d.ts.map +0 -1
  484. package/out/sharding.js.map +0 -1
  485. package/out/street-centroid-schema.d.ts.map +0 -1
  486. package/out/street-centroid.d.ts.map +0 -1
  487. package/out/street-centroid.js.map +0 -1
  488. package/out/street-morphology-fst-builder.d.ts.map +0 -1
  489. package/out/street-morphology-fst-builder.js.map +0 -1
  490. package/out/street-morphology-fst-loader.d.ts.map +0 -1
  491. package/out/street-morphology-fst-loader.js.map +0 -1
  492. package/out/street-name-lookup.d.ts.map +0 -1
  493. package/out/street-name-lookup.js.map +0 -1
  494. package/out/street-normalize.d.ts +0 -95
  495. package/out/street-normalize.d.ts.map +0 -1
  496. package/out/street-normalize.js +0 -272
  497. package/out/street-normalize.js.map +0 -1
  498. package/out/street-segment-schema.d.ts.map +0 -1
  499. package/sqlite-utils.ts +0 -46
  500. package/street-normalize.ts +0 -318
  501. /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Node reader for `uprn.db` — the OS Open UPRN layer (`uprn-schema.ts`). Two probes:
7
+ *
8
+ * - **`coordinateOf(uprn)`**: rowid B-tree hit on the `uprn` integer PK.
9
+ * - **`nearestUPRN(lat, lon, radiusM)`**: bounded nearest-point search over the res-9 `h3_cell`
10
+ * index — ring-by-ring `gridDisk` expansion with chunked `IN` probes and haversine ranking.
11
+ * Rings stop as soon as geometry proves no unprobed cell could beat the best hit — a distance
12
+ * bound, not POILookup's row-count accumulation, so the early exit can never strand a nearer
13
+ * point in an unprobed ring.
14
+ *
15
+ * ## `null` is a claim, scoped by coverage
16
+ *
17
+ * OS designates Open UPRN complete for GB (every UPRN in AddressBase Premium with geometry), and
18
+ * the builder writes `layer_coverage` with basis `designated` for every cell the product touches.
19
+ * So a `null` from either probe inside a covered cell is evidence of absence — "no such published
20
+ * GB UPRN" / "no UPRN within the radius". Outside coverage (Northern Ireland, the Isle of Man, the
21
+ * Channel Islands, open water) it is UNKNOWN, per the meaning-of-zero rule — callers building
22
+ * negative evidence must consult `readLayerCoverage`, not this reader alone.
23
+ *
24
+ * `latLngToCell`/`gridDisk` come from `h3-js`; the 48-bit short-cell packing is
25
+ * `@mailwoman/spatial`'s `shortCellToInt` via `uprnFullCell` — never reimplemented here.
26
+ */
27
+ import { haversineKm, shortCellToInt } from "@mailwoman/spatial";
28
+ import { DatabaseClient } from "@mailwoman/sqlite/client";
29
+ import { gridDisk } from "h3-js";
30
+ import { allRows } from "#sqlite-utils";
31
+ import { uprnFullCell } from "#uprn/schema";
32
+ /**
33
+ * Conservative FLOOR on how much CENTRE distance one unit of res-9 GRID distance buys, metres. Adjacent centres sit √3
34
+ * × edge apart (avg edge 174.4 m → ≈302 m); the worst bearing across a ring costs a further ×0.866, and H3's projection
35
+ * distortion shrinks edges by well under the slack this leaves (the true worst is ≈217 m per grid step). Dividing a
36
+ * radius by this over-counts rings and can never miss a cell; multiplying a grid distance by it under-states reach and
37
+ * can never end the ring walk early.
38
+ */
39
+ const RES9_CENTER_SPACING_FLOOR_M = 150;
40
+ /**
41
+ * Conservative CEILING on a res-9 cell's centre-to-vertex distance, metres (avg edge 174.4 m; distortion stays well
42
+ * under this). A point within `radiusM` of the query sits in a cell whose CENTRE is within `radiusM` + this.
43
+ */
44
+ const RES9_CELL_RADIUS_CEILING_M = 300;
45
+ /**
46
+ * Hard ceiling on `radiusM`. Keeps the probe bounded (10 km → ~72 rings ≈ 15.8k cells ≈ 18 `IN` chunks); a caller who
47
+ * wants a wider search than "which property is this coordinate" has outgrown this reader and should say so loudly.
48
+ */
49
+ export const UPRN_MAX_NEAREST_RADIUS_M = 10_000;
50
+ /**
51
+ * `IN`-list chunk size for the cell probe — far under SQLite's 32,766 bound-variable ceiling.
52
+ */
53
+ const CELL_PROBE_CHUNK = 900;
54
+ /**
55
+ * Node reader over `uprn.db`. `implements Disposable` so callers can `using lookup = new UPRNLookup(...)` — the same
56
+ * precedent as {@link POILookup}.
57
+ */
58
+ export class UPRNLookup {
59
+ #db;
60
+ /**
61
+ * Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
62
+ * ownership is membership rather than a flag a later branch has to check.
63
+ */
64
+ #resources = new DisposableStack();
65
+ /**
66
+ * `uprn` → its point (rowid-alias PK hit).
67
+ */
68
+ #coordinateProbe;
69
+ constructor(opts) {
70
+ if (opts.database) {
71
+ this.#db = opts.database;
72
+ }
73
+ else if (opts.databasePath) {
74
+ this.#db = this.#resources.use(new DatabaseClient(opts.databasePath, { readOnly: true }));
75
+ }
76
+ else {
77
+ throw new Error("UPRNLookup needs `databasePath` or `database`");
78
+ }
79
+ this.#coordinateProbe = this.#db.prepare("SELECT lat, lon FROM uprn WHERE uprn = ?");
80
+ }
81
+ /**
82
+ * The WGS84 point OS publishes for `uprn`, or `null` when the layer holds no such UPRN (see the module docstring for
83
+ * what that `null` claims).
84
+ */
85
+ coordinateOf(uprn) {
86
+ const row = this.#coordinateProbe.get(uprn);
87
+ return row ? { latitude: row.lat, longitude: row.lon } : null;
88
+ }
89
+ /**
90
+ * The single nearest UPRN within `radiusM` metres of the query point, or `null` when no UPRN lies inside the radius.
91
+ *
92
+ * Bounded two ways: `radiusM` is capped at {@link UPRN_MAX_NEAREST_RADIUS_M}, and rings expand outward only until no
93
+ * unprobed cell could beat the best hit found so far (or the radius, when nothing has been found). The stop rule is
94
+ * geometric — a cell at grid distance `g` holds no point nearer than `g` × spacing floor − cell radius, using the
95
+ * same conservative constants the reach math uses — so unlike POILookup's row-count accumulation there is no
96
+ * early-exit ambiguity: a break can never strand a nearer point in an unprobed ring. This is what keeps a
97
+ * capped-radius call over dense ground at milliseconds instead of a full-disk fetch (measured 6.4 s → 13 ms for a 10
98
+ * km radius over central London, 41.6M-row layer; an empty-sea miss at the cap runs the full expansion, 74 ms).
99
+ *
100
+ * @throws {RangeError} When `radiusM` is not a positive finite number, or exceeds the cap.
101
+ */
102
+ nearestUPRN(latitude, longitude, radiusM) {
103
+ if (!Number.isFinite(radiusM) || radiusM <= 0) {
104
+ throw new RangeError(`nearestUPRN: radiusM must be a positive finite number, received ${radiusM}`);
105
+ }
106
+ if (radiusM > UPRN_MAX_NEAREST_RADIUS_M) {
107
+ throw new RangeError(`nearestUPRN: radiusM ${radiusM} exceeds the ${UPRN_MAX_NEAREST_RADIUS_M} m cap`);
108
+ }
109
+ const origin = uprnFullCell(latitude, longitude);
110
+ const seenCells = new Set();
111
+ let best = null;
112
+ // `ring` is H3 grid distance; the loop terminates because the break bound is at most radiusM, which the
113
+ // RangeError above caps.
114
+ for (let ring = 0;; ring++) {
115
+ // A cell at grid distance `ring` holds no point nearer than this. Once it exceeds what could still
116
+ // win — the best hit so far, or the radius itself — further rings cannot improve the answer.
117
+ const closestPossibleM = ring * RES9_CENTER_SPACING_FLOOR_M - RES9_CELL_RADIUS_CEILING_M;
118
+ if (closestPossibleM > Math.min(radiusM, best?.distanceM ?? radiusM))
119
+ break;
120
+ // gridDisk(origin, ring) returns the WHOLE disk out to `ring`; diffing against what's already been
121
+ // probed derives just this ring's new cells (the POILookup pattern).
122
+ const diskCells = gridDisk(origin, ring);
123
+ const newCells = [];
124
+ for (const cell of diskCells) {
125
+ if (!seenCells.has(cell)) {
126
+ seenCells.add(cell);
127
+ newCells.push(shortCellToInt(cell));
128
+ }
129
+ }
130
+ for (let i = 0; i < newCells.length; i += CELL_PROBE_CHUNK) {
131
+ const chunk = newCells.slice(i, i + CELL_PROBE_CHUNK);
132
+ const placeholders = chunk.map(() => "?").join(", ");
133
+ // Prepared fresh per chunk arity — a cold, per-call path, same posture as POILookup's batched hydration.
134
+ const rows = allRows(this.#db.prepare(`SELECT uprn, lat, lon FROM uprn WHERE h3_cell IN (${placeholders})`), ...chunk);
135
+ for (const row of rows) {
136
+ const distanceM = haversineKm(latitude, longitude, row.lat, row.lon) * 1000;
137
+ if (distanceM <= radiusM && (best === null || distanceM < best.distanceM)) {
138
+ best = { uprn: row.uprn, latitude: row.lat, longitude: row.lon, distanceM };
139
+ }
140
+ }
141
+ }
142
+ }
143
+ return best;
144
+ }
145
+ [Symbol.dispose]() {
146
+ this.#resources[Symbol.dispose]();
147
+ }
148
+ }
149
+ //# sourceMappingURL=lookup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookup.js","sourceRoot":"","sources":["../../lib/uprn/lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAA;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,GAAG,CAAA;AAEvC;;;GAGG;AACH,MAAM,0BAA0B,GAAG,GAAG,CAAA;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAA;AAE/C;;GAEG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAkC5B;;;GAGG;AACH,MAAM,OAAO,UAAU;IACtB,GAAG,CAA8B;IACjC;;;OAGG;IACM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IAE3C;;OAEG;IACM,gBAAgB,CAAuC;IAEhE,YAAY,IAAoB;QAC/B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAA;QACzB,CAAC;aAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,cAAc,CAAe,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACxG,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QACjE,CAAC;QAED,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,0CAA0C,CAAC,CAAA;IACrF,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,IAAY;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAA6C,CAAA;QAEvF,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9D,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,QAAgB,EAAE,SAAiB,EAAE,OAAe;QAC/D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,UAAU,CAAC,mEAAmE,OAAO,EAAE,CAAC,CAAA;QACnG,CAAC;QAED,IAAI,OAAO,GAAG,yBAAyB,EAAE,CAAC;YACzC,MAAM,IAAI,UAAU,CAAC,wBAAwB,OAAO,gBAAgB,yBAAyB,QAAQ,CAAC,CAAA;QACvG,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;QACnC,IAAI,IAAI,GAA0B,IAAI,CAAA;QAEtC,wGAAwG;QACxG,yBAAyB;QACzB,KAAK,IAAI,IAAI,GAAG,CAAC,GAAI,IAAI,EAAE,EAAE,CAAC;YAC7B,mGAAmG;YACnG,6FAA6F;YAC7F,MAAM,gBAAgB,GAAG,IAAI,GAAG,2BAA2B,GAAG,0BAA0B,CAAA;YAExF,IAAI,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC;gBAAE,MAAK;YAE3E,mGAAmG;YACnG,qEAAqE;YACrE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAa,CAAA;YACpD,MAAM,QAAQ,GAAa,EAAE,CAAA;YAE7B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1B,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;oBACnB,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,IAAc,CAAC,CAAC,CAAA;gBAC9C,CAAC;YACF,CAAC;YAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,gBAAgB,EAAE,CAAC;gBAC5D,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAA;gBACrD,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAEpD,yGAAyG;gBACzG,MAAM,IAAI,GAAG,OAAO,CACnB,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,qDAAqD,YAAY,GAAG,CAAC,EACtF,GAAG,KAAK,CACR,CAAA;gBAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;oBACxB,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;oBAE3E,IAAI,SAAS,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;wBAC3E,IAAI,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,CAAA;oBAC5E,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,CAAC,MAAM,CAAC,OAAO,CAAC;QACf,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;IAClC,CAAC;CACD"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Typed schema for `uprn.db` — the OS Open UPRN spatial layer: every GB Unique Property Reference
7
+ * Number with its WGS84 point, so mailwoman results can carry UPRN as an interoperability key
8
+ * beside our own `@mailwoman/address-id`. One rowid table keyed `uprn INTEGER PRIMARY KEY` (the
9
+ * rowid alias — the optimal shape for an integer-PK point table; `WITHOUT ROWID` buys nothing
10
+ * here), plus a secondary res-9 `h3_cell` index for the bounded nearest-point probe.
11
+ *
12
+ * ## Coordinates are OS's own WGS84 columns
13
+ *
14
+ * The source CSV publishes BOTH coordinate systems per row — OSGB36 eastings/northings AND WGS84
15
+ * `LATITUDE`/`LONGITUDE`. This layer stores OS's own lat/lon verbatim and never reconverts from
16
+ * eastings: `@mailwoman/spatial`'s `osgb36ToWGS84` is a 7-parameter Helmert with a measured p95 of
17
+ * 4.18 m, and re-deriving what the publisher already computed (with OSTN15, exactly) would replace
18
+ * their answer with a strictly worse one.
19
+ *
20
+ * ## Why `h3_cell` exists at all
21
+ *
22
+ * The layer contract requires every domain row to be addressable by at least one spine key —
23
+ * `writeLayerManifest` throws on a manifest that declares none — and UPRN is its own id space, not
24
+ * H3/WOF/address-id/street. The res-9 short cell (`shortCellToInt`, the same packing as poi.db and
25
+ * the OSM situs extracts) is the spine that fits a point table, and its index doubles as the
26
+ * `nearestUPRN` ring probe.
27
+ *
28
+ * The DB also embeds the layer-contract tables from `@mailwoman/core/layers`; the builder
29
+ * (`packages/mailwoman/lib/gazetteer-pipeline/uprn-layer.ts`) writes the manifest and per-res-6-cell
30
+ * coverage.
31
+ */
32
+ import type { LayerContractDatabase } from "@mailwoman/core/layers";
33
+ import { type H3Cell } from "@mailwoman/spatial";
34
+ import type { Kysely } from "kysely";
35
+ /**
36
+ * Resolution the `uprn` table's `h3_cell` column is keyed at — the shared layer-spine resolution (poi.db, the OSM situs
37
+ * extracts).
38
+ */
39
+ export declare const UPRN_H3_RESOLUTION = 9;
40
+ /**
41
+ * Resolution of the layer's `layer_coverage` cells — coarse, per the contract (matches poi.db).
42
+ */
43
+ export declare const UPRN_COVERAGE_H3_RESOLUTION = 6;
44
+ /**
45
+ * One UPRN point. `uprn` is the rowid alias, so the primary probe (`coordinateOf`) is a rowid B-tree hit.
46
+ */
47
+ export interface UPRNTable {
48
+ /**
49
+ * The Unique Property Reference Number — up to 12 digits, so always within `Number.MAX_SAFE_INTEGER`.
50
+ */
51
+ uprn: number;
52
+ /**
53
+ * WGS84 latitude, as OS published it (never reconverted from eastings — see the module docstring).
54
+ */
55
+ lat: number;
56
+ /**
57
+ * WGS84 longitude, as OS published it.
58
+ */
59
+ lon: number;
60
+ /**
61
+ * 48-bit short H3 cell at {@link UPRN_H3_RESOLUTION} (`uprnH3Cell`) — the layer-contract spine key and the
62
+ * `nearestUPRN` probe index.
63
+ */
64
+ h3_cell: number;
65
+ }
66
+ /**
67
+ * Build-provenance key/value pairs the fixed `layer_manifest` columns have no room for: quality-drop counts, the header
68
+ * as found, the upstream licence text verbatim (the Code-Point provenance discipline).
69
+ */
70
+ export interface UPRNMetaTable {
71
+ key: string;
72
+ value: string;
73
+ }
74
+ export interface UPRNDatabase extends LayerContractDatabase {
75
+ uprn: UPRNTable;
76
+ uprn_meta: UPRNMetaTable;
77
+ }
78
+ /**
79
+ * The full res-9 cell for a UPRN point — the ONE derivation both the builder and every consumer share, so a fixture
80
+ * built by a test and a row built by the real ingest can never disagree on which cell a coordinate keys to.
81
+ */
82
+ export declare function uprnFullCell(latitude: number, longitude: number): H3Cell;
83
+ /**
84
+ * The `h3_cell` column value for a UPRN point: {@link uprnFullCell} packed to the shared 48-bit short-cell integer.
85
+ */
86
+ export declare function uprnH3Cell(latitude: number, longitude: number): number;
87
+ export declare function createUPRNTable(db: Kysely<UPRNDatabase>): Promise<void>;
88
+ export declare function createUPRNMetaTable(db: Kysely<UPRNDatabase>): Promise<void>;
89
+ /**
90
+ * Secondary index for the `nearestUPRN` ring probe. Builders call this AFTER the bulk load (index-after-load).
91
+ */
92
+ export declare function createUPRNIndexes(db: Kysely<UPRNDatabase>): Promise<void>;
93
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../lib/uprn/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AACnE,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEpC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC;;GAEG;AACH,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAa,SAAQ,qBAAqB;IAC1D,IAAI,EAAE,SAAS,CAAA;IACf,SAAS,EAAE,aAAa,CAAA;CACxB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,MAAM,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Typed schema for `uprn.db` — the OS Open UPRN spatial layer: every GB Unique Property Reference
7
+ * Number with its WGS84 point, so mailwoman results can carry UPRN as an interoperability key
8
+ * beside our own `@mailwoman/address-id`. One rowid table keyed `uprn INTEGER PRIMARY KEY` (the
9
+ * rowid alias — the optimal shape for an integer-PK point table; `WITHOUT ROWID` buys nothing
10
+ * here), plus a secondary res-9 `h3_cell` index for the bounded nearest-point probe.
11
+ *
12
+ * ## Coordinates are OS's own WGS84 columns
13
+ *
14
+ * The source CSV publishes BOTH coordinate systems per row — OSGB36 eastings/northings AND WGS84
15
+ * `LATITUDE`/`LONGITUDE`. This layer stores OS's own lat/lon verbatim and never reconverts from
16
+ * eastings: `@mailwoman/spatial`'s `osgb36ToWGS84` is a 7-parameter Helmert with a measured p95 of
17
+ * 4.18 m, and re-deriving what the publisher already computed (with OSTN15, exactly) would replace
18
+ * their answer with a strictly worse one.
19
+ *
20
+ * ## Why `h3_cell` exists at all
21
+ *
22
+ * The layer contract requires every domain row to be addressable by at least one spine key —
23
+ * `writeLayerManifest` throws on a manifest that declares none — and UPRN is its own id space, not
24
+ * H3/WOF/address-id/street. The res-9 short cell (`shortCellToInt`, the same packing as poi.db and
25
+ * the OSM situs extracts) is the spine that fits a point table, and its index doubles as the
26
+ * `nearestUPRN` ring probe.
27
+ *
28
+ * The DB also embeds the layer-contract tables from `@mailwoman/core/layers`; the builder
29
+ * (`packages/mailwoman/lib/gazetteer-pipeline/uprn-layer.ts`) writes the manifest and per-res-6-cell
30
+ * coverage.
31
+ */
32
+ import { shortCellToInt } from "@mailwoman/spatial";
33
+ import { latLngToCell } from "h3-js";
34
+ /**
35
+ * Resolution the `uprn` table's `h3_cell` column is keyed at — the shared layer-spine resolution (poi.db, the OSM situs
36
+ * extracts).
37
+ */
38
+ export const UPRN_H3_RESOLUTION = 9;
39
+ /**
40
+ * Resolution of the layer's `layer_coverage` cells — coarse, per the contract (matches poi.db).
41
+ */
42
+ export const UPRN_COVERAGE_H3_RESOLUTION = 6;
43
+ /**
44
+ * The full res-9 cell for a UPRN point — the ONE derivation both the builder and every consumer share, so a fixture
45
+ * built by a test and a row built by the real ingest can never disagree on which cell a coordinate keys to.
46
+ */
47
+ export function uprnFullCell(latitude, longitude) {
48
+ return latLngToCell(latitude, longitude, UPRN_H3_RESOLUTION);
49
+ }
50
+ /**
51
+ * The `h3_cell` column value for a UPRN point: {@link uprnFullCell} packed to the shared 48-bit short-cell integer.
52
+ */
53
+ export function uprnH3Cell(latitude, longitude) {
54
+ return shortCellToInt(uprnFullCell(latitude, longitude));
55
+ }
56
+ export async function createUPRNTable(db) {
57
+ await db.schema
58
+ .createTable("uprn")
59
+ .addColumn("uprn", "integer", (c) => c.primaryKey())
60
+ .addColumn("lat", "real", (c) => c.notNull())
61
+ .addColumn("lon", "real", (c) => c.notNull())
62
+ .addColumn("h3_cell", "integer", (c) => c.notNull())
63
+ .execute();
64
+ }
65
+ export async function createUPRNMetaTable(db) {
66
+ await db.schema
67
+ .createTable("uprn_meta")
68
+ .addColumn("key", "text", (c) => c.primaryKey())
69
+ .addColumn("value", "text", (c) => c.notNull())
70
+ .execute();
71
+ }
72
+ /**
73
+ * Secondary index for the `nearestUPRN` ring probe. Builders call this AFTER the bulk load (index-after-load).
74
+ */
75
+ export async function createUPRNIndexes(db) {
76
+ await db.schema.createIndex("uprn_h3_cell").on("uprn").column("h3_cell").execute();
77
+ }
78
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../lib/uprn/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAGpC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAEnC;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAA;AAuC5C;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,SAAiB;IAC/D,OAAO,YAAY,CAAC,QAAQ,EAAE,SAAS,EAAE,kBAAkB,CAAW,CAAA;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,SAAiB;IAC7D,OAAO,cAAc,CAAC,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAA;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAwB;IAC7D,MAAM,EAAE,CAAC,MAAM;SACb,WAAW,CAAC,MAAM,CAAC;SACnB,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;SACnD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC5C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC5C,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SACnD,OAAO,EAAE,CAAA;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAwB;IACjE,MAAM,EAAE,CAAC,MAAM;SACb,WAAW,CAAC,WAAW,CAAC;SACxB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;SAC/C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;SAC9C,OAAO,EAAE,CAAA;AACZ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EAAwB;IAC/D,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAA;AACnF,CAAC"}
@@ -0,0 +1,299 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ * Shared development tooling for weights overlays: the symlink primitives every overlay linker uses, the
6
+ * placetype-pair index build, and the manifest form ({@link materializeDevOverlay}) each locale's
7
+ * `scripts/link-dev-weights.ts` declares itself in.
8
+ */
9
+ /**
10
+ * Replicate `ln -sf SRC DEST` ATOMICALLY: symlink under a temp name, then rename over the destination. A plain
11
+ * unlink-then-symlink leaves a no-file window that concurrent vitest workers can hit mid-suite — bit CI on 2026-07-24.
12
+ * rename(2) replaces the destination atomically.
13
+ */
14
+ export declare function linkForce(src: string, dest: string): Promise<void>;
15
+ /**
16
+ * Remove a leftover local file/symlink so the #1179 base-weights fallback engages.
17
+ */
18
+ export declare function removeIfPresent(dest: string): Promise<void>;
19
+ /**
20
+ * Symlink one soft-feed sibling into an overlay, warning rather than failing when the source is absent.
21
+ *
22
+ * Every one of these artifacts is OPTIONAL by design — the runtime has a fallback for each, so a fresh worktree that
23
+ * has not built the gazetteer still geocodes. That is why the miss prints the consequence instead of throwing: the
24
+ * operator needs to know which channel just resolved OFF, not to have the link step abort.
25
+ */
26
+ export declare function linkSoftFeedSibling(source: string, destination: string, consequenceIfMissing: string): Promise<boolean>;
27
+ /**
28
+ * The calibrated pair-index emission bias every shipped artifact is built at today — the R5/R6/R9/R10/R11 bars were all
29
+ * measured at δ=10 (each linker's own docstring carries its locale's receipt).
30
+ */
31
+ export declare const PAIR_INDEX_DELTA = 10;
32
+ /**
33
+ * The decoder transition-entry bonus (TRANSITION-BETA build, 2026-07-24 — operator-approved β=5 from the
34
+ * transition-level probe). en-nz deliberately builds WITHOUT one (unmeasured there): the two magnitudes are calibrated
35
+ * independently, and a locale earning one says nothing about the other.
36
+ */
37
+ export declare const PAIR_INDEX_TRANSITION_BETA = 5;
38
+ /**
39
+ * The WHOLE-EDGE parent-bias magnitude (#46, default-on 2026-08-04) at the verdict's recommended δ=5 — see
40
+ * `docs/records/evals/2026-08-04-pix1-whole-edge-verdict.md`. Only the measured locales (us/gb/nz/fr) pass it; the
41
+ * D-rule's answer to an unmeasured locale is a per-locale absence, not an inherited magnitude.
42
+ */
43
+ export declare const PAIR_INDEX_PARENT_DELTA = 5;
44
+ /**
45
+ * What one pair-index build has to say about itself. Everything else is shared.
46
+ */
47
+ export interface PairIndexOverlay {
48
+ /**
49
+ * Workspace directory name, e.g. `neural-weights-de-de`.
50
+ */
51
+ packageDir: string;
52
+ /**
53
+ * ISO country code passed to `gazetteer pair-index --country`, and the suffix of the built artifact (`de` →
54
+ * `pair-index-de.bin`). NOT the locale tag: `en-in` builds `pair-index-in.bin`.
55
+ */
56
+ country: string;
57
+ /**
58
+ * Calibrated magnitudes the locale's bars were measured at. Baked into the artifact's PIX1 header, which is how the
59
+ * freshness check notices a change to any of them. An ABSENT `transitionBeta`/`parentDelta` means the flag is not
60
+ * passed and the header carries no such key — a real state, distinct from zero (see `PairIndexHeader.parentDelta`).
61
+ * The whole calibration feeds both the build FLAGS and the staleness EXPECTATION, so the two cannot disagree.
62
+ */
63
+ delta: number;
64
+ transitionBeta?: number;
65
+ parentDelta?: number;
66
+ /**
67
+ * Source FILES whose md5s the build records, in the order `gazetteer pair-index` records them. The freshness guard
68
+ * compares EVERY one against the existing header (#1734): a partial comparison leaves the guard blind to the rest,
69
+ * and a stale artifact then keeps reporting itself fresh while the data it was built from has moved. Empty means the
70
+ * build's source cannot be file-hashed (fr's BAN directory) and freshness rests on the magnitudes alone. Default: the
71
+ * WOF admin DB.
72
+ */
73
+ sources?: string[];
74
+ /**
75
+ * Inputs that must exist before a build is attempted — a missing one warns and returns, because a fresh clone has no
76
+ * data root and `yarn test` invokes the linkers to verify auto-resolve. Default: `sources`.
77
+ */
78
+ inputs?: string[];
79
+ /**
80
+ * Extra CLI args naming the build's sources (`--source`, `--borough-db`, `--pairs-jsonl`, `--ban-dir`). Default:
81
+ * `--borough-db <admin db>`.
82
+ */
83
+ extraArgs?: string[];
84
+ /**
85
+ * Refuse to trust an existing artifact smaller than this. fr-fr's guard: a pair index built from the WRONG source can
86
+ * carry matching magnitudes, and size is the one signal the header cannot fake.
87
+ */
88
+ minimumPlausibleBytes?: number;
89
+ }
90
+ /**
91
+ * The header fields a dev-weights freshness guard reads.
92
+ */
93
+ export interface PairIndexHeaderFields {
94
+ delta: number;
95
+ transitionBeta: number | undefined;
96
+ parentDelta: number | undefined;
97
+ schemaVersion: number;
98
+ /**
99
+ * One md5 per source the build read, in fold order. Empty on a header that recorded none.
100
+ */
101
+ sourceMD5s: string[];
102
+ }
103
+ /**
104
+ * Minimal PIX1 header reader — magic + header only, reimplemented so a data-only weights package gains no dependency on
105
+ * `@mailwoman/neural` (which pulls onnxruntime-node) to read a few fields. `neural/pair-index-resolver.ts`'s own header
106
+ * parse is the source of truth this must follow.
107
+ *
108
+ * Shared by the overlay build below AND by the four hand-written base linkers
109
+ * (`neural-weights-{en-us,en-gb,en-nz,fr-fr}/scripts/link-dev-weights.ts`), which each carried their own near-copy
110
+ * before 2026-08-04 — the ×5 clone the taste audit named, and the reason three of them were schema-blind while this one
111
+ * was not.
112
+ */
113
+ export declare function peekPairIndexHeaderFields(path: string): Promise<PairIndexHeaderFields>;
114
+ /**
115
+ * Md5 of `path`, cached in a standard `md5sum`-format sidecar (`<hash> <filename>`) beside it so a multi-gigabyte
116
+ * source is hashed once per change rather than once per linker run. The sidecar is trusted only when at least as new as
117
+ * the source; a missing or stale sidecar recomputes and rewrites, so the cache self-heals.
118
+ *
119
+ * The shared home for the copies the base linkers (`en-us`, `en-gb`, `en-nz`) each carry — new callers import this one.
120
+ */
121
+ export declare function md5FileWithSidecar(path: string): Promise<string>;
122
+ /**
123
+ * The calibrated magnitudes a linker bakes into its artifact. `undefined` means the flag is NOT passed and the header
124
+ * carries no such key — a real state, distinct from zero (see `PairIndexHeader.parentDelta`), so the comparison below
125
+ * is `!==` against `undefined` rather than a truthiness test.
126
+ */
127
+ export interface PairIndexCalibration {
128
+ delta: number;
129
+ transitionBeta?: number;
130
+ parentDelta?: number;
131
+ }
132
+ /**
133
+ * Why an existing `pair-index-*.bin` is stale against `expected`, or `undefined` when its header matches. Covers the
134
+ * FORMAT (schemaVersion) and every calibrated magnitude; source-md5 freshness stays with the caller, because each base
135
+ * linker passes a different set of sources and only it knows what they are.
136
+ *
137
+ * One place so a magnitude added to the header cannot be checked by some linkers and not others — which is exactly how
138
+ * three of the four base linkers ended up unable to notice a schema bump.
139
+ */
140
+ export declare function pairIndexStaleReason(header: PairIndexHeaderFields, expected: PairIndexCalibration): string | undefined;
141
+ /**
142
+ * The PIX1 schema this tree's reader requires. MUST equal `KNOWN_SCHEMA_VERSION` in `neural/pair-index-resolver.ts` —
143
+ * they are two ends of one fact, and this copy exists only because a data-only overlay must not gain a dependency on
144
+ * `@mailwoman/neural` (onnxruntime-node) to read one header field. Bump BOTH in the same commit; a schema bump that
145
+ * leaves this behind makes every dev checkout rebuild-loop or serve an artifact the runtime refuses.
146
+ *
147
+ * The freshness guard must compare it: a guard that checks only delta + source md5 reads a format-obsolete binary as
148
+ * "current" and leaves every dev checkout with artifacts the runtime refuses — the R5 freshness-guard lesson, format
149
+ * edition. Also compared by the four hand-written base linkers (`neural-weights-{en-us,en-gb,en-nz,fr-fr}`), which
150
+ * import this constant rather than re-typing the number.
151
+ */
152
+ export declare const REQUIRED_PAIR_INDEX_SCHEMA = 3;
153
+ /**
154
+ * Warn when the per-locale FST a linker just symlinked was built from a DIFFERENT admin database than the one on disk
155
+ * now.
156
+ *
157
+ * WHY IT WARNS RATHER THAN REBUILDS, unlike its pair-index sibling above. A pair index is seconds of work and the
158
+ * linker owns its whole recipe. A locale FST is a multi-minute build whose output goes to a STAGING dir on purpose —
159
+ * the swap into `fst-per-locale/` is operator-approved after the battery, because an FST changes decoder behaviour and
160
+ * the D-rule does not let that land unmeasured. So the guard's job is to make the drift impossible to miss, and to name
161
+ * the command that starts fixing it. It is also why a stale FST is never fatal: the artifact is a decode-time bias
162
+ * list, and a dev tree must still run.
163
+ *
164
+ * The source-side half of the comparison lives here rather than in `fst-freshness.ts` for the same reason
165
+ * `pairIndexStaleReason` splits: only the caller knows which database it built against. All three FST-linking base
166
+ * packages build against the same one, so they share this rather than each pinning it.
167
+ */
168
+ export declare function warnIfFSTStale(fstPath: string, locale: string): Promise<void>;
169
+ /**
170
+ * Symlink the per-locale FST gazetteer (`fst-<locale>.bin`) from the shared build area
171
+ * (`$MAILWOMAN_DATA_ROOT/wof/fst-per-locale/`) into an overlay so `resolveWeights` surfaces `fstPath` in dev and the
172
+ * runtime pipeline can auto-wire the gazetteer + street-context check, then run {@link warnIfFSTStale} on the linked
173
+ * artifact. The publish flow stages the real binary (release-sequenced).
174
+ */
175
+ export declare function linkLocaleFST(destDir: string, locale: string): Promise<void>;
176
+ /**
177
+ * Symlink the sealed locale-general street-morphology FST (`$MAILWOMAN_DATA_ROOT/wof/fst-street-morphology.bin`,
178
+ * `mailwoman gazetteer build street-morphology`) into an overlay so `resolveWeights` surfaces `streetMorphologyPath` in
179
+ * dev and the street-context check (#1315) deserializes the artifact instead of rebuilding from the libpostal
180
+ * dictionaries per process. Missing is non-fatal — the runtime loader's dictionary-build fallback covers it.
181
+ */
182
+ export declare function linkStreetMorphologyFST(destDir: string): Promise<void>;
183
+ /**
184
+ * Build `pair-index-<country>.bin` into the overlay, skipping the work when the artifact on disk was already built at
185
+ * these magnitudes FROM the sources on disk (see {@link pairIndexIsFresh}). The calibration object drives both the
186
+ * staleness expectation and the CLI flags, so a magnitude cannot be checked by the guard and dropped from the build.
187
+ *
188
+ * Exits non-zero on a failed build. Missing INPUTS (an unbuilt CLI, an absent source) warn and return instead: a fresh
189
+ * clone has neither, and `yarn test` invokes this to verify auto-resolve, so a hard failure there would be a failure to
190
+ * have run a build yet rather than a real fault.
191
+ */
192
+ export declare function buildPairIndexOverlay(overlay: PairIndexOverlay): Promise<void>;
193
+ /**
194
+ * A soft-feed sibling an overlay links: where it comes from, the name it takes in the overlay, and the consequence line
195
+ * printed when the source is missing (the link is warn-and-continue; the channel resolves OFF).
196
+ */
197
+ export interface SoftFeedLink {
198
+ source: string;
199
+ name: string;
200
+ consequenceIfMissing: string;
201
+ }
202
+ /**
203
+ * The committed soft-feed lexicons as links, by channel, read from `release.config.json` so the filename a manifest
204
+ * links is the one the release ships. `streetType` is offered for completeness; the manifests link the evidence
205
+ * lexicons by the generation their CARD names instead (`evidenceLexiconsFromCard`).
206
+ */
207
+ export declare function committedSoftFeedLinks(): Promise<{
208
+ anchor: SoftFeedLink;
209
+ country: SoftFeedLink;
210
+ streetType?: SoftFeedLink;
211
+ }>;
212
+ /**
213
+ * The slice of a weights package's committed `model-card.json` the dev materialization reads: the shipped digests the
214
+ * release re-verifies against the published tarball, and the channel requirements that name evidence lexicons.
215
+ */
216
+ export interface WeightsCard {
217
+ files_md5?: Record<string, string>;
218
+ requires?: Record<string, {
219
+ lexicon?: string;
220
+ span_mode?: string;
221
+ } | undefined>;
222
+ }
223
+ /**
224
+ * What one locale's `scripts/link-dev-weights.ts` declares, so an overlay is a manifest plus a call rather than a
225
+ * script cloned from a sibling. Every step is optional and runs only when named, in a fixed order: model pair,
226
+ * soft-feed siblings, card-named evidence lexicons, postcode binary, pair index, FSTs.
227
+ */
228
+ export interface DevOverlayManifest {
229
+ /**
230
+ * The overlay's locale tag, lower-case. The workspace is `neural-weights-<locale>` and the artifacts land in
231
+ * `$MAILWOMAN_DATA_ROOT/weights/<locale>/`, never in the tracked package: the binaries are not in git, so
232
+ * materializing them there made a fresh worktree unable to geocode, made `yarn test` mutate a tracked directory, and
233
+ * put a symlink into a publish tarball (`YN0035`).
234
+ */
235
+ locale: string;
236
+ /**
237
+ * What happens to `model.onnx` + `tokenizer.model`. `link`: the pair is symlinked from the paths
238
+ * `release.config.json`'s `weights` block names under the data root (`$MAILWOMAN_DEV_MODEL` /
239
+ * `$MAILWOMAN_DEV_TOKENIZER` override them), and when `digestCard` names a workspace the linked default bytes must
240
+ * match that workspace's card `files_md5` — the #397 drift guard, which fails loud instead of grading the wrong
241
+ * model; an override skips the check and says so. `inherit`: the package declares `mailwoman.baseWeights`, so any
242
+ * local pair is REMOVED — a stale local file shadows the base fallback and silently serves outdated bytes. Omitted:
243
+ * the pair is left to `packages/release-kit/lib/weights/link-weights-overlay.ts`, the recipe writer.
244
+ */
245
+ model?: {
246
+ kind: "link";
247
+ digestCard?: string;
248
+ } | {
249
+ kind: "inherit";
250
+ } | {
251
+ kind: "char";
252
+ family: string;
253
+ };
254
+ /**
255
+ * Soft-feed siblings linked warn-and-continue, in order.
256
+ */
257
+ softFeed?: ReadonlyArray<SoftFeedLink>;
258
+ /**
259
+ * Link the evidence lexicons the overlay's own card names under `requires.<channel>.lexicon`, so the generation comes
260
+ * from the card the loader reads and a card bump moves the artifact with it. `street-type-lexicon-v*.json` is
261
+ * committed under `data/gazetteer/`; `locality-surface-lexicon-v*.json` is 7–13 MB and lives in the data root.
262
+ */
263
+ evidenceLexiconsFromCard?: boolean;
264
+ /**
265
+ * Build `postcode-<country>.bin` from a WOF postcode extract through the compiled `gazetteer postcode-binary` CLI,
266
+ * skipped when already present (it rebuilds in seconds, and the extract is versionless on disk).
267
+ */
268
+ postcodeBinary?: {
269
+ country: string;
270
+ database: string;
271
+ };
272
+ /**
273
+ * The placetype-pair index build, minus `packageDir`, which follows from `locale`.
274
+ */
275
+ pairIndex?: Omit<PairIndexOverlay, "packageDir">;
276
+ /**
277
+ * Link `fst-<locale>.bin` with its freshness warning.
278
+ */
279
+ localeFST?: boolean;
280
+ /**
281
+ * Link the shared street-morphology FST.
282
+ */
283
+ streetMorphologyFST?: boolean;
284
+ }
285
+ /**
286
+ * What a materialized overlay hands back for the locale-specific step a manifest cannot express (en-gb's
287
+ * card-conditional postcode binary is the one that exists).
288
+ */
289
+ export interface DevOverlay {
290
+ destDir: string;
291
+ cli: string;
292
+ card: WeightsCard | undefined;
293
+ }
294
+ /**
295
+ * Materialize one locale's dev overlay from its manifest. The steps run in the order {@link DevOverlayManifest}
296
+ * documents, each independent on disk, and the result carries what a locale-specific step needs afterwards.
297
+ */
298
+ export declare function materializeDevOverlay(manifest: DevOverlayManifest): Promise<DevOverlay>;
299
+ //# sourceMappingURL=weights-overlay-linker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weights-overlay-linker.d.ts","sourceRoot":"","sources":["../lib/weights-overlay-linker.ts"],"names":[],"mappings":"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"}