@mailwoman/resolver-wof-sqlite 9.1.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -20
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +40 -28
- package/{address-point-schema.ts → lib/address/point-schema.ts} +34 -8
- package/lib/address/point.ts +280 -0
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +13 -8
- package/{build-candidate.ts → lib/build-candidate.ts} +243 -199
- package/{build-slim.ts → lib/build-slim.ts} +153 -168
- package/lib/candidate/alias-bags.ts +56 -0
- package/lib/candidate/ancestors-sidecar.ts +204 -0
- package/lib/candidate/country-display-names.ts +79 -0
- package/lib/candidate/extract-fold.ts +138 -0
- package/lib/candidate/name-roles.ts +238 -0
- package/lib/candidate/own-name.ts +146 -0
- package/lib/candidate/place-attrs.ts +44 -0
- package/lib/candidate-ancestors-schema.ts +195 -0
- package/{candidate-fts.ts → lib/candidate-fts.ts} +7 -5
- package/{candidate-importance.ts → lib/candidate-importance.ts} +54 -57
- package/lib/candidate-lookup.ts +976 -0
- package/{candidate-schema.ts → lib/candidate-schema.ts} +34 -6
- package/lib/candidate-scoring.ts +261 -0
- package/lib/capital-schema.ts +89 -0
- package/lib/capitals.ts +148 -0
- package/{coincident-roles.ts → lib/coincident-roles.ts} +75 -19
- package/{convention.ts → lib/convention/index.ts} +5 -5
- package/lib/convention/schema.ts +72 -0
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +15 -16
- package/lib/currency-backfill.ts +334 -0
- package/lib/env.ts +50 -0
- package/lib/exact-match.ts +113 -0
- package/{sharding.ts → lib/extracts.ts} +63 -60
- package/lib/fst/autocomplete.ts +176 -0
- package/{fst-builder.ts → lib/fst/builder.ts} +30 -27
- package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
- package/lib/fst/format.ts +106 -0
- package/{fst-freshness.ts → lib/fst/freshness.ts} +42 -75
- package/lib/fst/index.ts +14 -0
- package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
- package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
- package/{fst-types.ts → lib/fst/types.ts} +4 -2
- package/{fts.ts → lib/fts/index.ts} +28 -23
- package/{fts-query.ts → lib/fts/query.ts} +2 -2
- package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
- package/lib/geonames/index.ts +8 -0
- package/{geonames-postal.ts → lib/geonames/postal.ts} +16 -15
- package/{index.ts → lib/index.ts} +52 -48
- package/{interpolation.ts → lib/interpolation.ts} +137 -41
- package/lib/lookup.ts +861 -0
- package/{name-score.ts → lib/name-score.ts} +6 -4
- package/lib/nsul/index.ts +8 -0
- package/lib/nsul/lookup.ts +144 -0
- package/lib/nsul/schema.ts +130 -0
- package/{place-importance-schema.ts → lib/place-importance-schema.ts} +70 -22
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +32 -39
- package/{poi-schema.ts → lib/poi/schema.ts} +10 -6
- package/lib/polygon-schema.ts +47 -0
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +15 -21
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +4 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/lib/primary-preference.ts +226 -0
- package/lib/proximity-rerank.ts +120 -0
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/lib/region-keys.ts +144 -0
- package/{reverse.ts → lib/reverse.ts} +45 -56
- package/{schema.ts → lib/schema.ts} +11 -1
- package/lib/search-fetch.ts +257 -0
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/lib/sqlite-utils.ts +83 -0
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +12 -6
- package/{street-centroid.ts → lib/street/centroid.ts} +26 -28
- package/lib/street/index.ts +13 -0
- package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
- package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
- package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
- package/lib/street/normalize.ts +572 -0
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +13 -8
- package/{types.ts → lib/types.ts} +49 -9
- package/{unified-schema.ts → lib/unified-schema.ts} +21 -25
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/lib/uprn/lookup.ts +206 -0
- package/lib/uprn/schema.ts +124 -0
- package/lib/weights-overlay-linker.ts +878 -0
- package/out/address/index.d.ts +9 -0
- package/out/address/index.d.ts.map +1 -0
- package/out/address/index.js +9 -0
- package/out/address/index.js.map +1 -0
- package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +11 -10
- package/out/address/point-interpolation.d.ts.map +1 -0
- package/out/{address-point-interpolation.js → address/point-interpolation.js} +29 -23
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +30 -10
- package/out/address/point-schema.d.ts.map +1 -0
- package/out/{address-point-schema.js → address/point-schema.js} +7 -3
- package/out/address/point-schema.js.map +1 -0
- package/out/{address-point.d.ts → address/point.d.ts} +16 -8
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +191 -0
- package/out/address/point.js.map +1 -0
- package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
- package/out/ancestry/backfill.d.ts.map +1 -0
- package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
- package/out/ancestry/backfill.js.map +1 -0
- package/out/{ancestry.d.ts → ancestry/index.d.ts} +6 -5
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +7 -7
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +88 -7
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +145 -149
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +5 -5
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +127 -142
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +19 -0
- package/out/candidate/alias-bags.d.ts.map +1 -0
- package/out/candidate/alias-bags.js +39 -0
- package/out/candidate/alias-bags.js.map +1 -0
- package/out/candidate/ancestors-sidecar.d.ts +32 -0
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -0
- package/out/candidate/ancestors-sidecar.js +140 -0
- package/out/candidate/ancestors-sidecar.js.map +1 -0
- package/out/candidate/country-display-names.d.ts +35 -0
- package/out/candidate/country-display-names.d.ts.map +1 -0
- package/out/candidate/country-display-names.js +59 -0
- package/out/candidate/country-display-names.js.map +1 -0
- package/out/candidate/extract-fold.d.ts +32 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/extract-fold.js +104 -0
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +57 -0
- package/out/candidate/name-roles.d.ts.map +1 -0
- package/out/candidate/name-roles.js +166 -0
- package/out/candidate/name-roles.js.map +1 -0
- package/out/candidate/own-name.d.ts +50 -0
- package/out/candidate/own-name.d.ts.map +1 -0
- package/out/candidate/own-name.js +132 -0
- package/out/candidate/own-name.js.map +1 -0
- package/out/candidate/place-attrs.d.ts +43 -0
- package/out/candidate/place-attrs.d.ts.map +1 -0
- package/out/candidate/place-attrs.js +15 -0
- package/out/candidate/place-attrs.js.map +1 -0
- package/out/candidate-ancestors-schema.d.ts +150 -0
- package/out/candidate-ancestors-schema.d.ts.map +1 -0
- package/out/candidate-ancestors-schema.js +123 -0
- package/out/candidate-ancestors-schema.js.map +1 -0
- package/out/candidate-fts.d.ts +7 -5
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +5 -3
- package/out/candidate-fts.js.map +1 -1
- package/out/candidate-importance.d.ts +16 -16
- package/out/candidate-importance.d.ts.map +1 -1
- package/out/candidate-importance.js +47 -52
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +31 -52
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +380 -172
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +31 -7
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js +3 -0
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +34 -0
- package/out/candidate-scoring.d.ts.map +1 -0
- package/out/candidate-scoring.js +196 -0
- package/out/candidate-scoring.js.map +1 -0
- package/out/capital-schema.d.ts +51 -0
- package/out/capital-schema.d.ts.map +1 -0
- package/out/capital-schema.js +63 -0
- package/out/capital-schema.js.map +1 -0
- package/out/capitals.d.ts +69 -0
- package/out/capitals.d.ts.map +1 -0
- package/out/capitals.js +98 -0
- package/out/capitals.js.map +1 -0
- package/out/coincident-roles.d.ts +12 -4
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +43 -11
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +5 -5
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +4 -4
- package/out/convention/index.js.map +1 -0
- package/out/convention/schema.d.ts +51 -0
- package/out/convention/schema.d.ts.map +1 -0
- package/out/convention/schema.js +34 -0
- package/out/convention/schema.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +8 -8
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +6 -10
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +90 -0
- package/out/currency-backfill.d.ts.map +1 -0
- package/out/currency-backfill.js +196 -0
- package/out/currency-backfill.js.map +1 -0
- package/out/env.d.ts +43 -0
- package/out/env.d.ts.map +1 -0
- package/out/env.js +48 -0
- package/out/env.js.map +1 -0
- package/out/exact-match.d.ts +25 -0
- package/out/exact-match.d.ts.map +1 -0
- package/out/exact-match.js +88 -0
- package/out/exact-match.js.map +1 -0
- package/out/extracts.d.ts +114 -0
- package/out/extracts.d.ts.map +1 -0
- package/out/{sharding.js → extracts.js} +38 -38
- package/out/extracts.js.map +1 -0
- package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +13 -13
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/fst/autocomplete.js +113 -0
- package/out/fst/autocomplete.js.map +1 -0
- package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
- package/out/fst/builder.d.ts.map +1 -0
- package/out/{fst-builder.js → fst/builder.js} +24 -24
- package/out/fst/builder.js.map +1 -0
- package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -0
- package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
- package/out/fst/deserialize-web.js.map +1 -0
- package/out/fst/format.d.ts +80 -0
- package/out/fst/format.d.ts.map +1 -0
- package/out/fst/format.js +91 -0
- package/out/fst/format.js.map +1 -0
- package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +11 -14
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +42 -74
- package/out/fst/freshness.js.map +1 -0
- package/out/fst/index.d.ts +14 -0
- package/out/fst/index.d.ts.map +1 -0
- package/out/fst/index.js +14 -0
- package/out/fst/index.js.map +1 -0
- package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
- package/out/fst/matcher.d.ts.map +1 -0
- package/out/{fst-matcher.js → fst/matcher.js} +1 -1
- package/out/fst/matcher.js.map +1 -0
- package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
- package/out/fst/serialize.d.ts.map +1 -0
- package/out/{fst-serialize.js → fst/serialize.js} +18 -98
- package/out/fst/serialize.js.map +1 -0
- package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
- package/out/fst/types.d.ts.map +1 -0
- package/out/{fst-types.js → fst/types.js} +1 -1
- package/out/fst/types.js.map +1 -0
- package/out/{fts.d.ts → fts/index.d.ts} +20 -13
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +20 -15
- package/out/fts/index.js.map +1 -0
- package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
- package/out/fts/query.d.ts.map +1 -0
- package/out/{fts-query.js → fts/query.js} +2 -2
- package/out/fts/query.js.map +1 -0
- package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
- package/out/geonames/aliases.d.ts.map +1 -0
- package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
- package/out/geonames/aliases.js.map +1 -0
- package/out/geonames/index.d.ts +8 -0
- package/out/geonames/index.d.ts.map +1 -0
- package/out/geonames/index.js +8 -0
- package/out/geonames/index.js.map +1 -0
- package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +12 -10
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +11 -11
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -31
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -24
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +18 -9
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +108 -36
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +25 -25
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +174 -558
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts +0 -10
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js +6 -4
- package/out/name-score.js.map +1 -1
- package/out/nsul/index.d.ts +8 -0
- package/out/nsul/index.d.ts.map +1 -0
- package/out/nsul/index.js +8 -0
- package/out/nsul/index.js.map +1 -0
- package/out/nsul/lookup.d.ts +83 -0
- package/out/nsul/lookup.d.ts.map +1 -0
- package/out/nsul/lookup.js +80 -0
- package/out/nsul/lookup.js.map +1 -0
- package/out/nsul/schema.d.ts +100 -0
- package/out/nsul/schema.d.ts.map +1 -0
- package/out/nsul/schema.js +78 -0
- package/out/nsul/schema.js.map +1 -0
- package/out/place-importance-schema.d.ts +47 -10
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +56 -10
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/index.d.ts +8 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +8 -0
- package/out/poi/index.js.map +1 -0
- package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
- package/out/poi/lookup.d.ts.map +1 -0
- package/out/{poi-lookup.js → poi/lookup.js} +24 -29
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +10 -6
- package/out/poi/schema.d.ts.map +1 -0
- package/out/{poi-schema.js → poi/schema.js} +1 -1
- package/out/poi/schema.js.map +1 -0
- package/out/polygon-schema.d.ts +37 -0
- package/out/polygon-schema.d.ts.map +1 -0
- package/out/polygon-schema.js +23 -0
- package/out/polygon-schema.js.map +1 -0
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +7 -6
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +12 -16
- package/out/postal/city-alias-lookup.js.map +1 -0
- package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
- package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
- package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
- package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
- package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +4 -3
- package/out/postal/city-candidate-schema.d.ts.map +1 -0
- package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
- package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
- package/out/postal/index.d.ts +9 -0
- package/out/postal/index.d.ts.map +1 -0
- package/out/postal/index.js +9 -0
- package/out/postal/index.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +10 -10
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +13 -13
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +133 -0
- package/out/primary-preference.d.ts.map +1 -0
- package/out/primary-preference.js +146 -0
- package/out/primary-preference.js.map +1 -0
- package/out/proximity-rerank.d.ts +77 -0
- package/out/proximity-rerank.d.ts.map +1 -0
- package/out/proximity-rerank.js +86 -0
- package/out/proximity-rerank.js.map +1 -0
- package/out/ranking-weights.d.ts +15 -3
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +21 -3
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +47 -0
- package/out/region-keys.d.ts.map +1 -0
- package/out/region-keys.js +121 -0
- package/out/region-keys.js.map +1 -0
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +23 -35
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +10 -1
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +59 -0
- package/out/search-fetch.d.ts.map +1 -0
- package/out/search-fetch.js +184 -0
- package/out/search-fetch.js.map +1 -0
- package/out/sqlite-convention-source.d.ts +7 -7
- package/out/sqlite-convention-source.d.ts.map +1 -1
- package/out/sqlite-convention-source.js +5 -5
- package/out/sqlite-convention-source.js.map +1 -1
- package/out/sqlite-utils.d.ts +24 -6
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +24 -7
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +12 -7
- package/out/street/centroid-schema.d.ts.map +1 -0
- package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
- package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
- package/out/{street-centroid.d.ts → street/centroid.d.ts} +6 -6
- package/out/street/centroid.d.ts.map +1 -0
- package/out/{street-centroid.js → street/centroid.js} +18 -24
- package/out/street/centroid.js.map +1 -0
- package/out/street/index.d.ts +13 -0
- package/out/street/index.d.ts.map +1 -0
- package/out/street/index.js +13 -0
- package/out/street/index.js.map +1 -0
- package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
- package/out/street/morphology-fst-builder.d.ts.map +1 -0
- package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
- package/out/street/morphology-fst-builder.js.map +1 -0
- package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
- package/out/street/morphology-fst-loader.d.ts.map +1 -0
- package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
- package/out/street/morphology-fst-loader.js.map +1 -0
- package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
- package/out/street/name-lookup.d.ts.map +1 -0
- package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
- package/out/street/name-lookup.js.map +1 -0
- package/out/street/normalize.d.ts +179 -0
- package/out/street/normalize.d.ts.map +1 -0
- package/out/street/normalize.js +457 -0
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +13 -9
- package/out/street/segment-schema.d.ts.map +1 -0
- package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
- package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
- package/out/types.d.ts +49 -9
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +6 -5
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +16 -19
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +53 -0
- package/out/uprn/existence.d.ts.map +1 -0
- package/out/uprn/existence.js +61 -0
- package/out/uprn/existence.js.map +1 -0
- package/out/uprn/index.d.ts +9 -0
- package/out/uprn/index.d.ts.map +1 -0
- package/out/uprn/index.js +9 -0
- package/out/uprn/index.js.map +1 -0
- package/out/uprn/lookup.d.ts +85 -0
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/uprn/lookup.js +149 -0
- package/out/uprn/lookup.js.map +1 -0
- package/out/uprn/schema.d.ts +93 -0
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/uprn/schema.js +78 -0
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +299 -0
- package/out/weights-overlay-linker.d.ts.map +1 -0
- package/out/weights-overlay-linker.js +511 -0
- package/out/weights-overlay-linker.js.map +1 -0
- package/package.json +622 -154
- package/address-point.ts +0 -125
- package/candidate-lookup.ts +0 -720
- package/fst-autocomplete.ts +0 -204
- package/geo.ts +0 -121
- package/lookup.ts +0 -1354
- package/out/address-point-interpolation.d.ts.map +0 -1
- package/out/address-point-interpolation.js.map +0 -1
- package/out/address-point-schema.d.ts.map +0 -1
- package/out/address-point-schema.js.map +0 -1
- package/out/address-point.d.ts.map +0 -1
- package/out/address-point.js +0 -84
- package/out/address-point.js.map +0 -1
- package/out/ancestry-backfill.d.ts.map +0 -1
- package/out/ancestry-backfill.js.map +0 -1
- package/out/ancestry.d.ts.map +0 -1
- package/out/ancestry.js.map +0 -1
- package/out/convention.d.ts.map +0 -1
- package/out/convention.js.map +0 -1
- package/out/fst-autocomplete.d.ts.map +0 -1
- package/out/fst-autocomplete.js +0 -130
- package/out/fst-autocomplete.js.map +0 -1
- package/out/fst-builder.d.ts.map +0 -1
- package/out/fst-builder.js.map +0 -1
- package/out/fst-deserialize-web.d.ts.map +0 -1
- package/out/fst-deserialize-web.js.map +0 -1
- package/out/fst-freshness.d.ts.map +0 -1
- package/out/fst-freshness.js.map +0 -1
- package/out/fst-matcher.d.ts.map +0 -1
- package/out/fst-matcher.js.map +0 -1
- package/out/fst-serialize.d.ts.map +0 -1
- package/out/fst-serialize.js.map +0 -1
- package/out/fst-types.d.ts.map +0 -1
- package/out/fst-types.js.map +0 -1
- package/out/fts-query.d.ts.map +0 -1
- package/out/fts-query.js.map +0 -1
- package/out/fts.d.ts.map +0 -1
- package/out/fts.js.map +0 -1
- package/out/geo.d.ts +0 -74
- package/out/geo.d.ts.map +0 -1
- package/out/geo.js +0 -71
- package/out/geo.js.map +0 -1
- package/out/geonames-aliases.d.ts.map +0 -1
- package/out/geonames-aliases.js.map +0 -1
- package/out/geonames-postal.d.ts.map +0 -1
- package/out/geonames-postal.js.map +0 -1
- package/out/poi-lookup.d.ts.map +0 -1
- package/out/poi-lookup.js.map +0 -1
- package/out/poi-schema.d.ts.map +0 -1
- package/out/poi-schema.js.map +0 -1
- package/out/postal-city-alias-lookup.d.ts.map +0 -1
- package/out/postal-city-alias-lookup.js.map +0 -1
- package/out/postal-city-candidate-schema.d.ts.map +0 -1
- package/out/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.map +0 -1
- package/out/street-centroid-schema.d.ts.map +0 -1
- package/out/street-centroid.d.ts.map +0 -1
- package/out/street-centroid.js.map +0 -1
- package/out/street-morphology-fst-builder.d.ts.map +0 -1
- package/out/street-morphology-fst-builder.js.map +0 -1
- package/out/street-morphology-fst-loader.d.ts.map +0 -1
- package/out/street-morphology-fst-loader.js.map +0 -1
- package/out/street-name-lookup.d.ts.map +0 -1
- package/out/street-name-lookup.js.map +0 -1
- package/out/street-normalize.d.ts +0 -95
- package/out/street-normalize.d.ts.map +0 -1
- package/out/street-normalize.js +0 -272
- package/out/street-normalize.js.map +0 -1
- package/out/street-segment-schema.d.ts.map +0 -1
- package/sqlite-utils.ts +0 -46
- package/street-normalize.ts +0 -318
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* The locality-ranking weights and their shipped defaults. Its own module because every value here is
|
|
7
7
|
* a measured tuning decision with its rationale attached — the block reads as a reference table, not
|
|
8
|
-
* as part of the lookup's control flow, and the tests import it directly to pin one
|
|
8
|
+
* as part of the lookup's control flow, and the tests import it directly to pin one change at a time.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -96,7 +96,7 @@ export interface RankingWeights {
|
|
|
96
96
|
* Fixes unscoped "Åbo" → Turku (its official Swedish name) over a hamlet literally named Åbo; population still orders
|
|
97
97
|
* within the sub-tier, so Paris → Paris FR is untouched.
|
|
98
98
|
*
|
|
99
|
-
* Default true (operator-promoted 2026-07-03 after the pre-registered
|
|
99
|
+
* Default true (operator-promoted 2026-07-03 after the pre-registered eval battery: four intended exonym flips —
|
|
100
100
|
* Berne→Bern, Bruges→Brugge, Roma→Rome, Åbo→Turku — with the namesake/abbreviation rows and the US/FI panels
|
|
101
101
|
* byte-identical). Requires a gazetteer carrying the #940 ingest bit — on older DBs without the `official` column the
|
|
102
102
|
* probe fails soft and behavior is identical to the flag being off.
|
|
@@ -114,7 +114,7 @@ export interface RankingWeights {
|
|
|
114
114
|
|
|
115
115
|
/**
|
|
116
116
|
* The shipped weights. Every value is a measured decision — change one and re-run the resolver eval; the per-field docs
|
|
117
|
-
* on {@link RankingWeights} say what each
|
|
117
|
+
* on {@link RankingWeights} say what each change moves and what motivated its current value.
|
|
118
118
|
*/
|
|
119
119
|
export const DEFAULT_WEIGHTS: RankingWeights = {
|
|
120
120
|
placetypeMatchBoost: 0.5,
|
|
@@ -142,7 +142,33 @@ export const DEFAULT_WEIGHTS: RankingWeights = {
|
|
|
142
142
|
// consulted — keeps population as an intra-tier prominence tiebreaker, not a cross-tier promoter.
|
|
143
143
|
// Fixes the 2-letter-region-abbrev bug ("ME" → Maine, not the more-populous Missouri).
|
|
144
144
|
exactMatchTiering: true,
|
|
145
|
-
// #936 option 3 — promoted default-ON 2026-07-03 (
|
|
145
|
+
// #936 option 3 — promoted default-ON 2026-07-03 (eval battery PASS; see the RankingWeights docstring).
|
|
146
146
|
officialNameExact: true,
|
|
147
147
|
officialNameExactFloor: 100_000,
|
|
148
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The population contribution as a 0..1 fraction: `min(1, log10(1 + population) / populationScaleLog10)`. Zero for an
|
|
152
|
+
* absent or non-positive population — and zero for a non-positive scale, so a magnitude never carries its own absence.
|
|
153
|
+
* The coordinate-first locality path consumes this fraction directly; {@link populationBoostTerm} scales it.
|
|
154
|
+
*/
|
|
155
|
+
export function populationScaleTerm(
|
|
156
|
+
population: number | null | undefined,
|
|
157
|
+
weights: Pick<RankingWeights, "populationScaleLog10">
|
|
158
|
+
): number {
|
|
159
|
+
if (population == null || population <= 0 || weights.populationScaleLog10 <= 0) return 0
|
|
160
|
+
|
|
161
|
+
return Math.min(1, Math.log10(1 + population) / weights.populationScaleLog10)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The additive population boost: `populationBoost * populationScaleTerm(...)`, capped at `populationBoost` magnitude at
|
|
166
|
+
* `10^populationScaleLog10` people. Missing population contributes 0 — never a penalty. The one formula behind the Node
|
|
167
|
+
* weighted sum and the WASM re-rank, so the two backends cannot drift.
|
|
168
|
+
*/
|
|
169
|
+
export function populationBoostTerm(
|
|
170
|
+
population: number | null | undefined,
|
|
171
|
+
weights: Pick<RankingWeights, "populationBoost" | "populationScaleLog10">
|
|
172
|
+
): number {
|
|
173
|
+
return weights.populationBoost * populationScaleTerm(population, weights)
|
|
174
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The comparable-key expansion for a parsed REGION qualifier — one function, both consumers (the
|
|
7
|
+
* #861 rule). The admin-coherence verdicts (`mailwoman/admin-coherence.ts`) fold a qualifier and a
|
|
8
|
+
* winner-ancestry name through this to decide `confirmed`/`contradicted`; the candidate backend's
|
|
9
|
+
* admin-containment re-rank (#1717 stage 2, `candidate-lookup.ts`) folds the same qualifier through
|
|
10
|
+
* it to find the qualifier's own region-class rows in the candidate table. A check that says
|
|
11
|
+
* `contradicted` and a re-rank that cannot find the qualifier would otherwise be two readings of
|
|
12
|
+
* one string that silently disagree — the exact drift the shared-function rule exists to prevent.
|
|
13
|
+
*
|
|
14
|
+
* Lives HERE rather than in `mailwoman` because the dependency points this way: `mailwoman`
|
|
15
|
+
* depends on `@mailwoman/resolver-wof-sqlite` (which owns the fold and already depends on codex),
|
|
16
|
+
* never the reverse.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { matchSubdivision, matchSubdivisionIn } from "@mailwoman/codex/country"
|
|
20
|
+
|
|
21
|
+
import { normalizeLocalityForKey } from "#street/normalize"
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The ancestry placetypes that answer for a parsed `region` qualifier — WOF's admin band between country and locality.
|
|
25
|
+
* Deliberately the whole band: a qualifier stated at any grain ("Lancashire", a ceremonial county; "Thüringen", a Land)
|
|
26
|
+
* may confirm against whichever level the backend stored, and `contradicted` requires the entire band to miss, so
|
|
27
|
+
* widening the band only ever makes the check more conservative.
|
|
28
|
+
*/
|
|
29
|
+
export const REGION_CLASS_PLACETYPES: ReadonlySet<string> = new Set(["region", "macroregion", "county", "macrocounty"])
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* County-style qualifier prefixes stripped to produce a comparison VARIANT. Ireland writes `Co. Westmeath` where WOF
|
|
33
|
+
* stores `Westmeath`, so the prefix defeats the fold and every Irish county qualifier read `contradicted` on the first
|
|
34
|
+
* board census (2026-08-17, five rows). The stripped form is ADDED to the key set, never substituted — `County Durham`
|
|
35
|
+
* is a real name whose stripped variant simply also matches, and a set union can only widen confirmation, so the
|
|
36
|
+
* closure is monotone: `contradicted → confirmed` is the only movement it can cause.
|
|
37
|
+
*/
|
|
38
|
+
const COUNTY_QUALIFIER_PREFIXES = ["county", "co.", "co"] as const
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Trailing admin-qualifier words, the suffix sibling of the prefix above: `San José Province` (CR board row) folds
|
|
42
|
+
* against stored `San José` only with the word removed. Same monotone rule — the stripped form joins the set, never
|
|
43
|
+
* replaces the original.
|
|
44
|
+
*/
|
|
45
|
+
const ADMIN_QUALIFIER_SUFFIXES = ["province", "prov.", "prov"] as const
|
|
46
|
+
|
|
47
|
+
function withoutPrefix(value: string, prefixes: readonly string[]): string {
|
|
48
|
+
const folded = value.toLowerCase()
|
|
49
|
+
|
|
50
|
+
for (const prefix of prefixes) {
|
|
51
|
+
if (!folded.startsWith(prefix) || !/\s/u.test(value[prefix.length] ?? "")) continue
|
|
52
|
+
|
|
53
|
+
let offset = prefix.length
|
|
54
|
+
|
|
55
|
+
while (/\s/u.test(value[offset] ?? "")) {
|
|
56
|
+
offset++
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return value.slice(offset)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return value
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function withoutSuffix(value: string, suffixes: readonly string[]): string {
|
|
66
|
+
const folded = value.toLowerCase()
|
|
67
|
+
|
|
68
|
+
for (const suffix of suffixes) {
|
|
69
|
+
const offset = value.length - suffix.length
|
|
70
|
+
|
|
71
|
+
if (offset <= 0 || !folded.endsWith(suffix) || !/\s/u.test(value[offset - 1] ?? "")) continue
|
|
72
|
+
|
|
73
|
+
let end = offset
|
|
74
|
+
|
|
75
|
+
while (end > 0 && /\s/u.test(value[end - 1] ?? "")) {
|
|
76
|
+
end--
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return value.slice(0, end)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return value
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The comparable keys a region string expands to: its own fold (the shared candidate.db `name_key` normalizer,
|
|
87
|
+
* {@link normalizeLocalityForKey} — build side and check side agree by construction); a county-prefix-stripped variant;
|
|
88
|
+
* the codex subdivision expansions — the disjoint US+CA table always, plus the COUNTRY-SCOPED table when the caller
|
|
89
|
+
* knows a country (`WA` under AU is Western Australia; under US, Washington — the collision that keeps AU out of the
|
|
90
|
+
* unscoped table). Every expansion lands the canonical name and code folds in the set, so `IL`/`Illinois` and
|
|
91
|
+
* `WA`/`Western Australia` meet from either side.
|
|
92
|
+
*/
|
|
93
|
+
export function regionKeys(value: string, countryAlpha2?: string): Set<string> {
|
|
94
|
+
const keys = new Set([normalizeLocalityForKey(value)])
|
|
95
|
+
|
|
96
|
+
for (const stripped of [
|
|
97
|
+
withoutPrefix(value, COUNTY_QUALIFIER_PREFIXES),
|
|
98
|
+
withoutSuffix(value, ADMIN_QUALIFIER_SUFFIXES),
|
|
99
|
+
]) {
|
|
100
|
+
if (stripped !== value && stripped.trim()) {
|
|
101
|
+
keys.add(normalizeLocalityForKey(stripped))
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const expansions = [matchSubdivision(value), countryAlpha2 ? matchSubdivisionIn(countryAlpha2, value) : null]
|
|
106
|
+
|
|
107
|
+
for (const subdivision of expansions) {
|
|
108
|
+
if (subdivision) {
|
|
109
|
+
keys.add(normalizeLocalityForKey(subdivision.name))
|
|
110
|
+
keys.add(normalizeLocalityForKey(subdivision.code))
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// The empty fold stays IN the set on purpose — the admin-coherence verdicts have always compared
|
|
115
|
+
// the empty key (two empty-folding strings intersect → `confirmed`), and this move must not shift
|
|
116
|
+
// a verdict. A consumer probing a table by key filters the empty string out itself.
|
|
117
|
+
return keys
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The PROBE-side expansion for a region qualifier — {@link regionKeys} plus the county-PREFIXED variant of every key.
|
|
122
|
+
*
|
|
123
|
+
* The verdict implementation intersects two {@link regionKeys} SETS, so `Co. Donegal` meets stored `County Donegal` at
|
|
124
|
+
* the shared stripped key `donegal`. A table probe is one-sided: it matches the STORED fold verbatim, and WOF stores
|
|
125
|
+
* Irish counties under `county donegal` with no bare `donegal` key (measured on the shipped candidate.db — the
|
|
126
|
+
* qualifier probe missed every Irish county until this variant landed). Adding `county <key>` restores the
|
|
127
|
+
* two-sidedness for the one stored-form family with an evidenced case; the union is monotone (a wider qualifier set can
|
|
128
|
+
* only find more BEARERS, each of which must still genuinely contain a candidate before anything moves). The suffix
|
|
129
|
+
* sibling (`<key> province`) is deliberately absent — no stored-form case has been evidenced, and a change without a
|
|
130
|
+
* board does not get built.
|
|
131
|
+
*/
|
|
132
|
+
export function regionQualifierProbeKeys(value: string, countryAlpha2?: string): Set<string> {
|
|
133
|
+
const keys = regionKeys(value, countryAlpha2)
|
|
134
|
+
// Snapshot before widening: the loop adds `county <key>` members that must not themselves be revisited.
|
|
135
|
+
const bare = [...keys]
|
|
136
|
+
|
|
137
|
+
for (const key of bare) {
|
|
138
|
+
if (key && !key.startsWith("county ")) {
|
|
139
|
+
keys.add(`county ${key}`)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return keys
|
|
144
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
6
|
* Reverse geocoding (#484): `(lat, lon)` → the containing admin hierarchy. Assembly over existing
|
|
7
|
-
*
|
|
7
|
+
* implementation, per the 2026-06-11 scoping notes:
|
|
8
8
|
*
|
|
9
9
|
* 1. **Candidate fetch** — the admin DB's `place_bbox` R*Tree (built by `fts.ts`) for places whose
|
|
10
10
|
* bbox contains the point, smallest-area-first (so the FIRST polygon confirmation is the
|
|
@@ -28,14 +28,16 @@
|
|
|
28
28
|
* says so per result rather than pretending.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
import {
|
|
31
|
+
import { tryParsingJSON } from "@mailwoman/core/json"
|
|
32
|
+
import { bboxAround, geometryContains, haversineKm, type ParsedGeometry } from "@mailwoman/spatial"
|
|
33
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
34
|
+
import { tableExists } from "@mailwoman/sqlite/introspection"
|
|
32
35
|
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import type { PlaceCandidate, WOFPlacetype } from "./types.ts"
|
|
36
|
+
import { ancestorLineage, placetypeDepth } from "#ancestry/index"
|
|
37
|
+
import { PLACE_BBOX_TABLE } from "#fts/index"
|
|
38
|
+
import type { WOFDatabase } from "#schema"
|
|
39
|
+
import { allRows } from "#sqlite-utils"
|
|
40
|
+
import type { PlaceCandidate, WOFPlacetype } from "#types"
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Largest absolute latitude in WGS-84 degrees.
|
|
@@ -79,7 +81,7 @@ export interface WOFReverseGeocoderOpts {
|
|
|
79
81
|
/**
|
|
80
82
|
* Pre-opened admin DB — primarily for tests against an inline fixture.
|
|
81
83
|
*/
|
|
82
|
-
adminDatabase?:
|
|
84
|
+
adminDatabase?: DatabaseClient<WOFDatabase>
|
|
83
85
|
/**
|
|
84
86
|
* Path to the polygon sidecar DB (`wof-polygons.db`, table `polygons(id, geom)`). OPTIONAL — without it every result
|
|
85
87
|
* is `containment: "approximate"` (centroid-only mode). Mutually exclusive with `polygonDatabase`.
|
|
@@ -88,7 +90,7 @@ export interface WOFReverseGeocoderOpts {
|
|
|
88
90
|
/**
|
|
89
91
|
* Pre-opened polygon DB — primarily for tests.
|
|
90
92
|
*/
|
|
91
|
-
polygonDatabase?:
|
|
93
|
+
polygonDatabase?: DatabaseClient<WOFDatabase>
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
export interface ReverseGeocodeOpts {
|
|
@@ -159,9 +161,9 @@ function toPlaceCandidate(row: CandidateRow, distanceKm?: number): PlaceCandidat
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
export class WOFReverseGeocoder implements Disposable {
|
|
162
|
-
readonly #admin:
|
|
164
|
+
readonly #admin: DatabaseClient<WOFDatabase>
|
|
163
165
|
readonly #ownsAdmin: boolean
|
|
164
|
-
readonly #polygons:
|
|
166
|
+
readonly #polygons: DatabaseClient<WOFDatabase> | null
|
|
165
167
|
readonly #ownsPolygons: boolean
|
|
166
168
|
/**
|
|
167
169
|
* Parsed-geometry cache. Reverse queries cluster geographically (an eval run hits the same ~15 county polygons 1400
|
|
@@ -169,7 +171,7 @@ export class WOFReverseGeocoder implements Disposable {
|
|
|
169
171
|
* LRU-tracked; the polygons are DP-simplified and small, the cap exists only to keep a long-lived server process
|
|
170
172
|
* honest.
|
|
171
173
|
*/
|
|
172
|
-
readonly #geometryCache = new Map<number,
|
|
174
|
+
readonly #geometryCache = new Map<number, ParsedGeometry | null>()
|
|
173
175
|
static readonly #GEOMETRY_CACHE_CAP = 4096
|
|
174
176
|
|
|
175
177
|
constructor(opts: WOFReverseGeocoderOpts) {
|
|
@@ -185,38 +187,29 @@ export class WOFReverseGeocoder implements Disposable {
|
|
|
185
187
|
throw new Error("WOFReverseGeocoder: pass either `polygonDatabase` or `polygonDBPath`, not both")
|
|
186
188
|
}
|
|
187
189
|
|
|
188
|
-
this.#admin = opts.adminDatabase ?? new
|
|
190
|
+
this.#admin = opts.adminDatabase ?? new DatabaseClient<WOFDatabase>(opts.adminDBPath!, { readOnly: true })
|
|
189
191
|
this.#ownsAdmin = !opts.adminDatabase
|
|
190
192
|
|
|
191
193
|
this.#polygons =
|
|
192
|
-
opts.polygonDatabase ??
|
|
194
|
+
opts.polygonDatabase ??
|
|
195
|
+
(opts.polygonDBPath ? new DatabaseClient<WOFDatabase>(opts.polygonDBPath, { readOnly: true }) : null)
|
|
193
196
|
|
|
194
197
|
this.#ownsPolygons = !opts.polygonDatabase && Boolean(opts.polygonDBPath)
|
|
195
198
|
|
|
196
199
|
// Fail loudly up front — the R*Tree is a build artifact, not part of the upstream WOF
|
|
197
200
|
// distribution, and a missing index would otherwise surface as an opaque SQL error per query.
|
|
198
|
-
|
|
199
|
-
.prepare(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?`)
|
|
200
|
-
.get(PLACE_BBOX_TABLE)
|
|
201
|
-
|
|
202
|
-
if (!hasBbox) {
|
|
201
|
+
if (!tableExists(this.#admin, PLACE_BBOX_TABLE)) {
|
|
203
202
|
throw new Error(
|
|
204
203
|
`WOFReverseGeocoder: the admin DB has no \`${PLACE_BBOX_TABLE}\` R*Tree. Build it with ` +
|
|
205
204
|
"`mailwoman gazetteer build fts <path-to-wof.db>` (see resolver-wof-sqlite/README.md)."
|
|
206
205
|
)
|
|
207
206
|
}
|
|
208
207
|
|
|
209
|
-
if (this.#polygons) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (!hasPolygons) {
|
|
215
|
-
throw new Error(
|
|
216
|
-
"WOFReverseGeocoder: the polygon DB has no `polygons` table. Expected a `wof-polygons.db` " +
|
|
217
|
-
"built by scripts/build-wof-polygons.mjs."
|
|
218
|
-
)
|
|
219
|
-
}
|
|
208
|
+
if (this.#polygons && !tableExists(this.#polygons, "polygons")) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
"WOFReverseGeocoder: the polygon DB has no `polygons` table. Expected a `wof-polygons.db` " +
|
|
211
|
+
"built by scripts/build-wof-polygons.mjs."
|
|
212
|
+
)
|
|
220
213
|
}
|
|
221
214
|
}
|
|
222
215
|
|
|
@@ -389,16 +382,17 @@ export class WOFReverseGeocoder implements Disposable {
|
|
|
389
382
|
|
|
390
383
|
params.push(opts.maxCandidates ?? DEFAULT_MAX_CANDIDATES)
|
|
391
384
|
|
|
392
|
-
return
|
|
393
|
-
.prepare(
|
|
385
|
+
return allRows<CandidateRow>(
|
|
386
|
+
this.#admin.prepare(
|
|
394
387
|
`SELECT spr.id AS id, spr.name AS name, spr.placetype AS placetype, spr.country AS country,
|
|
395
388
|
spr.parent_id AS parent_id, spr.latitude AS lat, spr.longitude AS lon
|
|
396
389
|
FROM ${PLACE_BBOX_TABLE} bbox JOIN spr ON spr.id = bbox.id
|
|
397
390
|
WHERE ${where.join(" AND ")}
|
|
398
391
|
ORDER BY (bbox.max_lat - bbox.min_lat) * (bbox.max_lon - bbox.min_lon) ASC
|
|
399
392
|
LIMIT ?`
|
|
400
|
-
)
|
|
401
|
-
|
|
393
|
+
),
|
|
394
|
+
...params
|
|
395
|
+
)
|
|
402
396
|
}
|
|
403
397
|
|
|
404
398
|
/**
|
|
@@ -413,30 +407,29 @@ export class WOFReverseGeocoder implements Disposable {
|
|
|
413
407
|
lon: number,
|
|
414
408
|
maxApproximateKm: number
|
|
415
409
|
): CandidateRow[] {
|
|
416
|
-
const
|
|
410
|
+
const window = bboxAround(lat, lon, maxApproximateKm * 4)
|
|
417
411
|
|
|
418
|
-
return
|
|
419
|
-
.prepare(
|
|
412
|
+
return allRows<CandidateRow>(
|
|
413
|
+
this.#admin.prepare(
|
|
420
414
|
`SELECT s.id AS id, s.name AS name, s.placetype AS placetype, s.country AS country,
|
|
421
415
|
s.parent_id AS parent_id, s.latitude AS lat, s.longitude AS lon
|
|
422
416
|
FROM ancestors a JOIN spr s ON s.id = a.id
|
|
423
417
|
WHERE a.ancestor_id = ? AND s.placetype = ? AND s.is_current != 0 AND s.is_deprecated = 0
|
|
424
418
|
AND s.latitude BETWEEN ? AND ? AND s.longitude BETWEEN ? AND ?`
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
) as unknown as CandidateRow[]
|
|
419
|
+
),
|
|
420
|
+
parentID,
|
|
421
|
+
placetype,
|
|
422
|
+
window.minLat,
|
|
423
|
+
window.maxLat,
|
|
424
|
+
window.minLon,
|
|
425
|
+
window.maxLon
|
|
426
|
+
)
|
|
434
427
|
}
|
|
435
428
|
|
|
436
429
|
/**
|
|
437
430
|
* Parsed GeoJSON geometry for a WOF id, or null when absent / unparseable / no polygon DB.
|
|
438
431
|
*/
|
|
439
|
-
#geometry(id: number):
|
|
432
|
+
#geometry(id: number): ParsedGeometry | null {
|
|
440
433
|
if (!this.#polygons) return null
|
|
441
434
|
const cached = this.#geometryCache.get(id)
|
|
442
435
|
|
|
@@ -448,24 +441,20 @@ export class WOFReverseGeocoder implements Disposable {
|
|
|
448
441
|
|
|
449
442
|
const row = this.#polygons.prepare(`SELECT geom FROM polygons WHERE id = ?`).get(id) as { geom: string } | undefined
|
|
450
443
|
// Malformed row parses to null — treat as no-polygon rather than failing the query.
|
|
451
|
-
const geometry = row ? tryParsingJSON<
|
|
444
|
+
const geometry = row ? tryParsingJSON<ParsedGeometry>(row.geom) : null
|
|
452
445
|
|
|
453
446
|
this.#geometryCache.set(id, geometry)
|
|
454
447
|
|
|
455
448
|
return geometry
|
|
456
449
|
}
|
|
457
450
|
|
|
458
|
-
|
|
451
|
+
[Symbol.dispose](): void {
|
|
459
452
|
if (this.#ownsAdmin) {
|
|
460
|
-
this.#admin.
|
|
453
|
+
this.#admin.destroy()
|
|
461
454
|
}
|
|
462
455
|
|
|
463
456
|
if (this.#ownsPolygons) {
|
|
464
|
-
this.#polygons?.
|
|
457
|
+
this.#polygons?.destroy()
|
|
465
458
|
}
|
|
466
459
|
}
|
|
467
|
-
|
|
468
|
-
[Symbol.dispose](): void {
|
|
469
|
-
this.close()
|
|
470
|
-
}
|
|
471
460
|
}
|
|
@@ -159,11 +159,21 @@ export interface CoincidentRolesTable {
|
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
161
|
* The full schema we hand to `Kysely<WOFDatabase>` / `new DatabaseClient<WOFDatabase>(...)`. Tables not listed here
|
|
162
|
-
* will fail type-checked queries — by design. The reader ({@link
|
|
162
|
+
* will fail type-checked queries — by design. The reader ({@link WOFSQLitePlaceLookup}) already consumes this; the
|
|
163
163
|
* build/augment WRITERS adopt it so a column rename is a compile error on both sides (the drift that bit the corpus
|
|
164
164
|
* TIGER adapter).
|
|
165
165
|
*/
|
|
166
|
+
/**
|
|
167
|
+
* The provenance row every built extract carries: source fingerprints travelling WITH the database rather than in a
|
|
168
|
+
* document that can drift from it. Written by the postcode builders in `mailwoman/gazetteer-pipeline`.
|
|
169
|
+
*/
|
|
170
|
+
export interface ExtractMetaTable {
|
|
171
|
+
key: string
|
|
172
|
+
value: string | null
|
|
173
|
+
}
|
|
174
|
+
|
|
166
175
|
export interface WOFDatabase {
|
|
176
|
+
meta: ExtractMetaTable
|
|
167
177
|
place_search: PlaceSearchTable
|
|
168
178
|
spr: SprTable
|
|
169
179
|
names: NamesTable
|