@mailwoman/resolver-wof-sqlite 9.2.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 +16 -19
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +24 -22
- package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
- package/{address-point.ts → lib/address/point.ts} +89 -27
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +5 -3
- package/{build-candidate.ts → lib/build-candidate.ts} +84 -77
- package/{build-slim.ts → lib/build-slim.ts} +150 -165
- package/{candidate → lib/candidate}/alias-bags.ts +8 -6
- package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
- package/{candidate → lib/candidate}/country-display-names.ts +2 -2
- package/{candidate/shard-fold.ts → lib/candidate/extract-fold.ts} +26 -25
- package/{candidate → lib/candidate}/name-roles.ts +17 -16
- package/{candidate → lib/candidate}/own-name.ts +1 -1
- package/{candidate → lib/candidate}/place-attrs.ts +3 -3
- package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
- package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
- package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
- package/{candidate-lookup.ts → lib/candidate-lookup.ts} +76 -73
- package/{candidate-schema.ts → lib/candidate-schema.ts} +5 -5
- package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
- package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
- package/{capitals.ts → lib/capitals.ts} +2 -2
- package/{coincident-roles.ts → lib/coincident-roles.ts} +8 -11
- package/{convention.ts → lib/convention/index.ts} +3 -3
- package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +9 -10
- package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
- package/lib/env.ts +50 -0
- package/{exact-match.ts → lib/exact-match.ts} +23 -14
- package/{sharding.ts → lib/extracts.ts} +61 -58
- package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
- package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
- 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} +41 -74
- 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} +24 -19
- package/{fts-query.ts → lib/fts/query.ts} +1 -1
- 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} +14 -13
- package/{index.ts → lib/index.ts} +37 -37
- package/{interpolation.ts → lib/interpolation.ts} +27 -25
- package/{lookup.ts → lib/lookup.ts} +129 -141
- 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} +7 -8
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -28
- package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/{primary-preference.ts → lib/primary-preference.ts} +29 -10
- package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/{region-keys.ts → lib/region-keys.ts} +9 -9
- package/{reverse.ts → lib/reverse.ts} +34 -46
- package/{schema.ts → lib/schema.ts} +10 -0
- package/{search-fetch.ts → lib/search-fetch.ts} +29 -28
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -18
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
- package/{street-centroid.ts → lib/street/centroid.ts} +14 -21
- 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/{street-normalize.ts → lib/street/normalize.ts} +44 -19
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
- package/{types.ts → lib/types.ts} +18 -12
- package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -18
- package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
- 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} +18 -18
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
- 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 → address/point.js} +71 -20
- 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} +4 -3
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +3 -2
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +30 -24
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +50 -52
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +4 -4
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +124 -139
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +5 -3
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +2 -2
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors-sidecar.d.ts +9 -10
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
- package/out/candidate/ancestors-sidecar.js +7 -7
- package/out/candidate/ancestors-sidecar.js.map +1 -1
- package/out/candidate/country-display-names.d.ts +1 -1
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +1 -1
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +32 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/{shard-fold.js → extract-fold.js} +20 -20
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +13 -11
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +11 -10
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +1 -1
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +1 -1
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +3 -3
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +1 -1
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate-ancestors-schema.d.ts +4 -4
- package/out/candidate-ancestors-schema.d.ts.map +1 -1
- package/out/candidate-ancestors-schema.js +2 -2
- package/out/candidate-ancestors-schema.js.map +1 -1
- package/out/candidate-fts.d.ts +3 -3
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +1 -1
- 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 +46 -51
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +11 -9
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +61 -58
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +5 -5
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +7 -7
- package/out/candidate-scoring.d.ts.map +1 -1
- package/out/candidate-scoring.js +10 -14
- package/out/candidate-scoring.js.map +1 -1
- package/out/capital-schema.d.ts +3 -3
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +2 -2
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +1 -1
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +2 -2
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +6 -5
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +2 -4
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +4 -4
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +2 -2
- package/out/convention/index.js.map +1 -0
- package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
- package/out/convention/schema.d.ts.map +1 -0
- package/out/{convention-schema.js → convention/schema.js} +3 -3
- 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 +4 -4
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +51 -7
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +65 -49
- package/out/currency-backfill.js.map +1 -1
- 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 +5 -5
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +10 -11
- package/out/exact-match.js.map +1 -1
- 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} +2 -2
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
- 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} +14 -13
- 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} +10 -13
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +41 -73
- 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} +16 -9
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +16 -11
- 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} +1 -1
- 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} +10 -8
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +9 -9
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -32
- 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 +10 -9
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +20 -20
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +21 -20
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +102 -112
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts.map +1 -1
- 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 +5 -5
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -3
- 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} +14 -18
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
- 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.map +1 -1
- package/out/polygon-schema.js.map +1 -1
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
- 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} +3 -3
- package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
- 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 +13 -5
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +16 -8
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +2 -2
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +2 -2
- package/out/proximity-rerank.js.map +1 -1
- 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 +8 -8
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +9 -9
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +20 -29
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +9 -0
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +12 -10
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +21 -20
- package/out/search-fetch.js.map +1 -1
- 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 +8 -8
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +7 -8
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
- package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
- 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} +13 -19
- 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 → street/normalize.d.ts} +25 -14
- package/out/street/normalize.d.ts.map +1 -0
- package/out/{street-normalize.js → street/normalize.js} +36 -17
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
- package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
- 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 +18 -12
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +5 -4
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +15 -18
- 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 → uprn/lookup.d.ts} +4 -4
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
- package/out/uprn/lookup.js.map +1 -0
- package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/{uprn-schema.js → uprn/schema.js} +4 -4
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +184 -26
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +338 -86
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +465 -269
- 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.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/candidate/shard-fold.d.ts +0 -31
- package/out/candidate/shard-fold.d.ts.map +0 -1
- package/out/candidate/shard-fold.js.map +0 -1
- package/out/convention-schema.d.ts.map +0 -1
- package/out/convention-schema.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.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/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/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.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.map +0 -1
- package/out/street-normalize.js.map +0 -1
- package/out/uprn-lookup.d.ts.map +0 -1
- package/out/uprn-lookup.js.map +0 -1
- package/out/uprn-schema.d.ts.map +0 -1
- package/out/uprn-schema.js.map +0 -1
- package/weights-overlay-linker.ts +0 -377
- /package/{name-score.ts → lib/name-score.ts} +0 -0
- /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* Typed schema for the DERIVED STREET-CENTROID
|
|
7
|
-
* `ban/scripts/build-street-centroid-
|
|
8
|
-
* FR queries deserve a street-level answer"). The
|
|
9
|
-
* sealed rooftop address-point
|
|
6
|
+
* Typed schema for the DERIVED STREET-CENTROID extract (`street-centroids-<cc>.db`, built by
|
|
7
|
+
* `ban/scripts/build-street-centroid-extract.ts` — the #1042 street-level tier behind "street-only
|
|
8
|
+
* FR queries deserve a street-level answer"). The extract is a `GROUP BY street` roll-up of the
|
|
9
|
+
* sealed rooftop address-point extract: one row per (street, postcode, commune) carrying the street's
|
|
10
10
|
* CENTROID + bounding-box EXTENT + member-point count. No new data source — a derived artifact.
|
|
11
11
|
*
|
|
12
12
|
* Single source of truth for the columns shared by the BUILDER (a positional prepared INSERT for
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
import type { Kysely } from "kysely"
|
|
24
24
|
|
|
25
|
-
import type { NameKey, StreetKey } from "
|
|
25
|
+
import type { NameKey, StreetKey } from "#street/normalize"
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* One street roll-up. `(street_norm, postcode, locality_base)` is unique. `lat`/`lon` are the UNWEIGHTED mean of the
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* number) plus a postcode/commune scope, it returns the street's CENTROID + an honest extent-derived
|
|
9
9
|
* uncertainty from the derived `street-centroids-<cc>.db` roll-up.
|
|
10
10
|
*
|
|
11
|
-
* Query-side normalization is THE shared normalizer (`street-normalize.ts`), selected per the
|
|
11
|
+
* Query-side normalization is THE shared normalizer (`street-normalize.ts`), selected per the extract's
|
|
12
12
|
* `streetLocale`, so build-side and probe-side keys agree by construction. The commune scope folds
|
|
13
13
|
* through `normalizeLocalityForKey` + `stripArrondissement` (BAN names Paris/Lyon/Marseille per
|
|
14
14
|
* arrondissement; a query names the base commune).
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
* exact-after-normalization only (no fuzzy street matching in this tier).
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { DatabaseSync } from "node:sqlite"
|
|
23
|
-
|
|
24
22
|
import type { StreetCentroidHit, StreetCentroidLookup } from "@mailwoman/resolver"
|
|
23
|
+
import { haversineKm } from "@mailwoman/spatial"
|
|
24
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
25
25
|
|
|
26
|
-
import { hasTable, prepareGet, type PreparedGet } from "
|
|
26
|
+
import { hasTable, prepareGet, type PreparedGet } from "#sqlite-utils"
|
|
27
|
+
import type { StreetCentroidDatabase } from "#street/centroid-schema"
|
|
27
28
|
import {
|
|
28
29
|
normalizeLocalityForKey,
|
|
29
30
|
normalizeStreetForKeyLocale,
|
|
@@ -32,7 +33,7 @@ import {
|
|
|
32
33
|
streetLocaleForSurface,
|
|
33
34
|
type StreetLocale,
|
|
34
35
|
stripArrondissement,
|
|
35
|
-
} from "
|
|
36
|
+
} from "#street/normalize"
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* The weighted-centroid + extent + provenance an aggregate probe projects. `lat` is null when nothing matched.
|
|
@@ -61,33 +62,25 @@ const AGG_SELECT =
|
|
|
61
62
|
* Half the bbox diagonal, in METERS — an honest coarse radius for a street centroid.
|
|
62
63
|
*/
|
|
63
64
|
function extentRadiusM(minLat: number, maxLat: number, minLon: number, maxLon: number): number {
|
|
64
|
-
|
|
65
|
-
const toRad = (d: number): number => (d * Math.PI) / 180
|
|
66
|
-
const dLat = toRad(maxLat - minLat)
|
|
67
|
-
const dLon = toRad(maxLon - minLon)
|
|
68
|
-
const midLat = toRad((minLat + maxLat) / 2)
|
|
69
|
-
const a = Math.sin(dLat / 2) ** 2 + Math.cos(midLat) ** 2 * Math.sin(dLon / 2) ** 2
|
|
70
|
-
const diag = 2 * R * Math.asin(Math.min(1, Math.sqrt(a)))
|
|
71
|
-
|
|
72
|
-
return Math.round(diag / 2)
|
|
65
|
+
return Math.round(haversineKm(minLat, minLon, maxLat, maxLon) * 500)
|
|
73
66
|
}
|
|
74
67
|
|
|
75
68
|
export class StreetCentroidSqliteLookup implements StreetCentroidLookup {
|
|
76
|
-
readonly #db:
|
|
69
|
+
readonly #db: DatabaseClient<StreetCentroidDatabase>
|
|
77
70
|
readonly #locale: StreetLocale
|
|
78
71
|
readonly #byPostcode: PreparedGet<[postcode: string, street: StreetKey], AggRow> | undefined
|
|
79
72
|
readonly #byLocality: PreparedGet<[locality: NameKey, street: StreetKey], AggRow> | undefined
|
|
80
73
|
|
|
81
74
|
/**
|
|
82
|
-
* @param dbPath
|
|
83
|
-
* @param opts.streetLocale The street-normalization locale this
|
|
75
|
+
* @param dbPath Extract path.
|
|
76
|
+
* @param opts.streetLocale The street-normalization locale this extract was BUILT with — must match, or every key
|
|
84
77
|
* misses. Defaults to `"fr"` (BAN is the French national register; the tier is FR-only today).
|
|
85
78
|
*/
|
|
86
79
|
constructor(dbPath: string, opts: { streetLocale?: StreetLocale } = {}) {
|
|
87
|
-
this.#db = new
|
|
80
|
+
this.#db = new DatabaseClient<StreetCentroidDatabase>(dbPath, { readOnly: true })
|
|
88
81
|
this.#locale = opts.streetLocale ?? "fr"
|
|
89
82
|
|
|
90
|
-
// Degrade gracefully on an empty/tableless
|
|
83
|
+
// Degrade gracefully on an empty/tableless extract (interrupted build, stray 0-byte file): with no
|
|
91
84
|
// `street_centroid` table this lookup is a no-op miss, not a crash (mirrors the address-point reader).
|
|
92
85
|
if (hasTable(this.#db, "street_centroid")) {
|
|
93
86
|
this.#byPostcode = prepareGet(
|
|
@@ -130,7 +123,7 @@ export class StreetCentroidSqliteLookup implements StreetCentroidLookup {
|
|
|
130
123
|
}
|
|
131
124
|
}
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
this.#db.
|
|
126
|
+
[Symbol.dispose](): void {
|
|
127
|
+
this.#db[Symbol.dispose]()
|
|
135
128
|
}
|
|
136
129
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from "#street/centroid"
|
|
8
|
+
export * from "#street/centroid-schema"
|
|
9
|
+
export * from "#street/morphology-fst-builder"
|
|
10
|
+
export * from "#street/morphology-fst-loader"
|
|
11
|
+
export * from "#street/name-lookup"
|
|
12
|
+
export * from "#street/normalize"
|
|
13
|
+
export * from "#street/segment-schema"
|
|
@@ -23,14 +23,13 @@
|
|
|
23
23
|
* `fst-street-morphology.bin`.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
27
|
-
import { join } from "
|
|
28
|
-
|
|
26
|
+
import { isDirectory, readDirectory, readLocalTextFile, statPath } from "@mailwoman/core/fs/readers"
|
|
27
|
+
import { join } from "path-ts"
|
|
29
28
|
import { TextSpliterator } from "spliterator"
|
|
30
29
|
|
|
31
|
-
import type { FSTNode } from "
|
|
32
|
-
import { FSTMatcher, normalizeTokens } from "
|
|
33
|
-
import type { FSTProvenance, PlaceEntry } from "
|
|
30
|
+
import type { FSTNode } from "#fst/matcher"
|
|
31
|
+
import { FSTMatcher, normalizeTokens } from "#fst/matcher"
|
|
32
|
+
import type { FSTProvenance, PlaceEntry } from "#fst/types"
|
|
34
33
|
|
|
35
34
|
/**
|
|
36
35
|
* Reserved synthetic wofID base for street-morphology entries. 32-bit unsigned, well above any realistic WOF
|
|
@@ -96,7 +95,9 @@ function parseLine(line: string): { canonical: string; variants: string[] } | nu
|
|
|
96
95
|
return { canonical: parts[0]!, variants: parts }
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
export function buildStreetMorphologyFST(
|
|
98
|
+
export async function buildStreetMorphologyFST(
|
|
99
|
+
opts: BuildStreetMorphologyFSTOpts
|
|
100
|
+
): Promise<BuildStreetMorphologyFSTResult> {
|
|
100
101
|
const progress = opts.onProgress ?? (() => {})
|
|
101
102
|
const minVariantLength = opts.minVariantLength ?? 3
|
|
102
103
|
|
|
@@ -107,19 +108,28 @@ export function buildStreetMorphologyFST(opts: BuildStreetMorphologyFSTOpts): Bu
|
|
|
107
108
|
if (opts.locales && opts.locales.length) {
|
|
108
109
|
locales = opts.locales
|
|
109
110
|
} else {
|
|
110
|
-
|
|
111
|
+
const entries = await readDirectory(opts.dictionariesDir)
|
|
112
|
+
const localeProbes: Array<[string, boolean]> = []
|
|
113
|
+
|
|
114
|
+
for (const entry of entries) {
|
|
111
115
|
const localePath = join(opts.dictionariesDir, entry)
|
|
112
116
|
|
|
113
|
-
if (!
|
|
117
|
+
if (!(await isDirectory(localePath))) {
|
|
118
|
+
localeProbes.push([entry, false])
|
|
119
|
+
|
|
120
|
+
continue
|
|
121
|
+
}
|
|
114
122
|
|
|
115
123
|
try {
|
|
116
|
-
|
|
124
|
+
await statPath(join(localePath, STREET_TYPES_FILENAME))
|
|
117
125
|
|
|
118
|
-
|
|
126
|
+
localeProbes.push([entry, true])
|
|
119
127
|
} catch {
|
|
120
|
-
|
|
128
|
+
localeProbes.push([entry, false])
|
|
121
129
|
}
|
|
122
|
-
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
locales = localeProbes.filter(([, hasFile]) => hasFile).map(([entry]) => entry)
|
|
123
133
|
}
|
|
124
134
|
|
|
125
135
|
progress("discover", `Found ${locales.length} locales with ${STREET_TYPES_FILENAME}`)
|
|
@@ -130,7 +140,7 @@ export function buildStreetMorphologyFST(opts: BuildStreetMorphologyFSTOpts): Bu
|
|
|
130
140
|
|
|
131
141
|
for (const locale of locales) {
|
|
132
142
|
const filePath = join(opts.dictionariesDir, locale, STREET_TYPES_FILENAME)
|
|
133
|
-
const content =
|
|
143
|
+
const content = await readLocalTextFile(filePath)
|
|
134
144
|
|
|
135
145
|
for (const line of TextSpliterator.from(content)) {
|
|
136
146
|
const parsed = parseLine(line)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* Unified runtime loader for the street-morphology FST — the #1315 street-context
|
|
6
|
+
* Unified runtime loader for the street-morphology FST — the #1315 street-context check's signal
|
|
7
7
|
* source, previously rebuilt from the libpostal dictionaries per process at three duplicate call
|
|
8
8
|
* sites (runtime pipeline / parity eval / neural harness). The sealed artifact
|
|
9
9
|
* (`fst-street-morphology.bin`, built by `mailwoman gazetteer build street-morphology`) replaces
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
* `fst-deserialize-web.ts` (see the docs demo loader).
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {
|
|
24
|
+
import { dataRootPath } from "@mailwoman/core/data-root"
|
|
25
|
+
import { pathExists, readLocalBuffer } from "@mailwoman/core/fs/readers"
|
|
26
|
+
import { resourceDictionaryPath } from "@mailwoman/core/paths"
|
|
25
27
|
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
import type {
|
|
29
|
-
import {
|
|
30
|
-
import type { FSTProvenance } from "./fst-types.ts"
|
|
31
|
-
import { buildStreetMorphologyFST } from "./street-morphology-fst-builder.ts"
|
|
28
|
+
import type { FSTMatcher } from "#fst/matcher"
|
|
29
|
+
import { deserializeFST, readFSTProvenance } from "#fst/serialize"
|
|
30
|
+
import type { FSTProvenance } from "#fst/types"
|
|
31
|
+
import { buildStreetMorphologyFST } from "#street/morphology-fst-builder"
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* The sealed artifact's canonical filename — identical in the data-root staging dir and as a weights-package sibling.
|
|
@@ -77,13 +77,15 @@ export interface LoadedStreetMorphologyFST {
|
|
|
77
77
|
/**
|
|
78
78
|
* Load the street-morphology matcher: sealed artifact first, per-process dictionary build as the degrade path.
|
|
79
79
|
*/
|
|
80
|
-
export function loadStreetMorphologyFST(
|
|
80
|
+
export async function loadStreetMorphologyFST(
|
|
81
|
+
opts: LoadStreetMorphologyFSTOpts = {}
|
|
82
|
+
): Promise<LoadedStreetMorphologyFST> {
|
|
81
83
|
const warn = opts.onWarn ?? (() => {})
|
|
82
84
|
const artifactPath = opts.artifactPath ?? defaultStreetMorphologyArtifactPath()
|
|
83
85
|
|
|
84
|
-
if (
|
|
86
|
+
if (await pathExists(artifactPath)) {
|
|
85
87
|
try {
|
|
86
|
-
const buf =
|
|
88
|
+
const buf = await readLocalBuffer(artifactPath)
|
|
87
89
|
const matcher = deserializeFST(buf)
|
|
88
90
|
const provenance = readFSTProvenance(buf)
|
|
89
91
|
|
|
@@ -95,7 +97,7 @@ export function loadStreetMorphologyFST(opts: LoadStreetMorphologyFSTOpts = {}):
|
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
const built = buildStreetMorphologyFST({
|
|
100
|
+
const built = await buildStreetMorphologyFST({
|
|
99
101
|
dictionariesDir: opts.dictionariesDir ?? resourceDictionaryPath("libpostal"),
|
|
100
102
|
})
|
|
101
103
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Reads a street-name index (the FR instance = BAN `street-centroids-fr.db`, a `street_centroid`
|
|
9
9
|
* table of `street_norm × locality_base × postcode` rows) and answers "does this street surface
|
|
10
10
|
* exist as a name" for the k-best rerank. Sync-by-interface, `readOnly`, prepared statements,
|
|
11
|
-
* graceful-degrade on a tableless
|
|
11
|
+
* graceful-degrade on a tableless extract — the same reader discipline as `AddressPointSqliteLookup`.
|
|
12
12
|
*
|
|
13
13
|
* THE FOLD CONTRACT: the surface is folded with {@link foldStreetSurface} (the shared function),
|
|
14
14
|
* and the DB's `street_norm` column MUST have been built with that SAME fold or every hyphenated /
|
|
@@ -19,24 +19,11 @@
|
|
|
19
19
|
* the production rebuild is a tracked BAN-sdk follow-up.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { DatabaseSync } from "node:sqlite"
|
|
23
|
-
|
|
24
22
|
import { foldStreetSurface, type StreetEvidenceScope, type StreetLocalityEvidence } from "@mailwoman/resolver"
|
|
23
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return row !== undefined
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function hasColumn(db: DatabaseSync, table: string, column: string): boolean {
|
|
33
|
-
// `table` is a caller-controlled identifier (default `street_centroid`), not user input — safe to interpolate.
|
|
34
|
-
for (const row of db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>) {
|
|
35
|
-
if (row.name === column) return true
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
25
|
+
import type { WOFDatabase } from "#schema"
|
|
26
|
+
import { hasColumn, hasTable } from "#sqlite-utils"
|
|
40
27
|
|
|
41
28
|
export interface SQLiteStreetNameLookupOpts {
|
|
42
29
|
/**
|
|
@@ -53,22 +40,22 @@ export interface SQLiteStreetNameLookupOpts {
|
|
|
53
40
|
* A {@link StreetLocalityEvidence} backed by a street-name SQLite index. Positive evidence only: any doubt (missing
|
|
54
41
|
* table, read miss) returns `false`, so the rerank fails open to the model's ranking.
|
|
55
42
|
*/
|
|
56
|
-
export class SQLiteStreetNameLookup implements StreetLocalityEvidence {
|
|
43
|
+
export class SQLiteStreetNameLookup implements StreetLocalityEvidence, Disposable {
|
|
57
44
|
readonly countries: ReadonlySet<string>
|
|
58
|
-
readonly #db:
|
|
59
|
-
readonly #byName: ReturnType<
|
|
60
|
-
readonly #byNameLocality: ReturnType<
|
|
61
|
-
readonly #byNamePostcode: ReturnType<
|
|
45
|
+
readonly #db: DatabaseClient<WOFDatabase>
|
|
46
|
+
readonly #byName: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
47
|
+
readonly #byNameLocality: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
48
|
+
readonly #byNamePostcode: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
62
49
|
|
|
63
50
|
constructor(dbPath: string, opts: SQLiteStreetNameLookupOpts = {}) {
|
|
64
51
|
this.countries = new Set([...(opts.countries ?? ["FR"])].map((c) => c.toUpperCase()))
|
|
65
|
-
this.#db = new
|
|
52
|
+
this.#db = new DatabaseClient<WOFDatabase>(dbPath, { readOnly: true })
|
|
66
53
|
const table = opts.table ?? "street_centroid"
|
|
67
54
|
|
|
68
|
-
// Degrade gracefully on an empty/tableless
|
|
55
|
+
// Degrade gracefully on an empty/tableless extract — a no-op miss, never a crash (#568 discipline).
|
|
69
56
|
if (hasTable(this.#db, table)) {
|
|
70
57
|
// Prefer the #727 phase-4c `name_key` column (foldStreetSurface, indexed by `idx_sc_name` for a direct seek);
|
|
71
|
-
// fall back to `street_norm` on a pre-rebuild
|
|
58
|
+
// fall back to `street_norm` on a pre-rebuild extract (a skip-scan, but correct). The fold used to build
|
|
72
59
|
// `name_key` MUST match `foldStreetSurface` here (the fold-parity contract).
|
|
73
60
|
const keyCol = hasColumn(this.#db, table, "name_key") ? "name_key" : "street_norm"
|
|
74
61
|
this.#byName = this.#db.prepare(`SELECT 1 FROM ${table} WHERE ${keyCol} = ? LIMIT 1`)
|
|
@@ -104,10 +91,7 @@ export class SQLiteStreetNameLookup implements StreetLocalityEvidence {
|
|
|
104
91
|
return this.#byName.get(norm) !== undefined
|
|
105
92
|
}
|
|
106
93
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
*/
|
|
110
|
-
close(): void {
|
|
111
|
-
this.#db.close()
|
|
94
|
+
[Symbol.dispose](): void {
|
|
95
|
+
this.#db[Symbol.dispose]()
|
|
112
96
|
}
|
|
113
97
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* THE street normalizer for the address-point tier (#476). One function, used by BOTH the
|
|
7
|
-
* builder (`scripts/build-address-point-
|
|
6
|
+
* THE street normalizer for the address-point tier (#476). One function, used by BOTH the extract
|
|
7
|
+
* builder (`scripts/build-address-point-extract.ts`) and the lookup tier (`address-point.ts`) —
|
|
8
8
|
* never two implementations (the PLACETYPE_ORDER lesson: parallel copies silently corrupt).
|
|
9
9
|
*
|
|
10
10
|
* Normalization contract (deliberately aggressive — both sides apply the same function, so
|
|
@@ -27,13 +27,13 @@ import type { Tagged } from "type-fest"
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* A place name folded by {@link normalizeLocalityForKey} — the value stored in, and required to probe, every
|
|
30
|
-
* `name_key`-style column: the candidate gazetteer, the postal-city side-index, the street-centroid
|
|
31
|
-
* chain's `parent_name_key`, and the address-point locality scope.
|
|
30
|
+
* `name_key`-style column: the candidate gazetteer, the postal-city side-index, the street-centroid extract, an
|
|
31
|
+
* ancestor chain's `parent_name_key`, and the address-point locality scope.
|
|
32
32
|
*
|
|
33
33
|
* The brand is here because the fold is applied at BUILD time and is therefore mandatory at QUERY time, while a
|
|
34
34
|
* near-miss approximation of it (`toLowerCase()`, `trim()`) is still a `string`: it binds to the parameter, returns
|
|
35
35
|
* fewer rows, and the shortfall reads as a coverage gap in the data rather than a defect in the probe. Requiring the
|
|
36
|
-
* brand at the
|
|
36
|
+
* brand at the boundary turns that silent under-match into a compile error. Mint one only by calling the fold.
|
|
37
37
|
*/
|
|
38
38
|
export type NameKey = Tagged<string, "NameKey">
|
|
39
39
|
|
|
@@ -64,8 +64,8 @@ const MIN_TOKENS_FOR_TAIL_MERGE = 3
|
|
|
64
64
|
/**
|
|
65
65
|
* Spelled ordinal street names → their digit-ordinal form ("tenth" → "10th"), applied ONLY when a street-type suffix
|
|
66
66
|
* follows (#723 admin-tail) — so the ordinal cross-streets common in grid cities ("Tenth Street", "Fifth Avenue") match
|
|
67
|
-
* the
|
|
68
|
-
* Bank Rd" stays "first national …"). Digit-source
|
|
67
|
+
* the extracts' digit keys, WITHOUT rewriting ordinal-WORD names where the next token is not a suffix ("First National
|
|
68
|
+
* Bank Rd" stays "first national …"). Digit-source extracts are unaffected (a digit token isn't in this map), so the
|
|
69
69
|
* existing keys need no rebuild; a future rebuild folds any spelled-source key the same way (the one-function
|
|
70
70
|
* discipline).
|
|
71
71
|
*/
|
|
@@ -123,7 +123,7 @@ export function normalizeStreetForKey(street: string): StreetKey {
|
|
|
123
123
|
if (!tokens.length) return "" as StreetKey
|
|
124
124
|
|
|
125
125
|
// Spelled-ordinal street names → digit form when a street suffix follows ("Tenth Street" →
|
|
126
|
-
// "10th street", #723).
|
|
126
|
+
// "10th street", #723). Conditioned on the next token being a suffix so ordinal-WORD names are untouched.
|
|
127
127
|
for (let i = 0; i < tokens.length - 1; i++) {
|
|
128
128
|
const digit = SPELLED_ORDINAL_TO_DIGIT.get(tokens[i]!)
|
|
129
129
|
|
|
@@ -195,6 +195,31 @@ export function normalizeStreetForKey(street: string): StreetKey {
|
|
|
195
195
|
*/
|
|
196
196
|
export type StreetLocale = "us" | "en" | "fr" | "de" | "nl" | "pl" | "vn" | "id"
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Country → street-locale registry surface for the acquisition SDKs (BAN, OSM). Each SDK keeps its own map — membership
|
|
200
|
+
* is a per-register decision — and this factory owns the lookup discipline: throw for an unsupported country rather
|
|
201
|
+
* than silently folding with the wrong rules, because a extract built with the wrong normalizer keys every street
|
|
202
|
+
* incorrectly and looks fine until a probe misses. `label` is the SDK's own registration instructions, appended to the
|
|
203
|
+
* error verbatim.
|
|
204
|
+
*/
|
|
205
|
+
export function createStreetLocaleRegistry(
|
|
206
|
+
registry: ReadonlyMap<string, StreetLocale>,
|
|
207
|
+
label: string
|
|
208
|
+
): { localeFor: (countryCode: string) => StreetLocale; supported: () => string[] } {
|
|
209
|
+
return {
|
|
210
|
+
localeFor: (countryCode) => {
|
|
211
|
+
const locale = registry.get(countryCode.toLowerCase())
|
|
212
|
+
|
|
213
|
+
if (!locale) {
|
|
214
|
+
throw new Error(`No street-normalization locale registered for country "${countryCode}". ${label}`)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return locale
|
|
218
|
+
},
|
|
219
|
+
supported: () => [...registry.keys()],
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
198
223
|
/**
|
|
199
224
|
* French street-type abbreviations → canonical full form, applied per token after {@link fold}. French address types
|
|
200
225
|
* LEAD the name ("Av. de…", "Bd …", "Pl. …") and "St"/"Ste" abbreviate Saint/Sainte inside names ("Rue St-Honoré" →
|
|
@@ -223,7 +248,7 @@ const FR_STREET_ABBREV = new Map<string, string>([
|
|
|
223
248
|
])
|
|
224
249
|
|
|
225
250
|
/**
|
|
226
|
-
* Polish leading street-type tokens, STRIPPED rather than expanded. Measured on the 5.56M-row PL OSM
|
|
251
|
+
* Polish leading street-type tokens, STRIPPED rather than expanded. Measured on the 5.56M-row PL OSM extract
|
|
227
252
|
* (2026-08-19): OSM Poland tags `addr:street` BARE — `ulica%` covers 22 rows and `ul.%` eight, so an EXPANSION rule
|
|
228
253
|
* makes a typed query ("ul. Świętokrzyska" → "ulica swietokrzyska") miss the 3,846 bare "swietokrzyska" rows. Stripping
|
|
229
254
|
* the leading type on BOTH sides keys typed and bare surfaces identically. The full words are stripped too: the
|
|
@@ -255,7 +280,7 @@ const ID_STREET_ABBREV = new Map<string, string>([
|
|
|
255
280
|
* {@link PL_LEADING_TYPE} for the measured reason expansion was wrong for this source.
|
|
256
281
|
* - **vn** — fold + đ→d AND ð→d (both non-decomposing, and OSM mixes the two codepoints inside single values — see the
|
|
257
282
|
* branch comment). Deliberately NO type-abbreviation map yet: the common abbreviation is the single letter "Đ." for
|
|
258
|
-
* Đường, and expanding a bare folded "d" token would rewrite initials — measure the miss rate on the built
|
|
283
|
+
* Đường, and expanding a bare folded "d" token would rewrite initials — measure the miss rate on the built extract
|
|
259
284
|
* before adding anything.
|
|
260
285
|
* - **id** — fold + expand leading type abbreviations (jl/jln→jalan, gg→gang); Indonesian street surfaces are otherwise
|
|
261
286
|
* ASCII-clean.
|
|
@@ -268,7 +293,7 @@ export function normalizeStreetForKeyLocale(street: string, locale: StreetLocale
|
|
|
268
293
|
// robustness. It also splits a hyphenated abbreviation ("St-Honoré" → "st honore") into tokens the
|
|
269
294
|
// per-locale type/Saint map can see. Letter maps for non-decomposing letters (ß, ł, đ) live in the
|
|
270
295
|
// per-locale branches, NEVER here: widening the shared pipeline would silently change keys under
|
|
271
|
-
// every already-built
|
|
296
|
+
// every already-built extract of the other locales.
|
|
272
297
|
const tokens = fold(street)
|
|
273
298
|
.replaceAll("ß", "ss")
|
|
274
299
|
.replaceAll("-", " ")
|
|
@@ -317,7 +342,7 @@ export function normalizeStreetForKeyLocale(street: string, locale: StreetLocale
|
|
|
317
342
|
break
|
|
318
343
|
case "vn":
|
|
319
344
|
// đ (U+0111, d-with-stroke) AND ð (U+00F0, eth): OSM Vietnamese data mixes the two visually
|
|
320
|
-
// identical codepoints inside single values — the 2026-08-19
|
|
345
|
+
// identical codepoints inside single values — the 2026-08-19 extract measured `Đường Trần Hưng
|
|
321
346
|
// Đạo` carrying d-with-stroke at the front and ETH in `Đạo`, splitting the country's most
|
|
322
347
|
// common street into two keys with the MAJORITY variant (630 vs 421 rows) unreachable by a
|
|
323
348
|
// correctly-typed query. No abbreviation map — see the locale table.
|
|
@@ -347,7 +372,7 @@ const FRENCH_LEAD_TYPE =
|
|
|
347
372
|
/^(?:rue|ruelle|av|ave|avenue|boul|bd|boulevard|ch|che|chemin|all[ée]e|imp|impasse|mont[ée]e|c[ôo]te|pl|place|prom|promenade|rang|rte|route|autoroute|carr[eé]|croissant|terrasse|sentier)(?=[\s.-]|$)/i
|
|
348
373
|
|
|
349
374
|
/**
|
|
350
|
-
* Surface-driven street-locale ROUTER for bilingual
|
|
375
|
+
* Surface-driven street-locale ROUTER for bilingual extracts — the Québec finishing move on the CA rooftop extract.
|
|
351
376
|
*
|
|
352
377
|
* A country registers ONE street locale, but Canada's street surfaces are two languages: under the `en` rules a French
|
|
353
378
|
* surface passes through mostly unchanged (both sides fold identically, so those rows stay reachable), and what breaks
|
|
@@ -355,11 +380,11 @@ const FRENCH_LEAD_TYPE =
|
|
|
355
380
|
* misses a full-word row and vice versa. Routing on the SURFACE (not the province) also carries bilingual NB and the
|
|
356
381
|
* French street names outside Québec for free.
|
|
357
382
|
*
|
|
358
|
-
* ONE function, called by the
|
|
383
|
+
* ONE function, called by the extract BUILDER and the query PROBE alike — the #861 discipline: routing is part of the
|
|
359
384
|
* fold contract, and two transcriptions of this predicate would diverge exactly where it matters. Only an `en` base
|
|
360
|
-
* re-routes: a `fr`/`de`/`nl`
|
|
385
|
+
* re-routes: a `fr`/`de`/`nl` extract already speaks its own rules, and the US pipeline stays untouched.
|
|
361
386
|
*
|
|
362
|
-
* Measured basis (CA
|
|
387
|
+
* Measured basis (CA extract, 2026-08-19): 183,963 distinct surfaces, 43,762 French-lead; 29,682 fold differently under
|
|
363
388
|
* fr-vs-en (888,265 rows), and the non-French half of those are English surfaces this router keeps on `en` unchanged.
|
|
364
389
|
*/
|
|
365
390
|
export function streetLocaleForSurface(street: string, base: StreetLocale): StreetLocale {
|
|
@@ -453,9 +478,9 @@ export function stripLocalityQualifier(locality: string): string {
|
|
|
453
478
|
* (the state abbreviation form) fold to `state route N…`. Only digit-leading route numbers fold — `State Street` and
|
|
454
479
|
* friends never match.
|
|
455
480
|
*
|
|
456
|
-
* Used by BOTH the segment-
|
|
457
|
-
* one-function discipline as {@link normalizeStreetForKey}. The address-point tier (#476) does NOT apply it yet:
|
|
458
|
-
* adopting it there requires a
|
|
481
|
+
* Used by BOTH the segment-extract builder (`scripts/build-interpolation-extract.ts`) and the interpolation lookup —
|
|
482
|
+
* same one-function discipline as {@link normalizeStreetForKey}. The address-point tier (#476) does NOT apply it yet:
|
|
483
|
+
* adopting it there requires a extract rebuild (noted on #483).
|
|
459
484
|
*
|
|
460
485
|
* A same-numbered US and state route stay DISTINCT keys (`us route 5` vs `state route 5`); only the BARE `route N` form
|
|
461
486
|
* is ambiguous (designator unknown) and it stays unfolded — a bare-route query therefore misses rather than guessing a
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
* Typed schema for the TIGER STREET-SEGMENT interpolation
|
|
7
|
-
* built by `scripts/build-interpolation-
|
|
6
|
+
* Typed schema for the TIGER STREET-SEGMENT interpolation extracts (`street-segments-<cc>-<st>.db`,
|
|
7
|
+
* built by `scripts/build-interpolation-extract.ts` from TIGER EDGES) — the #483 Method-3 fallback
|
|
8
8
|
* the resolver drops to when the address-point tier (Method 2) can't bracket. Single source of
|
|
9
9
|
* truth for the columns the BUILDER writes and the READER ({@link StreetInterpolator}) probes, so
|
|
10
10
|
* a column rename in one is a compile error in the other.
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import type { Kysely } from "kysely"
|
|
19
19
|
|
|
20
|
-
import type { RouteKey } from "
|
|
20
|
+
import type { RouteKey } from "#street/normalize"
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* One TIGER street-segment edge: a `(from_hn, to_hn)` house-number range on one `side` of a named street, with the
|
|
@@ -74,11 +74,11 @@ export interface StreetSegmentTable {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
|
-
* The
|
|
77
|
+
* The extract's single-row calibration metadata (#374 doctrine, 2026-07-26): the conformal radius multiplier is a
|
|
78
78
|
* property of the CALIBRATION SET the artifact was built against — so it ships IN the artifact (the pair-index δ
|
|
79
79
|
* precedent, `neural/pair-index-resolver.ts`), not in caller code. Written once by the builder; read at open time by
|
|
80
|
-
* {@link StreetInterpolator}.
|
|
81
|
-
* and callers fall back to the in-code per-region table (never patch shipped DBs — rebuild).
|
|
80
|
+
* {@link StreetInterpolator}. Extracts built before this table exists simply lack it — the reader degrades to
|
|
81
|
+
* `undefined` and callers fall back to the in-code per-region table (never patch shipped DBs — rebuild).
|
|
82
82
|
*/
|
|
83
83
|
export interface InterpCalibrationRow {
|
|
84
84
|
/**
|
|
@@ -147,7 +147,7 @@ export async function createStreetSegmentTable(db: Kysely<StreetSegmentDatabase>
|
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
149
|
* Create + populate the single-row `interp_calibration` metadata table (see {@link InterpCalibrationRow}) — called once
|
|
150
|
-
* by the
|
|
150
|
+
* by the extract builder, after the value is selected from the calibration source of record. Build-time only (async
|
|
151
151
|
* Kysely is fine here); the READ side is the raw sync probe in {@link StreetInterpolator}'s constructor, per the
|
|
152
152
|
* sync-by-interface doctrine.
|
|
153
153
|
*/
|
|
@@ -91,8 +91,8 @@ export interface PlaceCandidate {
|
|
|
91
91
|
/**
|
|
92
92
|
* STRICT encyclopedia-evidence importance in [0, 1], fan-out-guarded per #1497 — CARRIED, NEVER RANKED ON.
|
|
93
93
|
*
|
|
94
|
-
* RESERVED SLOT awaiting a strict-channel source: present only when a
|
|
95
|
-
* split columns, and no shipped
|
|
94
|
+
* RESERVED SLOT awaiting a strict-channel source: present only when a extract's `place_importance` table carries the
|
|
95
|
+
* split columns, and no shipped extract does — the FTS lookup's clauses emit NULL for everything today. `undefined`
|
|
96
96
|
* means either "no encyclopedia entry for this place" or "this gazetteer predates the split"; both are absence, and
|
|
97
97
|
* neither is 0. The BLENDED prior the ranking reads is {@link PlaceCandidate.importance}.
|
|
98
98
|
*
|
|
@@ -126,10 +126,17 @@ export interface PlaceCandidate {
|
|
|
126
126
|
* Admin-containment stamp (#1717 stage 2) — TRI-STATE, mirroring `ResolvedPlace.containedByQualifier` in
|
|
127
127
|
* `@mailwoman/core`: `true` = the ancestors sidecar vouches this candidate sits under the query's
|
|
128
128
|
* {@link FindPlaceQuery.regionQualifier}; `false` = evaluated and not vouched for; absent = never evaluated (no
|
|
129
|
-
* qualifier on the query, or an artifact without the sidecar). Absence is
|
|
130
|
-
*
|
|
129
|
+
* qualifier on the query, or an artifact without the sidecar). Absence is required — the resolver walk reads it as
|
|
130
|
+
* `unavailable`, never as "not contained".
|
|
131
131
|
*/
|
|
132
132
|
containedByQualifier?: boolean
|
|
133
|
+
/**
|
|
134
|
+
* The #1882 exemption's firing mark (#1893), mirroring `ResolvedPlace.variantAliasExempted` in `@mailwoman/core`:
|
|
135
|
+
* present only when this candidate's row would have taken the cross-country alias penalty and the exemption prevented
|
|
136
|
+
* it. Emitted by the candidate-table backend alone — the WASM FTS lookup never runs the ranker, and its candidates
|
|
137
|
+
* omit the field (not evaluated, never "did not fire").
|
|
138
|
+
*/
|
|
139
|
+
variantAliasExempted?: true
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
/**
|
|
@@ -179,8 +186,8 @@ export interface FindPlaceQuery {
|
|
|
179
186
|
*/
|
|
180
187
|
fuzzyCountry?: string
|
|
181
188
|
/**
|
|
182
|
-
* Restrict name matching to PRIMARY-keyed rows (#1632) — set by probes whose surface is a RE-READING (a token
|
|
183
|
-
* of a longer classified span), which never named an alias. See the ResolverBackend contract in
|
|
189
|
+
* Restrict name matching to PRIMARY-keyed rows (#1632) — set by probes whose surface is a RE-READING (a token taken
|
|
190
|
+
* out of a longer classified span), which never named an alias. See the ResolverBackend contract in
|
|
184
191
|
* `@mailwoman/core/resolver`.
|
|
185
192
|
*/
|
|
186
193
|
primaryOnly?: boolean
|
|
@@ -197,14 +204,14 @@ export interface FindPlaceQuery {
|
|
|
197
204
|
* Sibling postcode. When set on a `locality` query AND a `postcode_locality` table is present, triggers the
|
|
198
205
|
* coordinate-first soft-score path: postcode→candidate localities are injected and scored `0.6·S_pc + 0.3·S_name +
|
|
199
206
|
* 0.1·S_pop` against the FTS name-match set, recovering small localities the name-match alone misses. Ignored when no
|
|
200
|
-
* postcode_locality
|
|
207
|
+
* postcode_locality extract is present.
|
|
201
208
|
*/
|
|
202
209
|
postcode?: string
|
|
203
210
|
/**
|
|
204
211
|
* Postcode-containment coherence (#31, Mechanism 2) — when true on a locality query that also carries `postcode`,
|
|
205
|
-
* candidate rows within `
|
|
206
|
-
* rest appended in their original order. Set by the resolver from `ResolveOpts.postcodeContainmentCoherence`;
|
|
207
|
-
* → the population-first order is untouched (byte-identical).
|
|
212
|
+
* candidate rows within `POSTCODE_CONTAINMENT_THRESHOLD_KM` of the postcode's own centroid sort by distance first,
|
|
213
|
+
* the rest appended in their original order. Set by the resolver from `ResolveOpts.postcodeContainmentCoherence`;
|
|
214
|
+
* absent → the population-first order is untouched (byte-identical).
|
|
208
215
|
*/
|
|
209
216
|
postcodeContainmentCoherence?: boolean
|
|
210
217
|
/**
|
|
@@ -243,7 +250,6 @@ export interface FindPlaceQuery {
|
|
|
243
250
|
* interface is async even though `node:sqlite` is sync — leaves room for `Worker`-backed implementations later without
|
|
244
251
|
* a public API break.
|
|
245
252
|
*/
|
|
246
|
-
export interface PlaceLookup {
|
|
253
|
+
export interface PlaceLookup extends Disposable {
|
|
247
254
|
findPlace(query: FindPlaceQuery): Promise<PlaceCandidate[]>
|
|
248
|
-
close(): void
|
|
249
255
|
}
|