@mailwoman/resolver-wof-sqlite 10.0.0 → 10.1.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 +8 -8
- package/lib/address/point/interpolation.ts +39 -37
- package/lib/address/point/schema.ts +17 -40
- package/lib/address/point.ts +315 -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 +123 -165
- package/lib/build/population-corrections.ts +64 -0
- package/lib/build/slim.ts +43 -113
- 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 +64 -67
- package/lib/candidate/lookup.ts +78 -382
- package/lib/candidate/name-roles.ts +15 -33
- package/lib/candidate/own-name.ts +34 -31
- package/lib/candidate/place-attrs.ts +20 -13
- package/lib/candidate/schema.ts +29 -65
- package/lib/candidate/scoring.ts +30 -69
- package/lib/capital-schema.ts +21 -17
- package/lib/capitals.ts +26 -24
- package/lib/coincident-roles.ts +74 -55
- package/lib/convention/schema.ts +13 -7
- package/lib/convention.ts +144 -0
- package/lib/coverage-manifest-schema.ts +34 -39
- package/lib/currency-backfill.ts +22 -67
- package/lib/env.ts +1 -1
- package/lib/exact-match.ts +31 -20
- package/lib/extracts.ts +96 -73
- package/lib/fst/autocomplete.ts +52 -35
- package/lib/fst/builder.ts +30 -36
- package/lib/fst/deserialize-web.ts +8 -9
- package/lib/fst/format.ts +41 -23
- package/lib/fst/freshness.ts +17 -95
- package/lib/fst/matcher.ts +2 -2
- package/lib/fst/serialize.ts +45 -60
- package/lib/fst/types.ts +71 -59
- package/lib/fts/query.ts +5 -36
- package/lib/fts.ts +280 -0
- package/lib/geonames/aliases.ts +71 -142
- package/lib/geonames/postal.ts +161 -70
- package/lib/index.ts +6 -6
- package/lib/interpolation.ts +43 -96
- package/lib/lookup.ts +132 -253
- package/lib/name-score.ts +9 -7
- package/lib/nsul/lookup.ts +36 -53
- package/lib/nsul/schema.ts +16 -43
- package/lib/paths.ts +159 -0
- package/lib/place-importance-schema.ts +57 -164
- package/lib/poi/lookup.ts +100 -109
- 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 +9 -19
- package/lib/primary-preference.ts +44 -124
- package/lib/proximity-rerank.ts +43 -32
- package/lib/ranking-weights.ts +98 -76
- package/lib/region-keys.ts +68 -40
- package/lib/reverse.ts +108 -72
- package/lib/schema.ts +74 -42
- package/lib/search-fetch.ts +90 -68
- package/lib/sqlite/convention-source.ts +12 -20
- package/lib/sqlite/utils.ts +18 -21
- package/lib/street/centroid/schema.ts +37 -42
- package/lib/street/{centroid/index.ts → centroid.ts} +15 -24
- package/lib/street/morphology/fst/builder.ts +50 -41
- package/lib/street/morphology/fst/loader.ts +35 -28
- package/lib/street/name-lookup.ts +43 -35
- package/lib/street/normalize.ts +85 -216
- package/lib/street/segment-schema.ts +116 -43
- package/lib/{street/index.ts → street.ts} +1 -1
- package/lib/types.ts +94 -140
- package/lib/unified-schema.ts +29 -29
- package/lib/uprn/existence.ts +30 -19
- package/lib/uprn/lookup.ts +28 -67
- package/lib/uprn/schema.ts +18 -40
- package/lib/weights-overlay-linker.ts +204 -232
- package/out/address/point/interpolation.d.ts +19 -23
- package/out/address/point/interpolation.d.ts.map +1 -1
- package/out/address/point/interpolation.js +37 -37
- 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 +56 -0
- package/out/address/point.d.ts.map +1 -0
- package/out/address/point.js +205 -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 +87 -107
- package/out/build/candidate.d.ts.map +1 -1
- package/out/build/candidate.js +19 -95
- 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 +32 -93
- 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 +55 -62
- package/out/candidate/importance.js.map +1 -1
- package/out/candidate/lookup.d.ts +11 -51
- package/out/candidate/lookup.d.ts.map +1 -1
- package/out/candidate/lookup.js +48 -361
- 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 +34 -31
- 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 +30 -69
- 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 +26 -24
- 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 +61 -50
- package/out/coincident-roles.js.map +1 -1
- package/out/convention/schema.d.ts +12 -6
- 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 +33 -38
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +20 -29
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +11 -33
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +12 -39
- 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 +31 -20
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +65 -54
- 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 +28 -20
- package/out/fst/autocomplete.d.ts.map +1 -1
- package/out/fst/autocomplete.js +38 -27
- package/out/fst/autocomplete.js.map +1 -1
- package/out/fst/builder.d.ts.map +1 -1
- package/out/fst/builder.js +30 -36
- package/out/fst/builder.js.map +1 -1
- package/out/fst/deserialize-web.d.ts +3 -3
- package/out/fst/deserialize-web.d.ts.map +1 -1
- package/out/fst/deserialize-web.js +8 -9
- 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 +11 -73
- package/out/fst/freshness.d.ts.map +1 -1
- package/out/fst/freshness.js +12 -76
- package/out/fst/freshness.js.map +1 -1
- package/out/fst/matcher.d.ts +1 -1
- package/out/fst/matcher.js +2 -2
- package/out/fst/matcher.js.map +1 -1
- package/out/fst/serialize.d.ts +30 -26
- package/out/fst/serialize.d.ts.map +1 -1
- package/out/fst/serialize.js +44 -58
- package/out/fst/serialize.js.map +1 -1
- package/out/fst/types.d.ts +71 -59
- 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} +1 -1
- package/out/fst.d.ts.map +1 -0
- package/out/{fst/index.d.ts → fst.js} +1 -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 +43 -115
- 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 +114 -72
- 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 +6 -6
- package/out/index.d.ts.map +1 -1
- package/out/index.js +5 -5
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +15 -52
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +25 -68
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +22 -51
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +114 -220
- 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 +49 -141
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +25 -140
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/lookup.d.ts +38 -42
- package/out/poi/lookup.d.ts.map +1 -1
- package/out/poi/lookup.js +67 -90
- 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 +9 -19
- 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 +13 -97
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +40 -29
- 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 +91 -62
- 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 +48 -29
- 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 +75 -50
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +61 -49
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +74 -42
- 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 +11 -15
- package/out/sqlite/convention-source.d.ts.map +1 -1
- package/out/sqlite/convention-source.js +11 -20
- package/out/sqlite/convention-source.js.map +1 -1
- package/out/sqlite/utils.d.ts +18 -18
- 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} +12 -23
- 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 +34 -33
- package/out/street/morphology/fst/builder.js.map +1 -1
- package/out/street/morphology/fst/loader.d.ts +32 -25
- package/out/street/morphology/fst/loader.d.ts.map +1 -1
- package/out/street/morphology/fst/loader.js +19 -19
- 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 +32 -31
- 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 +74 -191
- 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 +69 -138
- 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 +20 -56
- 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 +132 -141
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +86 -154
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +88 -593
- 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/{fst/index.ts → fst.ts} +0 -0
- /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/build/candidate.ts
CHANGED
|
@@ -2,48 +2,16 @@
|
|
|
2
2
|
* @copyright Sister Software
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
|
-
*
|
|
6
|
-
* Build the global "candidate" lookup DB from a unified admin WOF DB — the byte-range-optimal
|
|
7
|
-
* gazetteer the browser demo resolves against. Instead of FTS5 (whose postings for a common name
|
|
8
|
-
* scatter across a multi-GB file → hundreds of serial range fetches), this materializes one
|
|
9
|
-
* `WITHOUT ROWID` B-tree keyed `(name_key, country_id, region_id, placetype_id, neg_rank,
|
|
10
|
-
* spr_id)`: every place's normalized name + distinct aliases + region abbreviations become rows,
|
|
11
|
-
* population rank is precomputed into `neg_rank`, and the rows are bulk-loaded PRE-SORTED so a
|
|
12
|
-
* resolve is one contiguous B-tree probe (a handful of pages → 1-2 chunk fetches, regardless of
|
|
13
|
-
* global volume).
|
|
14
|
-
*
|
|
15
|
-
* Each row is DENORMALIZED — it carries the place's display `name`, centroid (`latitude`/
|
|
16
|
-
* `longitude`), and `min/max` bbox — so a resolve is one statement, no FTS, no join to spr:
|
|
17
|
-
* SELECT spr_id, name, latitude, longitude, min_lat, ... FROM candidate WHERE name_key = ? AND
|
|
18
|
-
* country_id = ? AND placetype_id IN (...) [AND latitude BETWEEN ...] ORDER BY neg_rank ASC LIMIT
|
|
19
|
-
* K; The demo cascade resolves a parsed region first (its bbox), then constrains the locality to
|
|
20
|
-
* that bbox; `region_id` (the place's region-tier ancestor) is also carried for a future region
|
|
21
|
-
* 2-step.
|
|
22
|
-
*
|
|
23
|
-
* The name_key normalizer is the SHARED {@link normalizeLocalityForKey} — the query side (the demo
|
|
24
|
-
* resolver {@link WOFCandidateTableLookup}) MUST use the same function, the one-normalizer
|
|
25
|
-
* discipline the address-point extract uses, so build/query stay consistent by construction.
|
|
26
|
-
*
|
|
27
|
-
* Measured (2026-06-20, vs the 2.6 GB full-DB FTS): ~5 M rows; ~12 range fetches per 8-query
|
|
28
|
-
* session (the full DB needs 243); US locality 96.8% (region bbox), EU coord parity 88.6%.
|
|
29
|
-
*
|
|
30
|
-
* #28 adds one more denormalized field, `importance` — the toponym-fame prior that decides a BARE
|
|
31
|
-
* city name, joined in from a separate score source by name rather than by id (see
|
|
32
|
-
* `candidate-importance.ts`, which owns that join and explains why the id would be wrong). It is
|
|
33
|
-
* optional: without {@link BuildCandidateOptions.importance} the column is NULL on every row, which
|
|
34
|
-
* the consumer reads as unmeasured and ignores.
|
|
35
|
-
*
|
|
36
|
-
* The build also materializes the ANCESTORS SIDECAR (`candidate_ancestor` closure rows +
|
|
37
|
-
* `candidate_interval` pre/post labels) from the source `ancestors` table — the containment
|
|
38
|
-
* lineage behind {@link WOFCandidateTableLookup.ancestors} and the admin-coherence check.
|
|
39
|
-
* `candidate-ancestors-schema.ts` owns the encoding decision and the DAG/absence semantics.
|
|
40
5
|
*/
|
|
41
6
|
|
|
42
7
|
import { COUNTRY_POPULATION } from "@mailwoman/codex/country"
|
|
43
8
|
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
44
9
|
import { removePath } from "@mailwoman/core/fs/writers"
|
|
10
|
+
import { stringifyJSON } from "@mailwoman/core/json"
|
|
45
11
|
import { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
12
|
+
import type { PathBuilderLike } from "path-ts"
|
|
46
13
|
|
|
14
|
+
import { POPULATION_CORRECTIONS } from "#build/population-corrections"
|
|
47
15
|
import { explodeAliasBags } from "#candidate/alias-bags"
|
|
48
16
|
import { buildAncestorsSidecar } from "#candidate/ancestors/sidecar"
|
|
49
17
|
import { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
@@ -64,158 +32,190 @@ import { resurrectCurrencyHoles } from "#currency-backfill"
|
|
|
64
32
|
import type { WOFDatabase } from "#schema"
|
|
65
33
|
import { normalizeLocalityForKey } from "#street/normalize"
|
|
66
34
|
|
|
67
|
-
|
|
68
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Re-exports the country display-name staging pass from the candidate build's public module.
|
|
37
|
+
*/
|
|
69
38
|
export { stageCountryDisplayNames } from "#candidate/country-display-names"
|
|
39
|
+
/**
|
|
40
|
+
* Re-exports the gloss detector's excluded placetypes and default key-count threshold.
|
|
41
|
+
*/
|
|
70
42
|
export { GLOSS_EXCLUDED_PLACETYPES, GLOSS_KEY_THRESHOLD } from "#candidate/name-roles"
|
|
43
|
+
/**
|
|
44
|
+
* Re-exports the per-place record that every candidate staging pass writes its rows from.
|
|
45
|
+
*/
|
|
71
46
|
export type { PlaceAttrs } from "#candidate/place-attrs"
|
|
72
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Options for {@link buildCandidateTable}.
|
|
50
|
+
*/
|
|
73
51
|
export interface BuildCandidateOptions {
|
|
74
52
|
/**
|
|
75
|
-
*
|
|
53
|
+
* The source WOF admin database.
|
|
54
|
+
*
|
|
55
|
+
* It must have the `spr`, `place_population`, `place_search`, `place_abbr` and `ancestors` tables.
|
|
76
56
|
*/
|
|
77
|
-
input:
|
|
57
|
+
input: PathBuilderLike
|
|
58
|
+
|
|
78
59
|
/**
|
|
79
|
-
*
|
|
60
|
+
* The candidate database to write, replacing any existing file.
|
|
80
61
|
*/
|
|
81
|
-
output:
|
|
62
|
+
output: PathBuilderLike
|
|
63
|
+
|
|
82
64
|
/**
|
|
83
|
-
* The capital
|
|
84
|
-
*
|
|
85
|
-
*
|
|
65
|
+
* The capital reference entries to store in the artifact's `capital` table.
|
|
66
|
+
*
|
|
67
|
+
* The caller supplies these entries because this published module cannot read repository paths.
|
|
68
|
+
* The builder creates no `capital` table when the caller omits them.
|
|
69
|
+
*
|
|
70
|
+
* The capital loader then falls back to the repository's `capitals-v1.json`.
|
|
86
71
|
*/
|
|
87
72
|
capitals?: readonly CapitalPoint[]
|
|
73
|
+
|
|
88
74
|
/**
|
|
89
|
-
*
|
|
90
|
-
* in as `postalcode` candidate rows so `findPlace(postalcode)` resolves a ZIP directly (the demo's primary postcode
|
|
91
|
-
* path; the postcode-*.bin anchor stays the fallback). Matches the slim wof-hot.db, which took one such postcode DB.
|
|
75
|
+
* Postcode extract databases whose located `spr` rows become `postalcode` candidate rows.
|
|
92
76
|
*
|
|
93
|
-
* Each extract's `names` table
|
|
94
|
-
* ("Brooklyn" for 11201), and they were previously reachable only through FTS.
|
|
77
|
+
* Each extract's `names` table becomes aliases, such as the delivery city "Brooklyn" for 11201.
|
|
95
78
|
*/
|
|
96
|
-
postcodes?:
|
|
79
|
+
postcodes?: readonly PathBuilderLike[]
|
|
80
|
+
|
|
97
81
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
82
|
+
* Locality extract databases whose located `spr` rows become `locality`
|
|
83
|
+
* candidate rows with zero population.
|
|
84
|
+
*
|
|
85
|
+
* Their `names` tables become non-primary aliases.
|
|
86
|
+
* When an extract's `ancestors` table gives a row's region, the row gets
|
|
87
|
+
* that region's scope and closure rows.
|
|
88
|
+
* Other rows stay unscoped.
|
|
105
89
|
*/
|
|
106
|
-
localities?:
|
|
90
|
+
localities?: readonly PathBuilderLike[]
|
|
91
|
+
|
|
107
92
|
/**
|
|
108
|
-
*
|
|
109
|
-
* toponym-fame prior that decides the bare-city-name class. Joined by `(name_key, country, placetype)` + nearest
|
|
110
|
-
* centroid, NOT by id; see `candidate-importance.ts` for why the id join silently drops the foreign homonyms the
|
|
111
|
-
* prior exists to demote.
|
|
93
|
+
* A WOF admin database with a `place_importance` table supplies the `importance` column.
|
|
112
94
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* population-derived stand-in written into a column that means fame.
|
|
95
|
+
* Rows join on name key, country and placetype, then on the nearest centroid.
|
|
96
|
+
* Without this option every row's `importance` is NULL.
|
|
97
|
+
* Consumers treat NULL as unmeasured.
|
|
117
98
|
*/
|
|
118
|
-
importance?:
|
|
99
|
+
importance?: PathBuilderLike
|
|
100
|
+
|
|
119
101
|
/**
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* Kent); an independent GeoNames P-class attestation of the same folded name within
|
|
126
|
-
* {@link CURRENCY_BACKFILL_RADIUS_KM}; and the attestor at or above {@link CURRENCY_BACKFILL_POP_FLOOR}. The staged
|
|
127
|
-
* row keeps the real WOF id, name, centroid and bbox — GeoNames only ATTESTS the place and supplies the population
|
|
128
|
-
* that lets it stand in prominence races. `countries` are judged only where `<cc>.txt` exists under `geonamesDir`;
|
|
129
|
-
* absent dumps are skipped loudly.
|
|
102
|
+
* Settings for restoring deprecated WOF places that have no successor and have a GeoNames attestation.
|
|
103
|
+
*
|
|
104
|
+
* A deprecated place is restored only when no live row of the same name lies within 10 km and
|
|
105
|
+
* a GeoNames populated place with the same folded name and at least 1,000 people lies within 10 km.
|
|
106
|
+
* Countries without `<cc>.txt` under `geonamesDir` are skipped and reported.
|
|
130
107
|
*/
|
|
131
108
|
currencyBackfill?: {
|
|
132
|
-
geonamesDir:
|
|
109
|
+
geonamesDir: PathBuilderLike
|
|
133
110
|
countries: readonly string[]
|
|
111
|
+
|
|
134
112
|
/**
|
|
135
|
-
* The
|
|
136
|
-
*
|
|
113
|
+
* The deprecated placetypes eligible for restoration.
|
|
114
|
+
* The default is `locality`.
|
|
137
115
|
*/
|
|
138
116
|
deadPlacetypes?: readonly string[]
|
|
139
117
|
}
|
|
118
|
+
|
|
140
119
|
/**
|
|
141
|
-
*
|
|
120
|
+
* Receives a phase name and a message as each build step runs.
|
|
142
121
|
*/
|
|
143
122
|
onProgress?: (phase: string, message: string) => void
|
|
123
|
+
|
|
144
124
|
/**
|
|
145
|
-
*
|
|
146
|
-
*
|
|
125
|
+
* The key-count threshold for the gloss anomaly detector.
|
|
126
|
+
* The default is {@link GLOSS_KEY_THRESHOLD}.
|
|
127
|
+
*
|
|
128
|
+
* Tests override it with a value sized for fixtures.
|
|
147
129
|
*/
|
|
148
130
|
glossKeyThreshold?: number
|
|
149
131
|
}
|
|
150
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Row and place counts from each stage of {@link buildCandidateTable}.
|
|
135
|
+
*/
|
|
151
136
|
export interface BuildCandidateResult {
|
|
152
137
|
rows: number
|
|
153
138
|
places: number
|
|
154
139
|
primaries: number
|
|
155
140
|
aliases: number
|
|
141
|
+
|
|
156
142
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
143
|
+
* The count of region aliases dropped because another region in the same
|
|
144
|
+
* country uses the name as its official name.
|
|
145
|
+
*
|
|
146
|
+
* The count is always zero for a source without a `names` table.
|
|
160
147
|
*/
|
|
161
148
|
regionOfficialRefused: number
|
|
162
149
|
abbrevs: number
|
|
163
150
|
postcodes: number
|
|
151
|
+
|
|
164
152
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* through `onProgress`.
|
|
153
|
+
* The count of aliases added to postcode rows from the extracts' `names` tables.
|
|
154
|
+
*
|
|
155
|
+
* An extract without a `names` table is reported through `onProgress`.
|
|
168
156
|
*/
|
|
169
157
|
postcodeAliases: number
|
|
158
|
+
|
|
170
159
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
160
|
+
* The count of closure rows written to the `candidate_ancestor` sidecar,
|
|
161
|
+
* including rows from locality extracts.
|
|
173
162
|
*/
|
|
174
163
|
ancestorRows: number
|
|
164
|
+
|
|
175
165
|
/**
|
|
176
|
-
*
|
|
166
|
+
* The count of places with at least one closure row.
|
|
177
167
|
*/
|
|
178
168
|
ancestorPlaces: number
|
|
169
|
+
|
|
179
170
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
171
|
+
* The count of places that received a pre/post interval label.
|
|
172
|
+
* It equals the node count of the canonical-parent forest.
|
|
173
|
+
*
|
|
174
|
+
* Containment against a place outside the forest is unknown.
|
|
183
175
|
*/
|
|
184
176
|
intervalPlaces: number
|
|
177
|
+
|
|
185
178
|
/**
|
|
186
|
-
*
|
|
179
|
+
* The count of places that received an `importance` score.
|
|
187
180
|
*
|
|
188
|
-
*
|
|
189
|
-
* would be the source matching NOTHING, which is a finding. Never collapse the two.
|
|
181
|
+
* It is `undefined` when no score source was given.
|
|
190
182
|
*/
|
|
191
183
|
importanceScored?: number
|
|
184
|
+
|
|
192
185
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
186
|
+
* The count of places that matched a scored group by name key, country and placetype
|
|
187
|
+
* but whose nearest scored centroid lay beyond {@link IMPORTANCE_JOIN_RADIUS_KM}.
|
|
195
188
|
*
|
|
196
|
-
*
|
|
197
|
-
* join is being asked to guess.
|
|
189
|
+
* A large change between rebuilds means the score source and the admin source have diverged.
|
|
198
190
|
*/
|
|
199
191
|
importanceFiltered?: number
|
|
192
|
+
|
|
200
193
|
/**
|
|
201
|
-
*
|
|
194
|
+
* The count of alias rows the gloss anomaly detector stamped `name_role = 'gloss'`.
|
|
202
195
|
*/
|
|
203
196
|
roleGloss: number
|
|
197
|
+
|
|
204
198
|
/**
|
|
205
|
-
*
|
|
199
|
+
* The count of alias rows stamped `name_role = 'abbr'`, which marks a variant in the official language.
|
|
206
200
|
*/
|
|
207
201
|
roleAbbr: number
|
|
202
|
+
|
|
208
203
|
/**
|
|
209
|
-
*
|
|
210
|
-
*
|
|
204
|
+
* The count of admin places whose staged key count reached the gloss key threshold.
|
|
205
|
+
* It is the denominator for `keyTailWithRole`.
|
|
211
206
|
*/
|
|
212
207
|
keyTailPlaces: number
|
|
208
|
+
|
|
213
209
|
/**
|
|
214
|
-
*
|
|
210
|
+
* The count of places in `keyTailPlaces` with at least one stamped role row.
|
|
215
211
|
*/
|
|
216
212
|
keyTailWithRole: number
|
|
217
213
|
}
|
|
218
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Builds the candidate lookup database from a WOF admin database and replaces any existing output.
|
|
217
|
+
* The builder adds an FTS5 trigram index for fuzzy lookup.
|
|
218
|
+
*/
|
|
219
219
|
export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<BuildCandidateResult> {
|
|
220
220
|
const progress = opts.onProgress ?? (() => {})
|
|
221
221
|
|
|
@@ -224,15 +224,12 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
using src = new DatabaseClient<WOFDatabase>(opts.input, { readOnly: true })
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// staging table come from the SHARED schema DDL, so they can't drift from {@link CandidateDatabase}.
|
|
227
|
+
using kdb = new DatabaseClient<CandidateDatabase>(opts.output)
|
|
228
|
+
|
|
230
229
|
kdb.exec("PRAGMA page_size=8192; PRAGMA journal_mode=OFF; PRAGMA synchronous=OFF; PRAGMA cache_size=-2000000;")
|
|
231
230
|
|
|
232
231
|
await createCandidateStagingTables(kdb)
|
|
233
232
|
|
|
234
|
-
// Build compact country and placetype code maps for clustered keys.
|
|
235
|
-
// assigned here; the rows are bulk-inserted via kdb once the passes have discovered every code. ---
|
|
236
233
|
const ccodes = new Map<string, number>()
|
|
237
234
|
const ptcodes = new Map<string, number>()
|
|
238
235
|
|
|
@@ -260,8 +257,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
260
257
|
return id
|
|
261
258
|
}
|
|
262
259
|
|
|
263
|
-
// Load the importance source before the only pass that sees each place.
|
|
264
|
-
// name/country/placetype/centroid together. Absent → every row's `importance` stays NULL. ---
|
|
265
260
|
let importance: ReturnType<typeof loadImportanceIndex> | undefined
|
|
266
261
|
|
|
267
262
|
if (opts.importance) {
|
|
@@ -274,23 +269,13 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
274
269
|
(importance.stats.unkeyable ? `; ${importance.stats.unkeyable.toLocaleString()} unkeyable names skipped` : "")
|
|
275
270
|
)
|
|
276
271
|
} else {
|
|
277
|
-
// Never a silent column of nulls: a build without a score source produces one, and the reason has
|
|
278
|
-
// to be visible in the log rather than inferred from the artifact.
|
|
279
272
|
progress("importance", "no score source given — `importance` will be NULL on every row")
|
|
280
273
|
}
|
|
281
274
|
|
|
282
|
-
// Derive each place's region ancestor for same-name disambiguation.
|
|
283
275
|
progress("region", "loading region ancestry")
|
|
284
276
|
const regionOf = new Map<number, number>()
|
|
285
277
|
let multiRegion = 0
|
|
286
278
|
|
|
287
|
-
// A place can carry more than one region-tier ancestor — 59 do on the 2026-08-03 artifact (42
|
|
288
|
-
// localities, mostly Chinese places on an ambiguous boundary). One `region_id` column holds one of
|
|
289
|
-
// them, and which one it ought to be is a real question this is not the place to answer.
|
|
290
|
-
//
|
|
291
|
-
// MIN is arbitrary but STABLE: an unordered pick lets the stamp for those places differ between two
|
|
292
|
-
// builds of the same source. The count is logged because the number is expected to grow, and should
|
|
293
|
-
// be visible rather than inferred.
|
|
294
279
|
for (const r of src
|
|
295
280
|
.prepare(
|
|
296
281
|
"SELECT id, MIN(ancestor_id) AS ancestor_id, COUNT(DISTINCT ancestor_id) AS n" +
|
|
@@ -310,12 +295,8 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
310
295
|
(multiRegion ? ` (${multiRegion.toLocaleString()} carry more than one; stamped with the lowest id)` : "")
|
|
311
296
|
)
|
|
312
297
|
|
|
313
|
-
// The hot path — millions of clustered rows. Kept a single positional prepared statement (the fastest
|
|
314
|
-
// node:sqlite insert) rather than a per-row query builder. Placeholders come from CANDIDATE_COLUMNS so
|
|
315
|
-
// the column COUNT can't drift; the positional run() args below MUST stay in CANDIDATE_COLUMNS order.
|
|
316
298
|
const insStage = kdb.prepare(`INSERT INTO cand_stage VALUES (${CANDIDATE_COLUMNS.map(() => "?").join(", ")})`)
|
|
317
299
|
|
|
318
|
-
// Stage primary names and attributes reused by later alias passes.
|
|
319
300
|
progress("primaries", "indexing place names")
|
|
320
301
|
const attrs = new Map<number, PlaceAttrs>()
|
|
321
302
|
let nPrim = 0
|
|
@@ -326,7 +307,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
326
307
|
`SELECT s.id AS id, s.name AS name, s.placetype AS placetype, s.country AS country,
|
|
327
308
|
s.latitude AS lat, s.longitude AS lon,
|
|
328
309
|
s.min_latitude AS mnlat, s.min_longitude AS mnlon, s.max_latitude AS mxlat, s.max_longitude AS mxlon,
|
|
329
|
-
|
|
310
|
+
pp.population AS pop
|
|
330
311
|
FROM spr s LEFT JOIN place_population pp ON pp.id = s.id
|
|
331
312
|
WHERE s.is_current != 0 AND s.is_deprecated = 0`
|
|
332
313
|
)
|
|
@@ -335,13 +316,14 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
335
316
|
const cid = ccID(r.country as string | null)
|
|
336
317
|
const ptid = ptID(r.placetype as string | null)
|
|
337
318
|
const rid = regionOf.get(sid) ?? 0
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
319
|
+
|
|
320
|
+
const wofPop = r.pop === null || r.pop === undefined ? null : Number(r.pop)
|
|
321
|
+
|
|
322
|
+
const pop =
|
|
323
|
+
POPULATION_CORRECTIONS[sid]?.population ??
|
|
324
|
+
(wofPop === null && r.placetype === "country" ? (COUNTRY_POPULATION[String(r.country ?? "")] ?? null) : wofPop)
|
|
325
|
+
|
|
326
|
+
const neg = -Math.log10((pop ?? 0) + 1)
|
|
345
327
|
const name = String(r.name ?? "")
|
|
346
328
|
const pkey = normalizeLocalityForKey(name)
|
|
347
329
|
const lat = r.lat as number
|
|
@@ -424,9 +406,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
424
406
|
)
|
|
425
407
|
}
|
|
426
408
|
|
|
427
|
-
// Stage country display names across scripts.
|
|
428
|
-
// Never a silent zero: a runtime whose ICU lacks these locales degrades to fewer surfaces, and the count is how a
|
|
429
|
-
// reader tells that apart from the pass not having run.
|
|
430
409
|
progress(
|
|
431
410
|
"country-display-names",
|
|
432
411
|
`${stageCountryDisplayNames({
|
|
@@ -438,8 +417,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
438
417
|
}).toLocaleString()} country surfaces`
|
|
439
418
|
)
|
|
440
419
|
|
|
441
|
-
// Backfill cross-source currency before later candidate passes.
|
|
442
|
-
// the alias pass so a resurrected place's alt names explode like any primary's. ---
|
|
443
420
|
if (opts.currencyBackfill) {
|
|
444
421
|
const nBackfill = await resurrectCurrencyHoles({
|
|
445
422
|
src,
|
|
@@ -458,12 +435,9 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
458
435
|
|
|
459
436
|
progress("currency-backfill", `${nBackfill.toLocaleString()} resurrections staged`)
|
|
460
437
|
} else {
|
|
461
|
-
// Never a silent absence: a build without the option leaves the deprecated-no-successor holes dead,
|
|
462
|
-
// and the log must say so rather than leave it inferable only from a missing row.
|
|
463
438
|
progress("currency-backfill", "not configured — deprecated-no-successor holes stay dead (#1737)")
|
|
464
439
|
}
|
|
465
440
|
|
|
466
|
-
// Stage distinct normalized aliases from alternate names.
|
|
467
441
|
progress("aliases", "exploding alias bags")
|
|
468
442
|
|
|
469
443
|
const { nAlias, keyCounts, regionOfficialRefused } = explodeAliasBags(src, kdb, attrs, stageRow, {
|
|
@@ -479,7 +453,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
479
453
|
: "")
|
|
480
454
|
)
|
|
481
455
|
|
|
482
|
-
// Stage region abbreviations.
|
|
483
456
|
let nAbbr = 0
|
|
484
457
|
kdb.exec("BEGIN")
|
|
485
458
|
|
|
@@ -498,9 +471,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
498
471
|
kdb.exec("COMMIT")
|
|
499
472
|
progress("abbrevs", `${nAbbr.toLocaleString()} abbrevs`)
|
|
500
473
|
|
|
501
|
-
// Stamp each name's semantic role.
|
|
502
|
-
// Independent of the sidecar below: this writes `cand_stage.name_role`, that writes the ancestor and
|
|
503
|
-
// interval tables, and neither reads the other's output. Ordered by label only.
|
|
504
474
|
const roles = stampNameRoles({
|
|
505
475
|
src,
|
|
506
476
|
out: kdb,
|
|
@@ -512,10 +482,8 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
512
482
|
progress,
|
|
513
483
|
})
|
|
514
484
|
|
|
515
|
-
// Stage the encoded ancestors sidecar.
|
|
516
485
|
const sidecar = await buildAncestorsSidecar({ src, out: kdb, attrs, ptID, progress })
|
|
517
486
|
|
|
518
|
-
// Fold postcode and locality extracts into candidate records.
|
|
519
487
|
let nPostcode = 0
|
|
520
488
|
let nPostcodeAlias = 0
|
|
521
489
|
|
|
@@ -569,7 +537,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
569
537
|
)
|
|
570
538
|
}
|
|
571
539
|
|
|
572
|
-
// Insert the small typed code dictionaries through Kysely.
|
|
573
540
|
if (ccodes.size) {
|
|
574
541
|
await kdb
|
|
575
542
|
.insertInto("country_codes")
|
|
@@ -584,7 +551,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
584
551
|
.execute()
|
|
585
552
|
}
|
|
586
553
|
|
|
587
|
-
// Insert the small typed capital-status reference table.
|
|
588
554
|
if (opts.capitals?.length) {
|
|
589
555
|
await createCapitalTable<CandidateDatabase>(kdb)
|
|
590
556
|
|
|
@@ -596,7 +562,7 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
596
562
|
latitude: entry.latitude,
|
|
597
563
|
longitude: entry.longitude,
|
|
598
564
|
level: entry.level,
|
|
599
|
-
keys:
|
|
565
|
+
keys: stringifyJSON(entry.k),
|
|
600
566
|
}))
|
|
601
567
|
)
|
|
602
568
|
.execute()
|
|
@@ -604,25 +570,18 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
604
570
|
progress("capitals", `${opts.capitals.length.toLocaleString()} capital-reference rows carried in-artifact`)
|
|
605
571
|
}
|
|
606
572
|
|
|
607
|
-
// Materialize the clustered WITHOUT ROWID table in sorted order.
|
|
608
573
|
progress("cluster", "building clustered candidate table + VACUUM")
|
|
609
|
-
|
|
610
|
-
// KEY) so the SELECT, the ORDER BY, and the table can't drift. The table comes from the shared
|
|
611
|
-
// createCandidateTable().
|
|
574
|
+
|
|
612
575
|
const cols = CANDIDATE_COLUMNS.join(", ")
|
|
613
576
|
const keyOrder = CANDIDATE_COLUMNS.slice(0, 6).join(", ")
|
|
614
577
|
await createCandidateTable(kdb)
|
|
615
|
-
|
|
616
|
-
// row. The bulk sorted INSERT…SELECT (clustered materialization) stays raw — a single hot bulk statement.
|
|
578
|
+
|
|
617
579
|
kdb.exec(`INSERT OR IGNORE INTO candidate (${cols}) SELECT ${cols} FROM cand_stage ORDER BY ${keyOrder};`)
|
|
618
580
|
await kdb.schema.dropTable("cand_stage").execute()
|
|
619
|
-
|
|
620
|
-
// recover misspellings, so FTS5-trigram over `name` lets the reader fuzzy-match on an exact+strip miss.
|
|
581
|
+
|
|
621
582
|
progress("fts", "building FTS5-trigram fuzzy index")
|
|
622
583
|
createCandidateFTS(kdb)
|
|
623
|
-
|
|
624
|
-
// `new DatabaseSync`, so the creation-time pragma is a no-op — only a VACUUM rebuilds at the new size.
|
|
625
|
-
// 8192 matches the sql.js-httpvfs 64 KiB request chunk cleanly (8 pages) and shallows the B-tree.
|
|
584
|
+
|
|
626
585
|
kdb.exec("PRAGMA page_size=8192")
|
|
627
586
|
kdb.exec("VACUUM")
|
|
628
587
|
|
|
@@ -631,7 +590,6 @@ export async function buildCandidateTable(opts: BuildCandidateOptions): Promise<
|
|
|
631
590
|
.select((eb) => eb.fn.countAll<number>().as("n"))
|
|
632
591
|
.executeTakeFirstOrThrow()
|
|
633
592
|
|
|
634
|
-
// closes the underlying `out` connection
|
|
635
593
|
return {
|
|
636
594
|
rows,
|
|
637
595
|
places: attrs.size,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file Populations the gazetteer records at a fraction of their size, corrected against the record's own concordance.
|
|
6
|
+
*
|
|
7
|
+
* This file records corrections for review. The build must not rewrite populations from a
|
|
8
|
+
* same-name-parent ratio. The detector cannot distinguish a district's mis-recorded namesake
|
|
9
|
+
* city from a small village with the district name. Both places are real.
|
|
10
|
+
*
|
|
11
|
+
* Each entry identifies one row that a reviewer checked against a second source.
|
|
12
|
+
* The row's own `gn:id` must agree with the coordinates. The GeoNames record must identify the same place.
|
|
13
|
+
*
|
|
14
|
+
* The correction applies to the candidate artifact rather than the admin gazetteer.
|
|
15
|
+
* `place_population` in `admin-global-priority.db` still stores the WOF figure, so a reader going
|
|
16
|
+
* there sees WOF's value and a reader going to `candidate.db` sees the corroborated number. The
|
|
17
|
+
* admin database is a transcription of its source, so correcting it there would make the
|
|
18
|
+
* transcription disagree with what it transcribes.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* One corrected population, with what corroborates it.
|
|
23
|
+
*/
|
|
24
|
+
export interface PopulationCorrection {
|
|
25
|
+
/**
|
|
26
|
+
* The GeoNames id from the WOF record's own `concordances` row makes this a
|
|
27
|
+
* correction rather than a substitution.
|
|
28
|
+
*
|
|
29
|
+
* The two sources describe the same place according to WOF.
|
|
30
|
+
*/
|
|
31
|
+
geonamesID: string
|
|
32
|
+
population: number
|
|
33
|
+
/**
|
|
34
|
+
* What the gazetteer recorded, kept so a reader can see the size of the
|
|
35
|
+
* disagreement without opening the artifact.
|
|
36
|
+
*/
|
|
37
|
+
recorded: number
|
|
38
|
+
/**
|
|
39
|
+
* The place and the reviewer's reading.
|
|
40
|
+
*/
|
|
41
|
+
note: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* WOF id → the corrected population.
|
|
46
|
+
*
|
|
47
|
+
* One entry, because one row has been followed.
|
|
48
|
+
* A second correction requires the same review.
|
|
49
|
+
*
|
|
50
|
+
* Read the row's `gn:id` and confirm the coordinates agree.
|
|
51
|
+
* Then record the second source's value.
|
|
52
|
+
*/
|
|
53
|
+
export const POPULATION_CORRECTIONS: Readonly<Record<number, PopulationCorrection>> = {
|
|
54
|
+
102_030_887: {
|
|
55
|
+
geonamesID: "1278149",
|
|
56
|
+
population: 1_175_116,
|
|
57
|
+
recorded: 19_172,
|
|
58
|
+
note:
|
|
59
|
+
"Aurangabad (Chhatrapati Sambhaji Nagar), Maharashtra. The WOF record sits at 19.870 / 75.349 and GeoNames " +
|
|
60
|
+
"1278149 — the id that record's own concordance names — sits at 19.878 / 75.342, about 1 km apart, classed " +
|
|
61
|
+
"`PPLA2`. WOF's 19,172 against its parent district's 3,701,282 is the 193x ratio that surfaced it; the " +
|
|
62
|
+
"corroborated figure makes the city 32% of its district rather than 0.5% of it.",
|
|
63
|
+
},
|
|
64
|
+
}
|