@mailwoman/resolver-wof-sqlite 9.2.0 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -19
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +25 -24
- package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
- package/lib/address/point.ts +328 -0
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +5 -4
- package/{build-candidate.ts → lib/build-candidate.ts} +99 -79
- package/{build-slim.ts → lib/build-slim.ts} +150 -165
- package/{candidate → lib/candidate}/alias-bags.ts +8 -6
- package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
- package/{candidate → lib/candidate}/country-display-names.ts +2 -2
- package/lib/candidate/extract-fold.ts +219 -0
- package/{candidate → lib/candidate}/name-roles.ts +17 -16
- package/{candidate → lib/candidate}/own-name.ts +2 -1
- package/{candidate → lib/candidate}/place-attrs.ts +3 -3
- package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
- package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
- package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
- package/{candidate-lookup.ts → lib/candidate-lookup.ts} +84 -80
- package/{candidate-schema.ts → lib/candidate-schema.ts} +6 -6
- package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
- package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
- package/{capitals.ts → lib/capitals.ts} +2 -2
- package/{coincident-roles.ts → lib/coincident-roles.ts} +9 -13
- package/{convention.ts → lib/convention/index.ts} +3 -3
- package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +10 -10
- package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
- package/lib/env.ts +50 -0
- package/{exact-match.ts → lib/exact-match.ts} +23 -14
- package/{sharding.ts → lib/extracts.ts} +61 -58
- package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
- package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
- package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
- package/lib/fst/format.ts +106 -0
- package/{fst-freshness.ts → lib/fst/freshness.ts} +40 -74
- package/lib/fst/index.ts +14 -0
- package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
- package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
- package/{fst-types.ts → lib/fst/types.ts} +4 -2
- package/{fts.ts → lib/fts/index.ts} +24 -19
- package/{fts-query.ts → lib/fts/query.ts} +1 -1
- package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
- package/lib/geonames/index.ts +8 -0
- package/{geonames-postal.ts → lib/geonames/postal.ts} +14 -13
- package/{index.ts → lib/index.ts} +37 -37
- package/{interpolation.ts → lib/interpolation.ts} +28 -26
- package/{lookup.ts → lib/lookup.ts} +130 -142
- package/lib/nsul/index.ts +8 -0
- package/lib/nsul/lookup.ts +144 -0
- package/lib/nsul/schema.ts +130 -0
- package/{place-importance-schema.ts → lib/place-importance-schema.ts} +7 -16
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -29
- package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/{primary-preference.ts → lib/primary-preference.ts} +43 -14
- package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/{region-keys.ts → lib/region-keys.ts} +9 -9
- package/{reverse.ts → lib/reverse.ts} +34 -47
- package/{schema.ts → lib/schema.ts} +10 -0
- package/{search-fetch.ts → lib/search-fetch.ts} +29 -29
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -19
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
- package/{street-centroid.ts → lib/street/centroid.ts} +15 -22
- package/lib/street/index.ts +13 -0
- package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
- package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
- package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
- package/{street-normalize.ts → lib/street/normalize.ts} +86 -20
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
- package/{types.ts → lib/types.ts} +18 -12
- package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -19
- package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
- package/lib/weights-overlay-linker.ts +879 -0
- package/out/address/index.d.ts +9 -0
- package/out/address/index.d.ts.map +1 -0
- package/out/address/index.js +9 -0
- package/out/address/index.js.map +1 -0
- package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +12 -11
- package/out/address/point-interpolation.d.ts.map +1 -0
- package/out/{address-point-interpolation.js → address/point-interpolation.js} +18 -18
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
- package/out/address/point-schema.d.ts.map +1 -0
- package/out/{address-point-schema.js → address/point-schema.js} +7 -3
- package/out/address/point-schema.js.map +1 -0
- package/out/{address-point.d.ts → address/point.d.ts} +19 -9
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +222 -0
- package/out/address/point.js.map +1 -0
- package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
- package/out/ancestry/backfill.d.ts.map +1 -0
- package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
- package/out/ancestry/backfill.js.map +1 -0
- package/out/{ancestry.d.ts → ancestry/index.d.ts} +4 -3
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +3 -2
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +32 -24
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +60 -54
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +4 -4
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +124 -139
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +5 -3
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +2 -2
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors-sidecar.d.ts +9 -10
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
- package/out/candidate/ancestors-sidecar.js +7 -7
- package/out/candidate/ancestors-sidecar.js.map +1 -1
- package/out/candidate/country-display-names.d.ts +1 -1
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +1 -1
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +41 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/extract-fold.js +153 -0
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +13 -11
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +11 -10
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +1 -1
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +2 -1
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +3 -3
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +1 -1
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate-ancestors-schema.d.ts +4 -4
- package/out/candidate-ancestors-schema.d.ts.map +1 -1
- package/out/candidate-ancestors-schema.js +2 -2
- package/out/candidate-ancestors-schema.js.map +1 -1
- package/out/candidate-fts.d.ts +3 -3
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +1 -1
- package/out/candidate-fts.js.map +1 -1
- package/out/candidate-importance.d.ts +16 -16
- package/out/candidate-importance.d.ts.map +1 -1
- package/out/candidate-importance.js +46 -51
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +16 -14
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +67 -63
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +6 -6
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js +1 -1
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +7 -7
- package/out/candidate-scoring.d.ts.map +1 -1
- package/out/candidate-scoring.js +10 -14
- package/out/candidate-scoring.js.map +1 -1
- package/out/capital-schema.d.ts +3 -3
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +2 -2
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +1 -1
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +2 -2
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +7 -6
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +2 -4
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +4 -4
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +2 -2
- package/out/convention/index.js.map +1 -0
- package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
- package/out/convention/schema.d.ts.map +1 -0
- package/out/{convention-schema.js → convention/schema.js} +3 -3
- package/out/convention/schema.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +8 -8
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +5 -4
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +51 -7
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +65 -49
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +43 -0
- package/out/env.d.ts.map +1 -0
- package/out/env.js +48 -0
- package/out/env.js.map +1 -0
- package/out/exact-match.d.ts +5 -5
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +10 -11
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +114 -0
- package/out/extracts.d.ts.map +1 -0
- package/out/{sharding.js → extracts.js} +38 -38
- package/out/extracts.js.map +1 -0
- package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +2 -2
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
- package/out/fst/autocomplete.js.map +1 -0
- package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
- package/out/fst/builder.d.ts.map +1 -0
- package/out/{fst-builder.js → fst/builder.js} +14 -13
- package/out/fst/builder.js.map +1 -0
- package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -0
- package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
- package/out/fst/deserialize-web.js.map +1 -0
- package/out/fst/format.d.ts +80 -0
- package/out/fst/format.d.ts.map +1 -0
- package/out/fst/format.js +91 -0
- package/out/fst/format.js.map +1 -0
- package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +9 -13
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +40 -73
- package/out/fst/freshness.js.map +1 -0
- package/out/fst/index.d.ts +14 -0
- package/out/fst/index.d.ts.map +1 -0
- package/out/fst/index.js +14 -0
- package/out/fst/index.js.map +1 -0
- package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
- package/out/fst/matcher.d.ts.map +1 -0
- package/out/{fst-matcher.js → fst/matcher.js} +1 -1
- package/out/fst/matcher.js.map +1 -0
- package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
- package/out/fst/serialize.d.ts.map +1 -0
- package/out/{fst-serialize.js → fst/serialize.js} +18 -98
- package/out/fst/serialize.js.map +1 -0
- package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
- package/out/fst/types.d.ts.map +1 -0
- package/out/{fst-types.js → fst/types.js} +1 -1
- package/out/fst/types.js.map +1 -0
- package/out/{fts.d.ts → fts/index.d.ts} +16 -9
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +16 -11
- package/out/fts/index.js.map +1 -0
- package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
- package/out/fts/query.d.ts.map +1 -0
- package/out/{fts-query.js → fts/query.js} +1 -1
- package/out/fts/query.js.map +1 -0
- package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
- package/out/geonames/aliases.d.ts.map +1 -0
- package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
- package/out/geonames/aliases.js.map +1 -0
- package/out/geonames/index.d.ts +8 -0
- package/out/geonames/index.d.ts.map +1 -0
- package/out/geonames/index.js +8 -0
- package/out/geonames/index.js.map +1 -0
- package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +10 -8
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +9 -9
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -32
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -24
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +11 -10
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +20 -20
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +22 -21
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +103 -113
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js.map +1 -1
- package/out/nsul/index.d.ts +8 -0
- package/out/nsul/index.d.ts.map +1 -0
- package/out/nsul/index.js +8 -0
- package/out/nsul/index.js.map +1 -0
- package/out/nsul/lookup.d.ts +83 -0
- package/out/nsul/lookup.d.ts.map +1 -0
- package/out/nsul/lookup.js +80 -0
- package/out/nsul/lookup.js.map +1 -0
- package/out/nsul/schema.d.ts +100 -0
- package/out/nsul/schema.d.ts.map +1 -0
- package/out/nsul/schema.js +78 -0
- package/out/nsul/schema.js.map +1 -0
- package/out/place-importance-schema.d.ts +5 -6
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -4
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/index.d.ts +8 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +8 -0
- package/out/poi/index.js.map +1 -0
- package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
- package/out/poi/lookup.d.ts.map +1 -0
- package/out/{poi-lookup.js → poi/lookup.js} +14 -18
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
- package/out/poi/schema.d.ts.map +1 -0
- package/out/{poi-schema.js → poi/schema.js} +1 -1
- package/out/poi/schema.js.map +1 -0
- package/out/polygon-schema.d.ts.map +1 -1
- package/out/polygon-schema.js.map +1 -1
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
- package/out/postal/city-alias-lookup.js.map +1 -0
- package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
- package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
- package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
- package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
- package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +3 -3
- package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
- package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
- package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
- package/out/postal/index.d.ts +9 -0
- package/out/postal/index.d.ts.map +1 -0
- package/out/postal/index.js +9 -0
- package/out/postal/index.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +10 -10
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +13 -13
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +15 -7
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +28 -12
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +2 -2
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +2 -2
- package/out/proximity-rerank.js.map +1 -1
- package/out/ranking-weights.d.ts +15 -3
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +21 -3
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +8 -8
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +9 -9
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +20 -29
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +9 -0
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +12 -10
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +21 -20
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite-convention-source.d.ts +7 -7
- package/out/sqlite-convention-source.d.ts.map +1 -1
- package/out/sqlite-convention-source.js +5 -5
- package/out/sqlite-convention-source.js.map +1 -1
- package/out/sqlite-utils.d.ts +8 -9
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +6 -10
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
- package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
- package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
- package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
- package/out/{street-centroid.d.ts → street/centroid.d.ts} +7 -7
- package/out/street/centroid.d.ts.map +1 -0
- package/out/{street-centroid.js → street/centroid.js} +13 -19
- package/out/street/centroid.js.map +1 -0
- package/out/street/index.d.ts +13 -0
- package/out/street/index.d.ts.map +1 -0
- package/out/street/index.js +13 -0
- package/out/street/index.js.map +1 -0
- package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
- package/out/street/morphology-fst-builder.d.ts.map +1 -0
- package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
- package/out/street/morphology-fst-builder.js.map +1 -0
- package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
- package/out/street/morphology-fst-loader.d.ts.map +1 -0
- package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
- package/out/street/morphology-fst-loader.js.map +1 -0
- package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
- package/out/street/name-lookup.d.ts.map +1 -0
- package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
- package/out/street/name-lookup.js.map +1 -0
- package/out/{street-normalize.d.ts → street/normalize.d.ts} +38 -15
- package/out/street/normalize.d.ts.map +1 -0
- package/out/{street-normalize.js → street/normalize.js} +73 -17
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
- package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
- package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
- package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
- package/out/types.d.ts +18 -12
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +5 -4
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +15 -18
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +53 -0
- package/out/uprn/existence.d.ts.map +1 -0
- package/out/uprn/existence.js +61 -0
- package/out/uprn/existence.js.map +1 -0
- package/out/uprn/index.d.ts +9 -0
- package/out/uprn/index.d.ts.map +1 -0
- package/out/uprn/index.js +9 -0
- package/out/uprn/index.js.map +1 -0
- package/out/{uprn-lookup.d.ts → uprn/lookup.d.ts} +4 -4
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
- package/out/uprn/lookup.js.map +1 -0
- package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/{uprn-schema.js → uprn/schema.js} +4 -4
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +184 -26
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +339 -86
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +465 -269
- package/address-point.ts +0 -218
- package/candidate/shard-fold.ts +0 -137
- package/out/address-point-interpolation.d.ts.map +0 -1
- package/out/address-point-interpolation.js.map +0 -1
- package/out/address-point-schema.d.ts.map +0 -1
- package/out/address-point-schema.js.map +0 -1
- package/out/address-point.d.ts.map +0 -1
- package/out/address-point.js +0 -140
- package/out/address-point.js.map +0 -1
- package/out/ancestry-backfill.d.ts.map +0 -1
- package/out/ancestry-backfill.js.map +0 -1
- package/out/ancestry.d.ts.map +0 -1
- package/out/ancestry.js.map +0 -1
- package/out/candidate/shard-fold.d.ts +0 -31
- package/out/candidate/shard-fold.d.ts.map +0 -1
- package/out/candidate/shard-fold.js +0 -104
- package/out/candidate/shard-fold.js.map +0 -1
- package/out/convention-schema.d.ts.map +0 -1
- package/out/convention-schema.js.map +0 -1
- package/out/convention.d.ts.map +0 -1
- package/out/convention.js.map +0 -1
- package/out/fst-autocomplete.d.ts.map +0 -1
- package/out/fst-autocomplete.js.map +0 -1
- package/out/fst-builder.d.ts.map +0 -1
- package/out/fst-builder.js.map +0 -1
- package/out/fst-deserialize-web.d.ts.map +0 -1
- package/out/fst-deserialize-web.js.map +0 -1
- package/out/fst-freshness.d.ts.map +0 -1
- package/out/fst-freshness.js.map +0 -1
- package/out/fst-matcher.d.ts.map +0 -1
- package/out/fst-matcher.js.map +0 -1
- package/out/fst-serialize.d.ts.map +0 -1
- package/out/fst-serialize.js.map +0 -1
- package/out/fst-types.d.ts.map +0 -1
- package/out/fst-types.js.map +0 -1
- package/out/fts-query.d.ts.map +0 -1
- package/out/fts-query.js.map +0 -1
- package/out/fts.d.ts.map +0 -1
- package/out/fts.js.map +0 -1
- package/out/geonames-aliases.d.ts.map +0 -1
- package/out/geonames-aliases.js.map +0 -1
- package/out/geonames-postal.d.ts.map +0 -1
- package/out/geonames-postal.js.map +0 -1
- package/out/poi-lookup.d.ts.map +0 -1
- package/out/poi-lookup.js.map +0 -1
- package/out/poi-schema.d.ts.map +0 -1
- package/out/poi-schema.js.map +0 -1
- package/out/postal-city-alias-lookup.d.ts.map +0 -1
- package/out/postal-city-alias-lookup.js.map +0 -1
- package/out/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.map +0 -1
- package/out/street-centroid.d.ts.map +0 -1
- package/out/street-centroid.js.map +0 -1
- package/out/street-morphology-fst-builder.d.ts.map +0 -1
- package/out/street-morphology-fst-builder.js.map +0 -1
- package/out/street-morphology-fst-loader.d.ts.map +0 -1
- package/out/street-morphology-fst-loader.js.map +0 -1
- package/out/street-name-lookup.d.ts.map +0 -1
- package/out/street-name-lookup.js.map +0 -1
- package/out/street-normalize.d.ts.map +0 -1
- package/out/street-normalize.js.map +0 -1
- package/out/uprn-lookup.d.ts.map +0 -1
- package/out/uprn-lookup.js.map +0 -1
- package/out/uprn-schema.d.ts.map +0 -1
- package/out/uprn-schema.js.map +0 -1
- package/weights-overlay-linker.ts +0 -377
- /package/{name-score.ts → lib/name-score.ts} +0 -0
- /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -45,14 +45,12 @@
|
|
|
45
45
|
* nothing.
|
|
46
46
|
*/
|
|
47
47
|
|
|
48
|
-
import {
|
|
49
|
-
import type { DatabaseSync } from "node:sqlite"
|
|
50
|
-
|
|
51
|
-
import { DatabaseClient } from "@mailwoman/core/kysley/client"
|
|
48
|
+
import { readDirectoryEntries } from "@mailwoman/core/fs/readers"
|
|
52
49
|
import { readWOFFeature } from "@mailwoman/core/resources/whosonfirst"
|
|
53
|
-
import {
|
|
50
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
51
|
+
import { join, resolvePath, type PathBuilderLike } from "path-ts"
|
|
54
52
|
|
|
55
|
-
import type { WOFDatabase } from "
|
|
53
|
+
import type { WOFDatabase } from "#schema"
|
|
56
54
|
|
|
57
55
|
/**
|
|
58
56
|
* Genuinely top-level placetypes — they never have (or need) an ancestor, so skip them.
|
|
@@ -76,23 +74,21 @@ export interface AncestryBackfillResult {
|
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
/**
|
|
79
|
-
* Discover the `data` directories under a WOF repos root that hold
|
|
77
|
+
* Discover the `data` directories under a WOF repos root that hold attached geojson, e.g.
|
|
80
78
|
* `<root>/whosonfirst-data/whosonfirst-data-admin-us/data`. Resolves an id to its geojson via these roots. Accepts both
|
|
81
79
|
* the nested lab layout (a `whosonfirst-data` group dir holding the admin repos) and a flat layout (admin repos
|
|
82
80
|
* directly under the root); searches at most two directory levels deep.
|
|
83
81
|
*/
|
|
84
|
-
export function discoverAdminDataRoots(reposRoot:
|
|
82
|
+
export async function discoverAdminDataRoots(reposRoot: PathBuilderLike): Promise<string[]> {
|
|
85
83
|
const roots: string[] = []
|
|
86
84
|
|
|
87
|
-
const visit = (dir: string, depth: number): void => {
|
|
85
|
+
const visit = async (dir: string, depth: number): Promise<void> => {
|
|
88
86
|
if (depth > 2) return
|
|
89
87
|
|
|
90
88
|
let names: string[]
|
|
91
89
|
|
|
92
90
|
try {
|
|
93
|
-
names =
|
|
94
|
-
.filter((e) => e.isDirectory())
|
|
95
|
-
.map((e) => e.name)
|
|
91
|
+
names = (await readDirectoryEntries(dir)).filter((e) => e.isDirectory()).map((e) => e.name)
|
|
96
92
|
} catch {
|
|
97
93
|
return
|
|
98
94
|
}
|
|
@@ -103,12 +99,12 @@ export function discoverAdminDataRoots(reposRoot: string): string[] {
|
|
|
103
99
|
if (name === "data") {
|
|
104
100
|
roots.push(child)
|
|
105
101
|
} else if (name.startsWith("whosonfirst-data")) {
|
|
106
|
-
visit(child, depth + 1)
|
|
102
|
+
await visit(child, depth + 1)
|
|
107
103
|
}
|
|
108
104
|
}
|
|
109
105
|
}
|
|
110
106
|
|
|
111
|
-
visit(reposRoot, 0)
|
|
107
|
+
await visit(resolvePath(reposRoot), 0)
|
|
112
108
|
|
|
113
109
|
return roots
|
|
114
110
|
}
|
|
@@ -136,18 +132,17 @@ function placetypeFromKey(key: string): string | null {
|
|
|
136
132
|
* skipped rows would have `noGeojson`-skipped anyway. Omit `maxID` (default) for the legacy WOF-only DBs.
|
|
137
133
|
*/
|
|
138
134
|
export async function backfillAncestorsFromHierarchy(
|
|
139
|
-
db:
|
|
135
|
+
db: DatabaseClient<WOFDatabase>,
|
|
140
136
|
geojsonRoots: readonly string[],
|
|
141
137
|
opts: { maxID?: number } = {}
|
|
142
138
|
): Promise<AncestryBackfillResult> {
|
|
143
139
|
const maxID = opts.maxID ?? Number.MAX_SAFE_INTEGER
|
|
144
|
-
const kdb = new DatabaseClient<WOFDatabase>({ database: db })
|
|
145
140
|
|
|
146
141
|
// "No country-tier ancestor" is the dead-end signal at any depth — see the module docstring. The
|
|
147
142
|
// earlier "<= 1 ancestor row" test only caught the dead end's origin, never the children that
|
|
148
143
|
// inherit it (a child of a repaired -4 place has two rows: itself and that parent) (#1445).
|
|
149
144
|
// The id bound is stated first so SQLite prunes by the PK index before the NOT EXISTS runs at all.
|
|
150
|
-
const candidateBase =
|
|
145
|
+
const candidateBase = db
|
|
151
146
|
.selectFrom("spr")
|
|
152
147
|
.where("id", "<", maxID)
|
|
153
148
|
.where((eb) =>
|
|
@@ -172,7 +167,7 @@ export async function backfillAncestorsFromHierarchy(
|
|
|
172
167
|
// (measured 2026-08-04).
|
|
173
168
|
const alreadyPresent = new Map<number, Set<number>>()
|
|
174
169
|
|
|
175
|
-
for (const row of await
|
|
170
|
+
for (const row of await db
|
|
176
171
|
.selectFrom("ancestors")
|
|
177
172
|
.select(["id", "ancestor_id"])
|
|
178
173
|
.where("id", "in", candidateBase.select("spr.id"))
|
|
@@ -198,7 +193,7 @@ export async function backfillAncestorsFromHierarchy(
|
|
|
198
193
|
|
|
199
194
|
for (const { id, placetype } of candidates) {
|
|
200
195
|
if (placetype && TOP_PLACETYPES.has(placetype)) continue
|
|
201
|
-
const gj = readWOFFeature(id, geojsonRoots)
|
|
196
|
+
const gj = await readWOFFeature(id, geojsonRoots)
|
|
202
197
|
const hierarchy = gj?.properties?.["wof:hierarchy"]
|
|
203
198
|
|
|
204
199
|
if (!hierarchy || !hierarchy.length) {
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
* geocoding always does).
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
import { allRows } from "./sqlite-utils.ts"
|
|
18
|
+
import { allRows } from "@mailwoman/core/utils"
|
|
19
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* WOF placetype → containment depth, coarsest = 1. Higher = finer. Placetypes we never resolve (continent, empire, …)
|
|
@@ -61,7 +60,7 @@ export interface AncestorPlaceRow {
|
|
|
61
60
|
* The ancestor lineage of `id` — self excluded, nearest-first. Returns `[]` when the place has no recorded ancestry.
|
|
62
61
|
* NOT memoized here; `WOFSQLitePlaceLookup` keeps its own per-id cache.
|
|
63
62
|
*/
|
|
64
|
-
export function ancestorLineage(db:
|
|
63
|
+
export function ancestorLineage<DB>(db: DatabaseClient<DB>, id: number, schemaName = "main"): AncestorPlaceRow[] {
|
|
65
64
|
const rows = allRows<AncestorPlaceRow>(
|
|
66
65
|
db.prepare(
|
|
67
66
|
`SELECT a.ancestor_id AS id, a.ancestor_placetype AS placetype, s.name AS name,
|
|
@@ -76,3 +75,5 @@ export function ancestorLineage(db: DatabaseSync, id: number, schemaName = "main
|
|
|
76
75
|
|
|
77
76
|
return rows
|
|
78
77
|
}
|
|
78
|
+
|
|
79
|
+
export * from "#ancestry/backfill"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*
|
|
23
23
|
* The name_key normalizer is the SHARED {@link normalizeLocalityForKey} — the query side (the demo
|
|
24
24
|
* resolver {@link WOFCandidateTableLookup}) MUST use the same function, the one-normalizer
|
|
25
|
-
* discipline the address-point
|
|
25
|
+
* discipline the address-point extract uses, so build/query stay consistent by construction.
|
|
26
26
|
*
|
|
27
27
|
* Measured (2026-06-20, vs the 2.6 GB full-DB FTS): ~5 M rows; ~12 range fetches per 8-query
|
|
28
28
|
* session (the full DB needs 243); US locality 96.8% (region bbox), EU coord parity 88.6%.
|
|
@@ -39,36 +39,36 @@
|
|
|
39
39
|
* `candidate-ancestors-schema.ts` owns the encoding decision and the DAG/absence semantics.
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
import { existsSync, rmSync } from "node:fs"
|
|
43
|
-
import { DatabaseSync } from "node:sqlite"
|
|
44
|
-
|
|
45
42
|
import { COUNTRY_POPULATION } from "@mailwoman/codex/country"
|
|
46
|
-
import {
|
|
43
|
+
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
44
|
+
import { removePath } from "@mailwoman/core/fs/writers"
|
|
45
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
47
46
|
|
|
48
|
-
import { createCandidateFTS } from "
|
|
49
|
-
import {
|
|
47
|
+
import { createCandidateFTS } from "#candidate-fts"
|
|
48
|
+
import { IMPORTANCE_JOIN_RADIUS_KM, loadImportanceIndex } from "#candidate-importance"
|
|
50
49
|
import {
|
|
51
50
|
CANDIDATE_COLUMNS,
|
|
52
51
|
createCandidateStagingTables,
|
|
53
52
|
createCandidateTable,
|
|
54
53
|
type CandidateDatabase,
|
|
55
|
-
} from "
|
|
56
|
-
import { explodeAliasBags } from "
|
|
57
|
-
import { buildAncestorsSidecar } from "
|
|
58
|
-
import { stageCountryDisplayNames } from "
|
|
59
|
-
import {
|
|
60
|
-
import
|
|
61
|
-
import {
|
|
62
|
-
import { createCapitalTable } from "
|
|
63
|
-
import type { CapitalPoint } from "
|
|
64
|
-
import { resurrectCurrencyHoles } from "
|
|
65
|
-
import {
|
|
54
|
+
} from "#candidate-schema"
|
|
55
|
+
import { explodeAliasBags } from "#candidate/alias-bags"
|
|
56
|
+
import { buildAncestorsSidecar } from "#candidate/ancestors-sidecar"
|
|
57
|
+
import { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
58
|
+
import { foldExtract } from "#candidate/extract-fold"
|
|
59
|
+
import { GLOSS_KEY_THRESHOLD, stampNameRoles } from "#candidate/name-roles"
|
|
60
|
+
import type { PlaceAttrs } from "#candidate/place-attrs"
|
|
61
|
+
import { createCapitalTable } from "#capital-schema"
|
|
62
|
+
import type { CapitalPoint } from "#capitals"
|
|
63
|
+
import { resurrectCurrencyHoles } from "#currency-backfill"
|
|
64
|
+
import type { WOFDatabase } from "#schema"
|
|
65
|
+
import { normalizeLocalityForKey } from "#street/normalize"
|
|
66
66
|
|
|
67
67
|
// The build's contract is this module path; the passes behind it live in `./candidate/`. Re-exported
|
|
68
68
|
// here so a consumer never has to know which pass owns which name.
|
|
69
|
-
export { stageCountryDisplayNames } from "
|
|
70
|
-
export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "
|
|
71
|
-
export type { PlaceAttrs } from "
|
|
69
|
+
export { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
70
|
+
export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "#candidate/name-roles"
|
|
71
|
+
export type { PlaceAttrs } from "#candidate/place-attrs"
|
|
72
72
|
|
|
73
73
|
export interface BuildCandidateOptions {
|
|
74
74
|
/**
|
|
@@ -86,20 +86,22 @@ export interface BuildCandidateOptions {
|
|
|
86
86
|
*/
|
|
87
87
|
capitals?: readonly CapitalPoint[]
|
|
88
88
|
/**
|
|
89
|
-
* Optional postcode
|
|
89
|
+
* Optional postcode extracts (`spr` rows with `placetype='postalcode'` + real coords, e.g. postalcode-us.db) — folded
|
|
90
90
|
* in as `postalcode` candidate rows so `findPlace(postalcode)` resolves a ZIP directly (the demo's primary postcode
|
|
91
91
|
* path; the postcode-*.bin anchor stays the fallback). Matches the slim wof-hot.db, which took one such postcode DB.
|
|
92
92
|
*
|
|
93
|
-
* Each
|
|
93
|
+
* Each extract's `names` table is folded in too (#1495) — that's where the GeoNames delivery-city names live
|
|
94
94
|
* ("Brooklyn" for 11201), and they were previously reachable only through FTS.
|
|
95
95
|
*/
|
|
96
96
|
postcodes?: string[]
|
|
97
97
|
/**
|
|
98
|
-
* Optional LOCALITY
|
|
99
|
-
* #1564 NZ suburb tier) — folded through the same
|
|
100
|
-
* rows with
|
|
101
|
-
*
|
|
102
|
-
*
|
|
98
|
+
* Optional LOCALITY extracts (`spr` rows with `placetype='locality'` + real coords, e.g. localities-nz-linz.db — the
|
|
99
|
+
* #1564 NZ suburb tier) — folded through the same extract loop as the postcode extracts, staged as `locality`
|
|
100
|
+
* candidate rows with UNMEASURED population (`neg_rank 0`: a extract row ranks behind any populated namesake and wins
|
|
101
|
+
* only where its key is the answer). Each extract's `names` table folds as aliases, `is_primary = 0`, same as the
|
|
102
|
+
* delivery-city pass. An extract whose `ancestors` table names an admin region for a row gives that row the region's
|
|
103
|
+
* scope (`region_id`) plus closure rows for the region and the region's own chain above it; an extract without one
|
|
104
|
+
* stays unscoped, as before.
|
|
103
105
|
*/
|
|
104
106
|
localities?: string[]
|
|
105
107
|
/**
|
|
@@ -118,21 +120,30 @@ export interface BuildCandidateOptions {
|
|
|
118
120
|
* Cross-source currency backfill (#1737). WOF carries deprecated-with-no-successor records for real, populated
|
|
119
121
|
* settlements (Rochester Kent, Aldershot, Telford — 120 GB localities alone), and the currency filter correctly drops
|
|
120
122
|
* them, leaving holes no ranking can fill. When this option is set, pass 1c resurrects a dead locality ONLY under
|
|
121
|
-
* three
|
|
122
|
-
* same-name row is a NAMESAKE and does not block — Rochester, Northumberland pop 318 must not veto Rochester,
|
|
123
|
-
* an independent GeoNames P-class attestation of the same folded name within
|
|
124
|
-
* the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged
|
|
125
|
-
* and bbox — GeoNames only ATTESTS the place and supplies the population
|
|
126
|
-
* `countries` are judged only where `<cc>.txt` exists under `geonamesDir`;
|
|
123
|
+
* three conditions, positive evidence throughout: no live same-name row of any placetype near the dead record (a
|
|
124
|
+
* distant same-name row is a NAMESAKE and does not block — Rochester, Northumberland pop 318 must not veto Rochester,
|
|
125
|
+
* Kent); an independent GeoNames P-class attestation of the same folded name within
|
|
126
|
+
* {@link CURRENCY_BACKFILL_RADIUS_KM}; and the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged
|
|
127
|
+
* row keeps the real WOF id, name, centroid and bbox — GeoNames only ATTESTS the place and supplies the population
|
|
128
|
+
* that lets it stand in prominence races. `countries` are judged only where `<cc>.txt` exists under `geonamesDir`;
|
|
129
|
+
* absent dumps are skipped loudly.
|
|
127
130
|
*/
|
|
128
|
-
currencyBackfill?: {
|
|
131
|
+
currencyBackfill?: {
|
|
132
|
+
geonamesDir: string
|
|
133
|
+
countries: readonly string[]
|
|
134
|
+
/**
|
|
135
|
+
* The dead placetypes the resurrection judges; `resurrectCurrencyHoles`'s default (`locality`) when absent. The
|
|
136
|
+
* `localadmin` widening #1746 named is admitted here once its census is read.
|
|
137
|
+
*/
|
|
138
|
+
deadPlacetypes?: readonly string[]
|
|
139
|
+
}
|
|
129
140
|
/**
|
|
130
141
|
* Optional progress callback for CLI / test introspection.
|
|
131
142
|
*/
|
|
132
143
|
onProgress?: (phase: string, message: string) => void
|
|
133
144
|
/**
|
|
134
145
|
* Key-count threshold for the gloss anomaly detector — {@link GLOSS_KEY_THRESHOLD} unless a test passes a
|
|
135
|
-
* fixture-scale value. The production number is the #1730 sweep's own
|
|
146
|
+
* fixture-scale value. The production number is the #1730 sweep's own threshold (4,000 places at >= 50 keys).
|
|
136
147
|
*/
|
|
137
148
|
glossKeyThreshold?: number
|
|
138
149
|
}
|
|
@@ -145,8 +156,8 @@ export interface BuildCandidateResult {
|
|
|
145
156
|
abbrevs: number
|
|
146
157
|
postcodes: number
|
|
147
158
|
/**
|
|
148
|
-
* Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the
|
|
149
|
-
* carried no alias names, NOT that the pass was skipped: a
|
|
159
|
+
* Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the extracts
|
|
160
|
+
* carried no alias names, NOT that the pass was skipped: a extract with no `names` table reports that separately
|
|
150
161
|
* through `onProgress`.
|
|
151
162
|
*/
|
|
152
163
|
postcodeAliases: number
|
|
@@ -161,7 +172,7 @@ export interface BuildCandidateResult {
|
|
|
161
172
|
ancestorPlaces: number
|
|
162
173
|
/**
|
|
163
174
|
* Places that received a pre/post interval label — the canonical-parent forest's node count. Places outside it (no
|
|
164
|
-
* recorded ancestry,
|
|
175
|
+
* recorded ancestry, extract rows, cycle-skipped) have NO label: containment against them is unverifiable, never
|
|
165
176
|
* false.
|
|
166
177
|
*/
|
|
167
178
|
intervalPlaces: number
|
|
@@ -174,12 +185,12 @@ export interface BuildCandidateResult {
|
|
|
174
185
|
importanceScored?: number
|
|
175
186
|
/**
|
|
176
187
|
* Places whose `(name_key, country, placetype)` matched a scored group but whose nearest scored centroid was outside
|
|
177
|
-
* {@link
|
|
188
|
+
* {@link IMPORTANCE_JOIN_RADIUS_KM} — a different town wearing the same name, refused rather than scored.
|
|
178
189
|
*
|
|
179
190
|
* Worth watching across rebuilds: a jump here means the score source and the admin source have drifted apart, and the
|
|
180
191
|
* join is being asked to guess.
|
|
181
192
|
*/
|
|
182
|
-
|
|
193
|
+
importanceFiltered?: number
|
|
183
194
|
/**
|
|
184
195
|
* Alias rows stamped `name_role = 'gloss'` — the anomaly detector's certain core (#1730).
|
|
185
196
|
*/
|
|
@@ -202,16 +213,16 @@ export interface BuildCandidateResult {
|
|
|
202
213
|
export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<BuildCandidateResult> {
|
|
203
214
|
const progress = opts.onProgress ?? (() => {})
|
|
204
215
|
|
|
205
|
-
if (
|
|
206
|
-
|
|
216
|
+
if (await pathExists(opts.output)) {
|
|
217
|
+
await removePath(opts.output)
|
|
207
218
|
}
|
|
208
219
|
|
|
209
|
-
|
|
210
|
-
|
|
220
|
+
using src = new DatabaseClient<WOFDatabase>(opts.input, { readOnly: true })
|
|
221
|
+
await using kdb = new DatabaseClient<CandidateDatabase>(opts.output)
|
|
211
222
|
// Build-tuning pragmas (raw — Kysely doesn't model PRAGMA). The code dictionaries + the transient
|
|
212
223
|
// staging table come from the SHARED schema DDL, so they can't drift from {@link CandidateDatabase}.
|
|
213
|
-
|
|
214
|
-
|
|
224
|
+
kdb.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
|
|
225
|
+
|
|
215
226
|
await createCandidateStagingTables(kdb)
|
|
216
227
|
|
|
217
228
|
// --- compact code maps (country/placetype → small int, shrinks the clustered key). The ids are
|
|
@@ -296,13 +307,13 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
296
307
|
// The hot path — millions of clustered rows. Kept a single positional prepared statement (the fastest
|
|
297
308
|
// node:sqlite insert) rather than a per-row query builder. Placeholders come from CANDIDATE_COLUMNS so
|
|
298
309
|
// the column COUNT can't drift; the positional run() args below MUST stay in CANDIDATE_COLUMNS order.
|
|
299
|
-
const insStage =
|
|
310
|
+
const insStage = kdb.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
|
|
300
311
|
|
|
301
312
|
// --- pass 1: primaries (and the per-place attrs the alias/abbrev passes reuse) ---
|
|
302
313
|
progress("primaries", "indexing place names")
|
|
303
314
|
const attrs = new Map<number, PlaceAttrs>()
|
|
304
315
|
let nPrim = 0
|
|
305
|
-
|
|
316
|
+
kdb.exec("BEGIN")
|
|
306
317
|
|
|
307
318
|
for (const r of src
|
|
308
319
|
.prepare(
|
|
@@ -374,14 +385,14 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
374
385
|
}
|
|
375
386
|
}
|
|
376
387
|
|
|
377
|
-
|
|
388
|
+
kdb.exec("COMMIT")
|
|
378
389
|
progress("primaries", `${nPrim.toLocaleString()} primaries; ${attrs.size.toLocaleString()} places`)
|
|
379
390
|
|
|
380
391
|
if (importance) {
|
|
381
392
|
progress(
|
|
382
393
|
"importance",
|
|
383
394
|
`${importance.matched.toLocaleString()} places scored; ` +
|
|
384
|
-
`${importance.
|
|
395
|
+
`${importance.refused.toLocaleString()} refused (nearest same-name place > ${IMPORTANCE_JOIN_RADIUS_KM} km away)`
|
|
385
396
|
)
|
|
386
397
|
}
|
|
387
398
|
|
|
@@ -417,18 +428,19 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
417
428
|
iso2ByID: new Map([...ccodes].map(([code, id]) => [id, code])),
|
|
418
429
|
countryPtID: ptID("country"),
|
|
419
430
|
stageRow,
|
|
420
|
-
tx:
|
|
431
|
+
tx: kdb,
|
|
421
432
|
}).toLocaleString()} country surfaces`
|
|
422
433
|
)
|
|
423
434
|
|
|
424
|
-
// --- pass 1c: cross-source currency backfill (#1737 — resurrectCurrencyHoles owns the
|
|
435
|
+
// --- pass 1c: cross-source currency backfill (#1737 — resurrectCurrencyHoles owns the checks). Runs BEFORE
|
|
425
436
|
// the alias pass so a resurrected place's alt names explode like any primary's. ---
|
|
426
437
|
if (opts.currencyBackfill) {
|
|
427
438
|
const nBackfill = await resurrectCurrencyHoles({
|
|
428
439
|
src,
|
|
429
|
-
tx:
|
|
440
|
+
tx: kdb,
|
|
430
441
|
geonamesDir: opts.currencyBackfill.geonamesDir,
|
|
431
442
|
countries: opts.currencyBackfill.countries,
|
|
443
|
+
...(opts.currencyBackfill.deadPlacetypes ? { deadPlacetypes: opts.currencyBackfill.deadPlacetypes } : {}),
|
|
432
444
|
attrs,
|
|
433
445
|
ccID,
|
|
434
446
|
ptID,
|
|
@@ -447,12 +459,12 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
447
459
|
|
|
448
460
|
// --- pass 2: distinct normalized aliases from place_search.alt_names (explodeAliasBags owns the loop) ---
|
|
449
461
|
progress("aliases", "exploding alias bags")
|
|
450
|
-
const { nAlias, keyCounts } = explodeAliasBags(src,
|
|
462
|
+
const { nAlias, keyCounts } = explodeAliasBags(src, kdb, attrs, stageRow)
|
|
451
463
|
progress("aliases", `${nAlias.toLocaleString()} aliases`)
|
|
452
464
|
|
|
453
465
|
// --- pass 3: region abbreviations (place_abbr) ---
|
|
454
466
|
let nAbbr = 0
|
|
455
|
-
|
|
467
|
+
kdb.exec("BEGIN")
|
|
456
468
|
|
|
457
469
|
for (const r of src.prepare("SELECT id, abbr FROM place_abbr").iterate()) {
|
|
458
470
|
const a = attrs.get(Number(r.id))
|
|
@@ -466,7 +478,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
466
478
|
nAbbr++
|
|
467
479
|
}
|
|
468
480
|
|
|
469
|
-
|
|
481
|
+
kdb.exec("COMMIT")
|
|
470
482
|
progress("abbrevs", `${nAbbr.toLocaleString()} abbrevs`)
|
|
471
483
|
|
|
472
484
|
// --- pass 3b: name roles (#1730 prototype — stampNameRoles owns the detectors) ---
|
|
@@ -474,7 +486,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
474
486
|
// interval tables, and neither reads the other's output. Ordered by label only.
|
|
475
487
|
const roles = stampNameRoles({
|
|
476
488
|
src,
|
|
477
|
-
out,
|
|
489
|
+
out: kdb,
|
|
478
490
|
attrs,
|
|
479
491
|
keyCounts,
|
|
480
492
|
glossThreshold: opts.glossKeyThreshold ?? GLOSS_KEY_THRESHOLD,
|
|
@@ -484,17 +496,17 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
484
496
|
})
|
|
485
497
|
|
|
486
498
|
// --- pass 3c: the ancestors sidecar (candidate-ancestors-schema.ts owns the encoding decision) ---
|
|
487
|
-
const sidecar = await buildAncestorsSidecar({ src, out
|
|
499
|
+
const sidecar = await buildAncestorsSidecar({ src, out: kdb, attrs, ptID, progress })
|
|
488
500
|
|
|
489
|
-
// --- pass 4 + 4b: postcode and locality
|
|
501
|
+
// --- pass 4 + 4b: postcode and locality extracts (foldExtract owns the per-extract loop) ---
|
|
490
502
|
let nPostcode = 0
|
|
491
503
|
let nPostcodeAlias = 0
|
|
492
504
|
|
|
493
505
|
for (const pcDB of opts.postcodes ?? []) {
|
|
494
|
-
const folded =
|
|
495
|
-
out,
|
|
496
|
-
|
|
497
|
-
|
|
506
|
+
const folded = foldExtract({
|
|
507
|
+
out: kdb,
|
|
508
|
+
extractPath: pcDB,
|
|
509
|
+
extractPlacetype: "postalcode",
|
|
498
510
|
ccID,
|
|
499
511
|
ptID,
|
|
500
512
|
stageRow,
|
|
@@ -510,23 +522,34 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
510
522
|
}
|
|
511
523
|
|
|
512
524
|
let nLocality = 0
|
|
525
|
+
let nLocalityScoped = 0
|
|
526
|
+
let nLocalityAncestor = 0
|
|
513
527
|
|
|
514
528
|
for (const locDB of opts.localities ?? []) {
|
|
515
|
-
const folded =
|
|
516
|
-
out,
|
|
517
|
-
|
|
518
|
-
|
|
529
|
+
const folded = foldExtract({
|
|
530
|
+
out: kdb,
|
|
531
|
+
extractPath: locDB,
|
|
532
|
+
extractPlacetype: "locality",
|
|
519
533
|
ccID,
|
|
520
534
|
ptID,
|
|
521
535
|
stageRow,
|
|
536
|
+
attrs,
|
|
522
537
|
progress,
|
|
523
538
|
})
|
|
524
539
|
|
|
525
540
|
nLocality += folded.primaries
|
|
541
|
+
nLocalityScoped += folded.scoped
|
|
542
|
+
nLocalityAncestor += folded.ancestorRows
|
|
526
543
|
}
|
|
527
544
|
|
|
528
545
|
if (nLocality > 0) {
|
|
529
|
-
progress(
|
|
546
|
+
progress(
|
|
547
|
+
"localities",
|
|
548
|
+
`${nLocality.toLocaleString()} extract localities folded` +
|
|
549
|
+
(nLocalityScoped
|
|
550
|
+
? `; ${nLocalityScoped.toLocaleString()} carry a region scope (${nLocalityAncestor.toLocaleString()} closure rows)`
|
|
551
|
+
: "")
|
|
552
|
+
)
|
|
530
553
|
}
|
|
531
554
|
|
|
532
555
|
// --- code dictionaries: typed batch inserts via kdb (a few hundred rows — Kysely is clean here) ---
|
|
@@ -574,26 +597,23 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
574
597
|
await createCandidateTable(kdb)
|
|
575
598
|
// OR IGNORE: an abbrev/alias can normalize to a place's primary key (same place, same rank) → any one
|
|
576
599
|
// row. The bulk sorted INSERT…SELECT (clustered materialization) stays raw — a single hot bulk statement.
|
|
577
|
-
|
|
600
|
+
kdb.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
|
|
578
601
|
await kdb.schema.dropTable("cand_stage").execute()
|
|
579
602
|
// Typo-tolerant fallback index (the unified gazetteer's second mode): the exact name_key probe can't
|
|
580
603
|
// recover misspellings, so FTS5-trigram over `name` lets the reader fuzzy-match on an exact+strip miss.
|
|
581
604
|
progress("fts", "building FTS5-trigram fuzzy index")
|
|
582
|
-
createCandidateFTS(
|
|
605
|
+
createCandidateFTS(kdb)
|
|
583
606
|
// page_size MUST be set right before VACUUM: node:sqlite initializes the file at the 4096 default on
|
|
584
607
|
// `new DatabaseSync`, so the creation-time pragma is a no-op — only a VACUUM rebuilds at the new size.
|
|
585
608
|
// 8192 matches the sql.js-httpvfs 64 KiB request chunk cleanly (8 pages) and shallows the B-tree.
|
|
586
|
-
|
|
587
|
-
|
|
609
|
+
kdb.exec("PRAGMA page_size=8192")
|
|
610
|
+
kdb.exec("VACUUM")
|
|
588
611
|
|
|
589
612
|
const { n: rows } = await kdb
|
|
590
613
|
.selectFrom("candidate")
|
|
591
614
|
.select((eb) => eb.fn.countAll<number>().as("n"))
|
|
592
615
|
.executeTakeFirstOrThrow()
|
|
593
616
|
|
|
594
|
-
src.close()
|
|
595
|
-
await kdb.destroy()
|
|
596
|
-
|
|
597
617
|
// closes the underlying `out` connection
|
|
598
618
|
return {
|
|
599
619
|
rows,
|
|
@@ -603,10 +623,10 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
603
623
|
abbrevs: nAbbr,
|
|
604
624
|
postcodes: nPostcode,
|
|
605
625
|
postcodeAliases: nPostcodeAlias,
|
|
606
|
-
ancestorRows: sidecar.ancestorRows,
|
|
607
|
-
ancestorPlaces: sidecar.ancestorPlaces,
|
|
626
|
+
ancestorRows: sidecar.ancestorRows + nLocalityAncestor,
|
|
627
|
+
ancestorPlaces: sidecar.ancestorPlaces + nLocalityScoped,
|
|
608
628
|
intervalPlaces: sidecar.intervalPlaces,
|
|
609
629
|
...roles,
|
|
610
|
-
...(importance ? { importanceScored: importance.matched,
|
|
630
|
+
...(importance ? { importanceScored: importance.matched, importanceFiltered: importance.refused } : {}),
|
|
611
631
|
}
|
|
612
632
|
}
|