@mailwoman/resolver-wof-sqlite 9.2.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -19
- package/lib/address/index.ts +9 -0
- package/{address-point-interpolation.ts → lib/address/point-interpolation.ts} +24 -22
- package/{address-point-schema.ts → lib/address/point-schema.ts} +18 -4
- package/{address-point.ts → lib/address/point.ts} +89 -27
- package/{ancestry-backfill.ts → lib/ancestry/backfill.ts} +14 -19
- package/{ancestry.ts → lib/ancestry/index.ts} +5 -3
- package/{build-candidate.ts → lib/build-candidate.ts} +84 -77
- package/{build-slim.ts → lib/build-slim.ts} +150 -165
- package/{candidate → lib/candidate}/alias-bags.ts +8 -6
- package/{candidate → lib/candidate}/ancestors-sidecar.ts +13 -15
- package/{candidate → lib/candidate}/country-display-names.ts +2 -2
- package/{candidate/shard-fold.ts → lib/candidate/extract-fold.ts} +26 -25
- package/{candidate → lib/candidate}/name-roles.ts +17 -16
- package/{candidate → lib/candidate}/own-name.ts +1 -1
- package/{candidate → lib/candidate}/place-attrs.ts +3 -3
- package/{candidate-ancestors-schema.ts → lib/candidate-ancestors-schema.ts} +4 -4
- package/{candidate-fts.ts → lib/candidate-fts.ts} +3 -3
- package/{candidate-importance.ts → lib/candidate-importance.ts} +53 -57
- package/{candidate-lookup.ts → lib/candidate-lookup.ts} +76 -73
- package/{candidate-schema.ts → lib/candidate-schema.ts} +5 -5
- package/{candidate-scoring.ts → lib/candidate-scoring.ts} +15 -22
- package/{capital-schema.ts → lib/capital-schema.ts} +5 -6
- package/{capitals.ts → lib/capitals.ts} +2 -2
- package/{coincident-roles.ts → lib/coincident-roles.ts} +8 -11
- package/{convention.ts → lib/convention/index.ts} +3 -3
- package/{convention-schema.ts → lib/convention/schema.ts} +2 -2
- package/{coverage-manifest-schema.ts → lib/coverage-manifest-schema.ts} +9 -10
- package/{currency-backfill.ts → lib/currency-backfill.ts} +126 -41
- package/lib/env.ts +50 -0
- package/{exact-match.ts → lib/exact-match.ts} +23 -14
- package/{sharding.ts → lib/extracts.ts} +61 -58
- package/{fst-autocomplete.ts → lib/fst/autocomplete.ts} +4 -4
- package/{fst-builder.ts → lib/fst/builder.ts} +17 -16
- package/{fst-deserialize-web.ts → lib/fst/deserialize-web.ts} +27 -87
- package/lib/fst/format.ts +106 -0
- package/{fst-freshness.ts → lib/fst/freshness.ts} +41 -74
- package/lib/fst/index.ts +14 -0
- package/{fst-matcher.ts → lib/fst/matcher.ts} +1 -1
- package/{fst-serialize.ts → lib/fst/serialize.ts} +37 -115
- package/{fst-types.ts → lib/fst/types.ts} +4 -2
- package/{fts.ts → lib/fts/index.ts} +24 -19
- package/{fts-query.ts → lib/fts/query.ts} +1 -1
- package/{geonames-aliases.ts → lib/geonames/aliases.ts} +13 -13
- package/lib/geonames/index.ts +8 -0
- package/{geonames-postal.ts → lib/geonames/postal.ts} +14 -13
- package/{index.ts → lib/index.ts} +37 -37
- package/{interpolation.ts → lib/interpolation.ts} +27 -25
- package/{lookup.ts → lib/lookup.ts} +129 -141
- package/lib/nsul/index.ts +8 -0
- package/lib/nsul/lookup.ts +144 -0
- package/lib/nsul/schema.ts +130 -0
- package/{place-importance-schema.ts → lib/place-importance-schema.ts} +7 -8
- package/lib/poi/index.ts +8 -0
- package/{poi-lookup.ts → lib/poi/lookup.ts} +22 -28
- package/{poi-schema.ts → lib/poi/schema.ts} +3 -4
- package/{postal-city-alias-lookup.ts → lib/postal/city-alias-lookup.ts} +14 -20
- package/{postal-city-candidate-schema.ts → lib/postal/city-candidate-schema.ts} +2 -2
- package/lib/postal/index.ts +9 -0
- package/{postcode-point-lookup.ts → lib/postcode-point-lookup.ts} +17 -15
- package/{primary-preference.ts → lib/primary-preference.ts} +29 -10
- package/{proximity-rerank.ts → lib/proximity-rerank.ts} +2 -2
- package/{ranking-weights.ts → lib/ranking-weights.ts} +30 -4
- package/{region-keys.ts → lib/region-keys.ts} +9 -9
- package/{reverse.ts → lib/reverse.ts} +34 -46
- package/{schema.ts → lib/schema.ts} +10 -0
- package/{search-fetch.ts → lib/search-fetch.ts} +29 -28
- package/{sqlite-convention-source.ts → lib/sqlite-convention-source.ts} +9 -10
- package/{sqlite-utils.ts → lib/sqlite-utils.ts} +14 -18
- package/{street-centroid-schema.ts → lib/street/centroid-schema.ts} +5 -5
- package/{street-centroid.ts → lib/street/centroid.ts} +14 -21
- package/lib/street/index.ts +13 -0
- package/{street-morphology-fst-builder.ts → lib/street/morphology-fst-builder.ts} +24 -14
- package/{street-morphology-fst-loader.ts → lib/street/morphology-fst-loader.ts} +14 -12
- package/{street-name-lookup.ts → lib/street/name-lookup.ts} +14 -30
- package/{street-normalize.ts → lib/street/normalize.ts} +44 -19
- package/{street-segment-schema.ts → lib/street/segment-schema.ts} +7 -7
- package/{types.ts → lib/types.ts} +18 -12
- package/{unified-schema.ts → lib/unified-schema.ts} +20 -24
- package/lib/uprn/existence.ts +84 -0
- package/lib/uprn/index.ts +9 -0
- package/{uprn-lookup.ts → lib/uprn/lookup.ts} +14 -18
- package/{uprn-schema.ts → lib/uprn/schema.ts} +3 -3
- package/lib/weights-overlay-linker.ts +878 -0
- package/out/address/index.d.ts +9 -0
- package/out/address/index.d.ts.map +1 -0
- package/out/address/index.js +9 -0
- package/out/address/index.js.map +1 -0
- package/out/{address-point-interpolation.d.ts → address/point-interpolation.d.ts} +11 -10
- package/out/address/point-interpolation.d.ts.map +1 -0
- package/out/{address-point-interpolation.js → address/point-interpolation.js} +18 -18
- package/out/address/point-interpolation.js.map +1 -0
- package/out/{address-point-schema.d.ts → address/point-schema.d.ts} +16 -6
- package/out/address/point-schema.d.ts.map +1 -0
- package/out/{address-point-schema.js → address/point-schema.js} +7 -3
- package/out/address/point-schema.js.map +1 -0
- package/out/{address-point.d.ts → address/point.d.ts} +16 -8
- package/out/address/point.d.ts.map +1 -0
- package/out/{address-point.js → address/point.js} +71 -20
- package/out/address/point.js.map +1 -0
- package/out/{ancestry-backfill.d.ts → ancestry/backfill.d.ts} +7 -5
- package/out/ancestry/backfill.d.ts.map +1 -0
- package/out/{ancestry-backfill.js → ancestry/backfill.js} +12 -16
- package/out/ancestry/backfill.js.map +1 -0
- package/out/{ancestry.d.ts → ancestry/index.d.ts} +4 -3
- package/out/ancestry/index.d.ts.map +1 -0
- package/out/{ancestry.js → ancestry/index.js} +3 -2
- package/out/ancestry/index.js.map +1 -0
- package/out/build-candidate.d.ts +30 -24
- package/out/build-candidate.d.ts.map +1 -1
- package/out/build-candidate.js +50 -52
- package/out/build-candidate.js.map +1 -1
- package/out/build-slim.d.ts +4 -4
- package/out/build-slim.d.ts.map +1 -1
- package/out/build-slim.js +124 -139
- package/out/build-slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +5 -3
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +2 -2
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors-sidecar.d.ts +9 -10
- package/out/candidate/ancestors-sidecar.d.ts.map +1 -1
- package/out/candidate/ancestors-sidecar.js +7 -7
- package/out/candidate/ancestors-sidecar.js.map +1 -1
- package/out/candidate/country-display-names.d.ts +1 -1
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +1 -1
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +32 -0
- package/out/candidate/extract-fold.d.ts.map +1 -0
- package/out/candidate/{shard-fold.js → extract-fold.js} +20 -20
- package/out/candidate/extract-fold.js.map +1 -0
- package/out/candidate/name-roles.d.ts +13 -11
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +11 -10
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +1 -1
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +1 -1
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +3 -3
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +1 -1
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate-ancestors-schema.d.ts +4 -4
- package/out/candidate-ancestors-schema.d.ts.map +1 -1
- package/out/candidate-ancestors-schema.js +2 -2
- package/out/candidate-ancestors-schema.js.map +1 -1
- package/out/candidate-fts.d.ts +3 -3
- package/out/candidate-fts.d.ts.map +1 -1
- package/out/candidate-fts.js +1 -1
- package/out/candidate-fts.js.map +1 -1
- package/out/candidate-importance.d.ts +16 -16
- package/out/candidate-importance.d.ts.map +1 -1
- package/out/candidate-importance.js +46 -51
- package/out/candidate-importance.js.map +1 -1
- package/out/candidate-lookup.d.ts +11 -9
- package/out/candidate-lookup.d.ts.map +1 -1
- package/out/candidate-lookup.js +61 -58
- package/out/candidate-lookup.js.map +1 -1
- package/out/candidate-schema.d.ts +5 -5
- package/out/candidate-schema.d.ts.map +1 -1
- package/out/candidate-schema.js.map +1 -1
- package/out/candidate-scoring.d.ts +7 -7
- package/out/candidate-scoring.d.ts.map +1 -1
- package/out/candidate-scoring.js +10 -14
- package/out/candidate-scoring.js.map +1 -1
- package/out/capital-schema.d.ts +3 -3
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +2 -2
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +1 -1
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +2 -2
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +6 -5
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +2 -4
- package/out/coincident-roles.js.map +1 -1
- package/out/{convention.d.ts → convention/index.d.ts} +4 -4
- package/out/convention/index.d.ts.map +1 -0
- package/out/{convention.js → convention/index.js} +2 -2
- package/out/convention/index.js.map +1 -0
- package/out/{convention-schema.d.ts → convention/schema.d.ts} +2 -2
- package/out/convention/schema.d.ts.map +1 -0
- package/out/{convention-schema.js → convention/schema.js} +3 -3
- package/out/convention/schema.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +8 -8
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +4 -4
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +51 -7
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +65 -49
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +43 -0
- package/out/env.d.ts.map +1 -0
- package/out/env.js +48 -0
- package/out/env.js.map +1 -0
- package/out/exact-match.d.ts +5 -5
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +10 -11
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +114 -0
- package/out/extracts.d.ts.map +1 -0
- package/out/{sharding.js → extracts.js} +38 -38
- package/out/extracts.js.map +1 -0
- package/out/{fst-autocomplete.d.ts → fst/autocomplete.d.ts} +2 -2
- package/out/fst/autocomplete.d.ts.map +1 -0
- package/out/{fst-autocomplete.js → fst/autocomplete.js} +3 -3
- package/out/fst/autocomplete.js.map +1 -0
- package/out/{fst-builder.d.ts → fst/builder.d.ts} +5 -5
- package/out/fst/builder.d.ts.map +1 -0
- package/out/{fst-builder.js → fst/builder.js} +14 -13
- package/out/fst/builder.js.map +1 -0
- package/out/{fst-deserialize-web.d.ts → fst/deserialize-web.d.ts} +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -0
- package/out/{fst-deserialize-web.js → fst/deserialize-web.js} +10 -74
- package/out/fst/deserialize-web.js.map +1 -0
- package/out/fst/format.d.ts +80 -0
- package/out/fst/format.d.ts.map +1 -0
- package/out/fst/format.js +91 -0
- package/out/fst/format.js.map +1 -0
- package/out/{fst-freshness.d.ts → fst/freshness.d.ts} +10 -13
- package/out/fst/freshness.d.ts.map +1 -0
- package/out/{fst-freshness.js → fst/freshness.js} +41 -73
- package/out/fst/freshness.js.map +1 -0
- package/out/fst/index.d.ts +14 -0
- package/out/fst/index.d.ts.map +1 -0
- package/out/fst/index.js +14 -0
- package/out/fst/index.js.map +1 -0
- package/out/{fst-matcher.d.ts → fst/matcher.d.ts} +2 -2
- package/out/fst/matcher.d.ts.map +1 -0
- package/out/{fst-matcher.js → fst/matcher.js} +1 -1
- package/out/fst/matcher.js.map +1 -0
- package/out/{fst-serialize.d.ts → fst/serialize.d.ts} +5 -10
- package/out/fst/serialize.d.ts.map +1 -0
- package/out/{fst-serialize.js → fst/serialize.js} +18 -98
- package/out/fst/serialize.js.map +1 -0
- package/out/{fst-types.d.ts → fst/types.d.ts} +4 -3
- package/out/fst/types.d.ts.map +1 -0
- package/out/{fst-types.js → fst/types.js} +1 -1
- package/out/fst/types.js.map +1 -0
- package/out/{fts.d.ts → fts/index.d.ts} +16 -9
- package/out/fts/index.d.ts.map +1 -0
- package/out/{fts.js → fts/index.js} +16 -11
- package/out/fts/index.js.map +1 -0
- package/out/{fts-query.d.ts → fts/query.d.ts} +2 -2
- package/out/fts/query.d.ts.map +1 -0
- package/out/{fts-query.js → fts/query.js} +1 -1
- package/out/fts/query.js.map +1 -0
- package/out/{geonames-aliases.d.ts → geonames/aliases.d.ts} +8 -6
- package/out/geonames/aliases.d.ts.map +1 -0
- package/out/{geonames-aliases.js → geonames/aliases.js} +7 -7
- package/out/geonames/aliases.js.map +1 -0
- package/out/geonames/index.d.ts +8 -0
- package/out/geonames/index.d.ts.map +1 -0
- package/out/geonames/index.js +8 -0
- package/out/geonames/index.js.map +1 -0
- package/out/{geonames-postal.d.ts → geonames/postal.d.ts} +10 -8
- package/out/geonames/postal.d.ts.map +1 -0
- package/out/{geonames-postal.js → geonames/postal.js} +9 -9
- package/out/geonames/postal.js.map +1 -0
- package/out/index.d.ts +32 -32
- package/out/index.d.ts.map +1 -1
- package/out/index.js +24 -24
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +10 -9
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +20 -20
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +21 -20
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +102 -112
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js.map +1 -1
- package/out/nsul/index.d.ts +8 -0
- package/out/nsul/index.d.ts.map +1 -0
- package/out/nsul/index.js +8 -0
- package/out/nsul/index.js.map +1 -0
- package/out/nsul/lookup.d.ts +83 -0
- package/out/nsul/lookup.d.ts.map +1 -0
- package/out/nsul/lookup.js +80 -0
- package/out/nsul/lookup.js.map +1 -0
- package/out/nsul/schema.d.ts +100 -0
- package/out/nsul/schema.d.ts.map +1 -0
- package/out/nsul/schema.js +78 -0
- package/out/nsul/schema.js.map +1 -0
- package/out/place-importance-schema.d.ts +5 -5
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -3
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/index.d.ts +8 -0
- package/out/poi/index.d.ts.map +1 -0
- package/out/poi/index.js +8 -0
- package/out/poi/index.js.map +1 -0
- package/out/{poi-lookup.d.ts → poi/lookup.d.ts} +8 -10
- package/out/poi/lookup.d.ts.map +1 -0
- package/out/{poi-lookup.js → poi/lookup.js} +14 -18
- package/out/poi/lookup.js.map +1 -0
- package/out/{poi-schema.d.ts → poi/schema.d.ts} +4 -4
- package/out/poi/schema.d.ts.map +1 -0
- package/out/{poi-schema.js → poi/schema.js} +1 -1
- package/out/poi/schema.js.map +1 -0
- package/out/polygon-schema.d.ts.map +1 -1
- package/out/polygon-schema.js.map +1 -1
- package/out/{postal-city-alias-lookup.d.ts → postal/city-alias-lookup.d.ts} +6 -5
- package/out/postal/city-alias-lookup.d.ts.map +1 -0
- package/out/{postal-city-alias-lookup.js → postal/city-alias-lookup.js} +11 -15
- package/out/postal/city-alias-lookup.js.map +1 -0
- package/out/{postal-city-alias-schema.d.ts → postal/city-alias-schema.d.ts} +1 -1
- package/out/{postal-city-alias-schema.d.ts.map → postal/city-alias-schema.d.ts.map} +1 -1
- package/out/{postal-city-alias-schema.js → postal/city-alias-schema.js} +1 -1
- package/out/{postal-city-alias-schema.js.map → postal/city-alias-schema.js.map} +1 -1
- package/out/{postal-city-candidate-schema.d.ts → postal/city-candidate-schema.d.ts} +3 -3
- package/out/{postal-city-candidate-schema.d.ts.map → postal/city-candidate-schema.d.ts.map} +1 -1
- package/out/{postal-city-candidate-schema.js → postal/city-candidate-schema.js} +2 -2
- package/out/{postal-city-candidate-schema.js.map → postal/city-candidate-schema.js.map} +1 -1
- package/out/postal/index.d.ts +9 -0
- package/out/postal/index.d.ts.map +1 -0
- package/out/postal/index.js +9 -0
- package/out/postal/index.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +10 -10
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +13 -13
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +13 -5
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +16 -8
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +2 -2
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +2 -2
- package/out/proximity-rerank.js.map +1 -1
- package/out/ranking-weights.d.ts +15 -3
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +21 -3
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +8 -8
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +9 -9
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +6 -6
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +20 -29
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +9 -0
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +12 -10
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +21 -20
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite-convention-source.d.ts +7 -7
- package/out/sqlite-convention-source.d.ts.map +1 -1
- package/out/sqlite-convention-source.js +5 -5
- package/out/sqlite-convention-source.js.map +1 -1
- package/out/sqlite-utils.d.ts +8 -8
- package/out/sqlite-utils.d.ts.map +1 -1
- package/out/sqlite-utils.js +7 -8
- package/out/sqlite-utils.js.map +1 -1
- package/out/{street-centroid-schema.d.ts → street/centroid-schema.d.ts} +6 -6
- package/out/{street-centroid-schema.d.ts.map → street/centroid-schema.d.ts.map} +1 -1
- package/out/{street-centroid-schema.js → street/centroid-schema.js} +5 -5
- package/out/{street-centroid-schema.js.map → street/centroid-schema.js.map} +1 -1
- package/out/{street-centroid.d.ts → street/centroid.d.ts} +6 -6
- package/out/street/centroid.d.ts.map +1 -0
- package/out/{street-centroid.js → street/centroid.js} +13 -19
- package/out/street/centroid.js.map +1 -0
- package/out/street/index.d.ts +13 -0
- package/out/street/index.d.ts.map +1 -0
- package/out/street/index.js +13 -0
- package/out/street/index.js.map +1 -0
- package/out/{street-morphology-fst-builder.d.ts → street/morphology-fst-builder.d.ts} +4 -4
- package/out/street/morphology-fst-builder.d.ts.map +1 -0
- package/out/{street-morphology-fst-builder.js → street/morphology-fst-builder.js} +18 -13
- package/out/street/morphology-fst-builder.js.map +1 -0
- package/out/{street-morphology-fst-loader.d.ts → street/morphology-fst-loader.d.ts} +5 -5
- package/out/street/morphology-fst-loader.d.ts.map +1 -0
- package/out/{street-morphology-fst-loader.js → street/morphology-fst-loader.js} +11 -10
- package/out/street/morphology-fst-loader.js.map +1 -0
- package/out/{street-name-lookup.d.ts → street/name-lookup.d.ts} +4 -7
- package/out/street/name-lookup.d.ts.map +1 -0
- package/out/{street-name-lookup.js → street/name-lookup.js} +9 -23
- package/out/street/name-lookup.js.map +1 -0
- package/out/{street-normalize.d.ts → street/normalize.d.ts} +25 -14
- package/out/street/normalize.d.ts.map +1 -0
- package/out/{street-normalize.js → street/normalize.js} +36 -17
- package/out/street/normalize.js.map +1 -0
- package/out/{street-segment-schema.d.ts → street/segment-schema.d.ts} +8 -8
- package/out/{street-segment-schema.d.ts.map → street/segment-schema.d.ts.map} +1 -1
- package/out/{street-segment-schema.js → street/segment-schema.js} +4 -4
- package/out/{street-segment-schema.js.map → street/segment-schema.js.map} +1 -1
- package/out/types.d.ts +18 -12
- package/out/types.d.ts.map +1 -1
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +5 -4
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +15 -18
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +53 -0
- package/out/uprn/existence.d.ts.map +1 -0
- package/out/uprn/existence.js +61 -0
- package/out/uprn/existence.js.map +1 -0
- package/out/uprn/index.d.ts +9 -0
- package/out/uprn/index.d.ts.map +1 -0
- package/out/uprn/index.js +9 -0
- package/out/uprn/index.js.map +1 -0
- package/out/{uprn-lookup.d.ts → uprn/lookup.d.ts} +4 -4
- package/out/uprn/lookup.d.ts.map +1 -0
- package/out/{uprn-lookup.js → uprn/lookup.js} +11 -14
- package/out/uprn/lookup.js.map +1 -0
- package/out/{uprn-schema.d.ts → uprn/schema.d.ts} +4 -4
- package/out/uprn/schema.d.ts.map +1 -0
- package/out/{uprn-schema.js → uprn/schema.js} +4 -4
- package/out/uprn/schema.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +184 -26
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +338 -86
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +465 -269
- package/out/address-point-interpolation.d.ts.map +0 -1
- package/out/address-point-interpolation.js.map +0 -1
- package/out/address-point-schema.d.ts.map +0 -1
- package/out/address-point-schema.js.map +0 -1
- package/out/address-point.d.ts.map +0 -1
- package/out/address-point.js.map +0 -1
- package/out/ancestry-backfill.d.ts.map +0 -1
- package/out/ancestry-backfill.js.map +0 -1
- package/out/ancestry.d.ts.map +0 -1
- package/out/ancestry.js.map +0 -1
- package/out/candidate/shard-fold.d.ts +0 -31
- package/out/candidate/shard-fold.d.ts.map +0 -1
- package/out/candidate/shard-fold.js.map +0 -1
- package/out/convention-schema.d.ts.map +0 -1
- package/out/convention-schema.js.map +0 -1
- package/out/convention.d.ts.map +0 -1
- package/out/convention.js.map +0 -1
- package/out/fst-autocomplete.d.ts.map +0 -1
- package/out/fst-autocomplete.js.map +0 -1
- package/out/fst-builder.d.ts.map +0 -1
- package/out/fst-builder.js.map +0 -1
- package/out/fst-deserialize-web.d.ts.map +0 -1
- package/out/fst-deserialize-web.js.map +0 -1
- package/out/fst-freshness.d.ts.map +0 -1
- package/out/fst-freshness.js.map +0 -1
- package/out/fst-matcher.d.ts.map +0 -1
- package/out/fst-matcher.js.map +0 -1
- package/out/fst-serialize.d.ts.map +0 -1
- package/out/fst-serialize.js.map +0 -1
- package/out/fst-types.d.ts.map +0 -1
- package/out/fst-types.js.map +0 -1
- package/out/fts-query.d.ts.map +0 -1
- package/out/fts-query.js.map +0 -1
- package/out/fts.d.ts.map +0 -1
- package/out/fts.js.map +0 -1
- package/out/geonames-aliases.d.ts.map +0 -1
- package/out/geonames-aliases.js.map +0 -1
- package/out/geonames-postal.d.ts.map +0 -1
- package/out/geonames-postal.js.map +0 -1
- package/out/poi-lookup.d.ts.map +0 -1
- package/out/poi-lookup.js.map +0 -1
- package/out/poi-schema.d.ts.map +0 -1
- package/out/poi-schema.js.map +0 -1
- package/out/postal-city-alias-lookup.d.ts.map +0 -1
- package/out/postal-city-alias-lookup.js.map +0 -1
- package/out/sharding.d.ts +0 -114
- package/out/sharding.d.ts.map +0 -1
- package/out/sharding.js.map +0 -1
- package/out/street-centroid.d.ts.map +0 -1
- package/out/street-centroid.js.map +0 -1
- package/out/street-morphology-fst-builder.d.ts.map +0 -1
- package/out/street-morphology-fst-builder.js.map +0 -1
- package/out/street-morphology-fst-loader.d.ts.map +0 -1
- package/out/street-morphology-fst-loader.js.map +0 -1
- package/out/street-name-lookup.d.ts.map +0 -1
- package/out/street-name-lookup.js.map +0 -1
- package/out/street-normalize.d.ts.map +0 -1
- package/out/street-normalize.js.map +0 -1
- package/out/uprn-lookup.d.ts.map +0 -1
- package/out/uprn-lookup.js.map +0 -1
- package/out/uprn-schema.d.ts.map +0 -1
- package/out/uprn-schema.js.map +0 -1
- package/weights-overlay-linker.ts +0 -377
- /package/{name-score.ts → lib/name-score.ts} +0 -0
- /package/{polygon-schema.ts → lib/polygon-schema.ts} +0 -0
- /package/{postal-city-alias-schema.ts → lib/postal/city-alias-schema.ts} +0 -0
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { basename } from "path-ts"
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @copyright Sister Software
|
|
3
5
|
* @license AGPL-3.0
|
|
4
6
|
* @author Teffen Ellis, et al.
|
|
5
7
|
*
|
|
6
|
-
* Multi-
|
|
7
|
-
* connection via `ATTACH DATABASE`, and routes queries to the right
|
|
8
|
+
* Multi-extract support for `WOFSQLitePlaceLookup` — opens multiple WOF SQLite distributions on one
|
|
9
|
+
* connection via `ATTACH DATABASE`, and routes queries to the right extract based on placetype.
|
|
8
10
|
*
|
|
9
11
|
* ## The FTS5 syntax rule that drove this design
|
|
10
12
|
*
|
|
11
13
|
* The naive `SELECT … FROM pc.place_search WHERE pc.place_search MATCH ?` fails — SQLite parses the
|
|
12
14
|
* schema-qualified table on the left of MATCH as "column place_search of table pc". Discovered in
|
|
13
|
-
* the spike at PR review time; documented as `
|
|
15
|
+
* the spike at PR review time; documented as `_EXTRACT_RULE.md` should it ever bite again.
|
|
14
16
|
*
|
|
15
17
|
* The working form: schema-qualified in FROM, bare table name in MATCH:
|
|
16
18
|
*
|
|
@@ -18,15 +20,13 @@
|
|
|
18
20
|
* SELECT … FROM pc.place_search WHERE place_search MATCH ?
|
|
19
21
|
* ```
|
|
20
22
|
*
|
|
21
|
-
* Identical table names across attached
|
|
23
|
+
* Identical table names across attached extracts (which is what we have — every extract ships its own
|
|
22
24
|
* `place_search` + `place_bbox`) are fine because the bare-name MATCH resolves against FROM
|
|
23
25
|
* scope.
|
|
24
26
|
*/
|
|
25
27
|
|
|
26
|
-
import { basename } from "node:path"
|
|
27
|
-
|
|
28
28
|
/**
|
|
29
|
-
* Derive a SQL-safe schema name from a WOF distribution filename. Used by `ATTACH DATABASE … AS <name>` so each
|
|
29
|
+
* Derive a SQL-safe schema name from a WOF distribution filename. Used by `ATTACH DATABASE … AS <name>` so each extract
|
|
30
30
|
* gets a stable, predictable handle.
|
|
31
31
|
*
|
|
32
32
|
* Convention strips the `whosonfirst-data-` prefix and the `-latest.db` (or just `.db`) suffix, then replaces `-` with
|
|
@@ -39,7 +39,7 @@ import { basename } from "node:path"
|
|
|
39
39
|
* - `whosonfirst-data-admin-latest.db` → `admin`
|
|
40
40
|
* - `my-custom.db` → `my_custom`
|
|
41
41
|
*
|
|
42
|
-
* Callers can override the derived name explicitly via `
|
|
42
|
+
* Callers can override the derived name explicitly via `ExtractConfig.schemaName` when the filename doesn't follow WOF
|
|
43
43
|
* convention.
|
|
44
44
|
*/
|
|
45
45
|
export function deriveSchemaName(path: string): string {
|
|
@@ -57,11 +57,11 @@ export function deriveSchemaName(path: string): string {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* Per-
|
|
61
|
-
* lets callers override the derived schema name (useful when a filename doesn't follow WOF convention) or attach
|
|
62
|
-
* extra hint about which placetypes route here.
|
|
60
|
+
* Per-extract configuration. The simple form is just a path string — the schema name is derived from it. The object
|
|
61
|
+
* form lets callers override the derived schema name (useful when a filename doesn't follow WOF convention) or attach
|
|
62
|
+
* an extra hint about which placetypes route here.
|
|
63
63
|
*/
|
|
64
|
-
export interface
|
|
64
|
+
export interface ExtractConfig {
|
|
65
65
|
path: string
|
|
66
66
|
/**
|
|
67
67
|
* Override the auto-derived schema name. Useful when the filename doesn't match WOF convention or when you want a
|
|
@@ -69,9 +69,9 @@ export interface ShardConfig {
|
|
|
69
69
|
*/
|
|
70
70
|
schemaName?: string
|
|
71
71
|
/**
|
|
72
|
-
* Optional explicit list of placetypes this
|
|
73
|
-
* to this
|
|
74
|
-
* placetype as a substring (e.g. `postalcode_us` for `postalcode` queries) is preferred for that placetype.
|
|
72
|
+
* Optional explicit list of placetypes this extract serves. When set, queries against any listed placetype are routed
|
|
73
|
+
* to this extract. When omitted, routing falls back to a name-match heuristic: a extract whose `schemaName` contains
|
|
74
|
+
* the placetype as a substring (e.g. `postalcode_us` for `postalcode` queries) is preferred for that placetype.
|
|
75
75
|
*/
|
|
76
76
|
placetypes?: readonly string[]
|
|
77
77
|
}
|
|
@@ -80,7 +80,7 @@ export interface ShardConfig {
|
|
|
80
80
|
* Resolved post-derivation: paired path + chosen schema name + (possibly empty) placetypes hint. Used internally by
|
|
81
81
|
* `WOFSQLitePlaceLookup` so the routing logic operates on uniform structures.
|
|
82
82
|
*/
|
|
83
|
-
export interface
|
|
83
|
+
export interface ResolvedExtract {
|
|
84
84
|
path: string
|
|
85
85
|
schemaName: string
|
|
86
86
|
placetypes: readonly string[]
|
|
@@ -93,40 +93,40 @@ const SQLITE_IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/u
|
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* Normalize the user-provided `databasePath` opt (which may be a single string, an array of strings, or an array of
|
|
96
|
-
* `
|
|
96
|
+
* `ExtractConfig` objects) into a uniform `ResolvedExtract[]`.
|
|
97
97
|
*
|
|
98
|
-
* The first
|
|
99
|
-
*
|
|
98
|
+
* The first extract becomes `main` regardless of its derived schema name — that's the SQLite convention. Subsequent
|
|
99
|
+
* extracts keep their derived (or override) schema name.
|
|
100
100
|
*/
|
|
101
|
-
export function
|
|
101
|
+
export function resolveExtracts(input: string | ReadonlyArray<string | ExtractConfig>): ResolvedExtract[] {
|
|
102
102
|
const list = typeof input === "string" ? [input] : input
|
|
103
103
|
|
|
104
|
-
if (!list.length) throw new Error("
|
|
104
|
+
if (!list.length) throw new Error("resolveExtracts: at least one extract is required")
|
|
105
105
|
|
|
106
106
|
const seen = new Set<string>()
|
|
107
|
-
const out:
|
|
107
|
+
const out: ResolvedExtract[] = []
|
|
108
108
|
|
|
109
109
|
for (let i = 0; i < list.length; i++) {
|
|
110
110
|
const entry = list[i]!
|
|
111
|
-
const cfg:
|
|
111
|
+
const cfg: ExtractConfig = typeof entry === "string" ? { path: entry } : entry
|
|
112
112
|
const derived = cfg.schemaName ?? deriveSchemaName(cfg.path)
|
|
113
113
|
|
|
114
114
|
if (!SQLITE_IDENT_RE.test(derived)) {
|
|
115
115
|
throw new Error(
|
|
116
|
-
`
|
|
116
|
+
`resolveExtracts: schema name ${JSON.stringify(derived)} is not a valid SQLite identifier ` +
|
|
117
117
|
`(derived from path ${JSON.stringify(cfg.path)}). Pass an explicit ` +
|
|
118
118
|
`{ path, schemaName } to override.`
|
|
119
119
|
)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// The first
|
|
123
|
-
// only. Subsequent
|
|
122
|
+
// The first extract is always main per SQLite semantics — its derived name is informational
|
|
123
|
+
// only. Subsequent extracts must have unique non-main names.
|
|
124
124
|
const schemaName = i === 0 ? "main" : derived
|
|
125
125
|
|
|
126
126
|
if (i > 0 && (schemaName === "main" || seen.has(schemaName))) {
|
|
127
127
|
throw new Error(
|
|
128
|
-
`
|
|
129
|
-
`(either with "main" or another
|
|
128
|
+
`resolveExtracts: schema name ${JSON.stringify(schemaName)} collides ` +
|
|
129
|
+
`(either with "main" or another extract). Pass an explicit { path, schemaName }.`
|
|
130
130
|
)
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -143,36 +143,39 @@ export function resolveShards(input: string | ReadonlyArray<string | ShardConfig
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
|
-
* Pick the
|
|
146
|
+
* Pick the extract to route a query to given the requested placetype(s).
|
|
147
147
|
*
|
|
148
148
|
* Routing rules, in order:
|
|
149
149
|
*
|
|
150
|
-
* 1. If any
|
|
151
|
-
* 2. Otherwise, if a non-main
|
|
152
|
-
* it.
|
|
150
|
+
* 1. If any extract has explicit `placetypes` that includes the requested placetype, use it.
|
|
151
|
+
* 2. Otherwise, if a non-main extract's `schemaName` matches the placetype (e.g. `postalcode_us` matches `postalcode`),
|
|
152
|
+
* use it.
|
|
153
153
|
* 3. Otherwise, fall back to `main`.
|
|
154
154
|
*
|
|
155
|
-
* This deliberately doesn't UNION across
|
|
156
|
-
* the typical mailwoman query has a single placetype anyway. If a caller needs cross-
|
|
157
|
-
* `findPlace` calls.
|
|
155
|
+
* This deliberately doesn't UNION across extracts — BM25 scores aren't comparable across separately- indexed corpora,
|
|
156
|
+
* and the typical mailwoman query has a single placetype anyway. If a caller needs cross-extract results they can issue
|
|
157
|
+
* two `findPlace` calls.
|
|
158
158
|
*/
|
|
159
159
|
/**
|
|
160
|
-
* All placetype-matching
|
|
161
|
-
* a country-less postcode query with proximity hints fans out across every matching
|
|
162
|
-
* single-
|
|
160
|
+
* All placetype-matching extracts, in routing order (the country-aware pick chooses among these). Used by the bias
|
|
161
|
+
* path: a country-less postcode query with proximity hints fans out across every matching extract and merges, because
|
|
162
|
+
* single-extract routing would hide the cross-country ambiguity the hints exist to resolve ("48026" lives in
|
|
163
163
|
* postalcode-us AND postalcode-intl).
|
|
164
164
|
*/
|
|
165
|
-
export function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
165
|
+
export function pickExtractsForPlacetype(
|
|
166
|
+
extracts: ResolvedExtract[],
|
|
167
|
+
placetype: string | undefined
|
|
168
|
+
): ResolvedExtract[] {
|
|
169
|
+
if (!placetype) return [extracts[0]!]
|
|
170
|
+
const matches: ResolvedExtract[] = []
|
|
171
|
+
|
|
172
|
+
for (const s of extracts) {
|
|
170
173
|
if (s.placetypes.includes(placetype)) {
|
|
171
174
|
matches.push(s)
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
177
|
|
|
175
|
-
for (const s of
|
|
178
|
+
for (const s of extracts) {
|
|
176
179
|
if (s.schemaName === "main" || matches.includes(s)) continue
|
|
177
180
|
|
|
178
181
|
if (
|
|
@@ -184,19 +187,19 @@ export function pickShardsForPlacetype(shards: ResolvedShard[], placetype: strin
|
|
|
184
187
|
}
|
|
185
188
|
}
|
|
186
189
|
|
|
187
|
-
return matches.length ? matches : [
|
|
190
|
+
return matches.length ? matches : [extracts[0]!]
|
|
188
191
|
}
|
|
189
192
|
|
|
190
|
-
export function
|
|
191
|
-
|
|
193
|
+
export function pickExtractForPlacetype(
|
|
194
|
+
extracts: ResolvedExtract[],
|
|
192
195
|
placetype: string | undefined,
|
|
193
196
|
opts?: {
|
|
194
197
|
/**
|
|
195
|
-
* #920: the query's country constraint, when the caller has one. With MULTIPLE
|
|
196
|
-
* (postalcode-us + postalcode-geonames-tail), first-match routing sent every postcode query to the first
|
|
197
|
-
* starved the rest — a FI postcode could never reach the tail
|
|
198
|
-
* probed country set contains it, that
|
|
199
|
-
* order remains the tiebreak when no
|
|
198
|
+
* #920: the query's country constraint, when the caller has one. With MULTIPLE extracts matching a placetype
|
|
199
|
+
* (postalcode-us + postalcode-geonames-tail), first-match routing sent every postcode query to the first extract
|
|
200
|
+
* and starved the rest — a FI postcode could never reach the tail extract. When `country` is given and a matching
|
|
201
|
+
* extract's probed country set contains it, that extract wins; extracts without the country are skipped; the
|
|
202
|
+
* placetype-match order remains the tiebreak when no extract claims the country (or none was probed).
|
|
200
203
|
*/
|
|
201
204
|
country?: string
|
|
202
205
|
/**
|
|
@@ -204,18 +207,18 @@ export function pickShardForPlacetype(
|
|
|
204
207
|
*/
|
|
205
208
|
countriesBySchema?: ReadonlyMap<string, ReadonlySet<string>>
|
|
206
209
|
}
|
|
207
|
-
):
|
|
208
|
-
if (!placetype) return
|
|
210
|
+
): ResolvedExtract {
|
|
211
|
+
if (!placetype) return extracts[0]!
|
|
209
212
|
|
|
210
|
-
const matches:
|
|
213
|
+
const matches: ResolvedExtract[] = []
|
|
211
214
|
|
|
212
|
-
for (const s of
|
|
215
|
+
for (const s of extracts) {
|
|
213
216
|
if (s.placetypes.includes(placetype)) {
|
|
214
217
|
matches.push(s)
|
|
215
218
|
}
|
|
216
219
|
}
|
|
217
220
|
|
|
218
|
-
for (const s of
|
|
221
|
+
for (const s of extracts) {
|
|
219
222
|
if (s.schemaName === "main" || matches.includes(s)) continue
|
|
220
223
|
|
|
221
224
|
// Substring match: `postalcode_us` matches `postalcode`. Conservative — requires the
|
|
@@ -230,7 +233,7 @@ export function pickShardForPlacetype(
|
|
|
230
233
|
}
|
|
231
234
|
}
|
|
232
235
|
|
|
233
|
-
if (!matches.length) return
|
|
236
|
+
if (!matches.length) return extracts[0]!
|
|
234
237
|
|
|
235
238
|
if (opts?.country && opts.countriesBySchema) {
|
|
236
239
|
for (const s of matches) {
|
|
@@ -26,9 +26,9 @@ import type {
|
|
|
26
26
|
} from "@mailwoman/ancestrie"
|
|
27
27
|
import { autocomplete as ancestrieAutocomplete } from "@mailwoman/ancestrie"
|
|
28
28
|
|
|
29
|
-
import type { FSTMatcher } from "
|
|
30
|
-
import { normalizeTokens } from "
|
|
31
|
-
import type { PlaceEntry } from "
|
|
29
|
+
import type { FSTMatcher } from "#fst/matcher"
|
|
30
|
+
import { normalizeTokens } from "#fst/matcher"
|
|
31
|
+
import type { PlaceEntry } from "#fst/types"
|
|
32
32
|
|
|
33
33
|
export interface AutocompleteResult {
|
|
34
34
|
query: string
|
|
@@ -85,7 +85,7 @@ function topByReferential(entries: readonly PlaceEntry[], k: number): PlaceEntry
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
|
-
* {@link FSTMatcher} presented through ancestrie's storage
|
|
88
|
+
* {@link FSTMatcher} presented through ancestrie's storage interface. Records carry the {@link PlaceEntry} itself as the
|
|
89
89
|
* payload, so the entry that WINS the algorithm's shallowest-depth rule is the entry whose fields the suggestion
|
|
90
90
|
* reports — a side lookup keyed on id could pick a different surface's row (`crossCountryBranches` differs per
|
|
91
91
|
* surface).
|
|
@@ -11,14 +11,16 @@
|
|
|
11
11
|
* PlaceEntry at terminals → return FSTMatcher.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
15
|
+
import { resolvePath } from "path-ts"
|
|
15
16
|
|
|
16
|
-
import { readWOFSourceIdentity } from "
|
|
17
|
-
import type { FSTNode } from "
|
|
18
|
-
import { FSTMatcher, normalizeTokens } from "
|
|
19
|
-
import type { BuildFSTOpts, BuildFSTResult, FSTProvenance, PlaceEntry, PlacetypeID } from "
|
|
20
|
-
import { loadImportanceSplit } from "
|
|
21
|
-
import {
|
|
17
|
+
import { readWOFSourceIdentity } from "#fst/freshness"
|
|
18
|
+
import type { FSTNode } from "#fst/matcher"
|
|
19
|
+
import { FSTMatcher, normalizeTokens } from "#fst/matcher"
|
|
20
|
+
import type { BuildFSTOpts, BuildFSTResult, FSTProvenance, PlaceEntry, PlacetypeID } from "#fst/types"
|
|
21
|
+
import { loadImportanceSplit } from "#place-importance-schema"
|
|
22
|
+
import type { WOFDatabase } from "#schema"
|
|
23
|
+
import { allRows, getRow } from "#sqlite-utils"
|
|
22
24
|
|
|
23
25
|
const DEFAULT_PLACETYPES: PlacetypeID[] = [
|
|
24
26
|
"country",
|
|
@@ -54,18 +56,19 @@ interface NameRow {
|
|
|
54
56
|
privateuse: string
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
export function buildFSTFromWOF(opts: BuildFSTOpts): {
|
|
59
|
+
export async function buildFSTFromWOF(opts: BuildFSTOpts): Promise<{
|
|
58
60
|
matcher: FSTMatcher
|
|
59
61
|
provenance: FSTProvenance
|
|
60
62
|
result: BuildFSTResult
|
|
61
|
-
} {
|
|
63
|
+
}> {
|
|
62
64
|
const countries = opts.countries ?? DEFAULT_COUNTRIES
|
|
63
65
|
const placetypes = opts.placetypes ?? DEFAULT_PLACETYPES
|
|
64
66
|
const languages = opts.languages ?? DEFAULT_LANGUAGES
|
|
65
67
|
const progress = opts.onProgress ?? (() => {})
|
|
68
|
+
const dbPath = resolvePath(opts.dbPath)
|
|
66
69
|
|
|
67
|
-
progress("open",
|
|
68
|
-
|
|
70
|
+
progress("open", dbPath)
|
|
71
|
+
using db = new DatabaseClient<WOFDatabase>(dbPath, { open: true })
|
|
69
72
|
|
|
70
73
|
// Phase 1: Load all matching SPR rows.
|
|
71
74
|
progress("spr", `Loading places for countries=[${countries}], placetypes=[${placetypes}]`)
|
|
@@ -324,8 +327,6 @@ export function buildFSTFromWOF(opts: BuildFSTOpts): {
|
|
|
324
327
|
}
|
|
325
328
|
}
|
|
326
329
|
|
|
327
|
-
db.close()
|
|
328
|
-
|
|
329
330
|
progress(
|
|
330
331
|
"done",
|
|
331
332
|
`Built trie: ${nodes.length} states, ${insertCount} name insertions` +
|
|
@@ -341,8 +342,8 @@ export function buildFSTFromWOF(opts: BuildFSTOpts): {
|
|
|
341
342
|
// and is free whenever the `.md5` sidecar is current, which the admin build already writes.
|
|
342
343
|
// `sourceIdentity` lets a caller that already knows the digest (or is building from something that
|
|
343
344
|
// is not a file at all) supply it instead.
|
|
344
|
-
progress("stamp", `Reading source identity for ${
|
|
345
|
-
const source = opts.sourceIdentity ?? readWOFSourceIdentity(
|
|
345
|
+
progress("stamp", `Reading source identity for ${dbPath}`)
|
|
346
|
+
const source = opts.sourceIdentity ?? (await readWOFSourceIdentity(dbPath))
|
|
346
347
|
|
|
347
348
|
const provenance: FSTProvenance = {
|
|
348
349
|
builtAt: new Date().toISOString(),
|
|
@@ -354,7 +355,7 @@ export function buildFSTFromWOF(opts: BuildFSTOpts): {
|
|
|
354
355
|
importanceMatches: split.referential.size,
|
|
355
356
|
encyclopedicMatches: split.encyclopedic.size,
|
|
356
357
|
importanceSource: split.source,
|
|
357
|
-
sourceDB:
|
|
358
|
+
sourceDB: dbPath,
|
|
358
359
|
sourceDBMD5: source.md5,
|
|
359
360
|
sourceDBBytes: source.bytes,
|
|
360
361
|
...(excludeSurfaces !== undefined || excludeAllTokensOf !== undefined
|
|
@@ -10,87 +10,27 @@
|
|
|
10
10
|
* build-time operation).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { tryParsingJSON } from "@mailwoman/core/
|
|
14
|
-
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* First format version carrying the trailing metadata block; older files simply have none.
|
|
37
|
-
*/
|
|
38
|
-
const VERSION_WITH_METADATA = 3
|
|
39
|
-
|
|
40
|
-
const HEADER_SIZE = 32
|
|
41
|
-
const EDGE_ENTRY_SIZE = 8
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Format version that split the single `importance` float into `referential` + `encyclopedic` (ROAD_TO_V9 §2 R1),
|
|
45
|
-
* growing the place entry from 56 to 60 bytes. Mirrors `fst-serialize.ts`'s constant of the same name.
|
|
46
|
-
*/
|
|
47
|
-
const VERSION_TWO_SCORE_SPLIT = 5
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Place-entry size in bytes at or above {@link VERSION_TWO_SCORE_SPLIT}.
|
|
51
|
-
*/
|
|
52
|
-
const SPLIT_PLACE_ENTRY_SIZE = 60
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Place-entry size in bytes below {@link VERSION_TWO_SCORE_SPLIT}.
|
|
56
|
-
*/
|
|
57
|
-
const LEGACY_PLACE_ENTRY_SIZE = 56
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Byte offset of the encyclopedic float inside a v5 place entry — immediately after the 8-slot parent chain.
|
|
61
|
-
*/
|
|
62
|
-
const ENCYCLOPEDIC_OFFSET = 56
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* `placeFlags` bit 0 (byte `pp+7`, v5+): this place carries an encyclopedic score. Per-place because absence is the
|
|
66
|
-
* common case; see `fst-serialize.ts`.
|
|
67
|
-
*/
|
|
68
|
-
const PLACE_FLAG_HAS_ENCYCLOPEDIC = 1
|
|
69
|
-
/**
|
|
70
|
-
* "FST\0".
|
|
71
|
-
*/
|
|
72
|
-
const MAGIC_BYTES = [0x46, 0x53, 0x54, 0x00]
|
|
73
|
-
/**
|
|
74
|
-
* Must track the serializer's VERSION (fst-serialize.ts, currently 5). The v3 provenance + v4 16-byte-state/u32-count
|
|
75
|
-
* layout logic below already matches the Node deserializer; only this gate was left stale at 2, so the browser FST
|
|
76
|
-
* loader rejected every real (v4) artifact. It was left stale again at 4 by the v5 two-score split until this line
|
|
77
|
-
* moved with it — the gate is a SEPARATE number from the layout branches, which is exactly why it keeps drifting.
|
|
78
|
-
*/
|
|
79
|
-
const MAX_VERSION = 5
|
|
80
|
-
|
|
81
|
-
const PLACETYPE_ORDER: readonly PlacetypeID[] = [
|
|
82
|
-
"country",
|
|
83
|
-
"region",
|
|
84
|
-
"county",
|
|
85
|
-
"locality",
|
|
86
|
-
"localadmin",
|
|
87
|
-
"borough",
|
|
88
|
-
"neighbourhood",
|
|
89
|
-
"postalcode",
|
|
90
|
-
"campus",
|
|
91
|
-
"dependency",
|
|
92
|
-
"street_affix",
|
|
93
|
-
]
|
|
13
|
+
import { tryParsingJSON } from "@mailwoman/core/json"
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
EDGE_ENTRY_SIZE,
|
|
17
|
+
ENCYCLOPEDIC_OFFSET,
|
|
18
|
+
FST_FORMAT_VERSION,
|
|
19
|
+
FST_MAGIC_BYTES,
|
|
20
|
+
HEADER_SIZE,
|
|
21
|
+
LEGACY_PLACE_ENTRY_SIZE,
|
|
22
|
+
NARROW_STATE_ENTRY_SIZE,
|
|
23
|
+
PLACE_FLAG_HAS_ENCYCLOPEDIC,
|
|
24
|
+
PLACETYPE_ORDER,
|
|
25
|
+
SPLIT_PLACE_ENTRY_SIZE,
|
|
26
|
+
VERSION_TWO_SCORE_SPLIT,
|
|
27
|
+
VERSION_WIDE_STATE_COUNTERS,
|
|
28
|
+
VERSION_WITH_METADATA,
|
|
29
|
+
WIDE_STATE_ENTRY_SIZE,
|
|
30
|
+
} from "#fst/format"
|
|
31
|
+
import type { FSTNode } from "#fst/matcher"
|
|
32
|
+
import { FSTMatcher } from "#fst/matcher"
|
|
33
|
+
import type { FSTProvenance, PlaceEntry } from "#fst/types"
|
|
94
34
|
|
|
95
35
|
export function deserializeFSTWeb(input: ArrayBuffer | Uint8Array): FSTMatcher {
|
|
96
36
|
const bytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input
|
|
@@ -100,18 +40,18 @@ export function deserializeFSTWeb(input: ArrayBuffer | Uint8Array): FSTMatcher {
|
|
|
100
40
|
if (bytes.byteLength < HEADER_SIZE) throw new Error("FST buffer too small for header")
|
|
101
41
|
|
|
102
42
|
if (
|
|
103
|
-
bytes[0] !==
|
|
104
|
-
bytes[1] !==
|
|
105
|
-
bytes[2] !==
|
|
106
|
-
bytes[3] !==
|
|
43
|
+
bytes[0] !== FST_MAGIC_BYTES[0] ||
|
|
44
|
+
bytes[1] !== FST_MAGIC_BYTES[1] ||
|
|
45
|
+
bytes[2] !== FST_MAGIC_BYTES[2] ||
|
|
46
|
+
bytes[3] !== FST_MAGIC_BYTES[3]
|
|
107
47
|
) {
|
|
108
48
|
throw new Error("FST magic mismatch")
|
|
109
49
|
}
|
|
110
50
|
|
|
111
51
|
const version = view.getUint16(4, true)
|
|
112
52
|
|
|
113
|
-
if (version < 1 || version >
|
|
114
|
-
throw new Error(`FST version ${version} unsupported (expected 1..${
|
|
53
|
+
if (version < 1 || version > FST_FORMAT_VERSION) {
|
|
54
|
+
throw new Error(`FST version ${version} unsupported (expected 1..${FST_FORMAT_VERSION})`)
|
|
115
55
|
}
|
|
116
56
|
|
|
117
57
|
const isV2 = version >= 2
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* The FST binary-format constants, shared by the Node serializer/deserializer (`fst-serialize.ts`)
|
|
7
|
+
* and the browser deserializer (`fst-deserialize-web.ts`). Platform-free by design — no Buffer at
|
|
8
|
+
* module scope; both runtimes convert {@link FST_MAGIC_BYTES} themselves.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { PlacetypeID } from "#fst/types"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Format version this tree WRITES and the maximum either deserializer accepts, published so a freshness guard can call
|
|
15
|
+
* an older artifact format-stale without re-typing the number (mirrors `REQUIRED_PAIR_INDEX_SCHEMA`'s role for PIX1 —
|
|
16
|
+
* see `fst-freshness.ts`).
|
|
17
|
+
*
|
|
18
|
+
* ONE constant for the writer and both readers, deliberately. The browser reader's acceptance criterion was a SEPARATE
|
|
19
|
+
* `MAX_VERSION` number from the layout branches, and it drifted twice: left stale at 2 when the v4 wide-state layout
|
|
20
|
+
* shipped (rejecting every real artifact), and stale again at 4 through the v5 two-score split until the line moved by
|
|
21
|
+
* hand. A check that is the writer's version cannot drift from it.
|
|
22
|
+
*/
|
|
23
|
+
export const FST_FORMAT_VERSION = 5
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Fixed header size in bytes: magic, version, and the section offsets that follow it.
|
|
27
|
+
*/
|
|
28
|
+
export const HEADER_SIZE = 32
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Edge-table entry: the transition label and the target state index.
|
|
32
|
+
*/
|
|
33
|
+
export const EDGE_ENTRY_SIZE = 8
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Format version that widened the per-state edge and place counters from 16 to 32 bits, growing the state entry from 12
|
|
37
|
+
* to 16 bytes. Readers branch on it to stay backward-compatible with v2/v3 files.
|
|
38
|
+
*/
|
|
39
|
+
export const VERSION_WIDE_STATE_COUNTERS = 4
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* State-table entry size in bytes at or above {@link VERSION_WIDE_STATE_COUNTERS}.
|
|
43
|
+
*/
|
|
44
|
+
export const WIDE_STATE_ENTRY_SIZE = 16
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* State-table entry size in bytes below {@link VERSION_WIDE_STATE_COUNTERS}.
|
|
48
|
+
*/
|
|
49
|
+
export const NARROW_STATE_ENTRY_SIZE = 12
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* First format version carrying the trailing metadata block; older files simply have none.
|
|
53
|
+
*/
|
|
54
|
+
export const VERSION_WITH_METADATA = 3
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Format version that split the single `importance` float into `referential` + `encyclopedic` (ROAD_TO_V9 §2 R1),
|
|
58
|
+
* growing the place entry from 56 to 60 bytes and claiming the previously-reserved `pp+7` byte as
|
|
59
|
+
* {@link PLACE_FLAG_HAS_ENCYCLOPEDIC}.
|
|
60
|
+
*/
|
|
61
|
+
export const VERSION_TWO_SCORE_SPLIT = 5
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Place-entry size in bytes at or above {@link VERSION_TWO_SCORE_SPLIT}.
|
|
65
|
+
*/
|
|
66
|
+
export const SPLIT_PLACE_ENTRY_SIZE = 60
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Place-entry size in bytes below {@link VERSION_TWO_SCORE_SPLIT}.
|
|
70
|
+
*/
|
|
71
|
+
export const LEGACY_PLACE_ENTRY_SIZE = 56
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Byte offset of the encyclopedic float inside a v5 place entry — immediately after the 8-slot parent chain.
|
|
75
|
+
*/
|
|
76
|
+
export const ENCYCLOPEDIC_OFFSET = 56
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* `placeFlags` bit 0 (byte `pp+7`, v5+): this place carries an encyclopedic score. Per-PLACE rather than per-file
|
|
80
|
+
* because absence is the common case — roughly 89% of the 2026-08-05 gazetteer has no Wikipedia article — and a
|
|
81
|
+
* file-level flag would force every one of those rows to claim a 0 it never had.
|
|
82
|
+
*/
|
|
83
|
+
export const PLACE_FLAG_HAS_ENCYCLOPEDIC = 1
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* File magic, "FST\0" as bytes. A reader rejects anything not starting with these four bytes before parsing further.
|
|
87
|
+
*/
|
|
88
|
+
export const FST_MAGIC_BYTES: readonly number[] = [0x46, 0x53, 0x54, 0x00]
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Placetypes in hierarchy order, largest first. The index into this array is what gets written into a place entry, so
|
|
92
|
+
* REORDERING IT BREAKS EVERY EXISTING FILE — append instead, and bump the version.
|
|
93
|
+
*/
|
|
94
|
+
export const PLACETYPE_ORDER: readonly PlacetypeID[] = [
|
|
95
|
+
"country",
|
|
96
|
+
"region",
|
|
97
|
+
"county",
|
|
98
|
+
"locality",
|
|
99
|
+
"localadmin",
|
|
100
|
+
"borough",
|
|
101
|
+
"neighbourhood",
|
|
102
|
+
"postalcode",
|
|
103
|
+
"campus",
|
|
104
|
+
"dependency",
|
|
105
|
+
"street_affix",
|
|
106
|
+
]
|