@mailwoman/resolver-wof-sqlite 9.2.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -19
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +24 -22
- package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
- package/{address-point.ts → lib/address/point.ts} +89 -27
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +5 -3
- package/{build-candidate.ts → lib/build-candidate.ts} +84 -77
- package/{build-slim.ts → lib/build-slim.ts} +150 -165
- package/{candidate → lib/candidate}/alias-bags.ts +8 -6
- package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
- package/{candidate → lib/candidate}/country-display-names.ts +2 -2
- package/{candidate/shard-fold.ts → lib/candidate/extract-fold.ts} +26 -25
- package/{candidate → lib/candidate}/name-roles.ts +17 -16
- package/{candidate → lib/candidate}/own-name.ts +1 -1
- package/{candidate → lib/candidate}/place-attrs.ts +3 -3
- package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
- package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
- package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
- package/{candidate-lookup.ts → lib/candidate-lookup.ts} +76 -73
- package/{candidate-schema.ts → lib/candidate-schema.ts} +5 -5
- package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
- package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
- package/{capitals.ts → lib/capitals.ts} +2 -2
- package/{coincident-roles.ts → lib/coincident-roles.ts} +8 -11
- package/{convention.ts → lib/convention/index.ts} +3 -3
- package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +9 -10
- package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
- package/lib/env.ts +50 -0
- package/{exact-match.ts → lib/exact-match.ts} +23 -14
- package/{sharding.ts → lib/extracts.ts} +61 -58
- package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
- package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
- package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
- package/lib/fst/format.ts +106 -0
- package/{fst-freshness.ts → lib/fst/freshness.ts} +41 -74
- package/lib/fst/index.ts +14 -0
- package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
- package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
- package/{fst-types.ts → lib/fst/types.ts} +4 -2
- package/{fts.ts → lib/fts/index.ts} +24 -19
- package/{fts-query.ts → lib/fts/query.ts} +1 -1
- package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
- package/lib/geonames/index.ts +8 -0
- package/{geonames-postal.ts → lib/geonames/postal.ts} +14 -13
- package/{index.ts → lib/index.ts} +37 -37
- package/{interpolation.ts → lib/interpolation.ts} +27 -25
- package/{lookup.ts → lib/lookup.ts} +129 -141
- package/lib/nsul/index.ts +8 -0
- package/lib/nsul/lookup.ts +144 -0
- package/lib/nsul/schema.ts +130 -0
- package/{place-importance-schema.ts → lib/place-importance-schema.ts} +7 -8
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -28
- package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/{primary-preference.ts → lib/primary-preference.ts} +29 -10
- package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/{region-keys.ts → lib/region-keys.ts} +9 -9
- package/{reverse.ts → lib/reverse.ts} +34 -46
- package/{schema.ts → lib/schema.ts} +10 -0
- package/{search-fetch.ts → lib/search-fetch.ts} +29 -28
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -18
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
- package/{street-centroid.ts → lib/street/centroid.ts} +14 -21
- package/lib/street/index.ts +13 -0
- package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
- package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
- package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
- package/{street-normalize.ts → lib/street/normalize.ts} +44 -19
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
- package/{types.ts → lib/types.ts} +18 -12
- package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -18
- package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
- package/lib/weights-overlay-linker.ts +878 -0
- package/out/address/index.d.ts +9 -0
- package/out/address/index.d.ts.map +1 -0
- package/out/address/index.js +9 -0
- package/out/address/index.js.map +1 -0
- package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +11 -10
- package/out/address/point-interpolation.d.ts.map +1 -0
- package/out/{address-point-interpolation.js → address/point-interpolation.js} +18 -18
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
- package/out/address/point-schema.d.ts.map +1 -0
- package/out/{address-point-schema.js → address/point-schema.js} +7 -3
- package/out/address/point-schema.js.map +1 -0
- package/out/{address-point.d.ts → address/point.d.ts} +16 -8
- package/out/address/point.d.ts.map +1 -0
- package/out/{address-point.js → address/point.js} +71 -20
- package/out/address/point.js.map +1 -0
- package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
- package/out/ancestry/backfill.d.ts.map +1 -0
- package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
- package/out/ancestry/backfill.js.map +1 -0
- package/out/{ancestry.d.ts → ancestry/index.d.ts} +4 -3
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +3 -2
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +30 -24
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +50 -52
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +4 -4
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +124 -139
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +5 -3
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +2 -2
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors-sidecar.d.ts +9 -10
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
- package/out/candidate/ancestors-sidecar.js +7 -7
- package/out/candidate/ancestors-sidecar.js.map +1 -1
- package/out/candidate/country-display-names.d.ts +1 -1
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +1 -1
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +32 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/{shard-fold.js → extract-fold.js} +20 -20
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +13 -11
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +11 -10
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +1 -1
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +1 -1
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +3 -3
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +1 -1
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate-ancestors-schema.d.ts +4 -4
- package/out/candidate-ancestors-schema.d.ts.map +1 -1
- package/out/candidate-ancestors-schema.js +2 -2
- package/out/candidate-ancestors-schema.js.map +1 -1
- package/out/candidate-fts.d.ts +3 -3
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +1 -1
- package/out/candidate-fts.js.map +1 -1
- package/out/candidate-importance.d.ts +16 -16
- package/out/candidate-importance.d.ts.map +1 -1
- package/out/candidate-importance.js +46 -51
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +11 -9
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +61 -58
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +5 -5
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +7 -7
- package/out/candidate-scoring.d.ts.map +1 -1
- package/out/candidate-scoring.js +10 -14
- package/out/candidate-scoring.js.map +1 -1
- package/out/capital-schema.d.ts +3 -3
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +2 -2
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +1 -1
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +2 -2
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +6 -5
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +2 -4
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +4 -4
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +2 -2
- package/out/convention/index.js.map +1 -0
- package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
- package/out/convention/schema.d.ts.map +1 -0
- package/out/{convention-schema.js → convention/schema.js} +3 -3
- package/out/convention/schema.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +8 -8
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +4 -4
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +51 -7
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +65 -49
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +43 -0
- package/out/env.d.ts.map +1 -0
- package/out/env.js +48 -0
- package/out/env.js.map +1 -0
- package/out/exact-match.d.ts +5 -5
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +10 -11
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +114 -0
- package/out/extracts.d.ts.map +1 -0
- package/out/{sharding.js → extracts.js} +38 -38
- package/out/extracts.js.map +1 -0
- package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +2 -2
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
- package/out/fst/autocomplete.js.map +1 -0
- package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
- package/out/fst/builder.d.ts.map +1 -0
- package/out/{fst-builder.js → fst/builder.js} +14 -13
- package/out/fst/builder.js.map +1 -0
- package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -0
- package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
- package/out/fst/deserialize-web.js.map +1 -0
- package/out/fst/format.d.ts +80 -0
- package/out/fst/format.d.ts.map +1 -0
- package/out/fst/format.js +91 -0
- package/out/fst/format.js.map +1 -0
- package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +10 -13
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +41 -73
- package/out/fst/freshness.js.map +1 -0
- package/out/fst/index.d.ts +14 -0
- package/out/fst/index.d.ts.map +1 -0
- package/out/fst/index.js +14 -0
- package/out/fst/index.js.map +1 -0
- package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
- package/out/fst/matcher.d.ts.map +1 -0
- package/out/{fst-matcher.js → fst/matcher.js} +1 -1
- package/out/fst/matcher.js.map +1 -0
- package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
- package/out/fst/serialize.d.ts.map +1 -0
- package/out/{fst-serialize.js → fst/serialize.js} +18 -98
- package/out/fst/serialize.js.map +1 -0
- package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
- package/out/fst/types.d.ts.map +1 -0
- package/out/{fst-types.js → fst/types.js} +1 -1
- package/out/fst/types.js.map +1 -0
- package/out/{fts.d.ts → fts/index.d.ts} +16 -9
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +16 -11
- package/out/fts/index.js.map +1 -0
- package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
- package/out/fts/query.d.ts.map +1 -0
- package/out/{fts-query.js → fts/query.js} +1 -1
- package/out/fts/query.js.map +1 -0
- package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
- package/out/geonames/aliases.d.ts.map +1 -0
- package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
- package/out/geonames/aliases.js.map +1 -0
- package/out/geonames/index.d.ts +8 -0
- package/out/geonames/index.d.ts.map +1 -0
- package/out/geonames/index.js +8 -0
- package/out/geonames/index.js.map +1 -0
- package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +10 -8
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +9 -9
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -32
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -24
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +10 -9
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +20 -20
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +21 -20
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +102 -112
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js.map +1 -1
- package/out/nsul/index.d.ts +8 -0
- package/out/nsul/index.d.ts.map +1 -0
- package/out/nsul/index.js +8 -0
- package/out/nsul/index.js.map +1 -0
- package/out/nsul/lookup.d.ts +83 -0
- package/out/nsul/lookup.d.ts.map +1 -0
- package/out/nsul/lookup.js +80 -0
- package/out/nsul/lookup.js.map +1 -0
- package/out/nsul/schema.d.ts +100 -0
- package/out/nsul/schema.d.ts.map +1 -0
- package/out/nsul/schema.js +78 -0
- package/out/nsul/schema.js.map +1 -0
- package/out/place-importance-schema.d.ts +5 -5
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -3
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/index.d.ts +8 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +8 -0
- package/out/poi/index.js.map +1 -0
- package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
- package/out/poi/lookup.d.ts.map +1 -0
- package/out/{poi-lookup.js → poi/lookup.js} +14 -18
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
- package/out/poi/schema.d.ts.map +1 -0
- package/out/{poi-schema.js → poi/schema.js} +1 -1
- package/out/poi/schema.js.map +1 -0
- package/out/polygon-schema.d.ts.map +1 -1
- package/out/polygon-schema.js.map +1 -1
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
- package/out/postal/city-alias-lookup.js.map +1 -0
- package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
- package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
- package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
- package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
- package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +3 -3
- package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
- package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
- package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
- package/out/postal/index.d.ts +9 -0
- package/out/postal/index.d.ts.map +1 -0
- package/out/postal/index.js +9 -0
- package/out/postal/index.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +10 -10
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +13 -13
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +13 -5
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +16 -8
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +2 -2
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +2 -2
- package/out/proximity-rerank.js.map +1 -1
- package/out/ranking-weights.d.ts +15 -3
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +21 -3
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +8 -8
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +9 -9
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +20 -29
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +9 -0
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +12 -10
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +21 -20
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite-convention-source.d.ts +7 -7
- package/out/sqlite-convention-source.d.ts.map +1 -1
- package/out/sqlite-convention-source.js +5 -5
- package/out/sqlite-convention-source.js.map +1 -1
- package/out/sqlite-utils.d.ts +8 -8
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +7 -8
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
- package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
- package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
- package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
- package/out/{street-centroid.d.ts → street/centroid.d.ts} +6 -6
- package/out/street/centroid.d.ts.map +1 -0
- package/out/{street-centroid.js → street/centroid.js} +13 -19
- package/out/street/centroid.js.map +1 -0
- package/out/street/index.d.ts +13 -0
- package/out/street/index.d.ts.map +1 -0
- package/out/street/index.js +13 -0
- package/out/street/index.js.map +1 -0
- package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
- package/out/street/morphology-fst-builder.d.ts.map +1 -0
- package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
- package/out/street/morphology-fst-builder.js.map +1 -0
- package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
- package/out/street/morphology-fst-loader.d.ts.map +1 -0
- package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
- package/out/street/morphology-fst-loader.js.map +1 -0
- package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
- package/out/street/name-lookup.d.ts.map +1 -0
- package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
- package/out/street/name-lookup.js.map +1 -0
- package/out/{street-normalize.d.ts → street/normalize.d.ts} +25 -14
- package/out/street/normalize.d.ts.map +1 -0
- package/out/{street-normalize.js → street/normalize.js} +36 -17
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
- package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
- package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
- package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
- package/out/types.d.ts +18 -12
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +5 -4
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +15 -18
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +53 -0
- package/out/uprn/existence.d.ts.map +1 -0
- package/out/uprn/existence.js +61 -0
- package/out/uprn/existence.js.map +1 -0
- package/out/uprn/index.d.ts +9 -0
- package/out/uprn/index.d.ts.map +1 -0
- package/out/uprn/index.js +9 -0
- package/out/uprn/index.js.map +1 -0
- package/out/{uprn-lookup.d.ts → uprn/lookup.d.ts} +4 -4
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
- package/out/uprn/lookup.js.map +1 -0
- package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/{uprn-schema.js → uprn/schema.js} +4 -4
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +184 -26
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +338 -86
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +465 -269
- package/out/address-point-interpolation.d.ts.map +0 -1
- package/out/address-point-interpolation.js.map +0 -1
- package/out/address-point-schema.d.ts.map +0 -1
- package/out/address-point-schema.js.map +0 -1
- package/out/address-point.d.ts.map +0 -1
- package/out/address-point.js.map +0 -1
- package/out/ancestry-backfill.d.ts.map +0 -1
- package/out/ancestry-backfill.js.map +0 -1
- package/out/ancestry.d.ts.map +0 -1
- package/out/ancestry.js.map +0 -1
- package/out/candidate/shard-fold.d.ts +0 -31
- package/out/candidate/shard-fold.d.ts.map +0 -1
- package/out/candidate/shard-fold.js.map +0 -1
- package/out/convention-schema.d.ts.map +0 -1
- package/out/convention-schema.js.map +0 -1
- package/out/convention.d.ts.map +0 -1
- package/out/convention.js.map +0 -1
- package/out/fst-autocomplete.d.ts.map +0 -1
- package/out/fst-autocomplete.js.map +0 -1
- package/out/fst-builder.d.ts.map +0 -1
- package/out/fst-builder.js.map +0 -1
- package/out/fst-deserialize-web.d.ts.map +0 -1
- package/out/fst-deserialize-web.js.map +0 -1
- package/out/fst-freshness.d.ts.map +0 -1
- package/out/fst-freshness.js.map +0 -1
- package/out/fst-matcher.d.ts.map +0 -1
- package/out/fst-matcher.js.map +0 -1
- package/out/fst-serialize.d.ts.map +0 -1
- package/out/fst-serialize.js.map +0 -1
- package/out/fst-types.d.ts.map +0 -1
- package/out/fst-types.js.map +0 -1
- package/out/fts-query.d.ts.map +0 -1
- package/out/fts-query.js.map +0 -1
- package/out/fts.d.ts.map +0 -1
- package/out/fts.js.map +0 -1
- package/out/geonames-aliases.d.ts.map +0 -1
- package/out/geonames-aliases.js.map +0 -1
- package/out/geonames-postal.d.ts.map +0 -1
- package/out/geonames-postal.js.map +0 -1
- package/out/poi-lookup.d.ts.map +0 -1
- package/out/poi-lookup.js.map +0 -1
- package/out/poi-schema.d.ts.map +0 -1
- package/out/poi-schema.js.map +0 -1
- package/out/postal-city-alias-lookup.d.ts.map +0 -1
- package/out/postal-city-alias-lookup.js.map +0 -1
- package/out/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.map +0 -1
- package/out/street-centroid.d.ts.map +0 -1
- package/out/street-centroid.js.map +0 -1
- package/out/street-morphology-fst-builder.d.ts.map +0 -1
- package/out/street-morphology-fst-builder.js.map +0 -1
- package/out/street-morphology-fst-loader.d.ts.map +0 -1
- package/out/street-morphology-fst-loader.js.map +0 -1
- package/out/street-name-lookup.d.ts.map +0 -1
- package/out/street-name-lookup.js.map +0 -1
- package/out/street-normalize.d.ts.map +0 -1
- package/out/street-normalize.js.map +0 -1
- package/out/uprn-lookup.d.ts.map +0 -1
- package/out/uprn-lookup.js.map +0 -1
- package/out/uprn-schema.d.ts.map +0 -1
- package/out/uprn-schema.js.map +0 -1
- package/weights-overlay-linker.ts +0 -377
- /package/{name-score.ts → lib/name-score.ts} +0 -0
- /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
* `bbox` field on {@link FindPlaceQuery}).
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { DatabaseSync } from "node:sqlite"
|
|
27
|
-
|
|
28
26
|
import { jaroWinkler, levenshteinSimilarity } from "@mailwoman/match/comparators"
|
|
29
27
|
import {
|
|
30
28
|
expandPlacetypeFilter,
|
|
@@ -33,6 +31,8 @@ import {
|
|
|
33
31
|
type GazetteerArtifactCoverage,
|
|
34
32
|
} from "@mailwoman/resolver"
|
|
35
33
|
import { haversineKm } from "@mailwoman/spatial"
|
|
34
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
35
|
+
import type { PathBuilderLike } from "path-ts"
|
|
36
36
|
|
|
37
37
|
import {
|
|
38
38
|
CANDIDATE_ANCESTOR_TABLE,
|
|
@@ -40,31 +40,31 @@ import {
|
|
|
40
40
|
intervalContains,
|
|
41
41
|
type CandidateAncestorTable,
|
|
42
42
|
type IntervalLabel,
|
|
43
|
-
} from "
|
|
44
|
-
import { CANDIDATE_FTS_TABLE } from "
|
|
45
|
-
import type { CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "
|
|
46
|
-
import { readGazetteerCoverageManifest } from "
|
|
47
|
-
import { referentialFromPopulation } from "
|
|
48
|
-
import { POSTAL_CITY_CANDIDATE_TABLE, type PostalCityCandidateTable } from "
|
|
49
|
-
import { rankByPrimaryPreference, type RankedRow, RERANK_FETCH } from "
|
|
50
|
-
import { applyProximityRerank } from "
|
|
51
|
-
import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "
|
|
52
|
-
import { allRows, hasColumn, hasTable } from "
|
|
53
|
-
import { type NameKey, normalizeLocalityForKey, stripLocalityQualifier } from "
|
|
54
|
-
import type { FindPlaceQuery, PlaceCandidate, PlaceLookup, WOFPlacetype } from "
|
|
55
|
-
|
|
56
|
-
export { rankByPrimaryPreference } from "
|
|
57
|
-
export type { RankedRow } from "
|
|
43
|
+
} from "#candidate-ancestors-schema"
|
|
44
|
+
import { CANDIDATE_FTS_TABLE } from "#candidate-fts"
|
|
45
|
+
import type { CandidateDatabase, CandidateTable, CountryCodeTable, PlacetypeCodeTable } from "#candidate-schema"
|
|
46
|
+
import { readGazetteerCoverageManifest } from "#coverage-manifest-schema"
|
|
47
|
+
import { referentialFromPopulation } from "#place-importance-schema"
|
|
48
|
+
import { POSTAL_CITY_CANDIDATE_TABLE, type PostalCityCandidateTable } from "#postal/city-candidate-schema"
|
|
49
|
+
import { rankByPrimaryPreference, type RankedRow, RERANK_FETCH } from "#primary-preference"
|
|
50
|
+
import { applyProximityRerank } from "#proximity-rerank"
|
|
51
|
+
import { REGION_CLASS_PLACETYPES, regionQualifierProbeKeys } from "#region-keys"
|
|
52
|
+
import { allRows, hasColumn, hasTable } from "#sqlite-utils"
|
|
53
|
+
import { type NameKey, normalizeLocalityForKey, stripLocalityQualifier } from "#street/normalize"
|
|
54
|
+
import type { FindPlaceQuery, PlaceCandidate, PlaceLookup, WOFPlacetype } from "#types"
|
|
55
|
+
|
|
56
|
+
export { rankByPrimaryPreference } from "#primary-preference"
|
|
57
|
+
export type { RankedRow } from "#primary-preference"
|
|
58
58
|
|
|
59
59
|
export interface WOFCandidateTableLookupOpts {
|
|
60
60
|
/**
|
|
61
61
|
* Path to a `candidate.db` built by `build-candidate.ts`. Opened read-only.
|
|
62
62
|
*/
|
|
63
|
-
databasePath?:
|
|
63
|
+
databasePath?: PathBuilderLike
|
|
64
64
|
/**
|
|
65
65
|
* Pre-opened handle (tests / shared connections). Mutually exclusive with `databasePath`.
|
|
66
66
|
*/
|
|
67
|
-
database?:
|
|
67
|
+
database?: DatabaseClient<CandidateDatabase>
|
|
68
68
|
/**
|
|
69
69
|
* #1882 opt-in: exempt `name_role = 'variant'` aliases — the holder's own primary name in another orthography,
|
|
70
70
|
* stamped by the build's own-name detector — from the cross-country primary-preference penalty. No-ops on an artifact
|
|
@@ -126,12 +126,12 @@ function wordFuzzySimilarity(a: string, b: string): number {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
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.
|
|
129
|
+
* Postcode-containment re-rank check radius (km) — the SAME value the resolver's country pass measures at
|
|
130
|
+
* (`POSTCODE_COUNTRY_COHERENCE_THRESHOLD_KM`, resolver/postcode-country-coherence.ts): a locality within this distance
|
|
131
|
+
* of the postcode's own centroid counts as "containing" it. One number, two passes — a divergence here would make the
|
|
132
|
+
* two mechanisms disagree about what is proximal.
|
|
133
133
|
*/
|
|
134
|
-
const
|
|
134
|
+
const POSTCODE_CONTAINMENT_THRESHOLD_KM = 25
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
137
|
* Unpadded character-trigrams of `s`, OR'd into an FTS5 trigram MATCH query (each quoted so FTS treats it as a literal
|
|
@@ -156,9 +156,13 @@ function ftsTrigramQuery(s: string): string {
|
|
|
156
156
|
* Node {@link PlaceLookup} over `candidate.db`. Drop-in for {@link WOFSQLitePlaceLookup} in `createWOFResolver(backend)`
|
|
157
157
|
* — same `findPlace` contract, population-first ranking.
|
|
158
158
|
*/
|
|
159
|
-
export class WOFCandidateTableLookup implements PlaceLookup {
|
|
160
|
-
#db:
|
|
161
|
-
|
|
159
|
+
export class WOFCandidateTableLookup implements PlaceLookup, Disposable {
|
|
160
|
+
#db: DatabaseClient<CandidateDatabase>
|
|
161
|
+
/**
|
|
162
|
+
* Resources this instance opened. A connection handed in by a caller is NOT in here, so disposal cannot reach it —
|
|
163
|
+
* ownership is membership rather than a flag a later branch has to check.
|
|
164
|
+
*/
|
|
165
|
+
readonly #resources = new DisposableStack()
|
|
162
166
|
readonly #countryToID = new Map<string, number>()
|
|
163
167
|
readonly #idToCountry = new Map<number, string>()
|
|
164
168
|
readonly #placetypeToID = new Map<string, number>()
|
|
@@ -167,29 +171,29 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
167
171
|
* Prepared `(name_key, postcode)` probe for the #741 postal-city side-index — `undefined` when the
|
|
168
172
|
* `postal_city_candidate` table isn't present, so a candidate.db built without it is byte-stable.
|
|
169
173
|
*/
|
|
170
|
-
readonly #postalCityProbe: ReturnType<
|
|
174
|
+
readonly #postalCityProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
171
175
|
/**
|
|
172
176
|
* Prepared FTS5-trigram MATCH probe for the typo-tolerant fallback — `undefined` when the `candidate_fts` index isn't
|
|
173
177
|
* present, so a candidate.db built without it is byte-stable (the fuzzy path is skipped, exactly like today).
|
|
174
178
|
*/
|
|
175
|
-
readonly #ftsProbe: ReturnType<
|
|
179
|
+
readonly #ftsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
176
180
|
/**
|
|
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`.
|
|
181
|
+
* Prepared UNFILTERED existence probe (`name_key` present anywhere, ignoring country/placetype/bbox). Checks the
|
|
182
|
+
* fuzzy fallback: fuzzy is a TYPO corrector, so it engages only when the name doesn't exist in the gazetteer at all.
|
|
183
|
+
* A name that DOES exist but missed under the active filter is a filter miss (e.g. a placer misroute "Vienna,
|
|
184
|
+
* Austria"→IT), not a spelling miss — fuzzing it would scrape an unrelated same-country place and defeat the
|
|
185
|
+
* cascade's country-agnostic retry. Prepared only alongside `#ftsProbe`.
|
|
182
186
|
*/
|
|
183
|
-
readonly #nameKeyExistsProbe: ReturnType<
|
|
187
|
+
readonly #nameKeyExistsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
184
188
|
/**
|
|
185
189
|
* Facts this candidate DB declares about itself — the coverage manifest (`country_coverage` + `country_bbox`) the
|
|
186
190
|
* gazetteer build emits, read once at open. `undefined` when the artifact predates the manifest, so every consumer
|
|
187
|
-
* (the hard-country coverage
|
|
191
|
+
* (the hard-country coverage check, guard-B plausibility) falls back to its code constants byte-identically.
|
|
188
192
|
*/
|
|
189
193
|
readonly artifactCoverage: GazetteerArtifactCoverage | undefined
|
|
190
194
|
/**
|
|
191
195
|
* `", importance"` when this artifact carries the #28 fame column, `""` when it does not — spliced into the probe's
|
|
192
|
-
* SELECT list. Existence-
|
|
196
|
+
* SELECT list. Existence-restricted exactly like `#ftsProbe` and `#postalCityProbe` above, and for the same reason: a
|
|
193
197
|
* candidate.db built before the column is a valid artifact, and naming a column it lacks would turn a stale gazetteer
|
|
194
198
|
* into `no such column` on the first keystroke rather than into "no fame signal", which is what it is.
|
|
195
199
|
*/
|
|
@@ -208,22 +212,22 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
208
212
|
/**
|
|
209
213
|
* Prepared chain probe over the `candidate_ancestor` sidecar — `undefined` when the artifact predates it.
|
|
210
214
|
*/
|
|
211
|
-
readonly #ancestorsProbe: ReturnType<
|
|
215
|
+
readonly #ancestorsProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
212
216
|
readonly #ancestorsCache = new Map<number, Ancestor[]>()
|
|
213
217
|
/**
|
|
214
218
|
* 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-
|
|
219
|
+
* is what makes the admin-containment re-rank (#1717 stage 2) capability-restricted: without it,
|
|
216
220
|
* `FindPlaceQuery.regionQualifier` is ignored, no candidate carries a `containedByQualifier` stamp, and the resolver
|
|
217
|
-
* walk reports the
|
|
221
|
+
* walk reports the change `unavailable` instead of silently dead.
|
|
218
222
|
*/
|
|
219
|
-
readonly #intervalProbe: ReturnType<
|
|
223
|
+
readonly #intervalProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
220
224
|
readonly #intervalCache = new Map<number, IntervalLabel | null>()
|
|
221
225
|
/**
|
|
222
226
|
* Prepared qualifier probe: the region-band rows (plus `country` — the region SLOT can hold a mislabeled country
|
|
223
227
|
* name, "Moscow, Russia" parses region="Russia") for one folded qualifier key. `undefined` when the artifact lacks
|
|
224
228
|
* the sidecar or the placetype dictionary lacks the band entirely.
|
|
225
229
|
*/
|
|
226
|
-
readonly #qualifierProbe: ReturnType<
|
|
230
|
+
readonly #qualifierProbe: ReturnType<DatabaseClient["prepare"]> | undefined
|
|
227
231
|
/**
|
|
228
232
|
* The ancestor lineage of a resolved place — nearest-first (locality-tier → county → region → … → country), the same
|
|
229
233
|
* order the FTS backend's `ancestorLineage` serves, read from the `candidate_ancestor` sidecar in one clustered
|
|
@@ -240,10 +244,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
240
244
|
constructor(opts: WOFCandidateTableLookupOpts) {
|
|
241
245
|
if (opts.database) {
|
|
242
246
|
this.#db = opts.database
|
|
243
|
-
this.#ownsDB = false
|
|
244
247
|
} else if (opts.databasePath) {
|
|
245
|
-
this.#db = new
|
|
246
|
-
this.#ownsDB = true
|
|
248
|
+
this.#db = this.#resources.use(new DatabaseClient<CandidateDatabase>(opts.databasePath, { readOnly: true }))
|
|
247
249
|
} else {
|
|
248
250
|
throw new Error("WOFCandidateTableLookup needs `databasePath` or `database`")
|
|
249
251
|
}
|
|
@@ -285,7 +287,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
285
287
|
this.#variantAliasExemption = opts.variantAliasExemption === true
|
|
286
288
|
this.#roleSelect = this.#hasNameRole ? ", name_role" : ""
|
|
287
289
|
|
|
288
|
-
// Ancestors sidecar (#1717): existence-
|
|
290
|
+
// Ancestors sidecar (#1717): existence-restricted like the probes above, and the CAPABILITY checks with
|
|
289
291
|
// it — see the `ancestors` property doc for why an older artifact must read as "no ancestors()"
|
|
290
292
|
// rather than as a method that answers [] everywhere.
|
|
291
293
|
if (hasTable(this.#db, CANDIDATE_ANCESTOR_TABLE)) {
|
|
@@ -297,7 +299,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
297
299
|
this.ancestors = (id) => this.#ancestorLineage(id)
|
|
298
300
|
}
|
|
299
301
|
|
|
300
|
-
// Admin-containment re-rank (#1717 stage 2):
|
|
302
|
+
// Admin-containment re-rank (#1717 stage 2): conditioned on the interval half of the sidecar (built in
|
|
301
303
|
// the same pass as the closure rows; probed separately so a hand-degraded artifact degrades
|
|
302
304
|
// truthfully) AND on the placetype dictionary carrying the qualifier band at all.
|
|
303
305
|
if (this.#ancestorsProbe && hasTable(this.#db, CANDIDATE_INTERVAL_TABLE)) {
|
|
@@ -314,7 +316,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
314
316
|
}
|
|
315
317
|
}
|
|
316
318
|
|
|
317
|
-
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-
|
|
319
|
+
// Coverage manifest (survey candidate #2): the artifact's own coverage facts, existence-restricted like
|
|
318
320
|
// the probes above — a candidate.db built before the manifest reads `undefined` and consumers keep
|
|
319
321
|
// their code-constant fallbacks byte-identically.
|
|
320
322
|
this.artifactCoverage = readGazetteerCoverageManifest(this.#db)
|
|
@@ -396,7 +398,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
396
398
|
* Is `sprID` contained by ANY of the qualifier's rows? Interval first — {@link intervalContains}, O(1), reflexive —
|
|
397
399
|
* then the closure rows where intervals abstain: the interval forest encodes only the CANONICAL parent per place, so
|
|
398
400
|
* 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
|
|
401
|
+
* ≤{@link MAX_ANCESTOR_DEPTH} rows) is the complete record that determines the result.
|
|
400
402
|
*/
|
|
401
403
|
#containedByQualifier(sprID: number, qualifierIDs: ReadonlySet<number>, qualifierLabels: IntervalLabel[]): boolean {
|
|
402
404
|
if (qualifierIDs.has(sprID)) return true
|
|
@@ -491,7 +493,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
491
493
|
// cannot reach a neighbourhood-tier namesake, so a CONTAINED one is structurally invisible no matter
|
|
492
494
|
// how the list reorders — the Astoria class: Queens' Astoria is a WOF neighbourhood, and the walk
|
|
493
495
|
// answered the Oregon locality under `qualifier="NY"` because nothing in the pool sat under NY. The
|
|
494
|
-
// widening is injection-only and triple-
|
|
496
|
+
// widening is injection-only and triple-conditioned: the band is explicit (neighbourhood/macrohood/microhood
|
|
495
497
|
// — never region or country tiers), admission still requires the sidecar's containment proof, and only
|
|
496
498
|
// primary-keyed rows enter (an alias-keyed neighbourhood is the #1626 scrape class). Recall can only
|
|
497
499
|
// widen, and only toward rows the qualifier vouches for. `opts.shapeFilters`' bbox clause is
|
|
@@ -601,7 +603,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
601
603
|
|
|
602
604
|
// #741: postcode-keyed postal-city alias. An exact `(name_key, postcode)` hit resolves a
|
|
603
605
|
// 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.
|
|
606
|
+
// ("Nashville"), bypassing the population/region ranking that can't see the postcode. Conditioned on
|
|
605
607
|
// the side-index being present, a postcode in the query, and a locality-tier request — so the
|
|
606
608
|
// common (no-postcode / non-locality) path is untouched. A hit short-circuits: the postcode is
|
|
607
609
|
// an exact, high-confidence disambiguator, so we return the single geographic locality.
|
|
@@ -632,7 +634,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
632
634
|
// SHAPE subset (placetype/bbox/primary — everything but the country scope) is kept separately
|
|
633
635
|
// because the admin-containment injection probe (#1717 stage 2) runs under the shape conds
|
|
634
636
|
// WITHOUT the country: bypassing a locale-inferred country scope for a qualifier-vouched
|
|
635
|
-
// candidate is the
|
|
637
|
+
// candidate is the change's whole point and the one filter injection may cross.
|
|
636
638
|
const filters: string[] = []
|
|
637
639
|
const filterParams: Array<string | number> = []
|
|
638
640
|
const shapeFilters: string[] = []
|
|
@@ -667,7 +669,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
667
669
|
}
|
|
668
670
|
|
|
669
671
|
// The re-reading guard (#1632, the #1626 rationale generalized to the caller): a probe whose surface
|
|
670
|
-
// is a token
|
|
672
|
+
// is a token taken out of a longer classified span never NAMED an alias, so alias-keyed rows must not
|
|
671
673
|
// answer it — 'Savile Row''s token 'Row' resolved Rhu, Scotland (585 km) through the village's
|
|
672
674
|
// historical-name alias key. Whole-input bare probes never set this, keeping the exonym recall the
|
|
673
675
|
// #1546 note protects (Москва's alias rows answer 'Moscow').
|
|
@@ -763,7 +765,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
763
765
|
// the same on either backend. The country/placetype/bbox/region filters still apply via `probe`.
|
|
764
766
|
// Skipped when the index is absent (byte-stable for an older candidate.db).
|
|
765
767
|
//
|
|
766
|
-
//
|
|
768
|
+
// Condition: only when the name doesn't exist in the gazetteer AT ALL (unfiltered). A name that exists
|
|
767
769
|
// but missed under the active country/placetype/bbox filter is a FILTER miss, not a spelling miss
|
|
768
770
|
// — fuzzing it scrapes an unrelated same-filter place ("Vienna, Austria" misrouted to IT would
|
|
769
771
|
// pull a tiny Italian name_key near Siena) and masks the cascade's country-agnostic retry that
|
|
@@ -821,7 +823,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
821
823
|
|
|
822
824
|
let rows = cascade(regionParentID)
|
|
823
825
|
// #1731: whether the rows the caller receives came from the UNSCOPED fallback below — the backend's
|
|
824
|
-
// interior
|
|
826
|
+
// interior check the resolver-side trace (#1721) cannot otherwise see. Stamped onto every returned
|
|
825
827
|
// place, because the re-admission path is exactly where a wrong-instance namesake enters.
|
|
826
828
|
let regionScopeMiss = false
|
|
827
829
|
|
|
@@ -838,8 +840,8 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
838
840
|
// holds 75001, not the one that holds a 75001-free namesake). The resolver sends this flag on locality
|
|
839
841
|
// lookups when `ResolveOpts.postcodeContainmentCoherence` is on. Strictly beneath the #741 postal-city
|
|
840
842
|
// 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-
|
|
843
|
+
// the region-scope fallback, so it sees the final row set. Rows within the radius sort by distance first;
|
|
844
|
+
// the out-of-radius tail keeps its original population-first order. No in-radius row, or no postcode row in
|
|
843
845
|
// the candidate table → unchanged (byte-identical to the flag-off path).
|
|
844
846
|
if (
|
|
845
847
|
query.postcode &&
|
|
@@ -850,32 +852,32 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
850
852
|
const anchor = this.#postcodeAnchor(query.postcode, query.country)
|
|
851
853
|
|
|
852
854
|
if (anchor) {
|
|
853
|
-
const
|
|
854
|
-
const
|
|
855
|
+
const insideThreshold: Array<{ row: RankedRow<CandidateRow>; distanceKm: number }> = []
|
|
856
|
+
const outsideThreshold: RankedRow<CandidateRow>[] = []
|
|
855
857
|
|
|
856
858
|
for (const row of rows) {
|
|
857
859
|
const distanceKm = haversineKm(anchor.lat, anchor.lon, Number(row.latitude), Number(row.longitude))
|
|
858
860
|
|
|
859
|
-
if (distanceKm <=
|
|
860
|
-
|
|
861
|
+
if (distanceKm <= POSTCODE_CONTAINMENT_THRESHOLD_KM) {
|
|
862
|
+
insideThreshold.push({ row, distanceKm })
|
|
861
863
|
} else {
|
|
862
|
-
|
|
864
|
+
outsideThreshold.push(row)
|
|
863
865
|
}
|
|
864
866
|
}
|
|
865
867
|
|
|
866
|
-
if (
|
|
868
|
+
if (insideThreshold.length) {
|
|
867
869
|
// oxlint-disable-next-line unicorn/no-array-sort -- sorts a freshly-built array; toSorted would double-allocate on a hot path
|
|
868
|
-
|
|
869
|
-
rows = [...
|
|
870
|
+
insideThreshold.sort((a, b) => a.distanceKm - b.distanceKm)
|
|
871
|
+
rows = [...insideThreshold.map(({ row }) => row), ...outsideThreshold]
|
|
870
872
|
}
|
|
871
873
|
}
|
|
872
874
|
}
|
|
873
875
|
|
|
874
876
|
// Admin-containment re-rank (#1717 stage 2): LAST, on the final row set — the qualifier is the
|
|
875
877
|
// address's outermost explicit statement, so its partition outranks the postcode-proximity order
|
|
876
|
-
// above (contained rows keep that order among themselves). Capability-
|
|
878
|
+
// above (contained rows keep that order among themselves). Capability-conditioned on the sidecar
|
|
877
879
|
// (`#qualifierProbe`); when the artifact predates it, `regionQualifier` is ignored, no stamp is
|
|
878
|
-
// written, and the resolver walk reports the
|
|
880
|
+
// written, and the resolver walk reports the change `unavailable`.
|
|
879
881
|
if (query.regionQualifier?.trim() && this.#qualifierProbe && this.#wantsLocality(query.placetype)) {
|
|
880
882
|
rows = this.#applyAdminContainment(rows, query.regionQualifier.trim(), query.country, {
|
|
881
883
|
nameKey,
|
|
@@ -893,13 +895,13 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
893
895
|
id: Number(row.spr_id),
|
|
894
896
|
name: String(row.name ?? ""),
|
|
895
897
|
placetype: (this.#idToPlacetype.get(Number(row.placetype_id)) ?? "") as WOFPlacetype,
|
|
896
|
-
// Surfaced so the cascade can country-
|
|
898
|
+
// Surfaced so the cascade can country-restrict a postcode by the resolved locality (an ambiguous
|
|
897
899
|
// international postcode like 10115 = Berlin DE AND New York US must not out-resolve the city).
|
|
898
900
|
country: this.#idToCountry.get(Number(row.country_id)) ?? "",
|
|
899
901
|
lat: Number(row.latitude),
|
|
900
902
|
lon: Number(row.longitude),
|
|
901
903
|
// `score` stays the RAW population rank (`-neg_rank`) — it feeds the resolver walk's absolute
|
|
902
|
-
// `minWinningScore`
|
|
904
|
+
// `minWinningScore` floor (`resolve.ts`), which must see real prominence, never a penalized value.
|
|
903
905
|
score: -Number(row.neg_rank),
|
|
904
906
|
// `prominence` carries the bounded cross-country primary preference (the effective, penalty-adjusted
|
|
905
907
|
// rank). The walk ORDERS candidates by `prominence ?? score` (`resolve.ts`), so this is what makes the
|
|
@@ -921,6 +923,9 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
921
923
|
// asked (a `regionQualifier` query over a sidecar-bearing artifact); its absence is what
|
|
922
924
|
// the resolver walk reports as `unavailable` (meaning-of-zero).
|
|
923
925
|
...(row.containedByQualifier === undefined ? {} : { containedByQualifier: row.containedByQualifier }),
|
|
926
|
+
// #1893 — the exemption's firing mark, carried only when the ranker actually spared this row
|
|
927
|
+
// the cross-country penalty (see RankedRow.variantExempted).
|
|
928
|
+
...(row.variantExempted ? { variantAliasExempted: true as const } : {}),
|
|
924
929
|
// The two-score split's carry (ROAD_TO_V9 §2). `referential` names the prominence this
|
|
925
930
|
// backend has always ordered by — `neg_rank` IS `-log10(population + 1)`, so the score and
|
|
926
931
|
// the sort key are two readings of the same number.
|
|
@@ -965,9 +970,7 @@ export class WOFCandidateTableLookup implements PlaceLookup {
|
|
|
965
970
|
return candidates
|
|
966
971
|
}
|
|
967
972
|
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
this.#db.close()
|
|
971
|
-
}
|
|
973
|
+
[Symbol.dispose](): void {
|
|
974
|
+
this.#resources[Symbol.dispose]()
|
|
972
975
|
}
|
|
973
976
|
}
|
|
@@ -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 type { DatabaseSync } from "node:sqlite"
|
|
11
|
-
|
|
12
10
|
import { haversineKm } from "@mailwoman/spatial"
|
|
11
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
13
12
|
|
|
14
|
-
import { exactMatchIDs, officialNameIDs } from "
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import type
|
|
18
|
-
import type {
|
|
13
|
+
import { exactMatchIDs, officialNameIDs } from "#exact-match"
|
|
14
|
+
import { foldQueryText } from "#fts/index"
|
|
15
|
+
import { compareReferential, referentialFromPopulation } from "#place-importance-schema"
|
|
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,12 +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 { DatabaseSync } from "node:sqlite"
|
|
42
|
-
|
|
43
41
|
import type { CoincidentLocality } from "@mailwoman/resolver"
|
|
44
42
|
import { haversineKm } from "@mailwoman/spatial"
|
|
43
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
44
|
+
import { tableExists } from "@mailwoman/sqlite/introspection"
|
|
45
45
|
|
|
46
|
-
import {
|
|
46
|
+
import type { WOFDatabase } from "#schema"
|
|
47
|
+
import { allRows } from "#sqlite-utils"
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Table of places that hold more than one admin role — a locality that is also its county seat. Written by the
|
|
@@ -105,16 +106,12 @@ interface CandidateRow {
|
|
|
105
106
|
pop: number
|
|
106
107
|
}
|
|
107
108
|
|
|
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
109
|
/**
|
|
113
110
|
* Derive the coincident-roles relation into `db`. Additive — only creates/replaces the `coincident_roles` table; never
|
|
114
111
|
* touches `spr`/`names`/`ancestors`. Idempotent.
|
|
115
112
|
*/
|
|
116
113
|
export function buildCoincidentRoles(
|
|
117
|
-
db:
|
|
114
|
+
db: DatabaseClient<WOFDatabase>,
|
|
118
115
|
opts: BuildCoincidentRolesOpts = {}
|
|
119
116
|
): BuildCoincidentRolesResult {
|
|
120
117
|
const start = Date.now()
|
|
@@ -215,7 +212,7 @@ export function buildCoincidentRoles(
|
|
|
215
212
|
/**
|
|
216
213
|
* True iff the relation table exists. Used by the resolver to decide whether completion can run.
|
|
217
214
|
*/
|
|
218
|
-
export function coincidentRolesExists(db:
|
|
215
|
+
export function coincidentRolesExists<DB>(db: DatabaseClient<DB>): boolean {
|
|
219
216
|
return tableExists(db, COINCIDENT_ROLES_TABLE)
|
|
220
217
|
}
|
|
221
218
|
|
|
@@ -224,7 +221,7 @@ export function coincidentRolesExists(db: DatabaseSync): boolean {
|
|
|
224
221
|
* MULTIPLE same-name descendants; the consumer disambiguates (min distance → population → abstain). Returns an empty
|
|
225
222
|
* map when the table is absent.
|
|
226
223
|
*/
|
|
227
|
-
export function loadCoincidentRoles(db:
|
|
224
|
+
export function loadCoincidentRoles<DB>(db: DatabaseClient<DB>): Map<number, CoincidentRole[]> {
|
|
228
225
|
const map = new Map<number, CoincidentRole[]>()
|
|
229
226
|
|
|
230
227
|
if (!coincidentRolesExists(db)) return map
|
|
@@ -269,7 +266,7 @@ export function loadCoincidentRoles(db: DatabaseSync): Map<number, CoincidentRol
|
|
|
269
266
|
* {@link loadCoincidentRoles}, carrying the canonical name and coordinates each coincident locality resolves to.
|
|
270
267
|
* Returns an empty map when the relation table is absent.
|
|
271
268
|
*/
|
|
272
|
-
export function loadCoincidentLocalities(db:
|
|
269
|
+
export function loadCoincidentLocalities<DB>(db: DatabaseClient<DB>): Map<number, CoincidentLocality[]> {
|
|
273
270
|
const map = new Map<number, CoincidentLocality[]>()
|
|
274
271
|
|
|
275
272
|
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>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import type { Kysely } from "kysely"
|
|
13
13
|
|
|
14
|
-
import { ADDRESS_CONVENTION_TABLE } from "
|
|
14
|
+
import { ADDRESS_CONVENTION_TABLE } from "#convention/index"
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* One convention profile, keyed by the WOF admin polygon it attaches to.
|
|
@@ -49,7 +49,7 @@ export type ConventionSchemaHandle = Pick<Kysely<ConventionDatabase>, "schema">
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Create `address_convention`. The table name comes from {@link ADDRESS_CONVENTION_TABLE} so the build script, the
|
|
52
|
-
* runtime source, and the
|
|
52
|
+
* runtime source, and the extract auto-detect cannot drift apart.
|
|
53
53
|
*/
|
|
54
54
|
export async function createAddressConventionTable(db: ConventionSchemaHandle): Promise<void> {
|
|
55
55
|
await db.schema
|