@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
|
@@ -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%.
|
|
@@ -32,27 +32,43 @@
|
|
|
32
32
|
* `candidate-importance.ts`, which owns that join and explains why the id would be wrong). It is
|
|
33
33
|
* optional: without {@link BuildCandidateOptions.importance} the column is NULL on every row, which
|
|
34
34
|
* the consumer reads as unmeasured and ignores.
|
|
35
|
+
*
|
|
36
|
+
* The build also materializes the ANCESTORS SIDECAR (`candidate_ancestor` closure rows +
|
|
37
|
+
* `candidate_interval` pre/post labels) from the source `ancestors` table — the containment
|
|
38
|
+
* lineage behind {@link WOFCandidateTableLookup.ancestors} and the admin-coherence check.
|
|
39
|
+
* `candidate-ancestors-schema.ts` owns the encoding decision and the DAG/absence semantics.
|
|
35
40
|
*/
|
|
36
41
|
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
|
|
40
|
-
import { DatabaseClient } from "@mailwoman/
|
|
42
|
+
import { COUNTRY_POPULATION } from "@mailwoman/codex/country"
|
|
43
|
+
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
44
|
+
import { removePath } from "@mailwoman/core/fs/writers"
|
|
45
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
41
46
|
|
|
42
|
-
import { createCandidateFTS } from "
|
|
43
|
-
import {
|
|
47
|
+
import { createCandidateFTS } from "#candidate-fts"
|
|
48
|
+
import { IMPORTANCE_JOIN_RADIUS_KM, loadImportanceIndex } from "#candidate-importance"
|
|
44
49
|
import {
|
|
45
50
|
CANDIDATE_COLUMNS,
|
|
46
51
|
createCandidateStagingTables,
|
|
47
52
|
createCandidateTable,
|
|
48
53
|
type CandidateDatabase,
|
|
49
|
-
} from "
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
+
|
|
67
|
+
// The build's contract is this module path; the passes behind it live in `./candidate/`. Re-exported
|
|
68
|
+
// here so a consumer never has to know which pass owns which name.
|
|
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"
|
|
56
72
|
|
|
57
73
|
export interface BuildCandidateOptions {
|
|
58
74
|
/**
|
|
@@ -64,14 +80,28 @@ export interface BuildCandidateOptions {
|
|
|
64
80
|
*/
|
|
65
81
|
output: string
|
|
66
82
|
/**
|
|
67
|
-
*
|
|
83
|
+
* The capital-status reference entries (#1880) to carry in-artifact — the parsed `data/gazetteer/capitals-v1.json`
|
|
84
|
+
* entries, passed by the CALLER because this module publishes to npm and must not read repo-root paths. Absent → the
|
|
85
|
+
* `capital` table is not created, and the session loader falls back to the repo file where one exists.
|
|
86
|
+
*/
|
|
87
|
+
capitals?: readonly CapitalPoint[]
|
|
88
|
+
/**
|
|
89
|
+
* Optional postcode extracts (`spr` rows with `placetype='postalcode'` + real coords, e.g. postalcode-us.db) — folded
|
|
68
90
|
* in as `postalcode` candidate rows so `findPlace(postalcode)` resolves a ZIP directly (the demo's primary postcode
|
|
69
91
|
* path; the postcode-*.bin anchor stays the fallback). Matches the slim wof-hot.db, which took one such postcode DB.
|
|
70
92
|
*
|
|
71
|
-
* Each
|
|
93
|
+
* Each extract's `names` table is folded in too (#1495) — that's where the GeoNames delivery-city names live
|
|
72
94
|
* ("Brooklyn" for 11201), and they were previously reachable only through FTS.
|
|
73
95
|
*/
|
|
74
96
|
postcodes?: string[]
|
|
97
|
+
/**
|
|
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 no region scope and UNMEASURED population (`neg_rank 0`: a extract row ranks behind any
|
|
101
|
+
* populated namesake and wins only where its key is the answer). Each extract's `names` table folds as aliases,
|
|
102
|
+
* `is_primary = 0`, same as the delivery-city pass.
|
|
103
|
+
*/
|
|
104
|
+
localities?: string[]
|
|
75
105
|
/**
|
|
76
106
|
* Optional WOF admin database carrying a `place_importance` table — the source of the `importance` column (#28), the
|
|
77
107
|
* toponym-fame prior that decides the bare-city-name class. Joined by `(name_key, country, placetype)` + nearest
|
|
@@ -84,10 +114,36 @@ export interface BuildCandidateOptions {
|
|
|
84
114
|
* population-derived stand-in written into a column that means fame.
|
|
85
115
|
*/
|
|
86
116
|
importance?: string
|
|
117
|
+
/**
|
|
118
|
+
* Cross-source currency backfill (#1737). WOF carries deprecated-with-no-successor records for real, populated
|
|
119
|
+
* settlements (Rochester Kent, Aldershot, Telford — 120 GB localities alone), and the currency filter correctly drops
|
|
120
|
+
* them, leaving holes no ranking can fill. When this option is set, pass 1c resurrects a dead locality ONLY under
|
|
121
|
+
* three conditions, positive evidence throughout: no live same-name row of any placetype near the dead record (a
|
|
122
|
+
* distant same-name row is a NAMESAKE and does not block — Rochester, Northumberland pop 318 must not veto Rochester,
|
|
123
|
+
* Kent); an independent GeoNames P-class attestation of the same folded name within
|
|
124
|
+
* {@link CURRENCY_BACKFILL_RADIUS_KM}; and the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged
|
|
125
|
+
* row keeps the real WOF id, name, centroid and bbox — GeoNames only ATTESTS the place and supplies the population
|
|
126
|
+
* that lets it stand in prominence races. `countries` are judged only where `<cc>.txt` exists under `geonamesDir`;
|
|
127
|
+
* absent dumps are skipped loudly.
|
|
128
|
+
*/
|
|
129
|
+
currencyBackfill?: {
|
|
130
|
+
geonamesDir: string
|
|
131
|
+
countries: readonly string[]
|
|
132
|
+
/**
|
|
133
|
+
* The dead placetypes the resurrection judges; `resurrectCurrencyHoles`'s default (`locality`) when absent. The
|
|
134
|
+
* `localadmin` widening #1746 named is admitted here once its census is read.
|
|
135
|
+
*/
|
|
136
|
+
deadPlacetypes?: readonly string[]
|
|
137
|
+
}
|
|
87
138
|
/**
|
|
88
139
|
* Optional progress callback for CLI / test introspection.
|
|
89
140
|
*/
|
|
90
141
|
onProgress?: (phase: string, message: string) => void
|
|
142
|
+
/**
|
|
143
|
+
* Key-count threshold for the gloss anomaly detector — {@link GLOSS_KEY_THRESHOLD} unless a test passes a
|
|
144
|
+
* fixture-scale value. The production number is the #1730 sweep's own threshold (4,000 places at >= 50 keys).
|
|
145
|
+
*/
|
|
146
|
+
glossKeyThreshold?: number
|
|
91
147
|
}
|
|
92
148
|
|
|
93
149
|
export interface BuildCandidateResult {
|
|
@@ -98,11 +154,26 @@ export interface BuildCandidateResult {
|
|
|
98
154
|
abbrevs: number
|
|
99
155
|
postcodes: number
|
|
100
156
|
/**
|
|
101
|
-
* Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the
|
|
102
|
-
* carried no alias names, NOT that the pass was skipped: a
|
|
157
|
+
* Delivery-city (and other `names`-table) aliases folded onto postcode rows — #1495. Zero here means the extracts
|
|
158
|
+
* carried no alias names, NOT that the pass was skipped: a extract with no `names` table reports that separately
|
|
103
159
|
* through `onProgress`.
|
|
104
160
|
*/
|
|
105
161
|
postcodeAliases: number
|
|
162
|
+
/**
|
|
163
|
+
* Closure rows in the `candidate_ancestor` sidecar (see candidate-ancestors-schema.ts). Zero means the source
|
|
164
|
+
* `ancestors` table contributed nothing within the resolvable placetypes — a finding, reported rather than implied.
|
|
165
|
+
*/
|
|
166
|
+
ancestorRows: number
|
|
167
|
+
/**
|
|
168
|
+
* Places carrying at least one closure row.
|
|
169
|
+
*/
|
|
170
|
+
ancestorPlaces: number
|
|
171
|
+
/**
|
|
172
|
+
* Places that received a pre/post interval label — the canonical-parent forest's node count. Places outside it (no
|
|
173
|
+
* recorded ancestry, extract rows, cycle-skipped) have NO label: containment against them is unverifiable, never
|
|
174
|
+
* false.
|
|
175
|
+
*/
|
|
176
|
+
intervalPlaces: number
|
|
106
177
|
/**
|
|
107
178
|
* Places that took an `importance` score from the join (#28).
|
|
108
179
|
*
|
|
@@ -112,49 +183,44 @@ export interface BuildCandidateResult {
|
|
|
112
183
|
importanceScored?: number
|
|
113
184
|
/**
|
|
114
185
|
* Places whose `(name_key, country, placetype)` matched a scored group but whose nearest scored centroid was outside
|
|
115
|
-
* {@link
|
|
186
|
+
* {@link IMPORTANCE_JOIN_RADIUS_KM} — a different town wearing the same name, refused rather than scored.
|
|
116
187
|
*
|
|
117
188
|
* Worth watching across rebuilds: a jump here means the score source and the admin source have drifted apart, and the
|
|
118
189
|
* join is being asked to guess.
|
|
119
190
|
*/
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
lon: number
|
|
130
|
-
mnLat: number
|
|
131
|
-
mnLon: number
|
|
132
|
-
mxLat: number
|
|
133
|
-
mxLon: number
|
|
134
|
-
pop: number
|
|
135
|
-
neg: number
|
|
136
|
-
pkey: string
|
|
191
|
+
importanceFiltered?: number
|
|
192
|
+
/**
|
|
193
|
+
* Alias rows stamped `name_role = 'gloss'` — the anomaly detector's certain core (#1730).
|
|
194
|
+
*/
|
|
195
|
+
roleGloss: number
|
|
196
|
+
/**
|
|
197
|
+
* Alias rows stamped `name_role = 'abbr'` — the variant-in-official-language provenance signal (#1730/#936).
|
|
198
|
+
*/
|
|
199
|
+
roleAbbr: number
|
|
137
200
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* Москва's score through the alias row that carries the key.
|
|
201
|
+
* Admin places whose staged key count reached {@link GLOSS_KEY_THRESHOLD} — the sweep's tail, reported so the stamped
|
|
202
|
+
* fraction has its denominator.
|
|
141
203
|
*/
|
|
142
|
-
|
|
204
|
+
keyTailPlaces: number
|
|
205
|
+
/**
|
|
206
|
+
* Of {@link BuildCandidateResult.keyTailPlaces}, how many carry at least one stamped role row.
|
|
207
|
+
*/
|
|
208
|
+
keyTailWithRole: number
|
|
143
209
|
}
|
|
144
210
|
|
|
145
211
|
export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<BuildCandidateResult> {
|
|
146
212
|
const progress = opts.onProgress ?? (() => {})
|
|
147
213
|
|
|
148
|
-
if (
|
|
149
|
-
|
|
214
|
+
if (await pathExists(opts.output)) {
|
|
215
|
+
await removePath(opts.output)
|
|
150
216
|
}
|
|
151
217
|
|
|
152
|
-
|
|
153
|
-
|
|
218
|
+
using src = new DatabaseClient<WOFDatabase>(opts.input, { readOnly: true })
|
|
219
|
+
await using kdb = new DatabaseClient<CandidateDatabase>(opts.output)
|
|
154
220
|
// Build-tuning pragmas (raw — Kysely doesn't model PRAGMA). The code dictionaries + the transient
|
|
155
221
|
// staging table come from the SHARED schema DDL, so they can't drift from {@link CandidateDatabase}.
|
|
156
|
-
|
|
157
|
-
|
|
222
|
+
kdb.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
|
|
223
|
+
|
|
158
224
|
await createCandidateStagingTables(kdb)
|
|
159
225
|
|
|
160
226
|
// --- compact code maps (country/placetype → small int, shrinks the clustered key). The ids are
|
|
@@ -239,13 +305,13 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
239
305
|
// The hot path — millions of clustered rows. Kept a single positional prepared statement (the fastest
|
|
240
306
|
// node:sqlite insert) rather than a per-row query builder. Placeholders come from CANDIDATE_COLUMNS so
|
|
241
307
|
// the column COUNT can't drift; the positional run() args below MUST stay in CANDIDATE_COLUMNS order.
|
|
242
|
-
const insStage =
|
|
308
|
+
const insStage = kdb.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
|
|
243
309
|
|
|
244
310
|
// --- pass 1: primaries (and the per-place attrs the alias/abbrev passes reuse) ---
|
|
245
311
|
progress("primaries", "indexing place names")
|
|
246
312
|
const attrs = new Map<number, PlaceAttrs>()
|
|
247
313
|
let nPrim = 0
|
|
248
|
-
|
|
314
|
+
kdb.exec("BEGIN")
|
|
249
315
|
|
|
250
316
|
for (const r of src
|
|
251
317
|
.prepare(
|
|
@@ -261,7 +327,12 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
261
327
|
const cid = ccID(r.country as string | null)
|
|
262
328
|
const ptid = ptID(r.placetype as string | null)
|
|
263
329
|
const rid = regionOf.get(sid) ?? 0
|
|
264
|
-
|
|
330
|
+
// A zero population on a COUNTRY row is a WOF absence artifact, never a real zero — 147 of 237
|
|
331
|
+
// primary country records carried none (measured 2026-08-18, #1650), which ranked those nations
|
|
332
|
+
// below any namesake hamlet in every prominence race ("Georgia" → Georgia VT). The codex table is
|
|
333
|
+
// the secondary source; a country absent from it too stays at zero honestly.
|
|
334
|
+
const wofPop = Number(r.pop) || 0
|
|
335
|
+
const pop = wofPop === 0 && r.placetype === "country" ? (COUNTRY_POPULATION[String(r.country ?? "")] ?? 0) : wofPop
|
|
265
336
|
const neg = -Math.log10(pop + 1)
|
|
266
337
|
const name = String(r.name ?? "")
|
|
267
338
|
const pkey = normalizeLocalityForKey(name)
|
|
@@ -304,21 +375,22 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
304
375
|
a.mxLon,
|
|
305
376
|
pop,
|
|
306
377
|
1,
|
|
307
|
-
a.imp
|
|
378
|
+
a.imp,
|
|
379
|
+
null
|
|
308
380
|
)
|
|
309
381
|
|
|
310
382
|
nPrim++
|
|
311
383
|
}
|
|
312
384
|
}
|
|
313
385
|
|
|
314
|
-
|
|
386
|
+
kdb.exec("COMMIT")
|
|
315
387
|
progress("primaries", `${nPrim.toLocaleString()} primaries; ${attrs.size.toLocaleString()} places`)
|
|
316
388
|
|
|
317
389
|
if (importance) {
|
|
318
390
|
progress(
|
|
319
391
|
"importance",
|
|
320
392
|
`${importance.matched.toLocaleString()} places scored; ` +
|
|
321
|
-
`${importance.
|
|
393
|
+
`${importance.refused.toLocaleString()} refused (nearest same-name place > ${IMPORTANCE_JOIN_RADIUS_KM} km away)`
|
|
322
394
|
)
|
|
323
395
|
}
|
|
324
396
|
|
|
@@ -339,39 +411,58 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
339
411
|
a.mxLon,
|
|
340
412
|
a.pop,
|
|
341
413
|
isPrimary,
|
|
342
|
-
a.imp
|
|
414
|
+
a.imp,
|
|
415
|
+
null
|
|
343
416
|
)
|
|
344
417
|
}
|
|
345
418
|
|
|
346
|
-
// --- pass
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const k = normalizeLocalityForKey(piece)
|
|
360
|
-
|
|
361
|
-
if (!k || seen.has(k)) continue
|
|
362
|
-
seen.add(k)
|
|
363
|
-
stageRow(k, a, Number(r.wof_id), 0)
|
|
419
|
+
// --- pass 1b: country surfaces across scripts (#1678 thread 1) — see stageCountryDisplayNames ---
|
|
420
|
+
// Never a silent zero: a runtime whose ICU lacks these locales degrades to fewer surfaces, and the count is how a
|
|
421
|
+
// reader tells that apart from the pass not having run.
|
|
422
|
+
progress(
|
|
423
|
+
"country-display-names",
|
|
424
|
+
`${stageCountryDisplayNames({
|
|
425
|
+
attrs,
|
|
426
|
+
iso2ByID: new Map([...ccodes].map(([code, id]) => [id, code])),
|
|
427
|
+
countryPtID: ptID("country"),
|
|
428
|
+
stageRow,
|
|
429
|
+
tx: kdb,
|
|
430
|
+
}).toLocaleString()} country surfaces`
|
|
431
|
+
)
|
|
364
432
|
|
|
365
|
-
|
|
366
|
-
|
|
433
|
+
// --- pass 1c: cross-source currency backfill (#1737 — resurrectCurrencyHoles owns the checks). Runs BEFORE
|
|
434
|
+
// the alias pass so a resurrected place's alt names explode like any primary's. ---
|
|
435
|
+
if (opts.currencyBackfill) {
|
|
436
|
+
const nBackfill = await resurrectCurrencyHoles({
|
|
437
|
+
src,
|
|
438
|
+
tx: kdb,
|
|
439
|
+
geonamesDir: opts.currencyBackfill.geonamesDir,
|
|
440
|
+
countries: opts.currencyBackfill.countries,
|
|
441
|
+
...(opts.currencyBackfill.deadPlacetypes ? { deadPlacetypes: opts.currencyBackfill.deadPlacetypes } : {}),
|
|
442
|
+
attrs,
|
|
443
|
+
ccID,
|
|
444
|
+
ptID,
|
|
445
|
+
regionOf,
|
|
446
|
+
importance,
|
|
447
|
+
stageRow,
|
|
448
|
+
progress,
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
progress("currency-backfill", `${nBackfill.toLocaleString()} resurrections staged`)
|
|
452
|
+
} else {
|
|
453
|
+
// Never a silent absence: a build without the option leaves the deprecated-no-successor holes dead,
|
|
454
|
+
// and the log must say so rather than leave it inferable only from a missing row.
|
|
455
|
+
progress("currency-backfill", "not configured — deprecated-no-successor holes stay dead (#1737)")
|
|
367
456
|
}
|
|
368
457
|
|
|
369
|
-
|
|
458
|
+
// --- pass 2: distinct normalized aliases from place_search.alt_names (explodeAliasBags owns the loop) ---
|
|
459
|
+
progress("aliases", "exploding alias bags")
|
|
460
|
+
const { nAlias, keyCounts } = explodeAliasBags(src, kdb, attrs, stageRow)
|
|
370
461
|
progress("aliases", `${nAlias.toLocaleString()} aliases`)
|
|
371
462
|
|
|
372
463
|
// --- pass 3: region abbreviations (place_abbr) ---
|
|
373
464
|
let nAbbr = 0
|
|
374
|
-
|
|
465
|
+
kdb.exec("BEGIN")
|
|
375
466
|
|
|
376
467
|
for (const r of src.prepare("SELECT id, abbr FROM place_abbr").iterate()) {
|
|
377
468
|
const a = attrs.get(Number(r.id))
|
|
@@ -385,128 +476,40 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
385
476
|
nAbbr++
|
|
386
477
|
}
|
|
387
478
|
|
|
388
|
-
|
|
479
|
+
kdb.exec("COMMIT")
|
|
389
480
|
progress("abbrevs", `${nAbbr.toLocaleString()} abbrevs`)
|
|
390
481
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
out.exec("BEGIN")
|
|
411
|
-
|
|
412
|
-
for (const r of pc
|
|
413
|
-
.prepare(
|
|
414
|
-
`SELECT id, name, country, latitude, longitude,
|
|
415
|
-
min_latitude AS mnlat, min_longitude AS mnlon, max_latitude AS mxlat, max_longitude AS mxlon
|
|
416
|
-
FROM spr WHERE placetype='postalcode' AND latitude != 0 AND longitude != 0`
|
|
417
|
-
)
|
|
418
|
-
.iterate()) {
|
|
419
|
-
const name = String(r.name ?? "")
|
|
420
|
-
const key = normalizeLocalityForKey(name)
|
|
421
|
-
|
|
422
|
-
if (!key) continue
|
|
423
|
-
|
|
424
|
-
const lat = r.latitude as number
|
|
425
|
-
const lon = r.longitude as number
|
|
426
|
-
|
|
427
|
-
// region_id 0 (a postcode is unique by name+country — no same-name disambiguation); neg_rank 0
|
|
428
|
-
// (no population). bbox = the postcode's own min/max (falls back to the centroid point).
|
|
429
|
-
const a: PlaceAttrs = {
|
|
430
|
-
cid: ccID(r.country as string | null),
|
|
431
|
-
rid: 0,
|
|
432
|
-
ptid: pcPtid,
|
|
433
|
-
name,
|
|
434
|
-
lat,
|
|
435
|
-
lon,
|
|
436
|
-
mnLat: (r.mnlat as number) || lat,
|
|
437
|
-
mnLon: (r.mnlon as number) || lon,
|
|
438
|
-
mxLat: (r.mxlat as number) || lat,
|
|
439
|
-
mxLon: (r.mxlon as number) || lon,
|
|
440
|
-
pop: 0,
|
|
441
|
-
neg: 0,
|
|
442
|
-
pkey: key,
|
|
443
|
-
// A postcode has no toponym fame — nobody writes an encyclopedia article about SW1A 2AA — and
|
|
444
|
-
// the score source carries no `postalcode` rows to join against anyway. NULL is the truthful
|
|
445
|
-
// value: unmeasured, so the ranking key leaves postcode rows exactly where they were.
|
|
446
|
-
imp: null,
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
pcAttrs.set(Number(r.id), a)
|
|
450
|
-
stageRow(key, a, Number(r.id), 1)
|
|
451
|
-
|
|
452
|
-
primaries++
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
out.exec("COMMIT")
|
|
456
|
-
|
|
457
|
-
// --- pass 4b: postcode ALIAS names (#1495) ---
|
|
458
|
-
//
|
|
459
|
-
// The delivery-city names GeoNames supplies for a ZIP ("Brooklyn" for 11201) are written into
|
|
460
|
-
// the shard's `names` table by `postcode/centroid-fills.ts`'s `geonamesNameFill`. Everything
|
|
461
|
-
// downstream of `names` picked them up EXCEPT this build: `fts.ts` unions `spr.name` with every
|
|
462
|
-
// `names` row into `place_search.alt_names`, so the FTS backend resolved "Brooklyn" → 11201
|
|
463
|
-
// while the candidate backend — whose every row IS an exact-tier row — had no key for it at
|
|
464
|
-
// all. Pass 2 does the equivalent fold for admin places, but reads the ADMIN `place_search`,
|
|
465
|
-
// and `attrs` holds admin ids only, so a postcode shard could never reach it.
|
|
466
|
-
//
|
|
467
|
-
// Same discipline as pass 2: `is_primary = 0` (so `rankByPrimaryPreference` treats it as an
|
|
468
|
-
// alias, not a canonical postcode name), the row stays denormalized onto the POSTCODE's own
|
|
469
|
-
// spr_id/coords/bbox, and the display `name` stays the postcode — resolving "brooklyn" answers
|
|
470
|
-
// with place 11201, it does not rename the place to its delivery city.
|
|
471
|
-
const hasNames = pc.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='names'").get() !== undefined
|
|
472
|
-
|
|
473
|
-
if (hasNames) {
|
|
474
|
-
out.exec("BEGIN")
|
|
475
|
-
|
|
476
|
-
for (const r of pc.prepare("SELECT id, name FROM names").iterate()) {
|
|
477
|
-
const a = pcAttrs.get(Number(r.id))
|
|
478
|
-
|
|
479
|
-
if (!a) continue
|
|
480
|
-
|
|
481
|
-
const k = normalizeLocalityForKey(String(r.name ?? ""))
|
|
482
|
-
|
|
483
|
-
// The postcode's own key is already staged as the primary; `INSERT OR IGNORE` at
|
|
484
|
-
// materialization dedupes repeats, so this only skips the obvious self-alias.
|
|
485
|
-
if (!k || k === a.pkey) continue
|
|
486
|
-
|
|
487
|
-
stageRow(k, a, Number(r.id), 0)
|
|
488
|
-
|
|
489
|
-
aliases++
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
out.exec("COMMIT")
|
|
493
|
-
} else {
|
|
494
|
-
// Never a silent zero: real shards come from `createUnifiedSchema`, which always creates
|
|
495
|
-
// `names`. A shard without it has no alias surface to lose, but say so rather than reporting
|
|
496
|
-
// "0 aliases" from a table that was never read.
|
|
497
|
-
progress("postcode-aliases", `${pcDB} has no \`names\` table — no delivery-city aliases to fold`)
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
pc.close()
|
|
501
|
-
|
|
502
|
-
return { primaries, aliases }
|
|
503
|
-
}
|
|
504
|
-
|
|
482
|
+
// --- pass 3b: name roles (#1730 prototype — stampNameRoles owns the detectors) ---
|
|
483
|
+
// Independent of the sidecar below: this writes `cand_stage.name_role`, that writes the ancestor and
|
|
484
|
+
// interval tables, and neither reads the other's output. Ordered by label only.
|
|
485
|
+
const roles = stampNameRoles({
|
|
486
|
+
src,
|
|
487
|
+
out: kdb,
|
|
488
|
+
attrs,
|
|
489
|
+
keyCounts,
|
|
490
|
+
glossThreshold: opts.glossKeyThreshold ?? GLOSS_KEY_THRESHOLD,
|
|
491
|
+
ptcodes,
|
|
492
|
+
ccodes,
|
|
493
|
+
progress,
|
|
494
|
+
})
|
|
495
|
+
|
|
496
|
+
// --- pass 3c: the ancestors sidecar (candidate-ancestors-schema.ts owns the encoding decision) ---
|
|
497
|
+
const sidecar = await buildAncestorsSidecar({ src, out: kdb, attrs, ptID, progress })
|
|
498
|
+
|
|
499
|
+
// --- pass 4 + 4b: postcode and locality extracts (foldExtract owns the per-extract loop) ---
|
|
505
500
|
let nPostcode = 0
|
|
506
501
|
let nPostcodeAlias = 0
|
|
507
502
|
|
|
508
503
|
for (const pcDB of opts.postcodes ?? []) {
|
|
509
|
-
const folded =
|
|
504
|
+
const folded = foldExtract({
|
|
505
|
+
out: kdb,
|
|
506
|
+
extractPath: pcDB,
|
|
507
|
+
extractPlacetype: "postalcode",
|
|
508
|
+
ccID,
|
|
509
|
+
ptID,
|
|
510
|
+
stageRow,
|
|
511
|
+
progress,
|
|
512
|
+
})
|
|
510
513
|
|
|
511
514
|
nPostcode += folded.primaries
|
|
512
515
|
nPostcodeAlias += folded.aliases
|
|
@@ -516,6 +519,26 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
516
519
|
progress("postcodes", `${nPostcode.toLocaleString()} postcodes; ${nPostcodeAlias.toLocaleString()} aliases`)
|
|
517
520
|
}
|
|
518
521
|
|
|
522
|
+
let nLocality = 0
|
|
523
|
+
|
|
524
|
+
for (const locDB of opts.localities ?? []) {
|
|
525
|
+
const folded = foldExtract({
|
|
526
|
+
out: kdb,
|
|
527
|
+
extractPath: locDB,
|
|
528
|
+
extractPlacetype: "locality",
|
|
529
|
+
ccID,
|
|
530
|
+
ptID,
|
|
531
|
+
stageRow,
|
|
532
|
+
progress,
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
nLocality += folded.primaries
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (nLocality > 0) {
|
|
539
|
+
progress("localities", `${nLocality.toLocaleString()} extract localities folded`)
|
|
540
|
+
}
|
|
541
|
+
|
|
519
542
|
// --- code dictionaries: typed batch inserts via kdb (a few hundred rows — Kysely is clean here) ---
|
|
520
543
|
if (ccodes.size) {
|
|
521
544
|
await kdb
|
|
@@ -531,6 +554,26 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
531
554
|
.execute()
|
|
532
555
|
}
|
|
533
556
|
|
|
557
|
+
// --- capital-status reference (#1880's distribution home) — cold, small (~3.7k rows), typed ---
|
|
558
|
+
if (opts.capitals?.length) {
|
|
559
|
+
await createCapitalTable<CandidateDatabase>(kdb)
|
|
560
|
+
|
|
561
|
+
await kdb
|
|
562
|
+
.insertInto("capital")
|
|
563
|
+
.values(
|
|
564
|
+
opts.capitals.map((entry) => ({
|
|
565
|
+
country: entry.country,
|
|
566
|
+
latitude: entry.latitude,
|
|
567
|
+
longitude: entry.longitude,
|
|
568
|
+
level: entry.level,
|
|
569
|
+
keys: JSON.stringify(entry.k),
|
|
570
|
+
}))
|
|
571
|
+
)
|
|
572
|
+
.execute()
|
|
573
|
+
|
|
574
|
+
progress("capitals", `${opts.capitals.length.toLocaleString()} capital-reference rows carried in-artifact`)
|
|
575
|
+
}
|
|
576
|
+
|
|
534
577
|
// --- materialize the clustered WITHOUT ROWID table (sorted insert → contiguous leaves) ---
|
|
535
578
|
progress("cluster", "building clustered candidate table + VACUUM")
|
|
536
579
|
// Column list + clustered-key order are sourced from CANDIDATE_COLUMNS (the first 6 ARE the PRIMARY
|
|
@@ -541,26 +584,23 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
541
584
|
await createCandidateTable(kdb)
|
|
542
585
|
// OR IGNORE: an abbrev/alias can normalize to a place's primary key (same place, same rank) → any one
|
|
543
586
|
// row. The bulk sorted INSERT…SELECT (clustered materialization) stays raw — a single hot bulk statement.
|
|
544
|
-
|
|
587
|
+
kdb.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
|
|
545
588
|
await kdb.schema.dropTable("cand_stage").execute()
|
|
546
589
|
// Typo-tolerant fallback index (the unified gazetteer's second mode): the exact name_key probe can't
|
|
547
590
|
// recover misspellings, so FTS5-trigram over `name` lets the reader fuzzy-match on an exact+strip miss.
|
|
548
591
|
progress("fts", "building FTS5-trigram fuzzy index")
|
|
549
|
-
createCandidateFTS(
|
|
592
|
+
createCandidateFTS(kdb)
|
|
550
593
|
// page_size MUST be set right before VACUUM: node:sqlite initializes the file at the 4096 default on
|
|
551
594
|
// `new DatabaseSync`, so the creation-time pragma is a no-op — only a VACUUM rebuilds at the new size.
|
|
552
595
|
// 8192 matches the sql.js-httpvfs 64 KiB request chunk cleanly (8 pages) and shallows the B-tree.
|
|
553
|
-
|
|
554
|
-
|
|
596
|
+
kdb.exec("PRAGMA page_size=8192")
|
|
597
|
+
kdb.exec("VACUUM")
|
|
555
598
|
|
|
556
599
|
const { n: rows } = await kdb
|
|
557
600
|
.selectFrom("candidate")
|
|
558
601
|
.select((eb) => eb.fn.countAll<number>().as("n"))
|
|
559
602
|
.executeTakeFirstOrThrow()
|
|
560
603
|
|
|
561
|
-
src.close()
|
|
562
|
-
await kdb.destroy()
|
|
563
|
-
|
|
564
604
|
// closes the underlying `out` connection
|
|
565
605
|
return {
|
|
566
606
|
rows,
|
|
@@ -570,6 +610,10 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
570
610
|
abbrevs: nAbbr,
|
|
571
611
|
postcodes: nPostcode,
|
|
572
612
|
postcodeAliases: nPostcodeAlias,
|
|
573
|
-
|
|
613
|
+
ancestorRows: sidecar.ancestorRows,
|
|
614
|
+
ancestorPlaces: sidecar.ancestorPlaces,
|
|
615
|
+
intervalPlaces: sidecar.intervalPlaces,
|
|
616
|
+
...roles,
|
|
617
|
+
...(importance ? { importanceScored: importance.matched, importanceFiltered: importance.refused } : {}),
|
|
574
618
|
}
|
|
575
619
|
}
|