@mailwoman/resolver-wof-sqlite 9.2.0 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -19
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +25 -24
- package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
- package/lib/address/point.ts +328 -0
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +5 -4
- package/{build-candidate.ts → lib/build-candidate.ts} +99 -79
- 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/lib/candidate/extract-fold.ts +219 -0
- package/{candidate → lib/candidate}/name-roles.ts +17 -16
- package/{candidate → lib/candidate}/own-name.ts +2 -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} +84 -80
- package/{candidate-schema.ts → lib/candidate-schema.ts} +6 -6
- 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} +9 -13
- 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} +10 -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} +40 -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} +28 -26
- package/{lookup.ts → lib/lookup.ts} +130 -142
- 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 -16
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -29
- 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} +43 -14
- 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 -47
- package/{schema.ts → lib/schema.ts} +10 -0
- package/{search-fetch.ts → lib/search-fetch.ts} +29 -29
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -19
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
- package/{street-centroid.ts → lib/street/centroid.ts} +15 -22
- 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} +86 -20
- 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 -19
- package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
- package/lib/weights-overlay-linker.ts +879 -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} +12 -11
- 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} +19 -9
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +222 -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} +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 +32 -24
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +60 -54
- 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 +41 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/extract-fold.js +153 -0
- 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 +2 -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 +16 -14
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +67 -63
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +6 -6
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js +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 +7 -6
- 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 +5 -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} +9 -13
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +40 -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 +11 -10
- 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 +22 -21
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +103 -113
- 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 -6
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -4
- 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 +15 -7
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +28 -12
- 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 -9
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +6 -10
- 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} +7 -7
- 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} +38 -15
- package/out/street/normalize.d.ts.map +1 -0
- package/out/{street-normalize.js → street/normalize.js} +73 -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 +339 -86
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +465 -269
- package/address-point.ts +0 -218
- package/candidate/shard-fold.ts +0 -137
- 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 -140
- 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 +0 -104
- 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
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* Warwick in America the fame of Warwick, Rhode Island, which is the fan-out defect
|
|
28
28
|
* `importance-fanout.ts` documents one layer up, re-introduced at the join. So the group is
|
|
29
29
|
* disambiguated GEOGRAPHICALLY: the nearest centroid wins, and only within
|
|
30
|
-
* {@link
|
|
30
|
+
* {@link IMPORTANCE_JOIN_RADIUS_KM}. Two artifacts describing the same settlement put its centroid in
|
|
31
31
|
* almost the same place; two same-named towns in one country do not.
|
|
32
32
|
*
|
|
33
33
|
* ## What lands in the column
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
* A place with no match gets NULL. NULL is UNMEASURED, never zero — the consumer
|
|
41
41
|
* (`resolver/toponym-prior.ts`) leaves an unmeasured candidate exactly where population put it.
|
|
42
42
|
*/
|
|
43
|
-
import { DatabaseSync } from "node:sqlite";
|
|
44
43
|
import { haversineKm } from "@mailwoman/spatial";
|
|
45
|
-
import {
|
|
44
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
45
|
+
import { normalizeLocalityForKey } from "#street/normalize";
|
|
46
46
|
/**
|
|
47
47
|
* How far apart two artifacts may put the same place's centroid and still be read as the same place.
|
|
48
48
|
*
|
|
@@ -51,18 +51,18 @@ import { normalizeLocalityForKey } from "./street-normalize.js";
|
|
|
51
51
|
* country, placetype)`). The nearest-centroid distance is **exactly 0.00 km for 577,080 of them (56.6%)** — the two
|
|
52
52
|
* snapshots agree to the bit — and 656,755 (64.4%) are inside 500 m.
|
|
53
53
|
*
|
|
54
|
-
* What sets the
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
54
|
+
* What sets the radius is where that mode ENDS, and the per-kilometre density states. It falls from 1,076 places/km
|
|
55
|
+
* over 3–5 km to a trough of **441 places/km over 7–10 km**, then climbs back and flattens onto a plateau of 760–780
|
|
56
|
+
* places/km from 30 km out to 100 km and beyond. That plateau is the background rate of two DIFFERENT towns wearing one
|
|
57
|
+
* name in one country, and it does not decay with distance because there is no reason it should. 10 km is the floor
|
|
58
|
+
* between the two populations. Admitting it scores 679,163 places (66.6% of the matched set); pushing the radius to 25
|
|
59
|
+
* km buys 8,722 more, and by then better than half of each additional kilometre is the wrong town.
|
|
60
60
|
*
|
|
61
61
|
* The four-row bare-GB board is insensitive across this whole range — 5 km and 25 km were both measured and select
|
|
62
|
-
* identical rows — so the value is chosen by what the join MEANS, not by what it scores. The
|
|
63
|
-
* "this is the same place"; widening it past the floor starts handing one town's fame to another.
|
|
62
|
+
* identical rows — so the value is chosen by what the join MEANS, not by what it scores. The radius is the definition
|
|
63
|
+
* of "this is the same place"; widening it past the floor starts handing one town's fame to another.
|
|
64
64
|
*/
|
|
65
|
-
export const
|
|
65
|
+
export const IMPORTANCE_JOIN_RADIUS_KM = 10;
|
|
66
66
|
/**
|
|
67
67
|
* `(name_key, country, placetype)` → the scored places under it. The separator is U+0000, which no WOF name carries and
|
|
68
68
|
* no fold can produce, so the three fields can't smear into one another.
|
|
@@ -77,24 +77,24 @@ export class ImportanceIndex {
|
|
|
77
77
|
#groups;
|
|
78
78
|
stats;
|
|
79
79
|
/**
|
|
80
|
-
* Places {@link find} matched inside the
|
|
80
|
+
* Places {@link find} matched inside the radius.
|
|
81
81
|
*/
|
|
82
82
|
matched = 0;
|
|
83
83
|
/**
|
|
84
|
-
* Places {@link find} REFUSED — the key matched a scored group, but the nearest member of it was outside the
|
|
85
|
-
* it is a different place wearing the same name.
|
|
84
|
+
* Places {@link find} REFUSED — the key matched a scored group, but the nearest member of it was outside the radius,
|
|
85
|
+
* so it is a different place wearing the same name.
|
|
86
86
|
*
|
|
87
87
|
* This is the number worth watching across rebuilds. A jump means the score source and the admin source have drifted
|
|
88
|
-
* apart and the join is being asked to guess; it does not mean the
|
|
88
|
+
* apart and the join is being asked to guess; it does not mean the radius is too tight.
|
|
89
89
|
*/
|
|
90
|
-
|
|
90
|
+
refused = 0;
|
|
91
91
|
constructor(groups, stats) {
|
|
92
92
|
this.#groups = groups;
|
|
93
93
|
this.stats = stats;
|
|
94
94
|
}
|
|
95
95
|
/**
|
|
96
96
|
* The importance of the scored place nearest `(lat, lon)` sharing `name`'s folded key, `country` and `placetype`, or
|
|
97
|
-
* null when there is no such place within {@link
|
|
97
|
+
* null when there is no such place within {@link IMPORTANCE_JOIN_RADIUS_KM}.
|
|
98
98
|
*
|
|
99
99
|
* Null is UNMEASURED. Never substitute a zero, and never fall back to a population-derived value here — the source
|
|
100
100
|
* column already carries that fallback where it has one, and inventing a second one would make an absence
|
|
@@ -116,8 +116,8 @@ export class ImportanceIndex {
|
|
|
116
116
|
best = place;
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
if (!best || bestKm >
|
|
120
|
-
this.
|
|
119
|
+
if (!best || bestKm > IMPORTANCE_JOIN_RADIUS_KM) {
|
|
120
|
+
this.refused++;
|
|
121
121
|
return null;
|
|
122
122
|
}
|
|
123
123
|
this.matched++;
|
|
@@ -137,38 +137,33 @@ export class ImportanceIndex {
|
|
|
137
137
|
* 25 s.
|
|
138
138
|
*/
|
|
139
139
|
export function loadImportanceIndex(databasePath) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const key = groupKey(nameKey, row.country, row.placetype);
|
|
160
|
-
let group = groups.get(key);
|
|
161
|
-
if (!group) {
|
|
162
|
-
group = [];
|
|
163
|
-
groups.set(key, group);
|
|
164
|
-
}
|
|
165
|
-
group.push({ lat: Number(row.latitude), lon: Number(row.longitude), importance });
|
|
166
|
-
places++;
|
|
140
|
+
using db = new DatabaseClient(databasePath, { readOnly: true });
|
|
141
|
+
const groups = new Map();
|
|
142
|
+
let places = 0;
|
|
143
|
+
let unkeyable = 0;
|
|
144
|
+
for (const row of db
|
|
145
|
+
.prepare(`SELECT s.name AS name, s.country AS country, s.placetype AS placetype,
|
|
146
|
+
s.latitude AS latitude, s.longitude AS longitude, i.importance AS importance
|
|
147
|
+
FROM place_importance i JOIN spr s ON s.id = i.id
|
|
148
|
+
WHERE s.is_current != 0 AND s.is_deprecated = 0`)
|
|
149
|
+
.iterate()) {
|
|
150
|
+
const importance = Number(row.importance);
|
|
151
|
+
if (!Number.isFinite(importance))
|
|
152
|
+
continue;
|
|
153
|
+
const nameKey = normalizeLocalityForKey(String(row.name ?? ""));
|
|
154
|
+
if (!nameKey) {
|
|
155
|
+
unkeyable++;
|
|
156
|
+
continue;
|
|
167
157
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
158
|
+
const key = groupKey(nameKey, row.country, row.placetype);
|
|
159
|
+
let group = groups.get(key);
|
|
160
|
+
if (!group) {
|
|
161
|
+
group = [];
|
|
162
|
+
groups.set(key, group);
|
|
163
|
+
}
|
|
164
|
+
group.push({ lat: Number(row.latitude), lon: Number(row.longitude), importance });
|
|
165
|
+
places++;
|
|
172
166
|
}
|
|
167
|
+
return new ImportanceIndex(groups, { places, keys: groups.size, unkeyable });
|
|
173
168
|
}
|
|
174
169
|
//# sourceMappingURL=candidate-importance.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidate-importance.js","sourceRoot":"","sources":["../candidate-importance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"candidate-importance.js","sourceRoot":"","sources":["../lib/candidate-importance.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
6
|
* Node-side {@link PlaceLookup} over the byte-range CANDIDATE table (`build-candidate.ts`) — the
|
|
7
|
-
* SAME gazetteer the browser
|
|
8
|
-
* `
|
|
9
|
-
* instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the
|
|
10
|
-
* lookup surface, one artifact, one ranking.
|
|
7
|
+
* SAME gazetteer the browser runtime resolves against ({@link WOFCandidateTableLookup} in
|
|
8
|
+
* `packages/resolver-wof-wasm/lib/httpvfs/resolver.ts`), but reading a LOCAL `candidate.db` via
|
|
9
|
+
* `node:sqlite` instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the
|
|
10
|
+
* browser: one lookup surface, one artifact, one ranking.
|
|
11
11
|
*
|
|
12
12
|
* The query is a single contiguous probe on the `WITHOUT ROWID` B-tree keyed `(name_key,
|
|
13
13
|
* country_id, region_id, placetype_id, neg_rank, spr_id)`. `name_key` is the SHARED
|
|
@@ -22,20 +22,22 @@
|
|
|
22
22
|
* stored bbox and the locality query is point-in-bbox-filtered on the candidate centroid (the
|
|
23
23
|
* `bbox` field on {@link FindPlaceQuery}).
|
|
24
24
|
*/
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import type {
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
import { type Ancestor, type GazetteerArtifactCoverage } from "@mailwoman/core/resolver";
|
|
26
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
27
|
+
import type { PathBuilderLike } from "path-ts";
|
|
28
|
+
import type { CandidateDatabase } from "#candidate-schema";
|
|
29
|
+
import type { FindPlaceQuery, PlaceCandidate, PlaceLookup } from "#types";
|
|
30
|
+
export { rankByPrimaryPreference } from "#primary-preference";
|
|
31
|
+
export type { RankedRow } from "#primary-preference";
|
|
30
32
|
export interface WOFCandidateTableLookupOpts {
|
|
31
33
|
/**
|
|
32
34
|
* Path to a `candidate.db` built by `build-candidate.ts`. Opened read-only.
|
|
33
35
|
*/
|
|
34
|
-
databasePath?:
|
|
36
|
+
databasePath?: PathBuilderLike;
|
|
35
37
|
/**
|
|
36
38
|
* Pre-opened handle (tests / shared connections). Mutually exclusive with `databasePath`.
|
|
37
39
|
*/
|
|
38
|
-
database?:
|
|
40
|
+
database?: DatabaseClient<CandidateDatabase>;
|
|
39
41
|
/**
|
|
40
42
|
* #1882 opt-in: exempt `name_role = 'variant'` aliases — the holder's own primary name in another orthography,
|
|
41
43
|
* stamped by the build's own-name detector — from the cross-country primary-preference penalty. No-ops on an artifact
|
|
@@ -47,12 +49,12 @@ export interface WOFCandidateTableLookupOpts {
|
|
|
47
49
|
* Node {@link PlaceLookup} over `candidate.db`. Drop-in for {@link WOFSQLitePlaceLookup} in `createWOFResolver(backend)`
|
|
48
50
|
* — same `findPlace` contract, population-first ranking.
|
|
49
51
|
*/
|
|
50
|
-
export declare class WOFCandidateTableLookup implements PlaceLookup {
|
|
52
|
+
export declare class WOFCandidateTableLookup implements PlaceLookup, Disposable {
|
|
51
53
|
#private;
|
|
52
54
|
/**
|
|
53
55
|
* Facts this candidate DB declares about itself — the coverage manifest (`country_coverage` + `country_bbox`) the
|
|
54
56
|
* gazetteer build emits, read once at open. `undefined` when the artifact predates the manifest, so every consumer
|
|
55
|
-
* (the hard-country coverage
|
|
57
|
+
* (the hard-country coverage check, guard-B plausibility) falls back to its code constants byte-identically.
|
|
56
58
|
*/
|
|
57
59
|
readonly artifactCoverage: GazetteerArtifactCoverage | undefined;
|
|
58
60
|
/**
|
|
@@ -69,6 +71,6 @@ export declare class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
69
71
|
readonly ancestors: ((id: number | string) => Ancestor[]) | undefined;
|
|
70
72
|
constructor(opts: WOFCandidateTableLookupOpts);
|
|
71
73
|
findPlace(query: FindPlaceQuery): Promise<PlaceCandidate[]>;
|
|
72
|
-
|
|
74
|
+
[Symbol.dispose](): void;
|
|
73
75
|
}
|
|
74
76
|
//# sourceMappingURL=candidate-lookup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidate-lookup.d.ts","sourceRoot":"","sources":["../candidate-lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"candidate-lookup.d.ts","sourceRoot":"","sources":["../lib/candidate-lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAEN,KAAK,QAAQ,EACb,KAAK,yBAAyB,EAE9B,MAAM,0BAA0B,CAAA;AAKjC,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAU9C,OAAO,KAAK,EAAE,iBAAiB,EAAwD,MAAM,mBAAmB,CAAA;AAQhH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAgB,MAAM,QAAQ,CAAA;AAEvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,2BAA2B;IAC3C;;OAEG;IACH,YAAY,CAAC,EAAE,eAAe,CAAA;IAC9B;;OAEG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAA;IAC5C;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAiFD;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,WAAW,EAAE,UAAU;;IA6BtE;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,yBAAyB,GAAG,SAAS,CAAA;IAsChE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,KAAK,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAA;gBAEzD,IAAI,EAAE,2BAA2B;IAsVvC,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAmYjE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;CAGxB"}
|
package/out/candidate-lookup.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
6
|
* Node-side {@link PlaceLookup} over the byte-range CANDIDATE table (`build-candidate.ts`) — the
|
|
7
|
-
* SAME gazetteer the browser
|
|
8
|
-
* `
|
|
9
|
-
* instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the
|
|
10
|
-
* lookup surface, one artifact, one ranking.
|
|
7
|
+
* SAME gazetteer the browser runtime resolves against ({@link WOFCandidateTableLookup} in
|
|
8
|
+
* `packages/resolver-wof-wasm/lib/httpvfs/resolver.ts`), but reading a LOCAL `candidate.db` via
|
|
9
|
+
* `node:sqlite` instead of sql.js-httpvfs. This is what makes the server/CLI resolver match the
|
|
10
|
+
* browser: one lookup surface, one artifact, one ranking.
|
|
11
11
|
*
|
|
12
12
|
* The query is a single contiguous probe on the `WITHOUT ROWID` B-tree keyed `(name_key,
|
|
13
13
|
* country_id, region_id, placetype_id, neg_rank, spr_id)`. `name_key` is the SHARED
|
|
@@ -22,21 +22,22 @@
|
|
|
22
22
|
* stored bbox and the locality query is point-in-bbox-filtered on the candidate centroid (the
|
|
23
23
|
* `bbox` field on {@link FindPlaceQuery}).
|
|
24
24
|
*/
|
|
25
|
-
import {
|
|
25
|
+
import { expandPlacetypeFilter, referentialFromPopulation, } from "@mailwoman/core/resolver";
|
|
26
|
+
import { allRows } from "@mailwoman/core/utils";
|
|
26
27
|
import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators";
|
|
27
|
-
import {
|
|
28
|
+
import { partitionByContainment } from "@mailwoman/resolver";
|
|
28
29
|
import { haversineKm } from "@mailwoman/spatial";
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import { POSTAL_CITY_CANDIDATE_TABLE } from "
|
|
34
|
-
import { rankByPrimaryPreference, RERANK_FETCH } from "
|
|
35
|
-
import { applyProximityRerank } from "
|
|
36
|
-
import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "
|
|
37
|
-
import {
|
|
38
|
-
import { normalizeLocalityForKey, stripLocalityQualifier } from "
|
|
39
|
-
export { rankByPrimaryPreference } from "
|
|
30
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client";
|
|
31
|
+
import { CANDIDATE_ANCESTOR_TABLE, CANDIDATE_INTERVAL_TABLE, intervalContains, } from "#candidate-ancestors-schema";
|
|
32
|
+
import { CANDIDATE_FTS_TABLE } from "#candidate-fts";
|
|
33
|
+
import { readGazetteerCoverageManifest } from "#coverage-manifest-schema";
|
|
34
|
+
import { POSTAL_CITY_CANDIDATE_TABLE } from "#postal/city-candidate-schema";
|
|
35
|
+
import { rankByPrimaryPreference, RERANK_FETCH } from "#primary-preference";
|
|
36
|
+
import { applyProximityRerank } from "#proximity-rerank";
|
|
37
|
+
import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "#region-keys";
|
|
38
|
+
import { hasColumn, hasTable } from "#sqlite-utils";
|
|
39
|
+
import { normalizeLocalityForKey, stripLocalityQualifier } from "#street/normalize";
|
|
40
|
+
export { rankByPrimaryPreference } from "#primary-preference";
|
|
40
41
|
/**
|
|
41
42
|
* FTS5-trigram over-fetch before the WORD-LEVEL re-rank. The trigram index stays the candidate GENERATOR (it is what
|
|
42
43
|
* the artifact carries); the scoring moved off trigram-Jaccard on 2026-08-12 (#1614), which the aucklnad receipts
|
|
@@ -60,12 +61,12 @@ function wordFuzzySimilarity(a, b) {
|
|
|
60
61
|
return Math.max(jaroWinkler(a, b), levenshteinSimilarity(a, b));
|
|
61
62
|
}
|
|
62
63
|
/**
|
|
63
|
-
* Postcode-containment re-rank
|
|
64
|
-
* (`
|
|
65
|
-
* the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
|
|
66
|
-
* mechanisms disagree about what is proximal.
|
|
64
|
+
* Postcode-containment re-rank check radius (km) — the SAME value the resolver's country pass measures at
|
|
65
|
+
* (`POSTCODE_COUNTRY_COHERENCE_THRESHOLD_KM`, resolver/postcode-country-coherence.ts): a locality within this distance
|
|
66
|
+
* of the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
|
|
67
|
+
* two mechanisms disagree about what is proximal.
|
|
67
68
|
*/
|
|
68
|
-
const
|
|
69
|
+
const POSTCODE_CONTAINMENT_THRESHOLD_KM = 25;
|
|
69
70
|
/**
|
|
70
71
|
* Unpadded character-trigrams of `s`, OR'd into an FTS5 trigram MATCH query (each quoted so FTS treats it as a literal
|
|
71
72
|
* term). Returns "" when `s` is shorter than a trigram or yields no clean grams — the caller then skips the fuzzy
|
|
@@ -87,7 +88,11 @@ function ftsTrigramQuery(s) {
|
|
|
87
88
|
*/
|
|
88
89
|
export class WOFCandidateTableLookup {
|
|
89
90
|
#db;
|
|
90
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
|
|
93
|
+
* ownership is membership rather than a flag a later branch has to check.
|
|
94
|
+
*/
|
|
95
|
+
#resources = new DisposableStack();
|
|
91
96
|
#countryToID = new Map();
|
|
92
97
|
#idToCountry = new Map();
|
|
93
98
|
#placetypeToID = new Map();
|
|
@@ -103,22 +108,22 @@ export class WOFCandidateTableLookup {
|
|
|
103
108
|
*/
|
|
104
109
|
#ftsProbe;
|
|
105
110
|
/**
|
|
106
|
-
* Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox).
|
|
107
|
-
* fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
|
|
108
|
-
* that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
|
|
109
|
-
* not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
|
|
110
|
-
* country-agnostic retry. Prepared only alongside `#ftsProbe`.
|
|
111
|
+
* Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox). Checks the
|
|
112
|
+
* fuzzy fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
|
|
113
|
+
* A name that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
|
|
114
|
+
* Austria"→IT), not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
|
|
115
|
+
* cascade's country-agnostic retry. Prepared only alongside `#ftsProbe`.
|
|
111
116
|
*/
|
|
112
117
|
#nameKeyExistsProbe;
|
|
113
118
|
/**
|
|
114
119
|
* Facts this candidate DB declares about itself — the coverage manifest (`country_coverage` + `country_bbox`) the
|
|
115
120
|
* gazetteer build emits, read once at open. `undefined` when the artifact predates the manifest, so every consumer
|
|
116
|
-
* (the hard-country coverage
|
|
121
|
+
* (the hard-country coverage check, guard-B plausibility) falls back to its code constants byte-identically.
|
|
117
122
|
*/
|
|
118
123
|
artifactCoverage;
|
|
119
124
|
/**
|
|
120
125
|
* `", importance"` when this artifact carries the #28 fame column, `""` when it does not — spliced into the probe's
|
|
121
|
-
* SELECT list. Existence-
|
|
126
|
+
* SELECT list. Existence-restricted exactly like `#ftsProbe` and `#postalCityProbe` above, and for the same reason: a
|
|
122
127
|
* candidate.db built before the column is a valid artifact, and naming a column it lacks would turn a stale gazetteer
|
|
123
128
|
* into `no such column` on the first keystroke rather than into "no fame signal", which is what it is.
|
|
124
129
|
*/
|
|
@@ -141,9 +146,9 @@ export class WOFCandidateTableLookup {
|
|
|
141
146
|
#ancestorsCache = new Map();
|
|
142
147
|
/**
|
|
143
148
|
* Prepared interval-label probe over `candidate_interval` — `undefined` when the artifact predates the sidecar, which
|
|
144
|
-
* is what makes the admin-containment re-rank (#1717 stage 2) capability-
|
|
149
|
+
* is what makes the admin-containment re-rank (#1717 stage 2) capability-restricted: without it,
|
|
145
150
|
* `FindPlaceQuery.regionQualifier` is ignored, no candidate carries a `containedByQualifier` stamp, and the resolver
|
|
146
|
-
* walk reports the
|
|
151
|
+
* walk reports the change `unavailable` instead of silently dead.
|
|
147
152
|
*/
|
|
148
153
|
#intervalProbe;
|
|
149
154
|
#intervalCache = new Map();
|
|
@@ -168,11 +173,9 @@ export class WOFCandidateTableLookup {
|
|
|
168
173
|
constructor(opts) {
|
|
169
174
|
if (opts.database) {
|
|
170
175
|
this.#db = opts.database;
|
|
171
|
-
this.#ownsDB = false;
|
|
172
176
|
}
|
|
173
177
|
else if (opts.databasePath) {
|
|
174
|
-
this.#db = new
|
|
175
|
-
this.#ownsDB = true;
|
|
178
|
+
this.#db = this.#resources.use(new DatabaseClient(opts.databasePath, { readOnly: true }));
|
|
176
179
|
}
|
|
177
180
|
else {
|
|
178
181
|
throw new Error("WOFCandidateTableLookup needs `databasePath` or `database`");
|
|
@@ -204,7 +207,7 @@ export class WOFCandidateTableLookup {
|
|
|
204
207
|
this.#hasNameRole = hasColumn(this.#db, "candidate", "name_role");
|
|
205
208
|
this.#variantAliasExemption = opts.variantAliasExemption === true;
|
|
206
209
|
this.#roleSelect = this.#hasNameRole ? ", name_role" : "";
|
|
207
|
-
// Ancestors sidecar (#1717): existence-
|
|
210
|
+
// Ancestors sidecar (#1717): existence-restricted like the probes above, and the CAPABILITY checks with
|
|
208
211
|
// it — see the `ancestors` property doc for why an older artifact must read as "no ancestors()"
|
|
209
212
|
// rather than as a method that answers [] everywhere.
|
|
210
213
|
if (hasTable(this.#db, CANDIDATE_ANCESTOR_TABLE)) {
|
|
@@ -212,7 +215,7 @@ export class WOFCandidateTableLookup {
|
|
|
212
215
|
" WHERE spr_id = ? ORDER BY depth ASC");
|
|
213
216
|
this.ancestors = (id) => this.#ancestorLineage(id);
|
|
214
217
|
}
|
|
215
|
-
// Admin-containment re-rank (#1717 stage 2):
|
|
218
|
+
// Admin-containment re-rank (#1717 stage 2): conditioned on the interval half of the sidecar (built in
|
|
216
219
|
// the same pass as the closure rows; probed separately so a hand-degraded artifact degrades
|
|
217
220
|
// truthfully) AND on the placetype dictionary carrying the qualifier band at all.
|
|
218
221
|
if (this.#ancestorsProbe && hasTable(this.#db, CANDIDATE_INTERVAL_TABLE)) {
|
|
@@ -224,7 +227,7 @@ export class WOFCandidateTableLookup {
|
|
|
224
227
|
this.#qualifierProbe = this.#db.prepare(`SELECT DISTINCT spr_id FROM candidate WHERE name_key = ? AND placetype_id IN (${bandIDs.join(",")}) LIMIT 8`);
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
|
-
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-
|
|
230
|
+
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-restricted like
|
|
228
231
|
// the probes above — a candidate.db built before the manifest reads `undefined` and consumers keep
|
|
229
232
|
// their code-constant fallbacks byte-identically.
|
|
230
233
|
this.artifactCoverage = readGazetteerCoverageManifest(this.#db);
|
|
@@ -289,7 +292,7 @@ export class WOFCandidateTableLookup {
|
|
|
289
292
|
* Is `sprID` contained by ANY of the qualifier's rows? Interval first — {@link intervalContains}, O(1), reflexive —
|
|
290
293
|
* then the closure rows where intervals abstain: the interval forest encodes only the CANONICAL parent per place, so
|
|
291
294
|
* a `false` there means "not contained along the canonical hierarchy", and the chain probe (one clustered read of
|
|
292
|
-
* ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that
|
|
295
|
+
* ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that determines the result.
|
|
293
296
|
*/
|
|
294
297
|
#containedByQualifier(sprID, qualifierIDs, qualifierLabels) {
|
|
295
298
|
if (qualifierIDs.has(sprID))
|
|
@@ -353,7 +356,7 @@ export class WOFCandidateTableLookup {
|
|
|
353
356
|
// cannot reach a neighbourhood-tier namesake, so a CONTAINED one is structurally invisible no matter
|
|
354
357
|
// how the list reorders — the Astoria class: Queens' Astoria is a WOF neighbourhood, and the walk
|
|
355
358
|
// answered the Oregon locality under `qualifier="NY"` because nothing in the pool sat under NY. The
|
|
356
|
-
// widening is injection-only and triple-
|
|
359
|
+
// widening is injection-only and triple-conditioned: the band is explicit (neighbourhood/macrohood/microhood
|
|
357
360
|
// — never region or country tiers), admission still requires the sidecar's containment proof, and only
|
|
358
361
|
// primary-keyed rows enter (an alias-keyed neighbourhood is the #1626 scrape class). Recall can only
|
|
359
362
|
// widen, and only toward rows the qualifier vouches for. `opts.shapeFilters`' bbox clause is
|
|
@@ -439,7 +442,7 @@ export class WOFCandidateTableLookup {
|
|
|
439
442
|
return [];
|
|
440
443
|
// #741: postcode-keyed postal-city alias. An exact `(name_key, postcode)` hit resolves a
|
|
441
444
|
// user-typed POSTAL city ("Antioch", 37013) to the geographic locality the postcode sits in
|
|
442
|
-
// ("Nashville"), bypassing the population/region ranking that can't see the postcode.
|
|
445
|
+
// ("Nashville"), bypassing the population/region ranking that can't see the postcode. Conditioned on
|
|
443
446
|
// the side-index being present, a postcode in the query, and a locality-tier request — so the
|
|
444
447
|
// common (no-postcode / non-locality) path is untouched. A hit short-circuits: the postcode is
|
|
445
448
|
// an exact, high-confidence disambiguator, so we return the single geographic locality.
|
|
@@ -465,7 +468,7 @@ export class WOFCandidateTableLookup {
|
|
|
465
468
|
// SHAPE subset (placetype/bbox/primary — everything but the country scope) is kept separately
|
|
466
469
|
// because the admin-containment injection probe (#1717 stage 2) runs under the shape conds
|
|
467
470
|
// WITHOUT the country: bypassing a locale-inferred country scope for a qualifier-vouched
|
|
468
|
-
// candidate is the
|
|
471
|
+
// candidate is the change's whole point and the one filter injection may cross.
|
|
469
472
|
const filters = [];
|
|
470
473
|
const filterParams = [];
|
|
471
474
|
const shapeFilters = [];
|
|
@@ -495,7 +498,7 @@ export class WOFCandidateTableLookup {
|
|
|
495
498
|
shapeParams.push(b.minLat, b.maxLat, b.minLon, b.maxLon);
|
|
496
499
|
}
|
|
497
500
|
// The re-reading guard (#1632, the #1626 rationale generalized to the caller): a probe whose surface
|
|
498
|
-
// is a token
|
|
501
|
+
// is a token taken out of a longer classified span never NAMED an alias, so alias-keyed rows must not
|
|
499
502
|
// answer it — 'Savile Row''s token 'Row' resolved Rhu, Scotland (585 km) through the village's
|
|
500
503
|
// historical-name alias key. Whole-input bare probes never set this, keeping the exonym recall the
|
|
501
504
|
// #1546 note protects (Москва's alias rows answer 'Moscow').
|
|
@@ -577,7 +580,7 @@ export class WOFCandidateTableLookup {
|
|
|
577
580
|
// the same on either backend. The country/placetype/bbox/region filters still apply via `probe`.
|
|
578
581
|
// Skipped when the index is absent (byte-stable for an older candidate.db).
|
|
579
582
|
//
|
|
580
|
-
//
|
|
583
|
+
// Condition: only when the name doesn't exist in the gazetteer AT ALL (unfiltered). A name that exists
|
|
581
584
|
// but missed under the active country/placetype/bbox filter is a FILTER miss, not a spelling miss
|
|
582
585
|
// — fuzzing it scrapes an unrelated same-filter place ("Vienna, Austria" misrouted to IT would
|
|
583
586
|
// pull a tiny Italian name_key near Siena) and masks the cascade's country-agnostic retry that
|
|
@@ -624,7 +627,7 @@ export class WOFCandidateTableLookup {
|
|
|
624
627
|
};
|
|
625
628
|
let rows = cascade(regionParentID);
|
|
626
629
|
// #1731: whether the rows the caller receives came from the UNSCOPED fallback below — the backend's
|
|
627
|
-
// interior
|
|
630
|
+
// interior check the resolver-side trace (#1721) cannot otherwise see. Stamped onto every returned
|
|
628
631
|
// place, because the re-admission path is exactly where a wrong-instance namesake enters.
|
|
629
632
|
let regionScopeMiss = false;
|
|
630
633
|
// Region-scope fallback: if scoping to the parent region found nothing across the whole cascade, retry
|
|
@@ -639,8 +642,8 @@ export class WOFCandidateTableLookup {
|
|
|
639
642
|
// holds 75001, not the one that holds a 75001-free namesake). The resolver sends this flag on locality
|
|
640
643
|
// lookups when `ResolveOpts.postcodeContainmentCoherence` is on. Strictly beneath the #741 postal-city
|
|
641
644
|
// short-circuit above — an exact (name, postcode) hit IS the answer and outranks any re-rank — and after
|
|
642
|
-
// the region-scope fallback, so it sees the final row set. Rows within the
|
|
643
|
-
// the out-
|
|
645
|
+
// the region-scope fallback, so it sees the final row set. Rows within the radius sort by distance first;
|
|
646
|
+
// the out-of-radius tail keeps its original population-first order. No in-radius row, or no postcode row in
|
|
644
647
|
// the candidate table → unchanged (byte-identical to the flag-off path).
|
|
645
648
|
if (query.postcode &&
|
|
646
649
|
query.postcodeContainmentCoherence === true &&
|
|
@@ -648,29 +651,29 @@ export class WOFCandidateTableLookup {
|
|
|
648
651
|
rows.length > 1) {
|
|
649
652
|
const anchor = this.#postcodeAnchor(query.postcode, query.country);
|
|
650
653
|
if (anchor) {
|
|
651
|
-
const
|
|
652
|
-
const
|
|
654
|
+
const insideThreshold = [];
|
|
655
|
+
const outsideThreshold = [];
|
|
653
656
|
for (const row of rows) {
|
|
654
657
|
const distanceKm = haversineKm(anchor.lat, anchor.lon, Number(row.latitude), Number(row.longitude));
|
|
655
|
-
if (distanceKm <=
|
|
656
|
-
|
|
658
|
+
if (distanceKm <= POSTCODE_CONTAINMENT_THRESHOLD_KM) {
|
|
659
|
+
insideThreshold.push({ row, distanceKm });
|
|
657
660
|
}
|
|
658
661
|
else {
|
|
659
|
-
|
|
662
|
+
outsideThreshold.push(row);
|
|
660
663
|
}
|
|
661
664
|
}
|
|
662
|
-
if (
|
|
665
|
+
if (insideThreshold.length) {
|
|
663
666
|
// oxlint-disable-next-line unicorn/no-array-sort -- sorts a freshly-built array; toSorted would double-allocate on a hot path
|
|
664
|
-
|
|
665
|
-
rows = [...
|
|
667
|
+
insideThreshold.sort((a, b) => a.distanceKm - b.distanceKm);
|
|
668
|
+
rows = [...insideThreshold.map(({ row }) => row), ...outsideThreshold];
|
|
666
669
|
}
|
|
667
670
|
}
|
|
668
671
|
}
|
|
669
672
|
// Admin-containment re-rank (#1717 stage 2): LAST, on the final row set — the qualifier is the
|
|
670
673
|
// address's outermost explicit statement, so its partition outranks the postcode-proximity order
|
|
671
|
-
// above (contained rows keep that order among themselves). Capability-
|
|
674
|
+
// above (contained rows keep that order among themselves). Capability-conditioned on the sidecar
|
|
672
675
|
// (`#qualifierProbe`); when the artifact predates it, `regionQualifier` is ignored, no stamp is
|
|
673
|
-
// written, and the resolver walk reports the
|
|
676
|
+
// written, and the resolver walk reports the change `unavailable`.
|
|
674
677
|
if (query.regionQualifier?.trim() && this.#qualifierProbe && this.#wantsLocality(query.placetype)) {
|
|
675
678
|
rows = this.#applyAdminContainment(rows, query.regionQualifier.trim(), query.country, {
|
|
676
679
|
nameKey,
|
|
@@ -686,13 +689,13 @@ export class WOFCandidateTableLookup {
|
|
|
686
689
|
id: Number(row.spr_id),
|
|
687
690
|
name: String(row.name ?? ""),
|
|
688
691
|
placetype: (this.#idToPlacetype.get(Number(row.placetype_id)) ?? ""),
|
|
689
|
-
// Surfaced so the cascade can country-
|
|
692
|
+
// Surfaced so the cascade can country-restrict a postcode by the resolved locality (an ambiguous
|
|
690
693
|
// international postcode like 10115 = Berlin DE AND New York US must not out-resolve the city).
|
|
691
694
|
country: this.#idToCountry.get(Number(row.country_id)) ?? "",
|
|
692
695
|
lat: Number(row.latitude),
|
|
693
696
|
lon: Number(row.longitude),
|
|
694
697
|
// `score` stays the RAW population rank (`-neg_rank`) — it feeds the resolver walk's absolute
|
|
695
|
-
// `minWinningScore`
|
|
698
|
+
// `minWinningScore` floor (`resolve.ts`), which must see real prominence, never a penalized value.
|
|
696
699
|
score: -Number(row.neg_rank),
|
|
697
700
|
// `prominence` carries the bounded cross-country primary preference (the effective, penalty-adjusted
|
|
698
701
|
// rank). The walk ORDERS candidates by `prominence ?? score` (`resolve.ts`), so this is what makes the
|
|
@@ -714,6 +717,9 @@ export class WOFCandidateTableLookup {
|
|
|
714
717
|
// asked (a `regionQualifier` query over a sidecar-bearing artifact); its absence is what
|
|
715
718
|
// the resolver walk reports as `unavailable` (meaning-of-zero).
|
|
716
719
|
...(row.containedByQualifier === undefined ? {} : { containedByQualifier: row.containedByQualifier }),
|
|
720
|
+
// #1893 — the exemption's firing mark, carried only when the ranker actually spared this row
|
|
721
|
+
// the cross-country penalty (see RankedRow.variantExempted).
|
|
722
|
+
...(row.variantExempted ? { variantAliasExempted: true } : {}),
|
|
717
723
|
// The two-score split's carry (ROAD_TO_V9 §2). `referential` names the prominence this
|
|
718
724
|
// backend has always ordered by — `neg_rank` IS `-log10(population + 1)`, so the score and
|
|
719
725
|
// the sort key are two readings of the same number.
|
|
@@ -755,10 +761,8 @@ export class WOFCandidateTableLookup {
|
|
|
755
761
|
}
|
|
756
762
|
return candidates;
|
|
757
763
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
this.#db.close();
|
|
761
|
-
}
|
|
764
|
+
[Symbol.dispose]() {
|
|
765
|
+
this.#resources[Symbol.dispose]();
|
|
762
766
|
}
|
|
763
767
|
}
|
|
764
768
|
//# sourceMappingURL=candidate-lookup.js.map
|