@mailwoman/resolver-wof-sqlite 10.1.0 → 10.2.1
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 +1 -0
- package/lib/address/point/interpolation.ts +6 -2
- package/lib/address/point.ts +15 -14
- package/lib/build/candidate.ts +11 -21
- package/lib/build/slim.ts +1 -1
- package/lib/candidate/importance.ts +1 -1
- package/lib/candidate/lookup.ts +47 -34
- package/lib/candidate/own-name.ts +1 -1
- package/lib/candidate/scoring.ts +29 -29
- package/lib/capitals.ts +3 -3
- package/lib/coincident-roles.ts +15 -4
- package/lib/convention/schema.ts +2 -9
- package/lib/convention.ts +7 -7
- package/lib/coverage-manifest-schema.ts +6 -6
- package/lib/currency-backfill.ts +13 -13
- package/lib/exact-match.ts +1 -1
- package/lib/extracts.ts +1 -1
- package/lib/fst/autocomplete.ts +2 -2
- package/lib/fst/builder.ts +9 -7
- package/lib/fst/deserialize-web.ts +8 -8
- package/lib/fst/freshness.ts +27 -26
- package/lib/fst/matcher.ts +5 -3
- package/lib/fst/serialize.ts +12 -17
- package/lib/fst/types.ts +14 -23
- package/lib/fst.ts +1 -0
- package/lib/fts.ts +1 -1
- package/lib/geonames/aliases.ts +3 -3
- package/lib/geonames/postal.ts +1 -1
- package/lib/index.ts +3 -2
- package/lib/interpolation.ts +7 -6
- package/lib/lookup.ts +26 -20
- package/lib/nsul/lookup.ts +1 -1
- package/lib/place-importance-schema.ts +5 -5
- package/lib/poi/lookup.ts +13 -21
- package/lib/postcode-point-lookup.ts +1 -10
- package/lib/primary-preference.ts +2 -2
- package/lib/proximity-rerank.ts +1 -1
- package/lib/ranking-weights.ts +15 -10
- package/lib/region-keys.ts +2 -2
- package/lib/reverse.ts +45 -18
- package/lib/schema.ts +3 -12
- package/lib/sqlite/convention-source.ts +3 -3
- package/lib/sqlite/utils.ts +1 -1
- package/lib/street/centroid.ts +1 -1
- package/lib/street/morphology/fst/builder.ts +16 -7
- package/lib/street/morphology/fst/loader.ts +8 -7
- package/lib/street/name-lookup.ts +4 -8
- package/lib/street/normalize.ts +3 -3
- package/lib/street/segment-schema.ts +2 -2
- package/lib/types.ts +17 -12
- package/lib/uprn/lookup.ts +1 -1
- package/lib/weights-overlay-linker.ts +38 -26
- package/out/address/point/interpolation.d.ts +1 -0
- package/out/address/point/interpolation.d.ts.map +1 -1
- package/out/address/point/interpolation.js +5 -2
- package/out/address/point/interpolation.js.map +1 -1
- package/out/address/point.d.ts +5 -4
- package/out/address/point.d.ts.map +1 -1
- package/out/address/point.js +11 -10
- package/out/address/point.js.map +1 -1
- package/out/build/candidate.d.ts +7 -17
- package/out/build/candidate.d.ts.map +1 -1
- package/out/build/candidate.js +4 -11
- package/out/build/candidate.js.map +1 -1
- package/out/build/slim.js +1 -1
- package/out/build/slim.js.map +1 -1
- package/out/candidate/importance.js +1 -1
- package/out/candidate/importance.js.map +1 -1
- package/out/candidate/lookup.d.ts +8 -5
- package/out/candidate/lookup.d.ts.map +1 -1
- package/out/candidate/lookup.js +35 -25
- package/out/candidate/lookup.js.map +1 -1
- package/out/candidate/own-name.js +1 -1
- package/out/candidate/own-name.js.map +1 -1
- package/out/candidate/scoring.js +27 -25
- package/out/candidate/scoring.js.map +1 -1
- package/out/capitals.d.ts +1 -1
- package/out/capitals.d.ts.map +1 -1
- package/out/capitals.js.map +1 -1
- package/out/coincident-roles.d.ts +4 -4
- package/out/coincident-roles.d.ts.map +1 -1
- package/out/coincident-roles.js +11 -0
- package/out/coincident-roles.js.map +1 -1
- package/out/convention/schema.d.ts +2 -8
- package/out/convention/schema.d.ts.map +1 -1
- package/out/convention/schema.js.map +1 -1
- package/out/convention.d.ts +4 -4
- package/out/convention.d.ts.map +1 -1
- package/out/convention.js +3 -3
- package/out/convention.js.map +1 -1
- package/out/coverage-manifest-schema.d.ts +1 -1
- package/out/coverage-manifest-schema.d.ts.map +1 -1
- package/out/coverage-manifest-schema.js +5 -5
- package/out/coverage-manifest-schema.js.map +1 -1
- package/out/currency-backfill.d.ts +6 -6
- package/out/currency-backfill.d.ts.map +1 -1
- package/out/currency-backfill.js +7 -7
- package/out/currency-backfill.js.map +1 -1
- package/out/exact-match.js +1 -1
- package/out/exact-match.js.map +1 -1
- package/out/extracts.d.ts +1 -1
- package/out/extracts.d.ts.map +1 -1
- package/out/extracts.js.map +1 -1
- package/out/fst/autocomplete.d.ts +1 -1
- package/out/fst/autocomplete.d.ts.map +1 -1
- package/out/fst/autocomplete.js +1 -1
- package/out/fst/autocomplete.js.map +1 -1
- package/out/fst/builder.d.ts.map +1 -1
- package/out/fst/builder.js +9 -7
- package/out/fst/builder.js.map +1 -1
- package/out/fst/deserialize-web.d.ts +1 -1
- package/out/fst/deserialize-web.d.ts.map +1 -1
- package/out/fst/deserialize-web.js +7 -7
- package/out/fst/deserialize-web.js.map +1 -1
- package/out/fst/freshness.d.ts +9 -9
- package/out/fst/freshness.d.ts.map +1 -1
- package/out/fst/freshness.js +19 -18
- package/out/fst/freshness.js.map +1 -1
- package/out/fst/matcher.d.ts +4 -3
- package/out/fst/matcher.d.ts.map +1 -1
- package/out/fst/matcher.js.map +1 -1
- package/out/fst/serialize.d.ts +1 -5
- package/out/fst/serialize.d.ts.map +1 -1
- package/out/fst/serialize.js +11 -15
- package/out/fst/serialize.js.map +1 -1
- package/out/fst/types.d.ts +14 -22
- package/out/fst/types.d.ts.map +1 -1
- package/out/fst.d.ts +1 -0
- package/out/fst.d.ts.map +1 -1
- package/out/fst.js +1 -0
- package/out/fst.js.map +1 -1
- package/out/fts.js +1 -1
- package/out/fts.js.map +1 -1
- package/out/geonames/aliases.d.ts +1 -1
- package/out/geonames/aliases.d.ts.map +1 -1
- package/out/geonames/aliases.js +2 -2
- package/out/geonames/aliases.js.map +1 -1
- package/out/geonames/postal.js +1 -1
- package/out/geonames/postal.js.map +1 -1
- package/out/index.d.ts +3 -2
- package/out/index.d.ts.map +1 -1
- package/out/index.js +1 -0
- package/out/index.js.map +1 -1
- package/out/interpolation.d.ts +4 -4
- package/out/interpolation.d.ts.map +1 -1
- package/out/interpolation.js +4 -3
- package/out/interpolation.js.map +1 -1
- package/out/lookup.d.ts +4 -3
- package/out/lookup.d.ts.map +1 -1
- package/out/lookup.js +22 -14
- package/out/lookup.js.map +1 -1
- package/out/nsul/lookup.js.map +1 -1
- package/out/place-importance-schema.d.ts +2 -2
- package/out/place-importance-schema.d.ts.map +1 -1
- package/out/place-importance-schema.js +3 -3
- package/out/place-importance-schema.js.map +1 -1
- package/out/poi/lookup.d.ts +10 -13
- package/out/poi/lookup.d.ts.map +1 -1
- package/out/poi/lookup.js +3 -7
- package/out/poi/lookup.js.map +1 -1
- package/out/postcode-point-lookup.d.ts +1 -9
- package/out/postcode-point-lookup.d.ts.map +1 -1
- package/out/postcode-point-lookup.js.map +1 -1
- package/out/primary-preference.js +2 -2
- package/out/primary-preference.js.map +1 -1
- package/out/proximity-rerank.d.ts +1 -1
- package/out/proximity-rerank.d.ts.map +1 -1
- package/out/ranking-weights.d.ts +15 -10
- package/out/ranking-weights.d.ts.map +1 -1
- package/out/ranking-weights.js.map +1 -1
- package/out/region-keys.d.ts +2 -2
- package/out/region-keys.d.ts.map +1 -1
- package/out/region-keys.js.map +1 -1
- package/out/reverse.d.ts +7 -4
- package/out/reverse.d.ts.map +1 -1
- package/out/reverse.js +38 -13
- package/out/reverse.js.map +1 -1
- package/out/schema.d.ts +2 -11
- package/out/schema.d.ts.map +1 -1
- package/out/sqlite/convention-source.d.ts +1 -1
- package/out/sqlite/convention-source.d.ts.map +1 -1
- package/out/sqlite/convention-source.js +2 -2
- package/out/sqlite/convention-source.js.map +1 -1
- package/out/sqlite/utils.d.ts +1 -1
- package/out/sqlite/utils.d.ts.map +1 -1
- package/out/street/centroid.js +1 -1
- package/out/street/centroid.js.map +1 -1
- package/out/street/morphology/fst/builder.d.ts +3 -3
- package/out/street/morphology/fst/builder.d.ts.map +1 -1
- package/out/street/morphology/fst/builder.js +13 -4
- package/out/street/morphology/fst/builder.js.map +1 -1
- package/out/street/morphology/fst/loader.d.ts +4 -4
- package/out/street/morphology/fst/loader.d.ts.map +1 -1
- package/out/street/morphology/fst/loader.js +4 -3
- package/out/street/morphology/fst/loader.js.map +1 -1
- package/out/street/name-lookup.d.ts +2 -2
- package/out/street/name-lookup.d.ts.map +1 -1
- package/out/street/name-lookup.js +2 -4
- package/out/street/name-lookup.js.map +1 -1
- package/out/street/normalize.js +3 -3
- package/out/street/normalize.js.map +1 -1
- package/out/street/segment-schema.d.ts +2 -2
- package/out/street/segment-schema.js +2 -2
- package/out/types.d.ts +16 -12
- package/out/types.d.ts.map +1 -1
- package/out/uprn/lookup.js +1 -1
- package/out/uprn/lookup.js.map +1 -1
- package/out/weights-overlay-linker.d.ts +9 -6
- package/out/weights-overlay-linker.d.ts.map +1 -1
- package/out/weights-overlay-linker.js +21 -7
- package/out/weights-overlay-linker.js.map +1 -1
- package/package.json +13 -13
|
@@ -146,8 +146,8 @@ export async function writeGazetteerCoverageManifest(
|
|
|
146
146
|
facts.coverage.map((f) => ({
|
|
147
147
|
country: f.country.toUpperCase(),
|
|
148
148
|
hard_filter_safe: f.hardFilterSafe ? 1 : 0,
|
|
149
|
-
hard_resolve_rate: f.hardResolveRate
|
|
150
|
-
sample_size: f.sampleSize
|
|
149
|
+
hard_resolve_rate: f.hardResolveRate,
|
|
150
|
+
sample_size: f.sampleSize,
|
|
151
151
|
measured_at: f.measuredAt,
|
|
152
152
|
source: f.source,
|
|
153
153
|
}))
|
|
@@ -180,11 +180,11 @@ export async function writeGazetteerCoverageManifest(
|
|
|
180
180
|
*
|
|
181
181
|
* The reads are synchronous because the candidate lookup calls this from its constructor.
|
|
182
182
|
*/
|
|
183
|
-
export function readGazetteerCoverageManifest<DB>(db: DatabaseClient<DB>): GazetteerArtifactCoverage |
|
|
183
|
+
export function readGazetteerCoverageManifest<DB>(db: DatabaseClient<DB>): GazetteerArtifactCoverage | null {
|
|
184
184
|
const hasCoverage = hasTable(db, COUNTRY_COVERAGE_TABLE)
|
|
185
185
|
const hasBBox = hasTable(db, COUNTRY_BBOX_TABLE)
|
|
186
186
|
|
|
187
|
-
if (!hasCoverage && !hasBBox) return
|
|
187
|
+
if (!hasCoverage && !hasBBox) return null
|
|
188
188
|
|
|
189
189
|
const countryCoverage = new Map<string, CountryCoverageFact>()
|
|
190
190
|
|
|
@@ -201,8 +201,8 @@ export function readGazetteerCoverageManifest<DB>(db: DatabaseClient<DB>): Gazet
|
|
|
201
201
|
countryCoverage.set(country, {
|
|
202
202
|
country,
|
|
203
203
|
hardFilterSafe: Number(row.hard_filter_safe) !== 0,
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
hardResolveRate: row.hard_resolve_rate === null ? null : Number(row.hard_resolve_rate),
|
|
205
|
+
sampleSize: row.sample_size === null ? null : Number(row.sample_size),
|
|
206
206
|
measuredAt: String(row.measured_at),
|
|
207
207
|
source: String(row.source),
|
|
208
208
|
})
|
package/lib/currency-backfill.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Restores deprecated WOF localities only when an independent source attests them.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
9
|
+
import { pathExists } from "@mailwoman/core/fs/readers/stat"
|
|
10
10
|
import { isStrictlyFiner } from "@mailwoman/core/resources/whosonfirst"
|
|
11
11
|
import { haversineKm } from "@mailwoman/spatial"
|
|
12
12
|
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
@@ -27,7 +27,7 @@ const CURRENCY_BACKFILL_POP_FLOOR = 1000
|
|
|
27
27
|
* Restore a deprecated locality only when no nearby live namesake exists and GeoNames
|
|
28
28
|
* attests the same folded name above {@link CURRENCY_BACKFILL_POP_FLOOR}.
|
|
29
29
|
*/
|
|
30
|
-
export interface
|
|
30
|
+
export interface CurrencyBackfillResults {
|
|
31
31
|
judged: number
|
|
32
32
|
blocked: number
|
|
33
33
|
unattested: number
|
|
@@ -36,14 +36,14 @@ export interface CurrencyBackfillOutcomes {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* One country's read of the check — every dead name judged, by
|
|
39
|
+
* One country's read of the check — every dead name judged, by result and by the dead
|
|
40
40
|
* row's placetype — so a census can say what a wider query admits.
|
|
41
41
|
*/
|
|
42
|
-
export interface CurrencyBackfillCountryReport extends
|
|
42
|
+
export interface CurrencyBackfillCountryReport extends CurrencyBackfillResults {
|
|
43
43
|
country: string
|
|
44
44
|
deadPlacetypes: readonly string[]
|
|
45
45
|
dumpPresent: boolean
|
|
46
|
-
byDeadPlacetype: Record<string,
|
|
46
|
+
byDeadPlacetype: Record<string, CurrencyBackfillResults>
|
|
47
47
|
/**
|
|
48
48
|
* The first resurrected names, `placetype:name`, capped because the report is a receipt and not the table.
|
|
49
49
|
*/
|
|
@@ -57,7 +57,7 @@ const REPORT_SAMPLE_SIZE = 25
|
|
|
57
57
|
*/
|
|
58
58
|
export const DEFAULT_DEAD_PLACETYPES: readonly string[] = ["locality"]
|
|
59
59
|
|
|
60
|
-
function
|
|
60
|
+
function emptyResults(): CurrencyBackfillResults {
|
|
61
61
|
return { judged: 0, blocked: 0, unattested: 0, floored: 0, resurrected: 0 }
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -73,7 +73,7 @@ export async function resurrectCurrencyHoles(ctx: {
|
|
|
73
73
|
ccID: (code: string | null) => number
|
|
74
74
|
ptID: (pt: string | null) => number
|
|
75
75
|
regionOf: Map<number, number>
|
|
76
|
-
importance: ReturnType<typeof loadImportanceIndex> |
|
|
76
|
+
importance: ReturnType<typeof loadImportanceIndex> | null
|
|
77
77
|
stageRow: StageRow
|
|
78
78
|
progress: (phase: string, message: string) => void
|
|
79
79
|
|
|
@@ -83,7 +83,7 @@ export async function resurrectCurrencyHoles(ctx: {
|
|
|
83
83
|
*/
|
|
84
84
|
dryRun?: boolean
|
|
85
85
|
/**
|
|
86
|
-
* Receives one report per country judged (a country with no dump or no dead rows reports zero
|
|
86
|
+
* Receives one report per country judged (a country with no dump or no dead rows reports zero results).
|
|
87
87
|
*/
|
|
88
88
|
onCountry?: (report: CurrencyBackfillCountryReport) => void
|
|
89
89
|
}): Promise<number> {
|
|
@@ -117,7 +117,7 @@ export async function resurrectCurrencyHoles(ctx: {
|
|
|
117
117
|
country: cc,
|
|
118
118
|
deadPlacetypes,
|
|
119
119
|
dumpPresent: await pathExists(dumpPath),
|
|
120
|
-
...
|
|
120
|
+
...emptyResults(),
|
|
121
121
|
byDeadPlacetype: {},
|
|
122
122
|
sample: [],
|
|
123
123
|
}
|
|
@@ -180,11 +180,11 @@ export async function resurrectCurrencyHoles(ctx: {
|
|
|
180
180
|
|
|
181
181
|
const seen = new Set<string>()
|
|
182
182
|
|
|
183
|
-
const count = (deadPlacetype: string,
|
|
184
|
-
report[
|
|
185
|
-
const bucket = (report.byDeadPlacetype[deadPlacetype] ??=
|
|
183
|
+
const count = (deadPlacetype: string, result: keyof CurrencyBackfillResults): void => {
|
|
184
|
+
report[result] += 1
|
|
185
|
+
const bucket = (report.byDeadPlacetype[deadPlacetype] ??= emptyResults())
|
|
186
186
|
|
|
187
|
-
bucket[
|
|
187
|
+
bucket[result] += 1
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
if (!dryRun) {
|
package/lib/exact-match.ts
CHANGED
package/lib/extracts.ts
CHANGED
|
@@ -213,7 +213,7 @@ export function pickExtractsForPlacetype(
|
|
|
213
213
|
*/
|
|
214
214
|
export function pickExtractForPlacetype(
|
|
215
215
|
extracts: ResolvedExtract[],
|
|
216
|
-
placetype: string |
|
|
216
|
+
placetype: string | null,
|
|
217
217
|
opts?: {
|
|
218
218
|
/**
|
|
219
219
|
* The query's country constraint, when the caller has one.
|
package/lib/fst/autocomplete.ts
CHANGED
|
@@ -54,7 +54,7 @@ export interface AutocompleteSuggestion {
|
|
|
54
54
|
* `undefined` means no article, or a pre-v5 binary.
|
|
55
55
|
* It is never 0.
|
|
56
56
|
*/
|
|
57
|
-
encyclopedic
|
|
57
|
+
encyclopedic: number | null
|
|
58
58
|
wofID: number
|
|
59
59
|
parentChain: number[]
|
|
60
60
|
matchDepth: number
|
|
@@ -182,7 +182,7 @@ export function autocomplete(fst: FSTMatcher, query: string, opts: AutocompleteO
|
|
|
182
182
|
name: entry.name,
|
|
183
183
|
placetype: entry.placetype,
|
|
184
184
|
referential: entry.referential,
|
|
185
|
-
|
|
185
|
+
encyclopedic: entry.encyclopedic,
|
|
186
186
|
wofID: s.id,
|
|
187
187
|
parentChain: s.parentIDs,
|
|
188
188
|
matchDepth: s.matchDepth,
|
package/lib/fst/builder.ts
CHANGED
|
@@ -234,7 +234,7 @@ export async function buildFSTFromWOF(opts: BuildFSTOpts): Promise<{
|
|
|
234
234
|
|
|
235
235
|
if (excludeSurfaces?.has(tokens.join(" "))) return true
|
|
236
236
|
|
|
237
|
-
if (excludeAllTokensOf
|
|
237
|
+
if (excludeAllTokensOf && tokens.every((t) => excludeAllTokensOf.has(t))) return true
|
|
238
238
|
|
|
239
239
|
return false
|
|
240
240
|
}
|
|
@@ -272,7 +272,7 @@ export async function buildFSTFromWOF(opts: BuildFSTOpts): Promise<{
|
|
|
272
272
|
const existing = nodes[stateID]!.places
|
|
273
273
|
|
|
274
274
|
if (!existing.some((p) => p.wofID === entry.wofID && p.placetype === entry.placetype)) {
|
|
275
|
-
if (surfaceCountryCounts
|
|
275
|
+
if (surfaceCountryCounts) {
|
|
276
276
|
const count = surfaceCountryCounts.get(tokens.join(" "))
|
|
277
277
|
existing.push({ ...entry, crossCountryBranches: Math.min(count ?? 1, 255) })
|
|
278
278
|
} else {
|
|
@@ -296,11 +296,12 @@ export async function buildFSTFromWOF(opts: BuildFSTOpts): Promise<{
|
|
|
296
296
|
name: row.name,
|
|
297
297
|
parentChain,
|
|
298
298
|
referential: split.referential.get(row.id) ?? 0,
|
|
299
|
-
//
|
|
300
|
-
// The serializer's per-place presence bit reads `!==
|
|
301
|
-
|
|
299
|
+
// A place with no Wikipedia article is `null` rather than a zero.
|
|
300
|
+
// The serializer's per-place presence bit reads `!== null`.
|
|
301
|
+
encyclopedic: encyclopedic ?? null,
|
|
302
302
|
lat: row.latitude,
|
|
303
303
|
lon: row.longitude,
|
|
304
|
+
crossCountryBranches: null,
|
|
304
305
|
}
|
|
305
306
|
|
|
306
307
|
const primaryTokens = normalizeTokens(row.name)
|
|
@@ -352,9 +353,10 @@ export async function buildFSTFromWOF(opts: BuildFSTOpts): Promise<{
|
|
|
352
353
|
sourceDB: dbPath,
|
|
353
354
|
sourceDBMD5: source.md5,
|
|
354
355
|
sourceDBBytes: source.bytes,
|
|
355
|
-
|
|
356
|
+
modelCardVersion: null,
|
|
357
|
+
...(excludeSurfaces || excludeAllTokensOf
|
|
356
358
|
? { exclusionPolicy: opts.exclusionPolicy ?? "unspecified", excludedInsertions: excludedCount }
|
|
357
|
-
: {}),
|
|
359
|
+
: { exclusionPolicy: null, excludedInsertions: null }),
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
return {
|
|
@@ -143,8 +143,8 @@ export function deserializeFSTWeb(input: ArrayBuffer | Uint8Array): FSTMatcher {
|
|
|
143
143
|
lat: view.getFloat32(pp + 16, true),
|
|
144
144
|
lon: view.getFloat32(pp + 20, true),
|
|
145
145
|
parentChain,
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
crossCountryBranches: hasAmbiguity ? view.getUint8(pp + 6) : null,
|
|
147
|
+
encyclopedic: hasEncyclopedic ? view.getFloat32(pp + ENCYCLOPEDIC_OFFSET, true) : null,
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -154,25 +154,25 @@ export function deserializeFSTWeb(input: ArrayBuffer | Uint8Array): FSTMatcher {
|
|
|
154
154
|
return FSTMatcher.fromNodes(nodes)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
export function readFSTProvenanceWeb(input: ArrayBuffer | Uint8Array): FSTProvenance |
|
|
157
|
+
export function readFSTProvenanceWeb(input: ArrayBuffer | Uint8Array): FSTProvenance | null {
|
|
158
158
|
const bytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input
|
|
159
159
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
160
160
|
const decoder = new TextDecoder("utf-8")
|
|
161
161
|
|
|
162
|
-
if (bytes.byteLength < HEADER_SIZE) return
|
|
162
|
+
if (bytes.byteLength < HEADER_SIZE) return null
|
|
163
163
|
const version = view.getUint16(4, true)
|
|
164
164
|
|
|
165
|
-
if (version < VERSION_WITH_METADATA) return
|
|
165
|
+
if (version < VERSION_WITH_METADATA) return null
|
|
166
166
|
const provenanceOffset = view.getUint32(28, true)
|
|
167
167
|
|
|
168
|
-
if (provenanceOffset === 0 || provenanceOffset >= bytes.byteLength) return
|
|
168
|
+
if (provenanceOffset === 0 || provenanceOffset >= bytes.byteLength) return null
|
|
169
169
|
|
|
170
170
|
try {
|
|
171
171
|
const jsonLen = view.getUint32(provenanceOffset, true)
|
|
172
172
|
const jsonStr = decoder.decode(bytes.subarray(provenanceOffset + 4, provenanceOffset + 4 + jsonLen))
|
|
173
173
|
|
|
174
|
-
return tryParsingJSON<FSTProvenance>(jsonStr) ??
|
|
174
|
+
return tryParsingJSON<FSTProvenance>(jsonStr) ?? null
|
|
175
175
|
} catch {
|
|
176
|
-
return
|
|
176
|
+
return null
|
|
177
177
|
}
|
|
178
178
|
}
|
package/lib/fst/freshness.ts
CHANGED
|
@@ -6,13 +6,14 @@
|
|
|
6
6
|
* Does an `fst-*.bin` still match the gazetteer it was built from?
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { readFileRange, readLocalTextFile } from "@mailwoman/core/fs/readers"
|
|
10
|
+
import { pathExists, statPath } from "@mailwoman/core/fs/readers/stat"
|
|
10
11
|
import { writeLocalTextFile } from "@mailwoman/core/fs/writers"
|
|
11
12
|
import { md5File } from "@mailwoman/core/hash"
|
|
12
13
|
import { tryParsingJSON } from "@mailwoman/core/json"
|
|
13
14
|
import { basename, resolvePath, type PathBuilderLike } from "path-ts"
|
|
14
15
|
|
|
15
|
-
import { FST_FORMAT_VERSION } from "#fst/
|
|
16
|
+
import { FST_FORMAT_VERSION } from "#fst/format"
|
|
16
17
|
import type { FSTProvenance } from "#fst/types"
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -48,7 +49,7 @@ export interface FSTSourceIdentity {
|
|
|
48
49
|
*/
|
|
49
50
|
export interface FSTStampFields {
|
|
50
51
|
formatVersion: number
|
|
51
|
-
provenance: FSTProvenance |
|
|
52
|
+
provenance: FSTProvenance | null
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
|
@@ -59,37 +60,37 @@ export interface FSTExpectation {
|
|
|
59
60
|
/**
|
|
60
61
|
* Serializer version to require, defaulting to {@link FST_FORMAT_VERSION}.
|
|
61
62
|
*/
|
|
62
|
-
formatVersion?: number
|
|
63
|
-
exclusionPolicy?: string
|
|
63
|
+
formatVersion?: number | null
|
|
64
|
+
exclusionPolicy?: string | null
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
/**
|
|
67
68
|
* Read an artifact's stamp without deserializing it.
|
|
68
69
|
*/
|
|
69
|
-
export async function peekFSTStampFields(path: PathBuilderLike): Promise<FSTStampFields |
|
|
70
|
-
if (!(await pathExists(path))) return
|
|
70
|
+
export async function peekFSTStampFields(path: PathBuilderLike): Promise<FSTStampFields | null> {
|
|
71
|
+
if (!(await pathExists(path))) return null
|
|
71
72
|
const size = (await statPath(path)).size
|
|
72
73
|
|
|
73
|
-
if (size < HEADER_SIZE) return
|
|
74
|
+
if (size < HEADER_SIZE) return null
|
|
74
75
|
const header = await readFileRange(path, 0, HEADER_SIZE)
|
|
75
76
|
|
|
76
|
-
if (header.readUInt32LE(0) !== MAGIC) return
|
|
77
|
+
if (header.readUInt32LE(0) !== MAGIC) return null
|
|
77
78
|
const formatVersion = header.readUInt16LE(4)
|
|
78
79
|
|
|
79
|
-
if (formatVersion < MIN_STAMPED_FORMAT_VERSION) return { formatVersion, provenance:
|
|
80
|
+
if (formatVersion < MIN_STAMPED_FORMAT_VERSION) return { formatVersion, provenance: null }
|
|
80
81
|
const trailerStart = header.readUInt32LE(PROVENANCE_OFFSET_FIELD)
|
|
81
82
|
|
|
82
83
|
// 0 means this build wrote no trailer and past-EOF means truncated.
|
|
83
84
|
// Both read as no stamp.
|
|
84
|
-
if (trailerStart === 0 || trailerStart + 4 > size) return { formatVersion, provenance:
|
|
85
|
+
if (trailerStart === 0 || trailerStart + 4 > size) return { formatVersion, provenance: null }
|
|
85
86
|
|
|
86
87
|
const jsonLength = (await readFileRange(path, trailerStart, 4)).readUInt32LE(0)
|
|
87
88
|
|
|
88
|
-
if (jsonLength === 0 || trailerStart + 4 + jsonLength > size) return { formatVersion, provenance:
|
|
89
|
+
if (jsonLength === 0 || trailerStart + 4 + jsonLength > size) return { formatVersion, provenance: null }
|
|
89
90
|
|
|
90
91
|
const json = await readFileRange(path, trailerStart + 4, jsonLength)
|
|
91
92
|
|
|
92
|
-
return { formatVersion, provenance: tryParsingJSON<FSTProvenance>(json.toString("utf8")) ??
|
|
93
|
+
return { formatVersion, provenance: tryParsingJSON<FSTProvenance>(json.toString("utf8")) ?? null }
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
/**
|
|
@@ -106,7 +107,7 @@ export async function readWOFSourceIdentity(
|
|
|
106
107
|
|
|
107
108
|
if (hit) return hit
|
|
108
109
|
const sidecarPath = `${path}.md5`
|
|
109
|
-
let md5: string |
|
|
110
|
+
let md5: string | null = null
|
|
110
111
|
|
|
111
112
|
if (await pathExists(sidecarPath)) {
|
|
112
113
|
const sidecarStats = await statPath(sidecarPath)
|
|
@@ -141,9 +142,9 @@ export async function readWOFSourceIdentity(
|
|
|
141
142
|
const sourceIdentityMemo = new Map<string, FSTSourceIdentity>()
|
|
142
143
|
|
|
143
144
|
/**
|
|
144
|
-
* Why an FST artifact is stale against `expected`, or `
|
|
145
|
+
* Why an FST artifact is stale against `expected`, or `null` when it still matches.
|
|
145
146
|
*/
|
|
146
|
-
export function fstStaleReason(fields: FSTStampFields |
|
|
147
|
+
export function fstStaleReason(fields: FSTStampFields | null, expected: FSTExpectation): string | null {
|
|
147
148
|
if (!fields) return "unreadable or not an FST artifact"
|
|
148
149
|
const requiredFormat = expected.formatVersion ?? FST_FORMAT_VERSION
|
|
149
150
|
|
|
@@ -167,15 +168,15 @@ export function fstStaleReason(fields: FSTStampFields | undefined, expected: FST
|
|
|
167
168
|
return `source db ${provenance.sourceDBMD5.slice(0, 8)} → ${expected.source.md5.slice(0, 8)} (built ${provenance.builtAt})`
|
|
168
169
|
}
|
|
169
170
|
|
|
170
|
-
if (provenance.sourceDBBytes
|
|
171
|
+
if (provenance.sourceDBBytes != null && provenance.sourceDBBytes !== expected.source.bytes) {
|
|
171
172
|
return `source db size ${provenance.sourceDBBytes} → ${expected.source.bytes} at a matching md5 — one of the two is misrecorded`
|
|
172
173
|
}
|
|
173
174
|
|
|
174
|
-
if (expected.exclusionPolicy
|
|
175
|
+
if (expected.exclusionPolicy && provenance.exclusionPolicy !== expected.exclusionPolicy) {
|
|
175
176
|
return `exclusion policy ${provenance.exclusionPolicy ?? "(none)"} → ${expected.exclusionPolicy}`
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
return
|
|
179
|
+
return null
|
|
179
180
|
}
|
|
180
181
|
|
|
181
182
|
/**
|
|
@@ -190,19 +191,19 @@ export async function fstFreshnessWarning({
|
|
|
190
191
|
}: {
|
|
191
192
|
fstPath: PathBuilderLike
|
|
192
193
|
sourceDBPath: PathBuilderLike
|
|
193
|
-
formatVersion?: number
|
|
194
|
-
exclusionPolicy?: string
|
|
194
|
+
formatVersion?: number | null
|
|
195
|
+
exclusionPolicy?: string | null
|
|
195
196
|
rebuildCommand: string
|
|
196
|
-
}): Promise<string |
|
|
197
|
-
if (!(await pathExists(fstPath)) || !(await pathExists(sourceDBPath))) return
|
|
197
|
+
}): Promise<string | null> {
|
|
198
|
+
if (!(await pathExists(fstPath)) || !(await pathExists(sourceDBPath))) return null
|
|
198
199
|
|
|
199
200
|
const reason = fstStaleReason(await peekFSTStampFields(fstPath), {
|
|
200
201
|
source: await readWOFSourceIdentity(sourceDBPath),
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
formatVersion: formatVersion ?? null,
|
|
203
|
+
exclusionPolicy: exclusionPolicy ?? null,
|
|
203
204
|
})
|
|
204
205
|
|
|
205
|
-
return reason
|
|
206
|
+
return reason ? formatFSTStaleWarning({ fstPath, reason, rebuildCommand }) : null
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
/**
|
package/lib/fst/matcher.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* arrays at accepting states.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { AncestrieMatch } from "@mailwoman/ancestrie"
|
|
12
|
+
|
|
13
|
+
import type { FSTContinuation, FSTQueryResult, PlaceEntry } from "#fst/types"
|
|
12
14
|
|
|
13
15
|
interface FSTNode {
|
|
14
16
|
edges: Map<string, number>
|
|
@@ -36,7 +38,7 @@ export class FSTMatcher {
|
|
|
36
38
|
return count
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
walk(tokens: string[]):
|
|
41
|
+
walk(tokens: string[]): AncestrieMatch | null {
|
|
40
42
|
let stateID = 0
|
|
41
43
|
|
|
42
44
|
for (const token of tokens) {
|
|
@@ -54,7 +56,7 @@ export class FSTMatcher {
|
|
|
54
56
|
return { stateID, accepted: node.places.length > 0, depth: tokens.length }
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
walkFrom(prev:
|
|
59
|
+
walkFrom(prev: AncestrieMatch, token: string): AncestrieMatch | null {
|
|
58
60
|
const node = this.nodes[prev.stateID]
|
|
59
61
|
|
|
60
62
|
if (!node) return null
|
package/lib/fst/serialize.ts
CHANGED
|
@@ -44,11 +44,6 @@ import type { FSTNode } from "#fst/matcher"
|
|
|
44
44
|
import { FSTMatcher } from "#fst/matcher"
|
|
45
45
|
import type { FSTProvenance, PlaceEntry } from "#fst/types"
|
|
46
46
|
|
|
47
|
-
/**
|
|
48
|
-
* Re-exports the format version that {@link serializeFST} writes.
|
|
49
|
-
*/
|
|
50
|
-
export { FST_FORMAT_VERSION } from "#fst/format"
|
|
51
|
-
|
|
52
47
|
const MAGIC = Buffer.from(FST_MAGIC_BYTES)
|
|
53
48
|
|
|
54
49
|
/**
|
|
@@ -119,7 +114,7 @@ export function serializeFST(matcher: FSTMatcher, provenance?: FSTProvenance): B
|
|
|
119
114
|
|
|
120
115
|
// Flag bit 0 marks that place rows include `crossCountryBranches`.
|
|
121
116
|
// Readers of a file without it report `undefined`.
|
|
122
|
-
const hasAmbiguity = nodes.some((n) => n.places.some((p) => p.crossCountryBranches
|
|
117
|
+
const hasAmbiguity = nodes.some((n) => n.places.some((p) => p.crossCountryBranches != null))
|
|
123
118
|
MAGIC.copy(buf, pos)
|
|
124
119
|
pos += 4
|
|
125
120
|
buf.writeUInt16LE(FST_FORMAT_VERSION, pos)
|
|
@@ -191,7 +186,7 @@ export function serializeFST(matcher: FSTMatcher, provenance?: FSTProvenance): B
|
|
|
191
186
|
buf.writeUInt8(hasAmbiguity ? Math.min(place.crossCountryBranches ?? 0, 255) : 0, pp + 6)
|
|
192
187
|
// An absent encyclopedic score writes flag 0 and a 0.0 float.
|
|
193
188
|
// Readers skip the float when the flag is 0.
|
|
194
|
-
const hasEncyclopedic = place.encyclopedic
|
|
189
|
+
const hasEncyclopedic = place.encyclopedic != null
|
|
195
190
|
buf.writeUInt8(hasEncyclopedic ? PLACE_FLAG_HAS_ENCYCLOPEDIC : 0, pp + 7)
|
|
196
191
|
buf.writeUInt32LE(intern(place.name), pp + 8)
|
|
197
192
|
buf.writeFloatLE(place.referential, pp + 12)
|
|
@@ -202,7 +197,7 @@ export function serializeFST(matcher: FSTMatcher, provenance?: FSTProvenance): B
|
|
|
202
197
|
buf.writeUInt32LE(ci < chainLen ? validChain[ci]! : 0, pp + 24 + ci * 4)
|
|
203
198
|
}
|
|
204
199
|
|
|
205
|
-
buf.writeFloatLE(
|
|
200
|
+
buf.writeFloatLE(place.encyclopedic ?? 0, pp + ENCYCLOPEDIC_OFFSET)
|
|
206
201
|
|
|
207
202
|
placeIdx++
|
|
208
203
|
}
|
|
@@ -320,8 +315,8 @@ export function deserializeFST(buf: Buffer): FSTMatcher {
|
|
|
320
315
|
lat: buf.readFloatLE(pp + 16),
|
|
321
316
|
lon: buf.readFloatLE(pp + 20),
|
|
322
317
|
parentChain,
|
|
323
|
-
|
|
324
|
-
|
|
318
|
+
crossCountryBranches: hasAmbiguity ? buf.readUInt8(pp + 6) : null,
|
|
319
|
+
encyclopedic: hasEncyclopedic ? buf.readFloatLE(pp + ENCYCLOPEDIC_OFFSET) : null,
|
|
325
320
|
}
|
|
326
321
|
}
|
|
327
322
|
|
|
@@ -335,23 +330,23 @@ export function deserializeFST(buf: Buffer): FSTMatcher {
|
|
|
335
330
|
* Reads the provenance trailer from an FST binary, or returns `undefined`
|
|
336
331
|
* when the file has none or it cannot be parsed.
|
|
337
332
|
*/
|
|
338
|
-
export function readFSTProvenance(buf: Buffer): FSTProvenance |
|
|
339
|
-
if (buf.length < HEADER_SIZE) return
|
|
333
|
+
export function readFSTProvenance(buf: Buffer): FSTProvenance | null {
|
|
334
|
+
if (buf.length < HEADER_SIZE) return null
|
|
340
335
|
|
|
341
|
-
if (!buf.subarray(0, 4).equals(MAGIC)) return
|
|
336
|
+
if (!buf.subarray(0, 4).equals(MAGIC)) return null
|
|
342
337
|
const version = buf.readUInt16LE(4)
|
|
343
338
|
|
|
344
|
-
if (version < VERSION_WITH_METADATA) return
|
|
339
|
+
if (version < VERSION_WITH_METADATA) return null
|
|
345
340
|
const provenanceOffset = buf.readUInt32LE(28)
|
|
346
341
|
|
|
347
|
-
if (provenanceOffset === 0 || provenanceOffset >= buf.length) return
|
|
342
|
+
if (provenanceOffset === 0 || provenanceOffset >= buf.length) return null
|
|
348
343
|
|
|
349
344
|
try {
|
|
350
345
|
const jsonLen = buf.readUInt32LE(provenanceOffset)
|
|
351
346
|
const jsonStr = buf.toString("utf8", provenanceOffset + 4, provenanceOffset + 4 + jsonLen)
|
|
352
347
|
|
|
353
|
-
return tryParsingJSON<FSTProvenance>(jsonStr) ??
|
|
348
|
+
return tryParsingJSON<FSTProvenance>(jsonStr) ?? null
|
|
354
349
|
} catch {
|
|
355
|
-
return
|
|
350
|
+
return null
|
|
356
351
|
}
|
|
357
352
|
}
|
package/lib/fst/types.ts
CHANGED
|
@@ -21,16 +21,16 @@ export interface PlaceEntry {
|
|
|
21
21
|
referential: number
|
|
22
22
|
/**
|
|
23
23
|
* The encyclopedic importance in [0, 1], for display only.
|
|
24
|
-
* It is `
|
|
24
|
+
* It is `null` when unavailable.
|
|
25
25
|
*/
|
|
26
|
-
encyclopedic
|
|
26
|
+
encyclopedic: number | null
|
|
27
27
|
lat: number
|
|
28
28
|
lon: number
|
|
29
29
|
/**
|
|
30
30
|
* The number of countries with a place of this surface, clamped to 255.
|
|
31
|
-
* It is `
|
|
31
|
+
* It is `null` when unavailable.
|
|
32
32
|
*/
|
|
33
|
-
crossCountryBranches
|
|
33
|
+
crossCountryBranches: number | null
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -49,15 +49,6 @@ export type PlacetypeID =
|
|
|
49
49
|
| "dependency"
|
|
50
50
|
| "street_affix"
|
|
51
51
|
|
|
52
|
-
/**
|
|
53
|
-
* The result of walking a token sequence through the FST.
|
|
54
|
-
*/
|
|
55
|
-
export interface FSTMatchResult {
|
|
56
|
-
stateID: number
|
|
57
|
-
accepted: boolean
|
|
58
|
-
depth: number
|
|
59
|
-
}
|
|
60
|
-
|
|
61
52
|
/**
|
|
62
53
|
* One outgoing edge from an FST state, with the number of places its target state accepts.
|
|
63
54
|
*/
|
|
@@ -96,16 +87,16 @@ export interface FSTProvenance {
|
|
|
96
87
|
/**
|
|
97
88
|
* The count of places with an encyclopedic score at build time.
|
|
98
89
|
*
|
|
99
|
-
* It is `
|
|
90
|
+
* It is `null` for a build that predates the separate encyclopedic score.
|
|
100
91
|
* The value `0` means a current build used a database without encyclopedic scores.
|
|
101
92
|
*/
|
|
102
|
-
encyclopedicMatches
|
|
93
|
+
encyclopedicMatches: number | null
|
|
103
94
|
/**
|
|
104
95
|
* The {@link ImportanceSplitSource} that records whether the encyclopedic score is real,
|
|
105
96
|
* reconstructed from a legacy column, or absent.
|
|
106
97
|
*/
|
|
107
|
-
importanceSource
|
|
108
|
-
sourceDB
|
|
98
|
+
importanceSource: string | null
|
|
99
|
+
sourceDB: string | null
|
|
109
100
|
/**
|
|
110
101
|
* The MD5 of the source database's bytes at build time.
|
|
111
102
|
* The freshness check compares it.
|
|
@@ -113,26 +104,26 @@ export interface FSTProvenance {
|
|
|
113
104
|
* `sourceDB` by itself cannot detect staleness.
|
|
114
105
|
* A rebuild replaces the admin database at the same path.
|
|
115
106
|
*
|
|
116
|
-
* The field is `
|
|
107
|
+
* The field is `null` for artifacts built before the stamp existed.
|
|
117
108
|
* An unknown digest has a different value.
|
|
118
109
|
*/
|
|
119
|
-
sourceDBMD5
|
|
110
|
+
sourceDBMD5: string | null
|
|
120
111
|
/**
|
|
121
112
|
* The byte size of the source database at build time.
|
|
122
113
|
*
|
|
123
114
|
* It detects a truncated source and makes a staleness warning readable.
|
|
124
115
|
*/
|
|
125
|
-
sourceDBBytes
|
|
126
|
-
modelCardVersion
|
|
116
|
+
sourceDBBytes: number | null
|
|
117
|
+
modelCardVersion: string | null
|
|
127
118
|
/**
|
|
128
119
|
* The surface-exclusion policy applied at build time.
|
|
129
120
|
* It is absent for an uncurated build.
|
|
130
121
|
*/
|
|
131
|
-
exclusionPolicy
|
|
122
|
+
exclusionPolicy: string | null
|
|
132
123
|
/**
|
|
133
124
|
* The count of name insertions the exclusion policy rejected.
|
|
134
125
|
*/
|
|
135
|
-
excludedInsertions
|
|
126
|
+
excludedInsertions: number | null
|
|
136
127
|
}
|
|
137
128
|
|
|
138
129
|
/**
|
package/lib/fst.ts
CHANGED
package/lib/fts.ts
CHANGED
|
@@ -51,7 +51,7 @@ export function foldQueryText(input: string): string {
|
|
|
51
51
|
* Only legacy bags use it.
|
|
52
52
|
*/
|
|
53
53
|
export function aliasBagExactMatch(altNames: string | null, normalizedQuery: string, anyStrictExact: boolean): boolean {
|
|
54
|
-
if (altNames
|
|
54
|
+
if (!altNames || altNames === "" || !normalizedQuery) return false
|
|
55
55
|
|
|
56
56
|
if (altNames.includes(ALIAS_SEPARATOR)) {
|
|
57
57
|
return altNames.split(ALIAS_SEPARATOR).some((alias) => foldQueryText(alias) === normalizedQuery)
|
package/lib/geonames/aliases.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { isOfficialLanguage } from "@mailwoman/codex/country"
|
|
8
8
|
import { readUnquotedTSV } from "@mailwoman/core/fs/delimited"
|
|
9
|
-
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
9
|
+
import { pathExists } from "@mailwoman/core/fs/readers/stat"
|
|
10
10
|
import { GEONAMES_ID_BASE, GEONAMES_POSTAL_ID_BASE } from "@mailwoman/core/resolver/synthetic-id-ranges"
|
|
11
11
|
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
12
12
|
import { type PathBuilderLike, resolvePathBuilder } from "path-ts"
|
|
@@ -63,7 +63,7 @@ export interface GeonamesIngestProgress {
|
|
|
63
63
|
*
|
|
64
64
|
* It distinguishes a sparse source from aliases that the fold discarded.
|
|
65
65
|
*/
|
|
66
|
-
aliasesRefused
|
|
66
|
+
aliasesRefused: number | null
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -211,7 +211,7 @@ export async function ingestGeonamesAliases(
|
|
|
211
211
|
const file = resolvePathBuilder(geonamesDir, `${cc}.txt`)
|
|
212
212
|
|
|
213
213
|
if (!(await pathExists(file))) {
|
|
214
|
-
report({ country: cc, places: 0, skipped: true }, file)
|
|
214
|
+
report({ country: cc, places: 0, skipped: true, aliasesRefused: null }, file)
|
|
215
215
|
|
|
216
216
|
continue
|
|
217
217
|
}
|
package/lib/geonames/postal.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { readUnquotedTSV } from "@mailwoman/core/fs/delimited"
|
|
27
|
-
import { pathExists } from "@mailwoman/core/fs/readers"
|
|
27
|
+
import { pathExists } from "@mailwoman/core/fs/readers/stat"
|
|
28
28
|
import { GEONAMES_POSTAL_ID_BASE } from "@mailwoman/core/resolver/synthetic-id-ranges"
|
|
29
29
|
import type { DatabaseClient } from "@mailwoman/sqlite/client"
|
|
30
30
|
import { type PathBuilderLike, resolvePathBuilder } from "path-ts"
|
package/lib/index.ts
CHANGED
|
@@ -19,7 +19,8 @@ export type {
|
|
|
19
19
|
WOFDatabase,
|
|
20
20
|
} from "#schema"
|
|
21
21
|
|
|
22
|
-
export { WOFSQLitePlaceLookup, type
|
|
22
|
+
export { WOFSQLitePlaceLookup, type WOFSQLitePlaceLookupOpts } from "#lookup"
|
|
23
|
+
export { type RankingWeights } from "#ranking-weights"
|
|
23
24
|
|
|
24
25
|
export {
|
|
25
26
|
CANDIDATE_ANCESTOR_COLUMNS,
|
|
@@ -98,7 +99,7 @@ export {
|
|
|
98
99
|
|
|
99
100
|
export { SqliteConventionSource } from "#sqlite/convention-source"
|
|
100
101
|
|
|
101
|
-
export { WOFPostcodeLookup
|
|
102
|
+
export { WOFPostcodeLookup } from "#postcode-point-lookup"
|
|
102
103
|
|
|
103
104
|
export {
|
|
104
105
|
PLACE_BBOX_TABLE,
|