@mailwoman/resolver-wof-sqlite 10.0.0 → 10.2.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 +9 -8
- package/lib/address/point/interpolation.ts +45 -39
- package/lib/address/point/schema.ts +17 -40
- package/lib/address/point.ts +316 -0
- package/lib/{address/index.ts → address.ts} +1 -1
- package/lib/ancestry/backfill.ts +20 -86
- package/lib/{ancestry/index.ts → ancestry.ts} +19 -15
- package/lib/build/candidate.ts +122 -174
- package/lib/build/population-corrections.ts +64 -0
- package/lib/build/slim.ts +44 -114
- package/lib/candidate/alias-bags.ts +16 -17
- package/lib/candidate/ancestors/schema.ts +77 -61
- package/lib/candidate/ancestors/sidecar.ts +15 -22
- package/lib/candidate/country-display-names.ts +6 -20
- package/lib/candidate/extract-fold.ts +10 -55
- package/lib/candidate/fts.ts +5 -23
- package/lib/candidate/importance.ts +65 -68
- package/lib/candidate/lookup.ts +124 -415
- package/lib/candidate/name-roles.ts +15 -33
- package/lib/candidate/own-name.ts +35 -32
- package/lib/candidate/place-attrs.ts +20 -13
- package/lib/candidate/schema.ts +29 -65
- package/lib/candidate/scoring.ts +54 -93
- package/lib/capital-schema.ts +21 -17
- package/lib/capitals.ts +29 -27
- package/lib/coincident-roles.ts +85 -55
- package/lib/convention/schema.ts +15 -16
- package/lib/convention.ts +144 -0
- package/lib/coverage-manifest-schema.ts +40 -45
- package/lib/currency-backfill.ts +34 -79
- package/lib/env.ts +1 -1
- package/lib/exact-match.ts +32 -21
- package/lib/extracts.ts +97 -74
- package/lib/fst/autocomplete.ts +54 -37
- package/lib/fst/builder.ts +37 -41
- package/lib/fst/deserialize-web.ts +16 -17
- package/lib/fst/format.ts +41 -23
- package/lib/fst/freshness.ts +43 -120
- package/lib/fst/matcher.ts +7 -5
- package/lib/fst/serialize.ts +54 -74
- package/lib/fst/types.ts +78 -75
- package/lib/{fst/index.ts → fst.ts} +1 -0
- package/lib/fts/query.ts +5 -36
- package/lib/fts.ts +280 -0
- package/lib/geonames/aliases.ts +73 -144
- package/lib/geonames/postal.ts +162 -71
- package/lib/index.ts +9 -8
- package/lib/interpolation.ts +48 -100
- package/lib/lookup.ts +155 -270
- package/lib/name-score.ts +9 -7
- package/lib/nsul/lookup.ts +37 -54
- package/lib/nsul/schema.ts +16 -43
- package/lib/paths.ts +159 -0
- package/lib/place-importance-schema.ts +62 -169
- package/lib/poi/lookup.ts +104 -121
- package/lib/poi/schema.ts +42 -26
- package/lib/polygon-schema.ts +10 -6
- package/lib/postal/city/alias/lookup.ts +22 -40
- package/lib/postal/city/alias/schema.ts +14 -10
- package/lib/postal/city/candidate-schema.ts +26 -20
- package/lib/postcode-point-lookup.ts +8 -27
- package/lib/primary-preference.ts +46 -126
- package/lib/proximity-rerank.ts +44 -33
- package/lib/ranking-weights.ts +105 -78
- package/lib/region-keys.ts +70 -42
- package/lib/reverse.ts +149 -86
- package/lib/schema.ts +73 -50
- package/lib/search-fetch.ts +90 -68
- package/lib/sqlite/convention-source.ts +15 -23
- package/lib/sqlite/utils.ts +19 -22
- package/lib/street/centroid/schema.ts +37 -42
- package/lib/street/{centroid/index.ts → centroid.ts} +16 -25
- package/lib/street/morphology/fst/builder.ts +60 -42
- package/lib/street/morphology/fst/loader.ts +40 -32
- package/lib/street/name-lookup.ts +45 -41
- package/lib/street/normalize.ts +88 -219
- package/lib/street/segment-schema.ts +116 -43
- package/lib/{street/index.ts → street.ts} +1 -1
- package/lib/types.ts +109 -150
- package/lib/unified-schema.ts +29 -29
- package/lib/uprn/existence.ts +30 -19
- package/lib/uprn/lookup.ts +29 -68
- package/lib/uprn/schema.ts +18 -40
- package/lib/weights-overlay-linker.ts +236 -252
- package/out/address/point/interpolation.d.ts +20 -23
- package/out/address/point/interpolation.d.ts.map +1 -1
- package/out/address/point/interpolation.js +42 -39
- package/out/address/point/interpolation.js.map +1 -1
- package/out/address/point/schema.d.ts +12 -35
- package/out/address/point/schema.d.ts.map +1 -1
- package/out/address/point/schema.js +3 -19
- package/out/address/point/schema.js.map +1 -1
- package/out/address/point.d.ts +57 -0
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +206 -0
- package/out/address/point.js.map +1 -0
- package/out/{address/index.js → address.d.ts} +2 -2
- package/out/address.d.ts.map +1 -0
- package/out/{address/index.d.ts → address.js} +2 -2
- package/out/address.js.map +1 -0
- package/out/ancestry/backfill.d.ts +11 -64
- package/out/ancestry/backfill.d.ts.map +1 -1
- package/out/ancestry/backfill.js +14 -74
- package/out/ancestry/backfill.js.map +1 -1
- package/out/ancestry.d.ts +49 -0
- package/out/ancestry.d.ts.map +1 -0
- package/out/ancestry.js +59 -0
- package/out/ancestry.js.map +1 -0
- package/out/build/candidate.d.ts +82 -112
- package/out/build/candidate.d.ts.map +1 -1
- package/out/build/candidate.js +17 -100
- package/out/build/candidate.js.map +1 -1
- package/out/build/population-corrections.d.ts +52 -0
- package/out/build/population-corrections.d.ts.map +1 -0
- package/out/build/population-corrections.js +40 -0
- package/out/build/population-corrections.js.map +1 -0
- package/out/build/slim.d.ts +8 -44
- package/out/build/slim.d.ts.map +1 -1
- package/out/build/slim.js +33 -94
- package/out/build/slim.js.map +1 -1
- package/out/candidate/alias-bags.d.ts +6 -6
- package/out/candidate/alias-bags.d.ts.map +1 -1
- package/out/candidate/alias-bags.js +16 -17
- package/out/candidate/alias-bags.js.map +1 -1
- package/out/candidate/ancestors/schema.d.ts +73 -57
- package/out/candidate/ancestors/schema.d.ts.map +1 -1
- package/out/candidate/ancestors/schema.js +56 -48
- package/out/candidate/ancestors/schema.js.map +1 -1
- package/out/candidate/ancestors/sidecar.d.ts +3 -8
- package/out/candidate/ancestors/sidecar.d.ts.map +1 -1
- package/out/candidate/ancestors/sidecar.js +15 -22
- package/out/candidate/ancestors/sidecar.js.map +1 -1
- package/out/candidate/country-display-names.d.ts +5 -15
- package/out/candidate/country-display-names.d.ts.map +1 -1
- package/out/candidate/country-display-names.js +6 -20
- package/out/candidate/country-display-names.js.map +1 -1
- package/out/candidate/extract-fold.d.ts +7 -15
- package/out/candidate/extract-fold.d.ts.map +1 -1
- package/out/candidate/extract-fold.js +5 -47
- package/out/candidate/extract-fold.js.map +1 -1
- package/out/candidate/fts.d.ts +5 -23
- package/out/candidate/fts.d.ts.map +1 -1
- package/out/candidate/fts.js +5 -23
- package/out/candidate/fts.js.map +1 -1
- package/out/candidate/importance.d.ts +60 -65
- package/out/candidate/importance.d.ts.map +1 -1
- package/out/candidate/importance.js +56 -63
- package/out/candidate/importance.js.map +1 -1
- package/out/candidate/lookup.d.ts +18 -55
- package/out/candidate/lookup.d.ts.map +1 -1
- package/out/candidate/lookup.js +82 -385
- package/out/candidate/lookup.js.map +1 -1
- package/out/candidate/name-roles.d.ts +9 -21
- package/out/candidate/name-roles.d.ts.map +1 -1
- package/out/candidate/name-roles.js +15 -33
- package/out/candidate/name-roles.js.map +1 -1
- package/out/candidate/own-name.d.ts +23 -25
- package/out/candidate/own-name.d.ts.map +1 -1
- package/out/candidate/own-name.js +35 -32
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/place-attrs.d.ts +20 -13
- package/out/candidate/place-attrs.d.ts.map +1 -1
- package/out/candidate/place-attrs.js +4 -5
- package/out/candidate/place-attrs.js.map +1 -1
- package/out/candidate/schema.d.ts +27 -62
- package/out/candidate/schema.d.ts.map +1 -1
- package/out/candidate/schema.js +10 -22
- package/out/candidate/schema.js.map +1 -1
- package/out/candidate/scoring.d.ts +7 -8
- package/out/candidate/scoring.d.ts.map +1 -1
- package/out/candidate/scoring.js +52 -89
- package/out/candidate/scoring.js.map +1 -1
- package/out/capital-schema.d.ts +21 -17
- package/out/capital-schema.d.ts.map +1 -1
- package/out/capital-schema.js +17 -15
- package/out/capital-schema.js.map +1 -1
- package/out/capitals.d.ts +27 -25
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js +23 -21
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +60 -43
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +72 -50
- package/out/coincident-roles.js.map +1 -1
- package/out/convention/schema.d.ts +14 -14
- package/out/convention/schema.d.ts.map +1 -1
- package/out/convention/schema.js +6 -4
- package/out/convention/schema.js.map +1 -1
- package/out/convention.d.ts +97 -0
- package/out/convention.d.ts.map +1 -0
- package/out/convention.js +81 -0
- package/out/convention.js.map +1 -0
- package/out/coverage-manifest-schema.d.ts +34 -39
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +25 -34
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +16 -38
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +19 -46
- package/out/currency-backfill.js.map +1 -1
- package/out/env.d.ts +1 -1
- package/out/env.js +1 -1
- package/out/exact-match.d.ts +19 -10
- package/out/exact-match.d.ts.map +1 -1
- package/out/exact-match.js +32 -21
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +66 -55
- package/out/extracts.d.ts.map +1 -1
- package/out/extracts.js +63 -55
- package/out/extracts.js.map +1 -1
- package/out/fst/autocomplete.d.ts +29 -21
- package/out/fst/autocomplete.d.ts.map +1 -1
- package/out/fst/autocomplete.js +39 -28
- package/out/fst/autocomplete.js.map +1 -1
- package/out/fst/builder.d.ts.map +1 -1
- package/out/fst/builder.js +37 -41
- package/out/fst/builder.js.map +1 -1
- package/out/fst/deserialize-web.d.ts +4 -4
- package/out/fst/deserialize-web.d.ts.map +1 -1
- package/out/fst/deserialize-web.js +15 -16
- package/out/fst/deserialize-web.js.map +1 -1
- package/out/fst/format.d.ts +41 -23
- package/out/fst/format.d.ts.map +1 -1
- package/out/fst/format.js +41 -23
- package/out/fst/format.js.map +1 -1
- package/out/fst/freshness.d.ts +19 -81
- package/out/fst/freshness.d.ts.map +1 -1
- package/out/fst/freshness.js +31 -94
- package/out/fst/freshness.js.map +1 -1
- package/out/fst/matcher.d.ts +5 -4
- package/out/fst/matcher.d.ts.map +1 -1
- package/out/fst/matcher.js +2 -2
- package/out/fst/matcher.js.map +1 -1
- package/out/fst/serialize.d.ts +28 -28
- package/out/fst/serialize.d.ts.map +1 -1
- package/out/fst/serialize.js +53 -71
- package/out/fst/serialize.js.map +1 -1
- package/out/fst/types.d.ts +78 -74
- package/out/fst/types.d.ts.map +1 -1
- package/out/fst/types.js +1 -4
- package/out/fst/types.js.map +1 -1
- package/out/{fst/index.js → fst.d.ts} +2 -1
- package/out/fst.d.ts.map +1 -0
- package/out/{fst/index.d.ts → fst.js} +2 -1
- package/out/fst.js.map +1 -0
- package/out/fts/query.d.ts +2 -27
- package/out/fts/query.d.ts.map +1 -1
- package/out/fts/query.js +5 -36
- package/out/fts/query.js.map +1 -1
- package/out/fts.d.ts +126 -0
- package/out/fts.d.ts.map +1 -0
- package/out/fts.js +188 -0
- package/out/fts.js.map +1 -0
- package/out/geonames/aliases.d.ts +26 -62
- package/out/geonames/aliases.d.ts.map +1 -1
- package/out/geonames/aliases.js +45 -117
- package/out/geonames/aliases.js.map +1 -1
- package/out/geonames/postal.d.ts +84 -44
- package/out/geonames/postal.d.ts.map +1 -1
- package/out/geonames/postal.js +115 -73
- package/out/geonames/postal.js.map +1 -1
- package/out/{geonames/index.js → geonames.d.ts} +1 -1
- package/out/geonames.d.ts.map +1 -0
- package/out/{geonames/index.d.ts → geonames.js} +1 -1
- package/out/geonames.js.map +1 -0
- package/out/index.d.ts +9 -8
- package/out/index.d.ts.map +1 -1
- package/out/index.js +6 -5
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +18 -55
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +27 -69
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +23 -51
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +136 -234
- package/out/lookup.js.map +1 -1
- package/out/name-score.d.ts +2 -2
- package/out/name-score.d.ts.map +1 -1
- package/out/name-score.js +9 -7
- package/out/name-score.js.map +1 -1
- package/out/nsul/lookup.d.ts +33 -34
- package/out/nsul/lookup.d.ts.map +1 -1
- package/out/nsul/lookup.js +26 -40
- package/out/nsul/lookup.js.map +1 -1
- package/out/nsul/schema.d.ts +16 -43
- package/out/nsul/schema.d.ts.map +1 -1
- package/out/nsul/schema.js +9 -35
- package/out/nsul/schema.js.map +1 -1
- package/out/{nsul/index.d.ts → nsul.d.ts} +1 -1
- package/out/nsul.d.ts.map +1 -0
- package/out/{nsul/index.js → nsul.js} +1 -1
- package/out/nsul.js.map +1 -0
- package/out/paths.d.ts +124 -0
- package/out/paths.d.ts.map +1 -0
- package/out/paths.js +104 -0
- package/out/paths.js.map +1 -0
- package/out/place-importance-schema.d.ts +51 -143
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +28 -143
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/lookup.d.ts +40 -47
- package/out/poi/lookup.d.ts.map +1 -1
- package/out/poi/lookup.js +69 -96
- package/out/poi/lookup.js.map +1 -1
- package/out/poi/schema.d.ts +41 -25
- package/out/poi/schema.d.ts.map +1 -1
- package/out/poi/schema.js +25 -17
- package/out/poi/schema.js.map +1 -1
- package/out/{poi/index.js → poi.d.ts} +1 -1
- package/out/poi.d.ts.map +1 -0
- package/out/{poi/index.d.ts → poi.js} +1 -1
- package/out/poi.js.map +1 -0
- package/out/polygon-schema.d.ts +10 -6
- package/out/polygon-schema.d.ts.map +1 -1
- package/out/polygon-schema.js +2 -2
- package/out/polygon-schema.js.map +1 -1
- package/out/postal/city/alias/lookup.d.ts +20 -23
- package/out/postal/city/alias/lookup.d.ts.map +1 -1
- package/out/postal/city/alias/lookup.js +17 -30
- package/out/postal/city/alias/lookup.js.map +1 -1
- package/out/postal/city/alias/schema.d.ts +14 -10
- package/out/postal/city/alias/schema.d.ts.map +1 -1
- package/out/postal/city/alias/schema.js +10 -8
- package/out/postal/city/alias/schema.js.map +1 -1
- package/out/postal/city/candidate-schema.d.ts +25 -19
- package/out/postal/city/candidate-schema.d.ts.map +1 -1
- package/out/postal/city/candidate-schema.js +21 -17
- package/out/postal/city/candidate-schema.js.map +1 -1
- package/out/{postal/index.d.ts → postal.d.ts} +1 -1
- package/out/postal.d.ts.map +1 -0
- package/out/{postal/index.js → postal.js} +1 -1
- package/out/postal.js.map +1 -0
- package/out/postcode-point-lookup.d.ts +6 -24
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js +5 -17
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.d.ts +38 -92
- package/out/primary-preference.d.ts.map +1 -1
- package/out/primary-preference.js +15 -99
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +41 -30
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/proximity-rerank.js +38 -29
- package/out/proximity-rerank.js.map +1 -1
- package/out/ranking-weights.d.ts +98 -64
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js +26 -25
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +50 -31
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js +68 -40
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +78 -50
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +98 -61
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +72 -49
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js +4 -5
- package/out/schema.js.map +1 -1
- package/out/search-fetch.d.ts +16 -12
- package/out/search-fetch.d.ts.map +1 -1
- package/out/search-fetch.js +83 -63
- package/out/search-fetch.js.map +1 -1
- package/out/sqlite/convention-source.d.ts +12 -16
- package/out/sqlite/convention-source.d.ts.map +1 -1
- package/out/sqlite/convention-source.js +13 -22
- package/out/sqlite/convention-source.js.map +1 -1
- package/out/sqlite/utils.d.ts +19 -19
- package/out/sqlite/utils.d.ts.map +1 -1
- package/out/sqlite/utils.js +14 -15
- package/out/sqlite/utils.js.map +1 -1
- package/out/street/centroid/schema.d.ts +37 -42
- package/out/street/centroid/schema.d.ts.map +1 -1
- package/out/street/centroid/schema.js +9 -21
- package/out/street/centroid/schema.js.map +1 -1
- package/out/street/centroid.d.ts +30 -0
- package/out/street/centroid.d.ts.map +1 -0
- package/out/street/{centroid/index.js → centroid.js} +13 -24
- package/out/street/centroid.js.map +1 -0
- package/out/street/morphology/fst/builder.d.ts +20 -10
- package/out/street/morphology/fst/builder.d.ts.map +1 -1
- package/out/street/morphology/fst/builder.js +44 -34
- package/out/street/morphology/fst/builder.js.map +1 -1
- package/out/street/morphology/fst/loader.d.ts +33 -26
- package/out/street/morphology/fst/loader.d.ts.map +1 -1
- package/out/street/morphology/fst/loader.js +23 -22
- package/out/street/morphology/fst/loader.js.map +1 -1
- package/out/street/name-lookup.d.ts +24 -18
- package/out/street/name-lookup.d.ts.map +1 -1
- package/out/street/name-lookup.js +34 -35
- package/out/street/name-lookup.js.map +1 -1
- package/out/street/normalize.d.ts +35 -136
- package/out/street/normalize.d.ts.map +1 -1
- package/out/street/normalize.js +77 -194
- package/out/street/normalize.js.map +1 -1
- package/out/street/segment-schema.d.ts +79 -39
- package/out/street/segment-schema.d.ts.map +1 -1
- package/out/street/segment-schema.js +71 -21
- package/out/street/segment-schema.js.map +1 -1
- package/out/{street/index.js → street.d.ts} +2 -2
- package/out/street.d.ts.map +1 -0
- package/out/{street/index.d.ts → street.js} +2 -2
- package/out/street.js.map +1 -0
- package/out/types.d.ts +84 -149
- package/out/types.d.ts.map +1 -1
- package/out/types.js +0 -6
- package/out/types.js.map +1 -1
- package/out/unified-schema.d.ts +8 -12
- package/out/unified-schema.d.ts.map +1 -1
- package/out/unified-schema.js +29 -29
- package/out/unified-schema.js.map +1 -1
- package/out/uprn/existence.d.ts +28 -17
- package/out/uprn/existence.d.ts.map +1 -1
- package/out/uprn/existence.js +26 -16
- package/out/uprn/existence.js.map +1 -1
- package/out/uprn/lookup.d.ts +14 -44
- package/out/uprn/lookup.d.ts.map +1 -1
- package/out/uprn/lookup.js +21 -57
- package/out/uprn/lookup.js.map +1 -1
- package/out/uprn/schema.d.ts +18 -40
- package/out/uprn/schema.d.ts.map +1 -1
- package/out/uprn/schema.js +10 -32
- package/out/uprn/schema.js.map +1 -1
- package/out/{uprn/index.d.ts → uprn.d.ts} +1 -1
- package/out/uprn.d.ts.map +1 -0
- package/out/{uprn/index.js → uprn.js} +1 -1
- package/out/uprn.js.map +1 -0
- package/out/weights-overlay-linker.d.ts +138 -144
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +105 -159
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +91 -596
- package/lib/address/point/index.ts +0 -328
- package/lib/convention/index.ts +0 -154
- package/lib/fts/index.ts +0 -361
- package/out/address/index.d.ts.map +0 -1
- package/out/address/index.js.map +0 -1
- package/out/address/point/index.d.ts +0 -53
- package/out/address/point/index.d.ts.map +0 -1
- package/out/address/point/index.js +0 -222
- package/out/address/point/index.js.map +0 -1
- package/out/ancestry/index.d.ts +0 -45
- package/out/ancestry/index.d.ts.map +0 -1
- package/out/ancestry/index.js +0 -55
- package/out/ancestry/index.js.map +0 -1
- package/out/convention/index.d.ts +0 -106
- package/out/convention/index.d.ts.map +0 -1
- package/out/convention/index.js +0 -93
- package/out/convention/index.js.map +0 -1
- package/out/fst/index.d.ts.map +0 -1
- package/out/fst/index.js.map +0 -1
- package/out/fts/index.d.ts +0 -184
- package/out/fts/index.d.ts.map +0 -1
- package/out/fts/index.js +0 -277
- package/out/fts/index.js.map +0 -1
- package/out/geonames/index.d.ts.map +0 -1
- package/out/geonames/index.js.map +0 -1
- package/out/nsul/index.d.ts.map +0 -1
- package/out/nsul/index.js.map +0 -1
- package/out/poi/index.d.ts.map +0 -1
- package/out/poi/index.js.map +0 -1
- package/out/postal/index.d.ts.map +0 -1
- package/out/postal/index.js.map +0 -1
- package/out/street/centroid/index.d.ts +0 -40
- package/out/street/centroid/index.d.ts.map +0 -1
- package/out/street/centroid/index.js.map +0 -1
- package/out/street/index.d.ts.map +0 -1
- package/out/street/index.js.map +0 -1
- package/out/uprn/index.d.ts.map +0 -1
- package/out/uprn/index.js.map +0 -1
- /package/lib/{geonames/index.ts → geonames.ts} +0 -0
- /package/lib/{nsul/index.ts → nsul.ts} +0 -0
- /package/lib/{poi/index.ts → poi.ts} +0 -0
- /package/lib/{postal/index.ts → postal.ts} +0 -0
- /package/lib/{uprn/index.ts → uprn.ts} +0 -0
package/lib/fst/types.ts
CHANGED
|
@@ -2,49 +2,40 @@
|
|
|
2
2
|
* @copyright Sister Software
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
|
-
*
|
|
6
|
-
* Types for the FST gazetteer language model. The FST maps token sequences (place names) to
|
|
7
|
-
* (placetype, wof_id, parent_chain) entries — pre-computing the valid interpretations for each
|
|
8
|
-
* prefix of every place name in the gazetteer.
|
|
5
|
+
* @file Types for the FST gazetteer. These types map place-name token sequences to place entries.
|
|
9
6
|
*/
|
|
10
7
|
|
|
11
8
|
import type { PathBuilderLike } from "path-ts"
|
|
12
9
|
|
|
10
|
+
/**
|
|
11
|
+
* One place that a token sequence in the FST accepts.
|
|
12
|
+
*/
|
|
13
13
|
export interface PlaceEntry {
|
|
14
14
|
wofID: number
|
|
15
15
|
placetype: PlacetypeID
|
|
16
16
|
name: string
|
|
17
17
|
parentChain: number[]
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
* decoder bias is allowed to read (ROAD_TO_V9 §2, ratified 2026-08-06).
|
|
21
|
-
*
|
|
22
|
-
* This field was called `importance` through format v4, where it carried whichever score the source database happened
|
|
23
|
-
* to hold: the population proxy on a database with no `place_importance` table (which is every shipped
|
|
24
|
-
* `fst-per-locale` binary), the Wikipedia score where the concordance join landed otherwise. The rename is the point
|
|
25
|
-
* — a v4 artifact's value is a CONFLATION that cannot be told apart after the fact, which is why `fst-freshness.ts`
|
|
26
|
-
* reports anything below {@link FST_FORMAT_VERSION} as format-stale rather than reading it as referential.
|
|
19
|
+
* The population-based referential likelihood in [0, 1] that the decoder bias uses.
|
|
27
20
|
*/
|
|
28
21
|
referential: number
|
|
29
22
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* `undefined` = this place has no encyclopedic signal, or the artifact predates format 5. NEVER conflate either with
|
|
34
|
-
* 0 — the meaning-of-zero rule; roughly 89% of the 2026-08-05 gazetteer's rows have no Wikipedia article at all.
|
|
23
|
+
* The encyclopedic importance in [0, 1], for display only.
|
|
24
|
+
* It is `null` when unavailable.
|
|
35
25
|
*/
|
|
36
|
-
encyclopedic
|
|
26
|
+
encyclopedic: number | null
|
|
37
27
|
lat: number
|
|
38
28
|
lon: number
|
|
39
29
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* place reached via different alias surfaces reports each surface's own count. `undefined` = built without ambiguity
|
|
43
|
-
* data (pre-2026-07-27 artifacts) — NEVER conflate with 1 (the unambiguous case); the meaning-of-zero rule.
|
|
30
|
+
* The number of countries with a place of this surface, clamped to 255.
|
|
31
|
+
* It is `null` when unavailable.
|
|
44
32
|
*/
|
|
45
|
-
crossCountryBranches
|
|
33
|
+
crossCountryBranches: number | null
|
|
46
34
|
}
|
|
47
35
|
|
|
36
|
+
/**
|
|
37
|
+
* The placetypes the FST stores.
|
|
38
|
+
*/
|
|
48
39
|
export type PlacetypeID =
|
|
49
40
|
| "country"
|
|
50
41
|
| "region"
|
|
@@ -58,18 +49,18 @@ export type PlacetypeID =
|
|
|
58
49
|
| "dependency"
|
|
59
50
|
| "street_affix"
|
|
60
51
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
depth: number
|
|
65
|
-
}
|
|
66
|
-
|
|
52
|
+
/**
|
|
53
|
+
* One outgoing edge from an FST state, with the number of places its target state accepts.
|
|
54
|
+
*/
|
|
67
55
|
export interface FSTContinuation {
|
|
68
56
|
token: string
|
|
69
57
|
targetState: number
|
|
70
58
|
acceptingCount: number
|
|
71
59
|
}
|
|
72
60
|
|
|
61
|
+
/**
|
|
62
|
+
* The places a token path accepts and the tokens that can extend it.
|
|
63
|
+
*/
|
|
73
64
|
export interface FSTQueryResult {
|
|
74
65
|
path: string[]
|
|
75
66
|
stateID: number
|
|
@@ -77,6 +68,9 @@ export interface FSTQueryResult {
|
|
|
77
68
|
continuations: FSTContinuation[]
|
|
78
69
|
}
|
|
79
70
|
|
|
71
|
+
/**
|
|
72
|
+
* The build metadata stored in an FST binary's provenance trailer.
|
|
73
|
+
*/
|
|
80
74
|
export interface FSTProvenance {
|
|
81
75
|
builtAt: string
|
|
82
76
|
countries: string[]
|
|
@@ -85,93 +79,102 @@ export interface FSTProvenance {
|
|
|
85
79
|
edgeCount: number
|
|
86
80
|
nameInsertions: number
|
|
87
81
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
82
|
+
* The count of places with a non-zero referential score at build time.
|
|
83
|
+
*
|
|
84
|
+
* The key keeps its older name so that existing provenance stamps stay readable.
|
|
91
85
|
*/
|
|
92
86
|
importanceMatches: number
|
|
93
87
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
88
|
+
* The count of places with an encyclopedic score at build time.
|
|
89
|
+
*
|
|
90
|
+
* It is `null` for a build that predates the separate encyclopedic score.
|
|
91
|
+
* The value `0` means a current build used a database without encyclopedic scores.
|
|
97
92
|
*/
|
|
98
|
-
encyclopedicMatches
|
|
93
|
+
encyclopedicMatches: number | null
|
|
99
94
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
95
|
+
* The {@link ImportanceSplitSource} that records whether the encyclopedic score is real,
|
|
96
|
+
* reconstructed from a legacy column, or absent.
|
|
102
97
|
*/
|
|
103
|
-
importanceSource
|
|
104
|
-
sourceDB
|
|
98
|
+
importanceSource: string | null
|
|
99
|
+
sourceDB: string | null
|
|
105
100
|
/**
|
|
106
|
-
* MD5 of the source database's bytes at build time
|
|
101
|
+
* The MD5 of the source database's bytes at build time.
|
|
102
|
+
* The freshness check compares it.
|
|
107
103
|
*
|
|
108
|
-
* `sourceDB`
|
|
109
|
-
*
|
|
110
|
-
* still names the current file and none of them was built from it. Compared by `fst-freshness.ts`.
|
|
104
|
+
* `sourceDB` by itself cannot detect staleness.
|
|
105
|
+
* A rebuild replaces the admin database at the same path.
|
|
111
106
|
*
|
|
112
|
-
* `
|
|
113
|
-
*
|
|
107
|
+
* The field is `null` for artifacts built before the stamp existed.
|
|
108
|
+
* An unknown digest has a different value.
|
|
114
109
|
*/
|
|
115
|
-
sourceDBMD5
|
|
110
|
+
sourceDBMD5: string | null
|
|
116
111
|
/**
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
112
|
+
* The byte size of the source database at build time.
|
|
113
|
+
*
|
|
114
|
+
* It detects a truncated source and makes a staleness warning readable.
|
|
120
115
|
*/
|
|
121
|
-
sourceDBBytes
|
|
122
|
-
modelCardVersion
|
|
116
|
+
sourceDBBytes: number | null
|
|
117
|
+
modelCardVersion: string | null
|
|
123
118
|
/**
|
|
124
|
-
*
|
|
119
|
+
* The surface-exclusion policy applied at build time.
|
|
120
|
+
* It is absent for an uncurated build.
|
|
125
121
|
*/
|
|
126
|
-
exclusionPolicy
|
|
122
|
+
exclusionPolicy: string | null
|
|
127
123
|
/**
|
|
128
|
-
*
|
|
124
|
+
* The count of name insertions the exclusion policy rejected.
|
|
129
125
|
*/
|
|
130
|
-
excludedInsertions
|
|
126
|
+
excludedInsertions: number | null
|
|
131
127
|
}
|
|
132
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Options for building an FST from a WOF admin database.
|
|
131
|
+
*/
|
|
133
132
|
export interface BuildFSTOpts {
|
|
134
133
|
dbPath: PathBuilderLike
|
|
135
134
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
135
|
+
* The precomputed identity of `dbPath` to record in provenance.
|
|
136
|
+
*
|
|
137
|
+
* When omitted, the builder reads it with `readWOFSourceIdentity`, which caches it in a sidecar file.
|
|
139
138
|
*/
|
|
140
139
|
sourceIdentity?: { md5: string; bytes: number }
|
|
141
140
|
countries?: string[]
|
|
142
141
|
placetypes?: PlacetypeID[]
|
|
143
142
|
languages?: string[]
|
|
144
143
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
144
|
+
* Surfaces the builder never inserts, such as the bare function word "la"
|
|
145
|
+
* or the bare street type "boulevard".
|
|
146
|
+
*
|
|
147
|
+
* These surfaces do not discriminate between places when used as decoder bias keys.
|
|
148
|
+
* The resolver's candidate tables still hold the excluded places.
|
|
149
|
+
* Keys must be `normalizeTokens(...).join(" ")`.
|
|
150
150
|
*/
|
|
151
151
|
excludeSurfaces?: ReadonlySet<string>
|
|
152
152
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
153
|
+
* Tokens that a name must not consist of entirely, such as "de la".
|
|
154
|
+
*
|
|
155
|
+
* Build this set from stopwords only.
|
|
156
|
+
* A street-type word can be part of a real name, as in "Avenue Road".
|
|
156
157
|
*/
|
|
157
158
|
excludeAllTokensOf?: ReadonlySet<string>
|
|
158
159
|
/**
|
|
159
|
-
*
|
|
160
|
+
* The policy label recorded in provenance when either exclusion set is supplied.
|
|
160
161
|
*/
|
|
161
162
|
exclusionPolicy?: string
|
|
162
163
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* the Option-A evidence channel) arrive behind their own measured checks.
|
|
164
|
+
* Maps each normalized surface to the number of distinct countries in the whole
|
|
165
|
+
* admin database with a place of that surface.
|
|
166
|
+
*
|
|
167
|
+
* When supplied, each inserted place entry records the count for its accepting
|
|
168
|
+
* surface as `PlaceEntry.crossCountryBranches`.
|
|
169
|
+
* A place reachable under several surfaces records each surface's own count.
|
|
170
170
|
*/
|
|
171
171
|
surfaceCountryCounts?: ReadonlyMap<string, number>
|
|
172
172
|
onProgress?: (phase: string, detail?: string) => void
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Counts reported by an FST build.
|
|
177
|
+
*/
|
|
175
178
|
export interface BuildFSTResult {
|
|
176
179
|
stateCount: number
|
|
177
180
|
placeCount: number
|
package/lib/fts/query.ts
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* Both turn a caller's loose input into something SQLite's FTS5 parser accepts without throwing —
|
|
8
|
-
* an unescaped quote or a bare `*` is a syntax error, not an empty result.
|
|
6
|
+
* Query shaping for the FTS5 lookup: placetype normalization and the match-expression sanitizer.
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
9
|
import type { FindPlaceQuery, WOFPlacetype } from "#types"
|
|
@@ -17,30 +15,7 @@ export function normalizePlacetypes(p: FindPlaceQuery["placetype"]): WOFPlacetyp
|
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
/**
|
|
20
|
-
* Make an arbitrary user-typed string safe for FTS5
|
|
21
|
-
*
|
|
22
|
-
* FTS5 has its own query syntax (`"phrase"`, `term1 OR term2`, `prefix*`, NEAR/N, etc.). Letting raw user input through
|
|
23
|
-
* means a user typing `Paris's` or `St. (Petersburg)` causes a syntax error.
|
|
24
|
-
*
|
|
25
|
-
* Per-token rules:
|
|
26
|
-
*
|
|
27
|
-
* - Strip all punctuation except trailing `*` from each whitespace-separated token.
|
|
28
|
-
* - **Trailing `*`** is preserved as FTS5 **prefix syntax** — `627*` becomes the literal `627*` (unquoted). The caller
|
|
29
|
-
* signaled they want a prefix; respect that.
|
|
30
|
-
* - All other tokens are wrapped in `"..."` as a single-word phrase. Conservative — handles apostrophes, parens, accented
|
|
31
|
-
* input, etc. safely.
|
|
32
|
-
* - Multiple tokens join with implicit AND.
|
|
33
|
-
*
|
|
34
|
-
* Examples:
|
|
35
|
-
*
|
|
36
|
-
* - `"Paris"` → `"Paris"` (phrase)
|
|
37
|
-
* - `"627*"` → `627*` (prefix)
|
|
38
|
-
* - `"St. (Petersburg)"` → `"St" "Petersburg"` (two phrases, AND-joined)
|
|
39
|
-
* - `"Thiron-Gardais"` → `"Thiron" "Gardais"` (intra-token punctuation SPLITS — #945; fusing to `ThironGardais` matched
|
|
40
|
-
* nothing because the FTS doc tokenizes the hyphenated name as two terms)
|
|
41
|
-
* - `"110 00"` with `fuseTokens` (postcode-typed) → `"110" "00"` per-token fused — the #920 name law
|
|
42
|
-
* - `"Pari* TX"` → `Pari* "TX"` (mixed prefix + phrase)
|
|
43
|
-
* - `"*"` alone → `""` (no body → drop)
|
|
18
|
+
* Make an arbitrary user-typed string safe for FTS5 match.
|
|
44
19
|
*/
|
|
45
20
|
export function sanitizeFTSQuery(text: string, opts?: { fuseTokens?: boolean }): string {
|
|
46
21
|
const out: string[] = []
|
|
@@ -51,8 +26,7 @@ export function sanitizeFTSQuery(text: string, opts?: { fuseTokens?: boolean }):
|
|
|
51
26
|
if (!trimmed) continue
|
|
52
27
|
const hasPrefixStar = trimmed.endsWith("*")
|
|
53
28
|
|
|
54
|
-
//
|
|
55
|
-
// remainder — postal names are stored in this collapsed shape ("SW1A" stays one term).
|
|
29
|
+
// Fused mode deletes intra-token punctuation because postal names are stored in that collapsed shape.
|
|
56
30
|
if (opts?.fuseTokens) {
|
|
57
31
|
const body = trimmed.replaceAll(/[^\p{L}\p{N}]/gu, "")
|
|
58
32
|
|
|
@@ -62,12 +36,7 @@ export function sanitizeFTSQuery(text: string, opts?: { fuseTokens?: boolean }):
|
|
|
62
36
|
continue
|
|
63
37
|
}
|
|
64
38
|
|
|
65
|
-
|
|
66
|
-
// promised ("St. (Petersburg)" → two phrases). The old code DELETED punctuation instead,
|
|
67
|
-
// fusing "Thiron-Gardais" into the unmatchable single term `ThironGardais` while the FTS
|
|
68
|
-
// doc holds two terms (#945 — the entire hyphenated-name class missed at the raw lookup;
|
|
69
|
-
// masked for years because pre-splice tokenizers never emitted hyphen-preserved values).
|
|
70
|
-
const parts = trimmed.split(/[^\p{L}\p{N}]+/u).filter((part) => part.length > 0)
|
|
39
|
+
const parts = trimmed.split(/[^\p{L}\p{N}]+/u).filter((part) => part.length)
|
|
71
40
|
|
|
72
41
|
if (!parts.length) continue
|
|
73
42
|
|
|
@@ -75,7 +44,7 @@ export function sanitizeFTSQuery(text: string, opts?: { fuseTokens?: boolean }):
|
|
|
75
44
|
const body = parts[i]!.replaceAll("*", "")
|
|
76
45
|
|
|
77
46
|
if (!body) continue
|
|
78
|
-
// The caller's trailing `*` applies to the
|
|
47
|
+
// The caller's trailing `*` applies only to the final part.
|
|
79
48
|
out.push(hasPrefixStar && i === parts.length - 1 ? `${body}*` : `"${body.replaceAll('"', '""')}"`)
|
|
80
49
|
}
|
|
81
50
|
}
|
package/lib/fts.ts
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
8
|
+
import { tableExists } from "@mailwoman/sqlite/introspection"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The name of the FTS5 virtual table that indexes WOF place names for `match` queries.
|
|
12
|
+
*/
|
|
13
|
+
export const PLACE_SEARCH_TABLE = "place_search"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The separator between aliases in the `alt_names` bag.
|
|
17
|
+
* It stops a phrase query from matching across two aliases.
|
|
18
|
+
*
|
|
19
|
+
* FTS5 assigns positions only to tokens.
|
|
20
|
+
* Spaces and punctuation are not tokens and would leave the aliases adjacent,
|
|
21
|
+
* but unicode61 indexes the Private Use Area codepoint U+E000 as a token.
|
|
22
|
+
*
|
|
23
|
+
* Query sanitizers strip this character, so no user query can match the separator.
|
|
24
|
+
*/
|
|
25
|
+
export const ALIAS_SEPARATOR = "\uE000"
|
|
26
|
+
|
|
27
|
+
const ALIAS_SEPARATOR_CODEPOINT = ALIAS_SEPARATOR.codePointAt(0) as number
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Folds a query or name for exact-tier comparison by lowercasing, trimming
|
|
31
|
+
* and collapsing internal whitespace.
|
|
32
|
+
*
|
|
33
|
+
* Every exact-tier consumer uses this function, so its output compares equal to
|
|
34
|
+
* the aliases that {@link aliasBagExactMatch} parses.
|
|
35
|
+
*/
|
|
36
|
+
export function foldQueryText(input: string): string {
|
|
37
|
+
return input.toLowerCase().trim().replaceAll(/\s+/g, " ")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns whether any alias in an `alt_names` bag exactly equals the folded query.
|
|
42
|
+
*
|
|
43
|
+
* A bag without {@link ALIAS_SEPARATOR} is a legacy space-joined bag without alias boundaries.
|
|
44
|
+
* For such a bag, the function checks word-bounded containment only when no candidate matched strictly.
|
|
45
|
+
*
|
|
46
|
+
* Containment by itself would promote fragments such as "York" inside "New York City".
|
|
47
|
+
*
|
|
48
|
+
* @param altNames The `alt_names` bag from `place_search`, or null when the row has no aliases.
|
|
49
|
+
* @param normalizedQuery The query folded by {@link foldQueryText}.
|
|
50
|
+
* @param anyStrictExact Whether any candidate already matched on its canonical name or region abbreviation.
|
|
51
|
+
* Only legacy bags use it.
|
|
52
|
+
*/
|
|
53
|
+
export function aliasBagExactMatch(altNames: string | null, normalizedQuery: string, anyStrictExact: boolean): boolean {
|
|
54
|
+
if (!altNames || altNames === "" || !normalizedQuery) return false
|
|
55
|
+
|
|
56
|
+
if (altNames.includes(ALIAS_SEPARATOR)) {
|
|
57
|
+
return altNames.split(ALIAS_SEPARATOR).some((alias) => foldQueryText(alias) === normalizedQuery)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (anyStrictExact) return false
|
|
61
|
+
|
|
62
|
+
return ` ${foldQueryText(altNames)} `.includes(` ${normalizedQuery} `)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The name of the R*Tree virtual table that indexes WOF place bounding boxes for bbox and proximity lookups.
|
|
67
|
+
*/
|
|
68
|
+
export const PLACE_BBOX_TABLE = "place_bbox"
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The name of the sparse table that stores `wof:population` per place.
|
|
72
|
+
*
|
|
73
|
+
* The lookup uses this value to apply the population ranking boost.
|
|
74
|
+
*
|
|
75
|
+
* A place without a row gets no boost and no penalty.
|
|
76
|
+
*/
|
|
77
|
+
export const PLACE_POPULATION_TABLE = "place_population"
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The name of the table of per-place `referential` and `encyclopedic` scores,
|
|
81
|
+
* built by `mailwoman gazetteer importance`.
|
|
82
|
+
*
|
|
83
|
+
* The lookup copies `encyclopedic` onto results without ranking by it.
|
|
84
|
+
* It refuses to read an older table with a single `importance` column.
|
|
85
|
+
*/
|
|
86
|
+
export const PLACE_IMPORTANCE_TABLE = "place_importance"
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The indexes a {@link buildPlaceSearchFTS} run built and their row counts.
|
|
90
|
+
*/
|
|
91
|
+
export interface BuildPlaceSearchFTSResult {
|
|
92
|
+
/**
|
|
93
|
+
* Whether this call built the FTS5 index.
|
|
94
|
+
* It is false when an existing index was kept.
|
|
95
|
+
*/
|
|
96
|
+
created: boolean
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The row count of the `place_search` table after the call.
|
|
100
|
+
*/
|
|
101
|
+
indexedRows: number
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Whether this call built the R*Tree bbox index.
|
|
105
|
+
* It is false when an existing index was kept.
|
|
106
|
+
*/
|
|
107
|
+
bboxCreated: boolean
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The row count of the `place_bbox` R*Tree after the call.
|
|
111
|
+
*/
|
|
112
|
+
bboxIndexedRows: number
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The wall-clock duration of the whole build in milliseconds.
|
|
116
|
+
*/
|
|
117
|
+
durationMs: number
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Options for {@link buildPlaceSearchFTS}.
|
|
122
|
+
*/
|
|
123
|
+
export interface BuildPlaceSearchFTSOpts {
|
|
124
|
+
/**
|
|
125
|
+
* Whether to drop and rebuild existing `place_search` and `place_bbox` tables,
|
|
126
|
+
* such as after an `spr` or `names` update.
|
|
127
|
+
* By default an existing index is kept.
|
|
128
|
+
*/
|
|
129
|
+
drop?: boolean
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Receives each build phase as it begins.
|
|
133
|
+
* A planet-scale build takes minutes to populate.
|
|
134
|
+
*/
|
|
135
|
+
onProgress?: (
|
|
136
|
+
phase: "checking" | "dropping" | "creating" | "populating" | "creating-bbox" | "populating-bbox" | "done",
|
|
137
|
+
detail?: string
|
|
138
|
+
) => void
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Builds the `place_search` FTS5 table and the `place_bbox` R*Tree from a WOF
|
|
143
|
+
* database's `spr` and `names` tables.
|
|
144
|
+
*
|
|
145
|
+
* Without `drop: true`, an existing index is kept.
|
|
146
|
+
*/
|
|
147
|
+
export function buildPlaceSearchFTS<DB>(
|
|
148
|
+
db: DatabaseClient<DB>,
|
|
149
|
+
opts: BuildPlaceSearchFTSOpts = {}
|
|
150
|
+
): BuildPlaceSearchFTSResult {
|
|
151
|
+
const start = Date.now()
|
|
152
|
+
const onProgress = opts.onProgress ?? (() => {})
|
|
153
|
+
|
|
154
|
+
onProgress("checking")
|
|
155
|
+
const ftsExisting = tableExists(db, PLACE_SEARCH_TABLE)
|
|
156
|
+
const bboxExisting = tableExists(db, PLACE_BBOX_TABLE)
|
|
157
|
+
|
|
158
|
+
let ftsCreated = false
|
|
159
|
+
|
|
160
|
+
if (ftsExisting && opts.drop) {
|
|
161
|
+
onProgress("dropping", PLACE_SEARCH_TABLE)
|
|
162
|
+
db.exec(`DROP TABLE ${PLACE_SEARCH_TABLE}`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!ftsExisting || opts.drop) {
|
|
166
|
+
onProgress("creating")
|
|
167
|
+
|
|
168
|
+
db.exec(`
|
|
169
|
+
CREATE VIRTUAL TABLE ${PLACE_SEARCH_TABLE} USING fts5(
|
|
170
|
+
wof_id UNINDEXED,
|
|
171
|
+
name,
|
|
172
|
+
alt_names,
|
|
173
|
+
tokenize = 'unicode61 remove_diacritics 2'
|
|
174
|
+
);
|
|
175
|
+
`)
|
|
176
|
+
|
|
177
|
+
onProgress("populating")
|
|
178
|
+
|
|
179
|
+
db.exec(`
|
|
180
|
+
INSERT INTO ${PLACE_SEARCH_TABLE} (wof_id, name, alt_names)
|
|
181
|
+
SELECT
|
|
182
|
+
spr.id,
|
|
183
|
+
spr.name,
|
|
184
|
+
COALESCE((
|
|
185
|
+
SELECT GROUP_CONCAT(
|
|
186
|
+
REPLACE(name, char(${ALIAS_SEPARATOR_CODEPOINT}), ' '),
|
|
187
|
+
' ' || char(${ALIAS_SEPARATOR_CODEPOINT}) || ' '
|
|
188
|
+
) || ' ' || char(${ALIAS_SEPARATOR_CODEPOINT})
|
|
189
|
+
FROM names WHERE names.id = spr.id
|
|
190
|
+
), '')
|
|
191
|
+
FROM spr
|
|
192
|
+
WHERE spr.is_current != 0
|
|
193
|
+
AND spr.is_deprecated = 0
|
|
194
|
+
AND spr.name IS NOT NULL;
|
|
195
|
+
`)
|
|
196
|
+
|
|
197
|
+
ftsCreated = true
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const ftsCountRow = db.prepare(`SELECT COUNT(*) AS n FROM ${PLACE_SEARCH_TABLE}`).get() as { n: number }
|
|
201
|
+
|
|
202
|
+
let bboxCreated = false
|
|
203
|
+
|
|
204
|
+
if (bboxExisting && opts.drop) {
|
|
205
|
+
onProgress("dropping", PLACE_BBOX_TABLE)
|
|
206
|
+
db.exec(`DROP TABLE ${PLACE_BBOX_TABLE}`)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (!bboxExisting || opts.drop) {
|
|
210
|
+
onProgress("creating-bbox")
|
|
211
|
+
|
|
212
|
+
db.exec(`
|
|
213
|
+
CREATE VIRTUAL TABLE ${PLACE_BBOX_TABLE} USING rtree(
|
|
214
|
+
id,
|
|
215
|
+
min_lat, max_lat,
|
|
216
|
+
min_lon, max_lon
|
|
217
|
+
);
|
|
218
|
+
`)
|
|
219
|
+
|
|
220
|
+
onProgress("populating-bbox")
|
|
221
|
+
|
|
222
|
+
db.exec(`
|
|
223
|
+
INSERT INTO ${PLACE_BBOX_TABLE} (id, min_lat, max_lat, min_lon, max_lon)
|
|
224
|
+
SELECT
|
|
225
|
+
spr.id,
|
|
226
|
+
spr.min_latitude,
|
|
227
|
+
spr.max_latitude,
|
|
228
|
+
spr.min_longitude,
|
|
229
|
+
spr.max_longitude
|
|
230
|
+
FROM spr
|
|
231
|
+
WHERE spr.is_current != 0
|
|
232
|
+
AND spr.is_deprecated = 0
|
|
233
|
+
AND spr.min_latitude IS NOT NULL
|
|
234
|
+
AND spr.max_latitude IS NOT NULL
|
|
235
|
+
AND spr.min_longitude IS NOT NULL
|
|
236
|
+
AND spr.max_longitude IS NOT NULL
|
|
237
|
+
AND NOT (spr.min_latitude = 0 AND spr.max_latitude = 0
|
|
238
|
+
AND spr.min_longitude = 0 AND spr.max_longitude = 0);
|
|
239
|
+
`)
|
|
240
|
+
|
|
241
|
+
bboxCreated = true
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const bboxCountRow = db.prepare(`SELECT COUNT(*) AS n FROM ${PLACE_BBOX_TABLE}`).get() as { n: number }
|
|
245
|
+
|
|
246
|
+
onProgress(
|
|
247
|
+
"done",
|
|
248
|
+
`${ftsCountRow.n} FTS rows + ${bboxCountRow.n} bbox rows ` +
|
|
249
|
+
`(${ftsCreated ? "built" : "preexisting"} / ${bboxCreated ? "built" : "preexisting"})`
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
created: ftsCreated,
|
|
254
|
+
indexedRows: ftsCountRow.n,
|
|
255
|
+
bboxCreated,
|
|
256
|
+
bboxIndexedRows: bboxCountRow.n,
|
|
257
|
+
durationMs: Date.now() - start,
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Returns whether the connected database has the `place_search` FTS table.
|
|
263
|
+
*/
|
|
264
|
+
export function placeSearchFTSExists<DB>(db: DatabaseClient<DB>): boolean {
|
|
265
|
+
return tableExists(db, PLACE_SEARCH_TABLE)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Returns whether the connected database has the `place_bbox` R*Tree table.
|
|
270
|
+
*/
|
|
271
|
+
export function placeBboxExists<DB>(db: DatabaseClient<DB>): boolean {
|
|
272
|
+
return tableExists(db, PLACE_BBOX_TABLE)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Returns whether the connected database has the `place_population` table.
|
|
277
|
+
*/
|
|
278
|
+
export function placePopulationExists<DB>(db: DatabaseClient<DB>): boolean {
|
|
279
|
+
return tableExists(db, PLACE_POPULATION_TABLE)
|
|
280
|
+
}
|