@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
|
@@ -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
|
|
@@ -23,16 +23,18 @@
|
|
|
23
23
|
* `bbox` field on {@link FindPlaceQuery}).
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { DatabaseSync } from "node:sqlite"
|
|
27
|
-
|
|
28
|
-
import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators"
|
|
29
26
|
import {
|
|
30
27
|
expandPlacetypeFilter,
|
|
31
|
-
partitionByContainment,
|
|
32
28
|
type Ancestor,
|
|
33
29
|
type GazetteerArtifactCoverage,
|
|
34
|
-
|
|
30
|
+
referentialFromPopulation,
|
|
31
|
+
} from "@mailwoman/core/resolver"
|
|
32
|
+
import { allRows } from "@mailwoman/core/utils"
|
|
33
|
+
import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators"
|
|
34
|
+
import { partitionByContainment } from "@mailwoman/resolver"
|
|
35
35
|
import { haversineKm } from "@mailwoman/spatial"
|
|
36
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
37
|
+
import type { PathBuilderLike } from "path-ts"
|
|
36
38
|
|
|
37
39
|
import {
|
|
38
40
|
CANDIDATE_ANCESTOR_TABLE,
|
|
@@ -40,31 +42,30 @@ import {
|
|
|
40
42
|
intervalContains,
|
|
41
43
|
type CandidateAncestorTable,
|
|
42
44
|
type IntervalLabel,
|
|
43
|
-
} from "
|
|
44
|
-
import { CANDIDATE_FTS_TABLE } from "
|
|
45
|
-
import type { CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "
|
|
46
|
-
import { readGazetteerCoverageManifest } from "
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
export {
|
|
57
|
-
export type { RankedRow } from "./primary-preference.ts"
|
|
45
|
+
} from "#candidate-ancestors-schema"
|
|
46
|
+
import { CANDIDATE_FTS_TABLE } from "#candidate-fts"
|
|
47
|
+
import type { CandidateDatabase, CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "#candidate-schema"
|
|
48
|
+
import { readGazetteerCoverageManifest } from "#coverage-manifest-schema"
|
|
49
|
+
import { POSTAL_CITY_CANDIDATE_TABLE, type PostalCityCandidateTable } from "#postal/city-candidate-schema"
|
|
50
|
+
import { rankByPrimaryPreference, type RankedRow, RERANK_FETCH } from "#primary-preference"
|
|
51
|
+
import { applyProximityRerank } from "#proximity-rerank"
|
|
52
|
+
import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "#region-keys"
|
|
53
|
+
import { hasColumn, hasTable } from "#sqlite-utils"
|
|
54
|
+
import { type NameKey, normalizeLocalityForKey, stripLocalityQualifier } from "#street/normalize"
|
|
55
|
+
import type { FindPlaceQuery, PlaceCandidate, PlaceLookup, WOFPlacetype } from "#types"
|
|
56
|
+
|
|
57
|
+
export { rankByPrimaryPreference } from "#primary-preference"
|
|
58
|
+
export type { RankedRow } from "#primary-preference"
|
|
58
59
|
|
|
59
60
|
export interface WOFCandidateTableLookupOpts {
|
|
60
61
|
/**
|
|
61
62
|
* Path to a `candidate.db` built by `build-candidate.ts`. Opened read-only.
|
|
62
63
|
*/
|
|
63
|
-
databasePath?:
|
|
64
|
+
databasePath?: PathBuilderLike
|
|
64
65
|
/**
|
|
65
66
|
* Pre-opened handle (tests / shared connections). Mutually exclusive with `databasePath`.
|
|
66
67
|
*/
|
|
67
|
-
database?:
|
|
68
|
+
database?: DatabaseClient<CandidateDatabase>
|
|
68
69
|
/**
|
|
69
70
|
* #1882 opt-in: exempt `name_role = 'variant'` aliases — the holder's own primary name in another orthography,
|
|
70
71
|
* stamped by the build's own-name detector — from the cross-country primary-preference penalty. No-ops on an artifact
|
|
@@ -126,12 +127,12 @@ function wordFuzzySimilarity(a: string, b: string): number {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
/**
|
|
129
|
-
* Postcode-containment re-rank
|
|
130
|
-
* (`
|
|
131
|
-
* the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
|
|
132
|
-
* mechanisms disagree about what is proximal.
|
|
130
|
+
* Postcode-containment re-rank check radius (km) — the SAME value the resolver's country pass measures at
|
|
131
|
+
* (`POSTCODE_COUNTRY_COHERENCE_THRESHOLD_KM`, resolver/postcode-country-coherence.ts): a locality within this distance
|
|
132
|
+
* of the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
|
|
133
|
+
* two mechanisms disagree about what is proximal.
|
|
133
134
|
*/
|
|
134
|
-
const
|
|
135
|
+
const POSTCODE_CONTAINMENT_THRESHOLD_KM = 25
|
|
135
136
|
|
|
136
137
|
/**
|
|
137
138
|
* Unpadded character-trigrams of `s`, OR'd into an FTS5 trigram MATCH query (each quoted so FTS treats it as a literal
|
|
@@ -156,9 +157,13 @@ function ftsTrigramQuery(s: string): string {
|
|
|
156
157
|
* Node {@link PlaceLookup} over `candidate.db`. Drop-in for {@link WOFSQLitePlaceLookup} in `createWOFResolver(backend)`
|
|
157
158
|
* — same `findPlace` contract, population-first ranking.
|
|
158
159
|
*/
|
|
159
|
-
export class WOFCandidateTableLookup implements PlaceLookup {
|
|
160
|
-
#db:
|
|
161
|
-
|
|
160
|
+
export class WOFCandidateTableLookup implements PlaceLookup, Disposable {
|
|
161
|
+
#db: DatabaseClient<CandidateDatabase>
|
|
162
|
+
/**
|
|
163
|
+
* Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
|
|
164
|
+
* ownership is membership rather than a flag a later branch has to check.
|
|
165
|
+
*/
|
|
166
|
+
readonly #resources = new DisposableStack()
|
|
162
167
|
readonly #countryToID = new Map<string, number>()
|
|
163
168
|
readonly #idToCountry = new Map<number, string>()
|
|
164
169
|
readonly #placetypeToID = new Map<string, number>()
|
|
@@ -167,29 +172,29 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
167
172
|
* Prepared `(name_key, postcode)` probe for the #741 postal-city side-index — `undefined` when the
|
|
168
173
|
* `postal_city_candidate` table isn't present, so a candidate.db built without it is byte-stable.
|
|
169
174
|
*/
|
|
170
|
-
readonly #postalCityProbe: ReturnType<
|
|
175
|
+
readonly #postalCityProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
171
176
|
/**
|
|
172
177
|
* Prepared FTS5-trigram MATCH probe for the typo-tolerant fallback — `undefined` when the `candidate_fts` index isn't
|
|
173
178
|
* present, so a candidate.db built without it is byte-stable (the fuzzy path is skipped, exactly like today).
|
|
174
179
|
*/
|
|
175
|
-
readonly #ftsProbe: ReturnType<
|
|
180
|
+
readonly #ftsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
176
181
|
/**
|
|
177
|
-
* Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox).
|
|
178
|
-
* fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
|
|
179
|
-
* that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
|
|
180
|
-
* not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
|
|
181
|
-
* country-agnostic retry. Prepared only alongside `#ftsProbe`.
|
|
182
|
+
* Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox). Checks the
|
|
183
|
+
* fuzzy fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
|
|
184
|
+
* A name that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
|
|
185
|
+
* Austria"→IT), not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
|
|
186
|
+
* cascade's country-agnostic retry. Prepared only alongside `#ftsProbe`.
|
|
182
187
|
*/
|
|
183
|
-
readonly #nameKeyExistsProbe: ReturnType<
|
|
188
|
+
readonly #nameKeyExistsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
184
189
|
/**
|
|
185
190
|
* Facts this candidate DB declares about itself — the coverage manifest (`country_coverage` + `country_bbox`) the
|
|
186
191
|
* gazetteer build emits, read once at open. `undefined` when the artifact predates the manifest, so every consumer
|
|
187
|
-
* (the hard-country coverage
|
|
192
|
+
* (the hard-country coverage check, guard-B plausibility) falls back to its code constants byte-identically.
|
|
188
193
|
*/
|
|
189
194
|
readonly artifactCoverage: GazetteerArtifactCoverage | undefined
|
|
190
195
|
/**
|
|
191
196
|
* `", importance"` when this artifact carries the #28 fame column, `""` when it does not — spliced into the probe's
|
|
192
|
-
* SELECT list. Existence-
|
|
197
|
+
* SELECT list. Existence-restricted exactly like `#ftsProbe` and `#postalCityProbe` above, and for the same reason: a
|
|
193
198
|
* candidate.db built before the column is a valid artifact, and naming a column it lacks would turn a stale gazetteer
|
|
194
199
|
* into `no such column` on the first keystroke rather than into "no fame signal", which is what it is.
|
|
195
200
|
*/
|
|
@@ -208,22 +213,22 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
208
213
|
/**
|
|
209
214
|
* Prepared chain probe over the `candidate_ancestor` sidecar — `undefined` when the artifact predates it.
|
|
210
215
|
*/
|
|
211
|
-
readonly #ancestorsProbe: ReturnType<
|
|
216
|
+
readonly #ancestorsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
212
217
|
readonly #ancestorsCache = new Map<number, Ancestor[]>()
|
|
213
218
|
/**
|
|
214
219
|
* Prepared interval-label probe over `candidate_interval` — `undefined` when the artifact predates the sidecar, which
|
|
215
|
-
* is what makes the admin-containment re-rank (#1717 stage 2) capability-
|
|
220
|
+
* is what makes the admin-containment re-rank (#1717 stage 2) capability-restricted: without it,
|
|
216
221
|
* `FindPlaceQuery.regionQualifier` is ignored, no candidate carries a `containedByQualifier` stamp, and the resolver
|
|
217
|
-
* walk reports the
|
|
222
|
+
* walk reports the change `unavailable` instead of silently dead.
|
|
218
223
|
*/
|
|
219
|
-
readonly #intervalProbe: ReturnType<
|
|
224
|
+
readonly #intervalProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
220
225
|
readonly #intervalCache = new Map<number, IntervalLabel | null>()
|
|
221
226
|
/**
|
|
222
227
|
* Prepared qualifier probe: the region-band rows (plus `country` — the region SLOT can hold a mislabeled country
|
|
223
228
|
* name, "Moscow, Russia" parses region="Russia") for one folded qualifier key. `undefined` when the artifact lacks
|
|
224
229
|
* the sidecar or the placetype dictionary lacks the band entirely.
|
|
225
230
|
*/
|
|
226
|
-
readonly #qualifierProbe: ReturnType<
|
|
231
|
+
readonly #qualifierProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
227
232
|
/**
|
|
228
233
|
* The ancestor lineage of a resolved place — nearest-first (locality-tier → county → region → … → country), the same
|
|
229
234
|
* order the FTS backend's `ancestorLineage` serves, read from the `candidate_ancestor` sidecar in one clustered
|
|
@@ -240,10 +245,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
240
245
|
constructor(opts: WOFCandidateTableLookupOpts) {
|
|
241
246
|
if (opts.database) {
|
|
242
247
|
this.#db = opts.database
|
|
243
|
-
this.#ownsDB = false
|
|
244
248
|
} else if (opts.databasePath) {
|
|
245
|
-
this.#db = new
|
|
246
|
-
this.#ownsDB = true
|
|
249
|
+
this.#db = this.#resources.use(new DatabaseClient<CandidateDatabase>(opts.databasePath, { readOnly: true }))
|
|
247
250
|
} else {
|
|
248
251
|
throw new Error("WOFCandidateTableLookup needs `databasePath` or `database`")
|
|
249
252
|
}
|
|
@@ -285,7 +288,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
285
288
|
this.#variantAliasExemption = opts.variantAliasExemption === true
|
|
286
289
|
this.#roleSelect = this.#hasNameRole ? ", name_role" : ""
|
|
287
290
|
|
|
288
|
-
// Ancestors sidecar (#1717): existence-
|
|
291
|
+
// Ancestors sidecar (#1717): existence-restricted like the probes above, and the CAPABILITY checks with
|
|
289
292
|
// it — see the `ancestors` property doc for why an older artifact must read as "no ancestors()"
|
|
290
293
|
// rather than as a method that answers [] everywhere.
|
|
291
294
|
if (hasTable(this.#db, CANDIDATE_ANCESTOR_TABLE)) {
|
|
@@ -297,7 +300,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
297
300
|
this.ancestors = (id) => this.#ancestorLineage(id)
|
|
298
301
|
}
|
|
299
302
|
|
|
300
|
-
// Admin-containment re-rank (#1717 stage 2):
|
|
303
|
+
// Admin-containment re-rank (#1717 stage 2): conditioned on the interval half of the sidecar (built in
|
|
301
304
|
// the same pass as the closure rows; probed separately so a hand-degraded artifact degrades
|
|
302
305
|
// truthfully) AND on the placetype dictionary carrying the qualifier band at all.
|
|
303
306
|
if (this.#ancestorsProbe && hasTable(this.#db, CANDIDATE_INTERVAL_TABLE)) {
|
|
@@ -314,7 +317,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
314
317
|
}
|
|
315
318
|
}
|
|
316
319
|
|
|
317
|
-
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-
|
|
320
|
+
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-restricted like
|
|
318
321
|
// the probes above — a candidate.db built before the manifest reads `undefined` and consumers keep
|
|
319
322
|
// their code-constant fallbacks byte-identically.
|
|
320
323
|
this.artifactCoverage = readGazetteerCoverageManifest(this.#db)
|
|
@@ -396,7 +399,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
396
399
|
* Is `sprID` contained by ANY of the qualifier's rows? Interval first — {@link intervalContains}, O(1), reflexive —
|
|
397
400
|
* then the closure rows where intervals abstain: the interval forest encodes only the CANONICAL parent per place, so
|
|
398
401
|
* a `false` there means "not contained along the canonical hierarchy", and the chain probe (one clustered read of
|
|
399
|
-
* ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that
|
|
402
|
+
* ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that determines the result.
|
|
400
403
|
*/
|
|
401
404
|
#containedByQualifier(sprID: number, qualifierIDs: ReadonlySet<number>, qualifierLabels: IntervalLabel[]): boolean {
|
|
402
405
|
if (qualifierIDs.has(sprID)) return true
|
|
@@ -491,7 +494,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
491
494
|
// cannot reach a neighbourhood-tier namesake, so a CONTAINED one is structurally invisible no matter
|
|
492
495
|
// how the list reorders — the Astoria class: Queens' Astoria is a WOF neighbourhood, and the walk
|
|
493
496
|
// answered the Oregon locality under `qualifier="NY"` because nothing in the pool sat under NY. The
|
|
494
|
-
// widening is injection-only and triple-
|
|
497
|
+
// widening is injection-only and triple-conditioned: the band is explicit (neighbourhood/macrohood/microhood
|
|
495
498
|
// — never region or country tiers), admission still requires the sidecar's containment proof, and only
|
|
496
499
|
// primary-keyed rows enter (an alias-keyed neighbourhood is the #1626 scrape class). Recall can only
|
|
497
500
|
// widen, and only toward rows the qualifier vouches for. `opts.shapeFilters`' bbox clause is
|
|
@@ -601,7 +604,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
601
604
|
|
|
602
605
|
// #741: postcode-keyed postal-city alias. An exact `(name_key, postcode)` hit resolves a
|
|
603
606
|
// user-typed POSTAL city ("Antioch", 37013) to the geographic locality the postcode sits in
|
|
604
|
-
// ("Nashville"), bypassing the population/region ranking that can't see the postcode.
|
|
607
|
+
// ("Nashville"), bypassing the population/region ranking that can't see the postcode. Conditioned on
|
|
605
608
|
// the side-index being present, a postcode in the query, and a locality-tier request — so the
|
|
606
609
|
// common (no-postcode / non-locality) path is untouched. A hit short-circuits: the postcode is
|
|
607
610
|
// an exact, high-confidence disambiguator, so we return the single geographic locality.
|
|
@@ -632,7 +635,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
632
635
|
// SHAPE subset (placetype/bbox/primary — everything but the country scope) is kept separately
|
|
633
636
|
// because the admin-containment injection probe (#1717 stage 2) runs under the shape conds
|
|
634
637
|
// WITHOUT the country: bypassing a locale-inferred country scope for a qualifier-vouched
|
|
635
|
-
// candidate is the
|
|
638
|
+
// candidate is the change's whole point and the one filter injection may cross.
|
|
636
639
|
const filters: string[] = []
|
|
637
640
|
const filterParams: Array<string | number> = []
|
|
638
641
|
const shapeFilters: string[] = []
|
|
@@ -667,7 +670,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
667
670
|
}
|
|
668
671
|
|
|
669
672
|
// The re-reading guard (#1632, the #1626 rationale generalized to the caller): a probe whose surface
|
|
670
|
-
// is a token
|
|
673
|
+
// is a token taken out of a longer classified span never NAMED an alias, so alias-keyed rows must not
|
|
671
674
|
// answer it — 'Savile Row''s token 'Row' resolved Rhu, Scotland (585 km) through the village's
|
|
672
675
|
// historical-name alias key. Whole-input bare probes never set this, keeping the exonym recall the
|
|
673
676
|
// #1546 note protects (Москва's alias rows answer 'Moscow').
|
|
@@ -763,7 +766,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
763
766
|
// the same on either backend. The country/placetype/bbox/region filters still apply via `probe`.
|
|
764
767
|
// Skipped when the index is absent (byte-stable for an older candidate.db).
|
|
765
768
|
//
|
|
766
|
-
//
|
|
769
|
+
// Condition: only when the name doesn't exist in the gazetteer AT ALL (unfiltered). A name that exists
|
|
767
770
|
// but missed under the active country/placetype/bbox filter is a FILTER miss, not a spelling miss
|
|
768
771
|
// — fuzzing it scrapes an unrelated same-filter place ("Vienna, Austria" misrouted to IT would
|
|
769
772
|
// pull a tiny Italian name_key near Siena) and masks the cascade's country-agnostic retry that
|
|
@@ -821,7 +824,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
821
824
|
|
|
822
825
|
let rows = cascade(regionParentID)
|
|
823
826
|
// #1731: whether the rows the caller receives came from the UNSCOPED fallback below — the backend's
|
|
824
|
-
// interior
|
|
827
|
+
// interior check the resolver-side trace (#1721) cannot otherwise see. Stamped onto every returned
|
|
825
828
|
// place, because the re-admission path is exactly where a wrong-instance namesake enters.
|
|
826
829
|
let regionScopeMiss = false
|
|
827
830
|
|
|
@@ -838,8 +841,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
838
841
|
// holds 75001, not the one that holds a 75001-free namesake). The resolver sends this flag on locality
|
|
839
842
|
// lookups when `ResolveOpts.postcodeContainmentCoherence` is on. Strictly beneath the #741 postal-city
|
|
840
843
|
// short-circuit above — an exact (name, postcode) hit IS the answer and outranks any re-rank — and after
|
|
841
|
-
// the region-scope fallback, so it sees the final row set. Rows within the
|
|
842
|
-
// the out-
|
|
844
|
+
// the region-scope fallback, so it sees the final row set. Rows within the radius sort by distance first;
|
|
845
|
+
// the out-of-radius tail keeps its original population-first order. No in-radius row, or no postcode row in
|
|
843
846
|
// the candidate table → unchanged (byte-identical to the flag-off path).
|
|
844
847
|
if (
|
|
845
848
|
query.postcode &&
|
|
@@ -850,32 +853,32 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
850
853
|
const anchor = this.#postcodeAnchor(query.postcode, query.country)
|
|
851
854
|
|
|
852
855
|
if (anchor) {
|
|
853
|
-
const
|
|
854
|
-
const
|
|
856
|
+
const insideThreshold: Array<{ row: RankedRow<CandidateRow>; distanceKm: number }> = []
|
|
857
|
+
const outsideThreshold: RankedRow<CandidateRow>[] = []
|
|
855
858
|
|
|
856
859
|
for (const row of rows) {
|
|
857
860
|
const distanceKm = haversineKm(anchor.lat, anchor.lon, Number(row.latitude), Number(row.longitude))
|
|
858
861
|
|
|
859
|
-
if (distanceKm <=
|
|
860
|
-
|
|
862
|
+
if (distanceKm <= POSTCODE_CONTAINMENT_THRESHOLD_KM) {
|
|
863
|
+
insideThreshold.push({ row, distanceKm })
|
|
861
864
|
} else {
|
|
862
|
-
|
|
865
|
+
outsideThreshold.push(row)
|
|
863
866
|
}
|
|
864
867
|
}
|
|
865
868
|
|
|
866
|
-
if (
|
|
869
|
+
if (insideThreshold.length) {
|
|
867
870
|
// oxlint-disable-next-line unicorn/no-array-sort -- sorts a freshly-built array; toSorted would double-allocate on a hot path
|
|
868
|
-
|
|
869
|
-
rows = [...
|
|
871
|
+
insideThreshold.sort((a, b) => a.distanceKm - b.distanceKm)
|
|
872
|
+
rows = [...insideThreshold.map(({ row }) => row), ...outsideThreshold]
|
|
870
873
|
}
|
|
871
874
|
}
|
|
872
875
|
}
|
|
873
876
|
|
|
874
877
|
// Admin-containment re-rank (#1717 stage 2): LAST, on the final row set — the qualifier is the
|
|
875
878
|
// address's outermost explicit statement, so its partition outranks the postcode-proximity order
|
|
876
|
-
// above (contained rows keep that order among themselves). Capability-
|
|
879
|
+
// above (contained rows keep that order among themselves). Capability-conditioned on the sidecar
|
|
877
880
|
// (`#qualifierProbe`); when the artifact predates it, `regionQualifier` is ignored, no stamp is
|
|
878
|
-
// written, and the resolver walk reports the
|
|
881
|
+
// written, and the resolver walk reports the change `unavailable`.
|
|
879
882
|
if (query.regionQualifier?.trim() && this.#qualifierProbe && this.#wantsLocality(query.placetype)) {
|
|
880
883
|
rows = this.#applyAdminContainment(rows, query.regionQualifier.trim(), query.country, {
|
|
881
884
|
nameKey,
|
|
@@ -893,13 +896,13 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
893
896
|
id: Number(row.spr_id),
|
|
894
897
|
name: String(row.name ?? ""),
|
|
895
898
|
placetype: (this.#idToPlacetype.get(Number(row.placetype_id)) ?? "") as WOFPlacetype,
|
|
896
|
-
// Surfaced so the cascade can country-
|
|
899
|
+
// Surfaced so the cascade can country-restrict a postcode by the resolved locality (an ambiguous
|
|
897
900
|
// international postcode like 10115 = Berlin DE AND New York US must not out-resolve the city).
|
|
898
901
|
country: this.#idToCountry.get(Number(row.country_id)) ?? "",
|
|
899
902
|
lat: Number(row.latitude),
|
|
900
903
|
lon: Number(row.longitude),
|
|
901
904
|
// `score` stays the RAW population rank (`-neg_rank`) — it feeds the resolver walk's absolute
|
|
902
|
-
// `minWinningScore`
|
|
905
|
+
// `minWinningScore` floor (`resolve.ts`), which must see real prominence, never a penalized value.
|
|
903
906
|
score: -Number(row.neg_rank),
|
|
904
907
|
// `prominence` carries the bounded cross-country primary preference (the effective, penalty-adjusted
|
|
905
908
|
// rank). The walk ORDERS candidates by `prominence ?? score` (`resolve.ts`), so this is what makes the
|
|
@@ -921,6 +924,9 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
921
924
|
// asked (a `regionQualifier` query over a sidecar-bearing artifact); its absence is what
|
|
922
925
|
// the resolver walk reports as `unavailable` (meaning-of-zero).
|
|
923
926
|
...(row.containedByQualifier === undefined ? {} : { containedByQualifier: row.containedByQualifier }),
|
|
927
|
+
// #1893 — the exemption's firing mark, carried only when the ranker actually spared this row
|
|
928
|
+
// the cross-country penalty (see RankedRow.variantExempted).
|
|
929
|
+
...(row.variantExempted ? { variantAliasExempted: true as const } : {}),
|
|
924
930
|
// The two-score split's carry (ROAD_TO_V9 §2). `referential` names the prominence this
|
|
925
931
|
// backend has always ordered by — `neg_rank` IS `-log10(population + 1)`, so the score and
|
|
926
932
|
// the sort key are two readings of the same number.
|
|
@@ -965,9 +971,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
965
971
|
return candidates
|
|
966
972
|
}
|
|
967
973
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
this.#db.close()
|
|
971
|
-
}
|
|
974
|
+
[Symbol.dispose](): void {
|
|
975
|
+
this.#resources[Symbol.dispose]()
|
|
972
976
|
}
|
|
973
977
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Typed schema for the byte-range CANDIDATE gazetteer (`candidate.db`) — the single source of truth
|
|
7
7
|
* for the columns shared by the BUILDER ({@link buildCandidateTable}) and the READERS (the Node
|
|
8
|
-
* {@link WOFCandidateTableLookup} + the browser
|
|
8
|
+
* {@link WOFCandidateTableLookup} + the browser `@mailwoman/resolver-wof-wasm/httpvfs/resolver`). Before this module each
|
|
9
9
|
* side hand-wrote the column list; a rename in one place broke the other at runtime. Now the
|
|
10
10
|
* contract is a Kysely `Database` interface (`new DatabaseClient<CandidateDatabase>(...)` for
|
|
11
11
|
* typed inserts) plus the table DDL as strings — so a column change is a compile error on every
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
|
|
18
18
|
import { sql, type Kysely } from "kysely"
|
|
19
19
|
|
|
20
|
-
import type { CandidateAncestorsDatabase } from "
|
|
21
|
-
import type { CapitalTable } from "
|
|
22
|
-
import type { NameKey } from "
|
|
20
|
+
import type { CandidateAncestorsDatabase } from "#candidate-ancestors-schema"
|
|
21
|
+
import type { CapitalTable } from "#capital-schema"
|
|
22
|
+
import type { NameKey } from "#street/normalize"
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* One candidate row. `name_key` + the four small int keys + `neg_rank` + `spr_id` form the clustered primary key; the
|
|
26
26
|
* rest is denormalized so a resolve is one probe (no join to `spr`). Coordinates + bbox + name are nullable at the SQL
|
|
27
|
-
* level (a postcode
|
|
27
|
+
* level (a postcode extract row may lack a bbox).
|
|
28
28
|
*/
|
|
29
29
|
export interface CandidateTable {
|
|
30
30
|
/**
|
|
@@ -99,7 +99,7 @@ export interface CandidateTable {
|
|
|
99
99
|
* core.
|
|
100
100
|
*
|
|
101
101
|
* NULL = no role detected. The column is WRITE-ONLY in this build generation: no ranking consumer reads it — a rank
|
|
102
|
-
* penalty is its own future, D-rule-
|
|
102
|
+
* penalty is its own future, D-rule-conditional step with the `gloss_key` board as regression check.
|
|
103
103
|
*/
|
|
104
104
|
name_role: string | null
|
|
105
105
|
}
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
* ordered — the weighted-sum score and the exact-match tiering that ranks over it.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
|
|
10
|
+
import { compareReferential, referentialFromPopulation } from "@mailwoman/core/resolver"
|
|
12
11
|
import { haversineKm } from "@mailwoman/spatial"
|
|
12
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
13
13
|
|
|
14
|
-
import { exactMatchIDs, officialNameIDs } from "
|
|
15
|
-
import {
|
|
16
|
-
import type
|
|
17
|
-
import type { RawSearchRow } from "
|
|
18
|
-
import type { FindPlaceQuery, PlaceCandidate, WOFPlacetype } from "
|
|
14
|
+
import { exactMatchIDs, officialNameIDs } from "#exact-match"
|
|
15
|
+
import { foldQueryText } from "#fts/index"
|
|
16
|
+
import { populationBoostTerm, type RankingWeights } from "#ranking-weights"
|
|
17
|
+
import type { RawSearchRow } from "#search-fetch"
|
|
18
|
+
import type { FindPlaceQuery, PlaceCandidate, WOFPlacetype } from "#types"
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Score one raw FTS row into a `PlaceCandidate`: the weighted sum over the negated BM25 baseline, the placetype /
|
|
@@ -95,14 +95,8 @@ export function candidateFromSearchRow(
|
|
|
95
95
|
|
|
96
96
|
// Population boost: capped at `populationBoost` magnitude at `10^populationScaleLog10`
|
|
97
97
|
// people. Missing population → no contribution. Never penalizes.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (row.population !== null && row.population > 0 && weights.populationScaleLog10 > 0) {
|
|
101
|
-
const popLog = Math.log10(1 + row.population)
|
|
102
|
-
const popFraction = Math.min(1, popLog / weights.populationScaleLog10)
|
|
103
|
-
popTerm = weights.populationBoost * popFraction
|
|
104
|
-
score += popTerm
|
|
105
|
-
}
|
|
98
|
+
const popTerm = populationBoostTerm(row.population, weights)
|
|
99
|
+
score += popTerm
|
|
106
100
|
|
|
107
101
|
// Combined prominence for the exact-tier sort when proximity hints are present: population
|
|
108
102
|
// and nearness in the SAME additive units, so the map view / the user's location can win a
|
|
@@ -154,13 +148,13 @@ export function candidateFromSearchRow(
|
|
|
154
148
|
}
|
|
155
149
|
|
|
156
150
|
/**
|
|
157
|
-
* Order `candidates` IN PLACE — the exact-match tier first when the
|
|
151
|
+
* Order `candidates` IN PLACE — the exact-match tier first when the extract can answer the name probes, otherwise plain
|
|
158
152
|
* weighted-score order. Every candidate is stamped with its `exactMatch` flag on the way through.
|
|
159
153
|
*/
|
|
160
|
-
export function rankCandidates(
|
|
154
|
+
export function rankCandidates<DB>(
|
|
161
155
|
candidates: PlaceCandidate[],
|
|
162
156
|
options: {
|
|
163
|
-
db:
|
|
157
|
+
db: DatabaseClient<DB>
|
|
164
158
|
schemaName: string
|
|
165
159
|
query: FindPlaceQuery
|
|
166
160
|
weights: RankingWeights
|
|
@@ -204,12 +198,11 @@ export function rankCandidates(
|
|
|
204
198
|
// widen recall, not to tie primaries. ME→Maine is untouched: 'ME' name-exact-matches
|
|
205
199
|
// nothing, so the alias sub-tier still decides there. Population orders within each
|
|
206
200
|
// sub-tier as before.
|
|
207
|
-
const
|
|
208
|
-
const needle = norm(query.text)
|
|
201
|
+
const needle = foldQueryText(query.text)
|
|
209
202
|
|
|
210
203
|
// #936 option 3: an OFFICIAL name (preferred form in an official language of the place's
|
|
211
204
|
// country, `names.official = 1`) counts as the place's own name for the sub-tier — "Åbo" is
|
|
212
|
-
// Turku's name, not merely its alias. Floor-
|
|
205
|
+
// Turku's name, not merely its alias. Floor-conditioned on the holder's population (see the
|
|
213
206
|
// RankingWeights docstring for the measured 100k boundary). officialIDs ⊆ exactIDs by
|
|
214
207
|
// construction (official rows are names rows), so only the sub-tier KIND changes.
|
|
215
208
|
const officialIDs = weights.officialNameExact
|
|
@@ -226,7 +219,7 @@ export function rankCandidates(
|
|
|
226
219
|
const kind = (c: PlaceCandidate): number => {
|
|
227
220
|
if (!exactIDs.has(c.id as number)) return 0
|
|
228
221
|
|
|
229
|
-
if (
|
|
222
|
+
if (foldQueryText(String(c.name ?? "")) === needle) return 2
|
|
230
223
|
|
|
231
224
|
return officialIDs?.has(c.id as number) ? 2 : 1
|
|
232
225
|
}
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
* keeps the coordinate radius from promoting a capital's same-name neighbours (`capitals.ts`).
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
import { tryParsingJSON } from "@mailwoman/core/objects"
|
|
17
|
+
import { tryParsingJSON } from "@mailwoman/core/json"
|
|
18
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
20
19
|
import type { Kysely } from "kysely"
|
|
21
20
|
|
|
22
|
-
import type { CapitalPoint } from "
|
|
23
|
-
import { hasTable } from "
|
|
21
|
+
import type { CapitalPoint } from "#capitals"
|
|
22
|
+
import { hasTable } from "#sqlite-utils"
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* The table name the builder writes and the reader probes — one word, singular, matching the artifact's other reference
|
|
@@ -63,7 +62,7 @@ export async function createCapitalTable<DB extends { capital: CapitalTable }>(d
|
|
|
63
62
|
* back to its next source rather than treating an old artifact as "no capitals" (the meaning-of-zero rule: a missing
|
|
64
63
|
* table is UNMEASURED, an empty one is a finding).
|
|
65
64
|
*/
|
|
66
|
-
export function readCapitalPoints(db:
|
|
65
|
+
export function readCapitalPoints<DB>(db: DatabaseClient<DB>): CapitalPoint[] | null {
|
|
67
66
|
if (!hasTable(db, CAPITAL_TABLE)) return null
|
|
68
67
|
|
|
69
68
|
const points: CapitalPoint[] = []
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Matching is an IDENTITY test with three conjuncts: same country, within
|
|
13
13
|
* {@link CAPITAL_MATCH_RADIUS_KM} of the reference point, and the candidate's own folded name a
|
|
14
14
|
* member of the reference entry's folded name set (name + romanization + the source's alternate
|
|
15
|
-
* names, so exonym rows — "Vienna" for Wien — still match). All three are
|
|
15
|
+
* names, so exonym rows — "Vienna" for Wien — still match). All three are required. The
|
|
16
16
|
* iteration-1 board run matched on country + coordinate alone, and the 25 km radius promoted
|
|
17
17
|
* capital-ADJACENT namesakes instead of capitals: North Salt Lake beside the Utah seat, a Gujarat
|
|
18
18
|
* Indiranagar beside Gandhinagar, Via delle Parti beside Perugia. The name set is what makes the
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
import { haversineKm } from "@mailwoman/spatial"
|
|
23
23
|
|
|
24
|
-
import { normalizeLocalityForKey } from "
|
|
24
|
+
import { normalizeLocalityForKey } from "#street/normalize"
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Capital status of one candidate: national capital, admin-1 seat, or neither. Numeric so the resolver's promotion can
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
* be wired as a post-step of the main `scripts/build-unified-wof.ts`.
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
|
-
import type {
|
|
42
|
-
|
|
43
|
-
import type { CoincidentLocality } from "@mailwoman/resolver"
|
|
41
|
+
import type { CoincidentLocality } from "@mailwoman/core/resolver"
|
|
42
|
+
import { allRows } from "@mailwoman/core/utils"
|
|
44
43
|
import { haversineKm } from "@mailwoman/spatial"
|
|
44
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
45
|
+
import { tableExists } from "@mailwoman/sqlite/introspection"
|
|
45
46
|
|
|
46
|
-
import {
|
|
47
|
-
|
|
47
|
+
import type { WOFDatabase } from "#schema"
|
|
48
48
|
/**
|
|
49
49
|
* Table of places that hold more than one admin role — a locality that is also its county seat. Written by the
|
|
50
50
|
* gazetteer build, read by the resolver when a coincident locality has to be chosen.
|
|
@@ -105,16 +105,12 @@ interface CandidateRow {
|
|
|
105
105
|
pop: number
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function tableExists(db: DatabaseSync, name: string): boolean {
|
|
109
|
-
return !!db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?").get(name)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
108
|
/**
|
|
113
109
|
* Derive the coincident-roles relation into `db`. Additive — only creates/replaces the `coincident_roles` table; never
|
|
114
110
|
* touches `spr`/`names`/`ancestors`. Idempotent.
|
|
115
111
|
*/
|
|
116
112
|
export function buildCoincidentRoles(
|
|
117
|
-
db:
|
|
113
|
+
db: DatabaseClient<WOFDatabase>,
|
|
118
114
|
opts: BuildCoincidentRolesOpts = {}
|
|
119
115
|
): BuildCoincidentRolesResult {
|
|
120
116
|
const start = Date.now()
|
|
@@ -215,7 +211,7 @@ export function buildCoincidentRoles(
|
|
|
215
211
|
/**
|
|
216
212
|
* True iff the relation table exists. Used by the resolver to decide whether completion can run.
|
|
217
213
|
*/
|
|
218
|
-
export function coincidentRolesExists(db:
|
|
214
|
+
export function coincidentRolesExists<DB>(db: DatabaseClient<DB>): boolean {
|
|
219
215
|
return tableExists(db, COINCIDENT_ROLES_TABLE)
|
|
220
216
|
}
|
|
221
217
|
|
|
@@ -224,7 +220,7 @@ export function coincidentRolesExists(db: DatabaseSync): boolean {
|
|
|
224
220
|
* MULTIPLE same-name descendants; the consumer disambiguates (min distance → population → abstain). Returns an empty
|
|
225
221
|
* map when the table is absent.
|
|
226
222
|
*/
|
|
227
|
-
export function loadCoincidentRoles(db:
|
|
223
|
+
export function loadCoincidentRoles<DB>(db: DatabaseClient<DB>): Map<number, CoincidentRole[]> {
|
|
228
224
|
const map = new Map<number, CoincidentRole[]>()
|
|
229
225
|
|
|
230
226
|
if (!coincidentRolesExists(db)) return map
|
|
@@ -269,7 +265,7 @@ export function loadCoincidentRoles(db: DatabaseSync): Map<number, CoincidentRol
|
|
|
269
265
|
* {@link loadCoincidentRoles}, carrying the canonical name and coordinates each coincident locality resolves to.
|
|
270
266
|
* Returns an empty map when the relation table is absent.
|
|
271
267
|
*/
|
|
272
|
-
export function loadCoincidentLocalities(db:
|
|
268
|
+
export function loadCoincidentLocalities<DB>(db: DatabaseClient<DB>): Map<number, CoincidentLocality[]> {
|
|
273
269
|
const map = new Map<number, CoincidentLocality[]>()
|
|
274
270
|
|
|
275
271
|
if (coincidentRolesExists(db)) {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* source).
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import type { FindPlaceQuery, PlaceCandidate } from "
|
|
24
|
+
import type { FindPlaceQuery, PlaceCandidate } from "#types"
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Soft-scoring weights for the `postcode_area_resolution` strategy: `pc·S_pc + name·S_name + pop·S_pop`.
|
|
@@ -76,13 +76,13 @@ export const WORLD_DEFAULT: ResolvedConvention = {
|
|
|
76
76
|
export const BUILTIN_STRATEGY_NAMES = ["postcode_area_resolution", "fallback_fuzzy_name_match"] as const
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
* Table name for the convention asset (#290). Carried here so the build script, the runtime source, and the
|
|
79
|
+
* Table name for the convention asset (#290). Carried here so the build script, the runtime source, and the extract
|
|
80
80
|
* auto-detect all agree.
|
|
81
81
|
*/
|
|
82
82
|
export const ADDRESS_CONVENTION_TABLE = "address_convention"
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* A named resolution primitive. Returns `null` to abstain (
|
|
85
|
+
* A named resolution primitive. Returns `null` to abstain (condition unmet / no data) → the dispatcher tries the next
|
|
86
86
|
* strategy; returns an array (possibly empty) to claim the result.
|
|
87
87
|
*/
|
|
88
88
|
export type Strategy = (query: FindPlaceQuery, convention: ResolvedConvention) => Promise<PlaceCandidate[] | null>
|