@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.
- package/README.md +36 -20
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +40 -28
- package/{address-point-schema.ts → lib/address/point-schema.ts} +34 -8
- package/lib/address/point.ts +280 -0
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +13 -8
- package/{build-candidate.ts → lib/build-candidate.ts} +243 -199
- package/{build-slim.ts → lib/build-slim.ts} +153 -168
- package/lib/candidate/alias-bags.ts +56 -0
- package/lib/candidate/ancestors-sidecar.ts +204 -0
- package/lib/candidate/country-display-names.ts +79 -0
- package/lib/candidate/extract-fold.ts +138 -0
- package/lib/candidate/name-roles.ts +238 -0
- package/lib/candidate/own-name.ts +146 -0
- package/lib/candidate/place-attrs.ts +44 -0
- package/lib/candidate-ancestors-schema.ts +195 -0
- package/{candidate-fts.ts → lib/candidate-fts.ts} +7 -5
- package/{candidate-importance.ts → lib/candidate-importance.ts} +54 -57
- package/lib/candidate-lookup.ts +976 -0
- package/{candidate-schema.ts → lib/candidate-schema.ts} +34 -6
- package/lib/candidate-scoring.ts +261 -0
- package/lib/capital-schema.ts +89 -0
- package/lib/capitals.ts +148 -0
- package/{coincident-roles.ts → lib/coincident-roles.ts} +75 -19
- package/{convention.ts → lib/convention/index.ts} +5 -5
- package/lib/convention/schema.ts +72 -0
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +15 -16
- package/lib/currency-backfill.ts +334 -0
- package/lib/env.ts +50 -0
- package/lib/exact-match.ts +113 -0
- package/{sharding.ts → lib/extracts.ts} +63 -60
- package/lib/fst/autocomplete.ts +176 -0
- package/{fst-builder.ts → lib/fst/builder.ts} +30 -27
- package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
- package/lib/fst/format.ts +106 -0
- package/{fst-freshness.ts → lib/fst/freshness.ts} +42 -75
- package/lib/fst/index.ts +14 -0
- package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
- package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
- package/{fst-types.ts → lib/fst/types.ts} +4 -2
- package/{fts.ts → lib/fts/index.ts} +28 -23
- package/{fts-query.ts → lib/fts/query.ts} +2 -2
- package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
- package/lib/geonames/index.ts +8 -0
- package/{geonames-postal.ts → lib/geonames/postal.ts} +16 -15
- package/{index.ts → lib/index.ts} +52 -48
- package/{interpolation.ts → lib/interpolation.ts} +137 -41
- package/lib/lookup.ts +861 -0
- package/{name-score.ts → lib/name-score.ts} +6 -4
- package/lib/nsul/index.ts +8 -0
- package/lib/nsul/lookup.ts +144 -0
- package/lib/nsul/schema.ts +130 -0
- package/{place-importance-schema.ts → lib/place-importance-schema.ts} +70 -22
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +32 -39
- package/{poi-schema.ts → lib/poi/schema.ts} +10 -6
- package/lib/polygon-schema.ts +47 -0
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +15 -21
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +4 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/lib/primary-preference.ts +226 -0
- package/lib/proximity-rerank.ts +120 -0
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/lib/region-keys.ts +144 -0
- package/{reverse.ts → lib/reverse.ts} +45 -56
- package/{schema.ts → lib/schema.ts} +11 -1
- package/lib/search-fetch.ts +257 -0
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/lib/sqlite-utils.ts +83 -0
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +12 -6
- package/{street-centroid.ts → lib/street/centroid.ts} +26 -28
- package/lib/street/index.ts +13 -0
- package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
- package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
- package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
- package/lib/street/normalize.ts +572 -0
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +13 -8
- package/{types.ts → lib/types.ts} +49 -9
- package/{unified-schema.ts → lib/unified-schema.ts} +21 -25
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/lib/uprn/lookup.ts +206 -0
- package/lib/uprn/schema.ts +124 -0
- package/lib/weights-overlay-linker.ts +878 -0
- package/out/address/index.d.ts +9 -0
- package/out/address/index.d.ts.map +1 -0
- package/out/address/index.js +9 -0
- package/out/address/index.js.map +1 -0
- package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +11 -10
- package/out/address/point-interpolation.d.ts.map +1 -0
- package/out/{address-point-interpolation.js → address/point-interpolation.js} +29 -23
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +30 -10
- package/out/address/point-schema.d.ts.map +1 -0
- package/out/{address-point-schema.js → address/point-schema.js} +7 -3
- package/out/address/point-schema.js.map +1 -0
- package/out/{address-point.d.ts → address/point.d.ts} +16 -8
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +191 -0
- package/out/address/point.js.map +1 -0
- package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
- package/out/ancestry/backfill.d.ts.map +1 -0
- package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
- package/out/ancestry/backfill.js.map +1 -0
- package/out/{ancestry.d.ts → ancestry/index.d.ts} +6 -5
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +7 -7
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +88 -7
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +145 -149
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +5 -5
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +127 -142
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +19 -0
- package/out/candidate/alias-bags.d.ts.map +1 -0
- package/out/candidate/alias-bags.js +39 -0
- package/out/candidate/alias-bags.js.map +1 -0
- package/out/candidate/ancestors-sidecar.d.ts +32 -0
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -0
- package/out/candidate/ancestors-sidecar.js +140 -0
- package/out/candidate/ancestors-sidecar.js.map +1 -0
- package/out/candidate/country-display-names.d.ts +35 -0
- package/out/candidate/country-display-names.d.ts.map +1 -0
- package/out/candidate/country-display-names.js +59 -0
- package/out/candidate/country-display-names.js.map +1 -0
- package/out/candidate/extract-fold.d.ts +32 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/extract-fold.js +104 -0
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +57 -0
- package/out/candidate/name-roles.d.ts.map +1 -0
- package/out/candidate/name-roles.js +166 -0
- package/out/candidate/name-roles.js.map +1 -0
- package/out/candidate/own-name.d.ts +50 -0
- package/out/candidate/own-name.d.ts.map +1 -0
- package/out/candidate/own-name.js +132 -0
- package/out/candidate/own-name.js.map +1 -0
- package/out/candidate/place-attrs.d.ts +43 -0
- package/out/candidate/place-attrs.d.ts.map +1 -0
- package/out/candidate/place-attrs.js +15 -0
- package/out/candidate/place-attrs.js.map +1 -0
- package/out/candidate-ancestors-schema.d.ts +150 -0
- package/out/candidate-ancestors-schema.d.ts.map +1 -0
- package/out/candidate-ancestors-schema.js +123 -0
- package/out/candidate-ancestors-schema.js.map +1 -0
- package/out/candidate-fts.d.ts +7 -5
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +5 -3
- package/out/candidate-fts.js.map +1 -1
- package/out/candidate-importance.d.ts +16 -16
- package/out/candidate-importance.d.ts.map +1 -1
- package/out/candidate-importance.js +47 -52
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +31 -52
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +380 -172
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +31 -7
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js +3 -0
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +34 -0
- package/out/candidate-scoring.d.ts.map +1 -0
- package/out/candidate-scoring.js +196 -0
- package/out/candidate-scoring.js.map +1 -0
- package/out/capital-schema.d.ts +51 -0
- package/out/capital-schema.d.ts.map +1 -0
- package/out/capital-schema.js +63 -0
- package/out/capital-schema.js.map +1 -0
- package/out/capitals.d.ts +69 -0
- package/out/capitals.d.ts.map +1 -0
- package/out/capitals.js +98 -0
- package/out/capitals.js.map +1 -0
- package/out/coincident-roles.d.ts +12 -4
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +43 -11
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +5 -5
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +4 -4
- package/out/convention/index.js.map +1 -0
- package/out/convention/schema.d.ts +51 -0
- package/out/convention/schema.d.ts.map +1 -0
- package/out/convention/schema.js +34 -0
- package/out/convention/schema.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +8 -8
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +6 -10
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +90 -0
- package/out/currency-backfill.d.ts.map +1 -0
- package/out/currency-backfill.js +196 -0
- package/out/currency-backfill.js.map +1 -0
- package/out/env.d.ts +43 -0
- package/out/env.d.ts.map +1 -0
- package/out/env.js +48 -0
- package/out/env.js.map +1 -0
- package/out/exact-match.d.ts +25 -0
- package/out/exact-match.d.ts.map +1 -0
- package/out/exact-match.js +88 -0
- package/out/exact-match.js.map +1 -0
- package/out/extracts.d.ts +114 -0
- package/out/extracts.d.ts.map +1 -0
- package/out/{sharding.js → extracts.js} +38 -38
- package/out/extracts.js.map +1 -0
- package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +13 -13
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/fst/autocomplete.js +113 -0
- package/out/fst/autocomplete.js.map +1 -0
- package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
- package/out/fst/builder.d.ts.map +1 -0
- package/out/{fst-builder.js → fst/builder.js} +24 -24
- package/out/fst/builder.js.map +1 -0
- package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -0
- package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
- package/out/fst/deserialize-web.js.map +1 -0
- package/out/fst/format.d.ts +80 -0
- package/out/fst/format.d.ts.map +1 -0
- package/out/fst/format.js +91 -0
- package/out/fst/format.js.map +1 -0
- package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +11 -14
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +42 -74
- package/out/fst/freshness.js.map +1 -0
- package/out/fst/index.d.ts +14 -0
- package/out/fst/index.d.ts.map +1 -0
- package/out/fst/index.js +14 -0
- package/out/fst/index.js.map +1 -0
- package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
- package/out/fst/matcher.d.ts.map +1 -0
- package/out/{fst-matcher.js → fst/matcher.js} +1 -1
- package/out/fst/matcher.js.map +1 -0
- package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
- package/out/fst/serialize.d.ts.map +1 -0
- package/out/{fst-serialize.js → fst/serialize.js} +18 -98
- package/out/fst/serialize.js.map +1 -0
- package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
- package/out/fst/types.d.ts.map +1 -0
- package/out/{fst-types.js → fst/types.js} +1 -1
- package/out/fst/types.js.map +1 -0
- package/out/{fts.d.ts → fts/index.d.ts} +20 -13
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +20 -15
- package/out/fts/index.js.map +1 -0
- package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
- package/out/fts/query.d.ts.map +1 -0
- package/out/{fts-query.js → fts/query.js} +2 -2
- package/out/fts/query.js.map +1 -0
- package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
- package/out/geonames/aliases.d.ts.map +1 -0
- package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
- package/out/geonames/aliases.js.map +1 -0
- package/out/geonames/index.d.ts +8 -0
- package/out/geonames/index.d.ts.map +1 -0
- package/out/geonames/index.js +8 -0
- package/out/geonames/index.js.map +1 -0
- package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +12 -10
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +11 -11
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -31
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -24
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +18 -9
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +108 -36
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +25 -25
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +174 -558
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts +0 -10
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js +6 -4
- package/out/name-score.js.map +1 -1
- package/out/nsul/index.d.ts +8 -0
- package/out/nsul/index.d.ts.map +1 -0
- package/out/nsul/index.js +8 -0
- package/out/nsul/index.js.map +1 -0
- package/out/nsul/lookup.d.ts +83 -0
- package/out/nsul/lookup.d.ts.map +1 -0
- package/out/nsul/lookup.js +80 -0
- package/out/nsul/lookup.js.map +1 -0
- package/out/nsul/schema.d.ts +100 -0
- package/out/nsul/schema.d.ts.map +1 -0
- package/out/nsul/schema.js +78 -0
- package/out/nsul/schema.js.map +1 -0
- package/out/place-importance-schema.d.ts +47 -10
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +56 -10
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/index.d.ts +8 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +8 -0
- package/out/poi/index.js.map +1 -0
- package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
- package/out/poi/lookup.d.ts.map +1 -0
- package/out/{poi-lookup.js → poi/lookup.js} +24 -29
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +10 -6
- package/out/poi/schema.d.ts.map +1 -0
- package/out/{poi-schema.js → poi/schema.js} +1 -1
- package/out/poi/schema.js.map +1 -0
- package/out/polygon-schema.d.ts +37 -0
- package/out/polygon-schema.d.ts.map +1 -0
- package/out/polygon-schema.js +23 -0
- package/out/polygon-schema.js.map +1 -0
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +7 -6
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +12 -16
- package/out/postal/city-alias-lookup.js.map +1 -0
- package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
- package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
- package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
- package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
- package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +4 -3
- package/out/postal/city-candidate-schema.d.ts.map +1 -0
- package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
- package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
- package/out/postal/index.d.ts +9 -0
- package/out/postal/index.d.ts.map +1 -0
- package/out/postal/index.js +9 -0
- package/out/postal/index.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +10 -10
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +13 -13
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +133 -0
- package/out/primary-preference.d.ts.map +1 -0
- package/out/primary-preference.js +146 -0
- package/out/primary-preference.js.map +1 -0
- package/out/proximity-rerank.d.ts +77 -0
- package/out/proximity-rerank.d.ts.map +1 -0
- package/out/proximity-rerank.js +86 -0
- package/out/proximity-rerank.js.map +1 -0
- package/out/ranking-weights.d.ts +15 -3
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +21 -3
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +47 -0
- package/out/region-keys.d.ts.map +1 -0
- package/out/region-keys.js +121 -0
- package/out/region-keys.js.map +1 -0
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +23 -35
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +10 -1
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +59 -0
- package/out/search-fetch.d.ts.map +1 -0
- package/out/search-fetch.js +184 -0
- package/out/search-fetch.js.map +1 -0
- package/out/sqlite-convention-source.d.ts +7 -7
- package/out/sqlite-convention-source.d.ts.map +1 -1
- package/out/sqlite-convention-source.js +5 -5
- package/out/sqlite-convention-source.js.map +1 -1
- package/out/sqlite-utils.d.ts +24 -6
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +24 -7
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +12 -7
- package/out/street/centroid-schema.d.ts.map +1 -0
- package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
- package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
- package/out/{street-centroid.d.ts → street/centroid.d.ts} +6 -6
- package/out/street/centroid.d.ts.map +1 -0
- package/out/{street-centroid.js → street/centroid.js} +18 -24
- package/out/street/centroid.js.map +1 -0
- package/out/street/index.d.ts +13 -0
- package/out/street/index.d.ts.map +1 -0
- package/out/street/index.js +13 -0
- package/out/street/index.js.map +1 -0
- package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
- package/out/street/morphology-fst-builder.d.ts.map +1 -0
- package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
- package/out/street/morphology-fst-builder.js.map +1 -0
- package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
- package/out/street/morphology-fst-loader.d.ts.map +1 -0
- package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
- package/out/street/morphology-fst-loader.js.map +1 -0
- package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
- package/out/street/name-lookup.d.ts.map +1 -0
- package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
- package/out/street/name-lookup.js.map +1 -0
- package/out/street/normalize.d.ts +179 -0
- package/out/street/normalize.d.ts.map +1 -0
- package/out/street/normalize.js +457 -0
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +13 -9
- package/out/street/segment-schema.d.ts.map +1 -0
- package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
- package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
- package/out/types.d.ts +49 -9
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +6 -5
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +16 -19
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +53 -0
- package/out/uprn/existence.d.ts.map +1 -0
- package/out/uprn/existence.js +61 -0
- package/out/uprn/existence.js.map +1 -0
- package/out/uprn/index.d.ts +9 -0
- package/out/uprn/index.d.ts.map +1 -0
- package/out/uprn/index.js +9 -0
- package/out/uprn/index.js.map +1 -0
- package/out/uprn/lookup.d.ts +85 -0
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/uprn/lookup.js +149 -0
- package/out/uprn/lookup.js.map +1 -0
- package/out/uprn/schema.d.ts +93 -0
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/uprn/schema.js +78 -0
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +299 -0
- package/out/weights-overlay-linker.d.ts.map +1 -0
- package/out/weights-overlay-linker.js +511 -0
- package/out/weights-overlay-linker.js.map +1 -0
- package/package.json +622 -154
- package/address-point.ts +0 -125
- package/candidate-lookup.ts +0 -720
- package/fst-autocomplete.ts +0 -204
- package/geo.ts +0 -121
- package/lookup.ts +0 -1354
- package/out/address-point-interpolation.d.ts.map +0 -1
- package/out/address-point-interpolation.js.map +0 -1
- package/out/address-point-schema.d.ts.map +0 -1
- package/out/address-point-schema.js.map +0 -1
- package/out/address-point.d.ts.map +0 -1
- package/out/address-point.js +0 -84
- package/out/address-point.js.map +0 -1
- package/out/ancestry-backfill.d.ts.map +0 -1
- package/out/ancestry-backfill.js.map +0 -1
- package/out/ancestry.d.ts.map +0 -1
- package/out/ancestry.js.map +0 -1
- package/out/convention.d.ts.map +0 -1
- package/out/convention.js.map +0 -1
- package/out/fst-autocomplete.d.ts.map +0 -1
- package/out/fst-autocomplete.js +0 -130
- package/out/fst-autocomplete.js.map +0 -1
- package/out/fst-builder.d.ts.map +0 -1
- package/out/fst-builder.js.map +0 -1
- package/out/fst-deserialize-web.d.ts.map +0 -1
- package/out/fst-deserialize-web.js.map +0 -1
- package/out/fst-freshness.d.ts.map +0 -1
- package/out/fst-freshness.js.map +0 -1
- package/out/fst-matcher.d.ts.map +0 -1
- package/out/fst-matcher.js.map +0 -1
- package/out/fst-serialize.d.ts.map +0 -1
- package/out/fst-serialize.js.map +0 -1
- package/out/fst-types.d.ts.map +0 -1
- package/out/fst-types.js.map +0 -1
- package/out/fts-query.d.ts.map +0 -1
- package/out/fts-query.js.map +0 -1
- package/out/fts.d.ts.map +0 -1
- package/out/fts.js.map +0 -1
- package/out/geo.d.ts +0 -74
- package/out/geo.d.ts.map +0 -1
- package/out/geo.js +0 -71
- package/out/geo.js.map +0 -1
- package/out/geonames-aliases.d.ts.map +0 -1
- package/out/geonames-aliases.js.map +0 -1
- package/out/geonames-postal.d.ts.map +0 -1
- package/out/geonames-postal.js.map +0 -1
- package/out/poi-lookup.d.ts.map +0 -1
- package/out/poi-lookup.js.map +0 -1
- package/out/poi-schema.d.ts.map +0 -1
- package/out/poi-schema.js.map +0 -1
- package/out/postal-city-alias-lookup.d.ts.map +0 -1
- package/out/postal-city-alias-lookup.js.map +0 -1
- package/out/postal-city-candidate-schema.d.ts.map +0 -1
- package/out/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.map +0 -1
- package/out/street-centroid-schema.d.ts.map +0 -1
- package/out/street-centroid.d.ts.map +0 -1
- package/out/street-centroid.js.map +0 -1
- package/out/street-morphology-fst-builder.d.ts.map +0 -1
- package/out/street-morphology-fst-builder.js.map +0 -1
- package/out/street-morphology-fst-loader.d.ts.map +0 -1
- package/out/street-morphology-fst-loader.js.map +0 -1
- package/out/street-name-lookup.d.ts.map +0 -1
- package/out/street-name-lookup.js.map +0 -1
- package/out/street-normalize.d.ts +0 -95
- package/out/street-normalize.d.ts.map +0 -1
- package/out/street-normalize.js +0 -272
- package/out/street-normalize.js.map +0 -1
- package/out/street-segment-schema.d.ts.map +0 -1
- package/sqlite-utils.ts +0 -46
- package/street-normalize.ts +0 -318
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export type { FindPlaceQuery, GeoBbox, GeoPoint, PlaceCandidate, PlaceLookup, WOFPlacetype } from "
|
|
7
|
+
export type { FindPlaceQuery, GeoBbox, GeoPoint, PlaceCandidate, PlaceLookup, WOFPlacetype } from "#types"
|
|
8
8
|
|
|
9
9
|
export type {
|
|
10
10
|
AncestorsTable,
|
|
@@ -17,20 +17,37 @@ export type {
|
|
|
17
17
|
PlaceSearchTable,
|
|
18
18
|
SprTable,
|
|
19
19
|
WOFDatabase,
|
|
20
|
-
} from "
|
|
20
|
+
} from "#schema"
|
|
21
21
|
|
|
22
|
-
export {
|
|
22
|
+
export { WOFSQLitePlaceLookup, type RankingWeights, type WOFSQLitePlaceLookupOpts } from "#lookup"
|
|
23
23
|
|
|
24
|
-
export {
|
|
24
|
+
export {
|
|
25
|
+
CANDIDATE_ANCESTOR_COLUMNS,
|
|
26
|
+
CANDIDATE_ANCESTOR_TABLE,
|
|
27
|
+
CANDIDATE_INTERVAL_TABLE,
|
|
28
|
+
createCandidateAncestorTable,
|
|
29
|
+
createCandidateIntervalTable,
|
|
30
|
+
intervalContains,
|
|
31
|
+
MAX_ANCESTOR_DEPTH,
|
|
32
|
+
} from "#candidate-ancestors-schema"
|
|
33
|
+
|
|
34
|
+
export type {
|
|
35
|
+
CandidateAncestorsDatabase,
|
|
36
|
+
CandidateAncestorTable,
|
|
37
|
+
CandidateIntervalTable,
|
|
38
|
+
IntervalLabel,
|
|
39
|
+
} from "#candidate-ancestors-schema"
|
|
40
|
+
|
|
41
|
+
export { CANDIDATE_FTS_TABLE, createCandidateFTS } from "#candidate-fts"
|
|
25
42
|
|
|
26
43
|
export {
|
|
27
44
|
ImportanceIndex,
|
|
28
|
-
|
|
45
|
+
IMPORTANCE_JOIN_RADIUS_KM,
|
|
29
46
|
type ImportanceIndexStats,
|
|
30
47
|
loadImportanceIndex,
|
|
31
|
-
} from "
|
|
48
|
+
} from "#candidate-importance"
|
|
32
49
|
|
|
33
|
-
export { WOFCandidateTableLookup, type WOFCandidateTableLookupOpts } from "
|
|
50
|
+
export { WOFCandidateTableLookup, type WOFCandidateTableLookupOpts } from "#candidate-lookup"
|
|
34
51
|
|
|
35
52
|
export {
|
|
36
53
|
COUNTRY_BBOX_TABLE,
|
|
@@ -39,38 +56,38 @@ export {
|
|
|
39
56
|
createCountryCoverageTable,
|
|
40
57
|
readGazetteerCoverageManifest,
|
|
41
58
|
writeGazetteerCoverageManifest,
|
|
42
|
-
} from "
|
|
59
|
+
} from "#coverage-manifest-schema"
|
|
43
60
|
|
|
44
|
-
export type { CountryBBoxTable, CountryCoverageTable, GazetteerCoverageDatabase } from "
|
|
45
|
-
export { SQLiteStreetNameLookup, type SQLiteStreetNameLookupOpts } from "
|
|
61
|
+
export type { CountryBBoxTable, CountryCoverageTable, GazetteerCoverageDatabase } from "#coverage-manifest-schema"
|
|
62
|
+
export { SQLiteStreetNameLookup, type SQLiteStreetNameLookupOpts } from "#street/name-lookup"
|
|
46
63
|
|
|
47
64
|
export {
|
|
48
65
|
GEONAMES_ID_BASE,
|
|
49
66
|
type GeonamesIngestProgress,
|
|
50
67
|
ingestGeonamesAliases,
|
|
51
68
|
purgeGeonamesAliasRange,
|
|
52
|
-
} from "
|
|
69
|
+
} from "#geonames/aliases"
|
|
53
70
|
|
|
54
|
-
export { GEONAMES_POSTAL_ID_BASE } from "
|
|
71
|
+
export { GEONAMES_POSTAL_ID_BASE } from "#geonames/postal"
|
|
55
72
|
|
|
56
|
-
export { ADDRESS_POINT_COLUMNS, createAddressPointIndexes, createAddressPointTable } from "
|
|
57
|
-
export type { AddressPointDatabase, AddressPointTable } from "
|
|
73
|
+
export { ADDRESS_POINT_COLUMNS, createAddressPointIndexes, createAddressPointTable } from "#address/point-schema"
|
|
74
|
+
export type { AddressPointDatabase, AddressPointTable } from "#address/point-schema"
|
|
58
75
|
|
|
59
76
|
export {
|
|
60
77
|
WOFPostalCityAliasLookup,
|
|
61
78
|
type PostalCityAlias,
|
|
62
79
|
type WOFPostalCityAliasLookupOpts,
|
|
63
|
-
} from "
|
|
80
|
+
} from "#postal/city-alias-lookup"
|
|
64
81
|
|
|
65
|
-
export type { PostalCityAliasDatabase, PostalCityAliasTable } from "
|
|
82
|
+
export type { PostalCityAliasDatabase, PostalCityAliasTable } from "#postal/city-alias-schema"
|
|
66
83
|
|
|
67
84
|
export {
|
|
68
85
|
POSTAL_CITY_CANDIDATE_COLUMNS,
|
|
69
86
|
POSTAL_CITY_CANDIDATE_TABLE,
|
|
70
87
|
createPostalCityCandidateTable,
|
|
71
|
-
} from "
|
|
88
|
+
} from "#postal/city-candidate-schema"
|
|
72
89
|
|
|
73
|
-
export type { PostalCityCandidateDatabase, PostalCityCandidateTable } from "
|
|
90
|
+
export type { PostalCityCandidateDatabase, PostalCityCandidateTable } from "#postal/city-candidate-schema"
|
|
74
91
|
|
|
75
92
|
export {
|
|
76
93
|
ADDRESS_CONVENTION_TABLE,
|
|
@@ -84,11 +101,11 @@ export {
|
|
|
84
101
|
type ResolvedConvention,
|
|
85
102
|
type ScoringWeights,
|
|
86
103
|
type Strategy,
|
|
87
|
-
} from "
|
|
104
|
+
} from "#convention/index"
|
|
88
105
|
|
|
89
|
-
export { SqliteConventionSource } from "
|
|
106
|
+
export { SqliteConventionSource } from "#sqlite-convention-source"
|
|
90
107
|
|
|
91
|
-
export { WOFPostcodeLookup, type PostcodePlace } from "
|
|
108
|
+
export { WOFPostcodeLookup, type PostcodePlace } from "#postcode-point-lookup"
|
|
92
109
|
|
|
93
110
|
export {
|
|
94
111
|
PLACE_BBOX_TABLE,
|
|
@@ -98,22 +115,9 @@ export {
|
|
|
98
115
|
placeSearchFTSExists,
|
|
99
116
|
type BuildPlaceSearchFTSOpts,
|
|
100
117
|
type BuildPlaceSearchFTSResult,
|
|
101
|
-
} from "
|
|
118
|
+
} from "#fts/index"
|
|
102
119
|
|
|
103
|
-
export {
|
|
104
|
-
bboxAround,
|
|
105
|
-
geometryContains,
|
|
106
|
-
haversineKm,
|
|
107
|
-
pointInPolygonRings,
|
|
108
|
-
pointInRing,
|
|
109
|
-
type Bbox,
|
|
110
|
-
type GeojsonGeometry,
|
|
111
|
-
type GeojsonMultiPolygon,
|
|
112
|
-
type GeojsonPolygon,
|
|
113
|
-
type GeojsonPosition,
|
|
114
|
-
} from "./geo.ts"
|
|
115
|
-
|
|
116
|
-
export { PLACETYPE_DEPTH, ancestorLineage, placetypeDepth, type AncestorPlaceRow } from "./ancestry.ts"
|
|
120
|
+
export { PLACETYPE_DEPTH, ancestorLineage, placetypeDepth, type AncestorPlaceRow } from "#ancestry/index"
|
|
117
121
|
|
|
118
122
|
export {
|
|
119
123
|
WOFReverseGeocoder,
|
|
@@ -121,31 +125,31 @@ export {
|
|
|
121
125
|
type ReverseGeocodeOpts,
|
|
122
126
|
type ReverseGeocodeResult,
|
|
123
127
|
type WOFReverseGeocoderOpts,
|
|
124
|
-
} from "
|
|
128
|
+
} from "#reverse"
|
|
125
129
|
|
|
126
|
-
export { AddressPointInterpolator } from "
|
|
127
|
-
export { AddressPointSqliteLookup } from "
|
|
130
|
+
export { AddressPointInterpolator } from "#address/point-interpolation"
|
|
131
|
+
export { AddressPointSqliteLookup } from "#address/point"
|
|
128
132
|
|
|
129
133
|
export {
|
|
130
134
|
STREET_CENTROID_COLUMNS,
|
|
131
135
|
createStreetCentroidIndexes,
|
|
132
136
|
createStreetCentroidTable,
|
|
133
|
-
} from "
|
|
137
|
+
} from "#street/centroid-schema"
|
|
134
138
|
|
|
135
|
-
export type { StreetCentroidDatabase, StreetCentroidTable } from "
|
|
136
|
-
export { StreetCentroidSqliteLookup } from "
|
|
139
|
+
export type { StreetCentroidDatabase, StreetCentroidTable } from "#street/centroid-schema"
|
|
140
|
+
export { StreetCentroidSqliteLookup } from "#street/centroid"
|
|
137
141
|
|
|
138
142
|
export {
|
|
139
143
|
StreetInterpolator,
|
|
140
144
|
type InterpolatedHit,
|
|
141
145
|
type InterpolationMethod,
|
|
142
146
|
type InterpolationQuery,
|
|
143
|
-
} from "
|
|
147
|
+
} from "#interpolation"
|
|
144
148
|
|
|
145
149
|
export {
|
|
146
150
|
deriveSchemaName,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
type
|
|
150
|
-
type
|
|
151
|
-
} from "
|
|
151
|
+
pickExtractForPlacetype,
|
|
152
|
+
resolveExtracts,
|
|
153
|
+
type ResolvedExtract,
|
|
154
|
+
type ExtractConfig,
|
|
155
|
+
} from "#extracts"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* then linear interpolation along the segment polyline. Design:
|
|
9
9
|
* `docs/articles/plan/2026-06-11-interpolation-design.md`.
|
|
10
10
|
*
|
|
11
|
-
* Reads the per-state
|
|
11
|
+
* Reads the per-state extract built by `scripts/build-interpolation-extract.ts` (`street_segment`: one
|
|
12
12
|
* row per TIGER edge SIDE — independent left/right ranges, ZIPs, parity). Query-side
|
|
13
13
|
* normalization is THE shared normalizer (`street-normalize.ts`) — identical to build-side, by
|
|
14
14
|
* construction.
|
|
@@ -26,20 +26,19 @@
|
|
|
26
26
|
* `AddressPointLookup.find()` to keep that wiring mechanical.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
import { parseJSONStrict } from "@mailwoman/core/objects"
|
|
29
|
+
import { parseJSONStrict } from "@mailwoman/core/json"
|
|
32
30
|
import type { InterpolationLookup } from "@mailwoman/resolver"
|
|
33
|
-
import { clampFraction, pointAlong } from "@mailwoman/spatial"
|
|
31
|
+
import { clampFraction, haversineKm, pointAlong } from "@mailwoman/spatial"
|
|
32
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
34
33
|
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
34
|
+
import { hasTable, prepareAll, type PreparedAll } from "#sqlite-utils"
|
|
35
|
+
import { canonicalizeRouteKey, type RouteKey, streetKeyVariants } from "#street/normalize"
|
|
36
|
+
import type { StreetSegmentDatabase } from "#street/segment-schema"
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* How an interpolated answer was computed (#483 Method 2):
|
|
41
40
|
*
|
|
42
|
-
* - `address_point` — bracketed/extrapolated between REAL neighbor points from the #476
|
|
41
|
+
* - `address_point` — bracketed/extrapolated between REAL neighbor points from the #476 extract
|
|
43
42
|
* (`AddressPointInterpolator`), replacing TIGER's uniform-spacing assumption with occupancy.
|
|
44
43
|
* - `tiger_range` — linear position within a TIGER segment's theoretical house-number range (`StreetInterpolator`), the
|
|
45
44
|
* fallback for streets too sparse to bracket.
|
|
@@ -92,8 +91,27 @@ export interface InterpolationQuery {
|
|
|
92
91
|
* ZIP scope — strongly preferred; without it common street names abstain (see module doc).
|
|
93
92
|
*/
|
|
94
93
|
postcode?: string
|
|
94
|
+
/**
|
|
95
|
+
* The resolved locality's coordinate — the tie-breaker when no postcode was given and the parity-preferred covering
|
|
96
|
+
* ranges still span several postcodes. See {@link NEAR_MAX_KM} for the acceptance geometry.
|
|
97
|
+
*/
|
|
98
|
+
near?: { lat: number; lon: number }
|
|
95
99
|
}
|
|
96
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Acceptance geometry for the `near` tie-break: the winning postcode group's closest segment must sit within this many
|
|
103
|
+
* kilometres of `near`, AND the runner-up group must be at least {@link NEAR_DOMINANCE} times farther. Both measured on
|
|
104
|
+
* the two live failures: Brooklyn's `st pauls place` 11226 segment is ~2 km from the Brooklyn centroid with Great
|
|
105
|
+
* Neck's 11021 at ~24 km (12×); Fraser's `east 13 mile road` 48026 is ~2 km with Mecosta's namesake ~190 km away. A
|
|
106
|
+
* near-tie between groups is genuine ambiguity and stays an abstention.
|
|
107
|
+
*/
|
|
108
|
+
const NEAR_MAX_KM = 25
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* See {@link NEAR_MAX_KM}.
|
|
112
|
+
*/
|
|
113
|
+
const NEAR_DOMINANCE = 2
|
|
114
|
+
|
|
97
115
|
interface SegmentRow {
|
|
98
116
|
from_hn: number
|
|
99
117
|
to_hn: number
|
|
@@ -106,44 +124,94 @@ interface SegmentRow {
|
|
|
106
124
|
release: string
|
|
107
125
|
}
|
|
108
126
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
127
|
+
/**
|
|
128
|
+
* The postcode group nearest `near`, under the {@link NEAR_MAX_KM} dominance geometry — or null when no group qualifies
|
|
129
|
+
* (out of range, or the runner-up is too close to call). A group's distance is its closest segment's first polyline
|
|
130
|
+
* vertex; a segment whose geometry fails to parse prices as unreachable rather than aborting the tie-break.
|
|
131
|
+
*/
|
|
132
|
+
function nearestPostcodeGroup(pool: readonly SegmentRow[], near: { lat: number; lon: number }): SegmentRow[] | null {
|
|
133
|
+
const groups = new Map<string, { rows: SegmentRow[]; km: number }>()
|
|
134
|
+
|
|
135
|
+
for (const row of pool) {
|
|
136
|
+
const key = row.postcode ?? ""
|
|
137
|
+
let km = Number.POSITIVE_INFINITY
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const [firstVertex] = parseJSONStrict<[number, number][]>(row.geometry)
|
|
141
|
+
|
|
142
|
+
if (firstVertex) {
|
|
143
|
+
km = haversineKm(near.lat, near.lon, firstVertex[1], firstVertex[0])
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
// Unparseable geometry: this row cannot be sited, so it cannot win the tie-break.
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const group = groups.get(key)
|
|
150
|
+
|
|
151
|
+
if (group) {
|
|
152
|
+
group.rows.push(row)
|
|
153
|
+
group.km = Math.min(group.km, km)
|
|
154
|
+
} else {
|
|
155
|
+
groups.set(key, { rows: [row], km })
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const ranked = [...groups.values()].toSorted((a, b) => a.km - b.km)
|
|
160
|
+
const [winner, runnerUp] = ranked
|
|
161
|
+
|
|
162
|
+
if (!winner || winner.km > NEAR_MAX_KM) return null
|
|
163
|
+
|
|
164
|
+
if (runnerUp && runnerUp.km < winner.km * NEAR_DOMINANCE) return null
|
|
165
|
+
|
|
166
|
+
return winner.rows
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export class StreetInterpolator<
|
|
170
|
+
DB extends StreetSegmentDatabase = StreetSegmentDatabase,
|
|
171
|
+
> implements InterpolationLookup {
|
|
172
|
+
readonly #db: DatabaseClient<DB>
|
|
173
|
+
/**
|
|
174
|
+
* Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
|
|
175
|
+
* ownership is membership rather than a flag a later branch has to check.
|
|
176
|
+
*/
|
|
177
|
+
readonly #resources = new DisposableStack()
|
|
178
|
+
readonly #byPostcode:
|
|
179
|
+
| PreparedAll<[postcode: string, street: RouteKey, minNumber: number, maxNumber: number], SegmentRow>
|
|
180
|
+
| undefined
|
|
181
|
+
readonly #byStreet: PreparedAll<[street: RouteKey, minNumber: number, maxNumber: number], SegmentRow> | undefined
|
|
114
182
|
readonly #radiusCalibration: number | undefined
|
|
115
183
|
|
|
116
|
-
constructor(opts: { dbPath?: string; database?:
|
|
184
|
+
constructor(opts: { dbPath?: string; database?: DatabaseClient<DB> }) {
|
|
117
185
|
if (opts.database) {
|
|
118
186
|
this.#db = opts.database
|
|
119
|
-
this.#ownsDB = false
|
|
120
187
|
} else if (opts.dbPath) {
|
|
121
|
-
this.#db = new
|
|
122
|
-
this.#ownsDB = true
|
|
188
|
+
this.#db = this.#resources.use(new DatabaseClient<DB>(opts.dbPath, { readOnly: true }))
|
|
123
189
|
} else {
|
|
124
190
|
throw new Error("StreetInterpolator: one of dbPath or database is required")
|
|
125
191
|
}
|
|
126
192
|
|
|
127
|
-
// Degrade gracefully on an empty/tableless
|
|
193
|
+
// Degrade gracefully on an empty/tableless extract (interrupted build, stray 0-byte file): with no
|
|
128
194
|
// `street_segment` table this interpolator is a no-op miss, not a crash that loses the state (#568).
|
|
129
195
|
if (hasTable(this.#db, "street_segment")) {
|
|
130
196
|
const columns = `from_hn, to_hn, min_hn, max_hn, parity, postcode, geometry, source, release`
|
|
131
197
|
|
|
132
|
-
this.#byPostcode =
|
|
198
|
+
this.#byPostcode = prepareAll(
|
|
199
|
+
this.#db,
|
|
133
200
|
`SELECT ${columns} FROM street_segment
|
|
134
201
|
WHERE postcode = ? AND street_norm = ? AND min_hn <= ? AND max_hn >= ?`
|
|
135
202
|
)
|
|
136
203
|
|
|
137
|
-
this.#byStreet =
|
|
204
|
+
this.#byStreet = prepareAll(
|
|
205
|
+
this.#db,
|
|
138
206
|
`SELECT ${columns} FROM street_segment
|
|
139
207
|
WHERE street_norm = ? AND min_hn <= ? AND max_hn >= ?`
|
|
140
208
|
)
|
|
141
209
|
}
|
|
142
210
|
|
|
143
211
|
// #374 doctrine: the conformal radius multiplier is a property of the calibration set the ARTIFACT was
|
|
144
|
-
// built against, so it ships in the
|
|
212
|
+
// built against, so it ships in the extract's `interp_calibration` metadata table (street-segment-schema.ts)
|
|
145
213
|
// and is read here, once, at open time — sync raw `.prepare()` per the sync-by-interface doctrine
|
|
146
|
-
// (AGENTS.md).
|
|
214
|
+
// (AGENTS.md). Extracts predating the table (the pre-2026-07 fleet) yield `undefined`; callers then fall
|
|
147
215
|
// back to their in-code table, byte-identically.
|
|
148
216
|
if (hasTable(this.#db, "interp_calibration")) {
|
|
149
217
|
const row = this.#db.prepare("SELECT radius_multiplier FROM interp_calibration LIMIT 1").get() as
|
|
@@ -159,9 +227,9 @@ export class StreetInterpolator implements InterpolationLookup {
|
|
|
159
227
|
}
|
|
160
228
|
|
|
161
229
|
/**
|
|
162
|
-
* The artifact's own conformal radius multiplier (#374), read from the
|
|
163
|
-
* construction. `undefined` = the
|
|
164
|
-
* artifact default and callers may supply a legacy fallback.
|
|
230
|
+
* The artifact's own conformal radius multiplier (#374), read from the extract's `interp_calibration` metadata table
|
|
231
|
+
* at construction. `undefined` = the extract predates the table (or carries no valid row) — the resolver then applies
|
|
232
|
+
* no artifact default and callers may supply a legacy fallback.
|
|
165
233
|
*/
|
|
166
234
|
get radiusCalibration(): number | undefined {
|
|
167
235
|
return this.#radiusCalibration
|
|
@@ -169,29 +237,41 @@ export class StreetInterpolator implements InterpolationLookup {
|
|
|
169
237
|
|
|
170
238
|
find(query: InterpolationQuery): InterpolatedHit | null {
|
|
171
239
|
if (!this.#byPostcode || !this.#byStreet) return null
|
|
172
|
-
const streetNorm = canonicalizeRouteKey(normalizeStreetForKey(query.street))
|
|
173
240
|
const numberRaw = query.number.trim()
|
|
174
241
|
|
|
175
242
|
// Strictly-numeric house numbers only — this tier estimates, it doesn't guess at
|
|
176
243
|
// hyphenated/alphanumeric schemes the ranges don't model.
|
|
177
|
-
if (
|
|
244
|
+
if (!/^\d+$/.test(numberRaw)) return null
|
|
178
245
|
const n = Number(numberRaw)
|
|
179
246
|
|
|
180
|
-
|
|
247
|
+
// Key-variant ladder (see `streetKeyVariants`): the literal key first, then the doubled-type
|
|
248
|
+
// collapse and the saint↔st register swap. A variant advances the ladder when it produces no
|
|
249
|
+
// ANSWER, not merely no rows — a wrong-register key can cover the number in far-away towns and
|
|
250
|
+
// then fail the ambiguity check ("saint pauls place" reaches Nassau's rows; the Brooklyn answer
|
|
251
|
+
// lives under "st pauls place"), and stopping at rows would eclipse the right variant.
|
|
252
|
+
for (const variant of streetKeyVariants(query.street)) {
|
|
253
|
+
const streetNorm = canonicalizeRouteKey(variant)
|
|
181
254
|
|
|
182
|
-
if (query.postcode) {
|
|
183
255
|
// A given ZIP that scopes to nothing is a MISS, not a statewide guess: the retry was
|
|
184
256
|
// measured (2026-06-11 VT eval) at +2.3pp coverage for a poisoned tail (p99 1.0 → 20.8
|
|
185
257
|
// km, max 204 km — a unique name statewide can live in a far-away town).
|
|
186
|
-
rows =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
258
|
+
const rows = query.postcode
|
|
259
|
+
? this.#byPostcode(query.postcode.trim(), streetNorm, n, n)
|
|
260
|
+
: this.#byStreet(streetNorm, n, n)
|
|
261
|
+
|
|
262
|
+
const hit = this.#answerFromRows(rows, n, query)
|
|
191
263
|
|
|
192
|
-
if (
|
|
264
|
+
if (hit) return hit
|
|
193
265
|
}
|
|
194
266
|
|
|
267
|
+
return null
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Resolve one key variant's covering rows to an answer, or null when they cannot honestly give one — the
|
|
272
|
+
* parity/ambiguity/tightest-range pipeline the module doc describes.
|
|
273
|
+
*/
|
|
274
|
+
#answerFromRows(rows: SegmentRow[], n: number, query: InterpolationQuery): InterpolatedHit | null {
|
|
195
275
|
if (!rows.length) return null
|
|
196
276
|
|
|
197
277
|
// Parity preference: exact side first, then 'mixed' (matches either), then the
|
|
@@ -200,9 +280,27 @@ export class StreetInterpolator implements InterpolationLookup {
|
|
|
200
280
|
const exact = rows.filter((r) => r.parity === (wantOdd ? "odd" : "even"))
|
|
201
281
|
const mixed = rows.filter((r) => r.parity === "mixed")
|
|
202
282
|
const preferred = exact.length ? exact : mixed
|
|
203
|
-
|
|
283
|
+
let pool = preferred.length ? preferred : rows
|
|
204
284
|
const parityMatched = preferred.length > 0
|
|
205
285
|
|
|
286
|
+
// No scope given: the covering ranges must agree on ONE postcode or the lookup abstains — a
|
|
287
|
+
// name spanning towns is ambiguity, not an answer. Counted over the PARITY pool, not all
|
|
288
|
+
// rows: a section-line boundary road carries a different ZIP per side ("east 13 mile road"
|
|
289
|
+
// is Fraser 48026 odd / Roseville 48066 even), and the opposite side can never hold the
|
|
290
|
+
// number it would otherwise veto. When several postcodes survive parity, the caller's
|
|
291
|
+
// resolved-locality coordinate breaks the tie by segment proximity under the dominance
|
|
292
|
+
// geometry of {@link NEAR_MAX_KM} — a near-tie stays an abstention.
|
|
293
|
+
if (!query.postcode) {
|
|
294
|
+
const postcodes = new Set(pool.map((r) => r.postcode ?? ""))
|
|
295
|
+
|
|
296
|
+
if (postcodes.size > 1) {
|
|
297
|
+
const scoped = query.near ? nearestPostcodeGroup(pool, query.near) : null
|
|
298
|
+
|
|
299
|
+
if (!scoped) return null
|
|
300
|
+
pool = scoped
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
206
304
|
// Tightest range wins — the most specific claim about where this number lives.
|
|
207
305
|
let best = pool[0]!
|
|
208
306
|
|
|
@@ -229,9 +327,7 @@ export class StreetInterpolator implements InterpolationLookup {
|
|
|
229
327
|
}
|
|
230
328
|
}
|
|
231
329
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
this.#db.close()
|
|
235
|
-
}
|
|
330
|
+
[Symbol.dispose](): void {
|
|
331
|
+
this.#resources[Symbol.dispose]()
|
|
236
332
|
}
|
|
237
333
|
}
|