@mailwoman/core 3.0.0 → 4.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/out/decoder/build-tree.d.ts +21 -4
- package/out/decoder/build-tree.d.ts.map +1 -1
- package/out/decoder/build-tree.js +38 -9
- package/out/decoder/build-tree.js.map +1 -1
- package/out/decoder/calibration.d.ts +50 -0
- package/out/decoder/calibration.d.ts.map +1 -0
- package/out/decoder/calibration.js +74 -0
- package/out/decoder/calibration.js.map +1 -0
- package/out/decoder/containment.d.ts +31 -2
- package/out/decoder/containment.d.ts.map +1 -1
- package/out/decoder/containment.js +36 -3
- package/out/decoder/containment.js.map +1 -1
- package/out/decoder/index.d.ts +2 -0
- package/out/decoder/index.d.ts.map +1 -1
- package/out/decoder/index.js +2 -0
- package/out/decoder/index.js.map +1 -1
- package/out/decoder/serialize-json.d.ts +4 -0
- package/out/decoder/serialize-json.d.ts.map +1 -1
- package/out/decoder/serialize-json.js +10 -0
- package/out/decoder/serialize-json.js.map +1 -1
- package/out/decoder/serialize-xml.d.ts.map +1 -1
- package/out/decoder/serialize-xml.js +6 -0
- package/out/decoder/serialize-xml.js.map +1 -1
- package/out/decoder/types.d.ts +46 -0
- package/out/decoder/types.d.ts.map +1 -1
- package/out/decoder/validate-tree.d.ts +39 -0
- package/out/decoder/validate-tree.d.ts.map +1 -0
- package/out/decoder/validate-tree.js +79 -0
- package/out/decoder/validate-tree.js.map +1 -0
- package/out/pipeline/runtime-pipeline.d.ts +17 -1
- package/out/pipeline/runtime-pipeline.d.ts.map +1 -1
- package/out/pipeline/runtime-pipeline.js +76 -16
- package/out/pipeline/runtime-pipeline.js.map +1 -1
- package/out/pipeline/span-logit-aggregation.d.ts +4 -2
- package/out/pipeline/span-logit-aggregation.d.ts.map +1 -1
- package/out/pipeline/span-logit-aggregation.js +11 -2
- package/out/pipeline/span-logit-aggregation.js.map +1 -1
- package/out/pipeline/types.d.ts +12 -3
- package/out/pipeline/types.d.ts.map +1 -1
- package/out/resolver/index.d.ts +1 -1
- package/out/resolver/index.d.ts.map +1 -1
- package/out/resolver/resolve.d.ts.map +1 -1
- package/out/resolver/resolve.js +162 -10
- package/out/resolver/resolve.js.map +1 -1
- package/out/resolver/types.d.ts +125 -0
- package/out/resolver/types.d.ts.map +1 -1
- package/out/resolver/types.js.map +1 -1
- package/out/resources/whosonfirst/PlacetypeDataSource.d.ts.map +1 -1
- package/out/resources/whosonfirst/PlacetypeDataSource.js +3 -1
- package/out/resources/whosonfirst/PlacetypeDataSource.js.map +1 -1
- package/out/resources/whosonfirst/placetypes/graph.d.ts +47 -0
- package/out/resources/whosonfirst/placetypes/graph.d.ts.map +1 -0
- package/out/resources/whosonfirst/placetypes/graph.js +0 -0
- package/out/resources/whosonfirst/placetypes/graph.js.map +1 -0
- package/out/resources/whosonfirst/placetypes/index.d.ts +2 -0
- package/out/resources/whosonfirst/placetypes/index.d.ts.map +1 -1
- package/out/resources/whosonfirst/placetypes/index.js +2 -0
- package/out/resources/whosonfirst/placetypes/index.js.map +1 -1
- package/out/resources/whosonfirst/placetypes/mermaid.d.ts +35 -3
- package/out/resources/whosonfirst/placetypes/mermaid.d.ts.map +1 -1
- package/out/resources/whosonfirst/placetypes/mermaid.js +87 -15
- package/out/resources/whosonfirst/placetypes/mermaid.js.map +1 -1
- package/out/resources/whosonfirst/placetypes/tree.d.ts +30 -0
- package/out/resources/whosonfirst/placetypes/tree.d.ts.map +1 -0
- package/out/resources/whosonfirst/placetypes/tree.js +28 -0
- package/out/resources/whosonfirst/placetypes/tree.js.map +1 -0
- package/out/tokenization/Graph.d.ts +1 -1
- package/out/tokenization/Graph.d.ts.map +1 -1
- package/out/tokenization/Graph.js +5 -1
- package/out/tokenization/Graph.js.map +1 -1
- package/package.json +8 -2
package/out/resolver/resolve.js
CHANGED
|
@@ -20,6 +20,38 @@ import { DEFAULT_PLACETYPE_MAP, } from "./types.js";
|
|
|
20
20
|
export function createWofResolver(backend) {
|
|
21
21
|
return new WofResolver(backend);
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Pick the completion locality when an admin maps to several coincident same-name candidates
|
|
25
|
+
* (#405). Population is the PRIMARY signal — the principal city is the populous one, and it can sit
|
|
26
|
+
* FARTHER from the admin centroid than a tiny same-name hamlet (the Niigata case from #403).
|
|
27
|
+
* Nearest centroid breaks a population tie; a genuine tie (same population AND distance) ABSTAINS
|
|
28
|
+
* rather than guess.
|
|
29
|
+
*/
|
|
30
|
+
function pickCompletion(candidates) {
|
|
31
|
+
if (candidates.length === 0)
|
|
32
|
+
return null;
|
|
33
|
+
if (candidates.length === 1)
|
|
34
|
+
return candidates[0];
|
|
35
|
+
const ranked = [...candidates].sort((a, b) => b.population - a.population || a.distanceKm - b.distanceKm);
|
|
36
|
+
const [first, second] = ranked;
|
|
37
|
+
if (first.population === second.population && first.distanceKm === second.distanceKm)
|
|
38
|
+
return null;
|
|
39
|
+
return first;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Find the first postcode value anywhere in the tree (a one-shot pre-scan; postcode and locality
|
|
43
|
+
* are siblings, so the top-down walk wouldn't otherwise let the locality lookup see it).
|
|
44
|
+
*/
|
|
45
|
+
function firstPostcodeValue(roots) {
|
|
46
|
+
const stack = [...roots];
|
|
47
|
+
while (stack.length > 0) {
|
|
48
|
+
const n = stack.pop();
|
|
49
|
+
if (n.tag === "postcode" && n.value.trim().length > 0)
|
|
50
|
+
return n.value.trim();
|
|
51
|
+
stack.push(...n.children);
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
23
55
|
class WofResolver {
|
|
24
56
|
#backend;
|
|
25
57
|
constructor(backend) {
|
|
@@ -33,23 +65,86 @@ class WofResolver {
|
|
|
33
65
|
placetypeMap: opts.placetypeMap ?? DEFAULT_PLACETYPE_MAP,
|
|
34
66
|
minWinningScore: opts.minWinningScore ?? 0,
|
|
35
67
|
candidatesPerLookup: opts.candidatesPerLookup ?? 5,
|
|
68
|
+
defaultCountry: opts.defaultCountry,
|
|
69
|
+
parentFallback: opts.parentFallback ?? true,
|
|
70
|
+
postcode: firstPostcodeValue(tree.roots),
|
|
71
|
+
anchorPosterior: opts.anchorPosterior,
|
|
72
|
+
anchorWeight: opts.anchorWeight ?? 2.0,
|
|
73
|
+
// Default-ON (#402): completion only fires for a dual-role region whose locality the parser
|
|
74
|
+
// dropped, and no-ops entirely when the backend has no relation (the browser WASM resolver, or
|
|
75
|
+
// a gazetteer without `coincident_roles`). Pass `hierarchyCompletion: false` to opt out.
|
|
76
|
+
// `cityStateFallback` is the #387 alias that #405 generalized — still honored.
|
|
77
|
+
hierarchyCompletion: opts.hierarchyCompletion ?? opts.cityStateFallback ?? true,
|
|
78
|
+
includeAncestors: opts.includeAncestors ?? false,
|
|
79
|
+
localityNodePresent: false,
|
|
80
|
+
resolvedRegion: null,
|
|
81
|
+
resolvedRegionNode: null,
|
|
36
82
|
};
|
|
37
83
|
const newRoots = [];
|
|
38
84
|
for (const root of tree.roots) {
|
|
39
85
|
newRoots.push(await this.#walk(root, /* parentResolved */ null, state));
|
|
40
86
|
}
|
|
87
|
+
// Dual-role hierarchy completion (#405/#415). Only when enabled, a region resolved, and the parser
|
|
88
|
+
// emitted NO locality — record the dropped locality as a SECONDARY ROLE (an interpretation) on the
|
|
89
|
+
// resolved region node, from the backend's precomputed coincident-roles relation (#403). One node,
|
|
90
|
+
// one span, two roles — no synthesized sibling. See ResolveOpts.hierarchyCompletion.
|
|
91
|
+
if (state.hierarchyCompletion && state.resolvedRegion && state.resolvedRegionNode && !state.localityNodePresent) {
|
|
92
|
+
this.#completeRegionRole(state.resolvedRegion, state.resolvedRegionNode);
|
|
93
|
+
}
|
|
41
94
|
return { raw: tree.raw, roots: newRoots };
|
|
42
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Record a dropped dual-role locality as a `locality` INTERPRETATION on the resolved region node
|
|
98
|
+
* (#415, generalizes #405's synthesized node). Consults `coincidentLocalitiesFor(regionId)` (O(1)
|
|
99
|
+
* map lookup — no distance math, no backend query), picks the principal city
|
|
100
|
+
* ({@link pickCompletion}: population-primary, distance tiebreak, abstain on a genuine tie), and
|
|
101
|
+
* appends an interpretation to `regionNode.interpretations`. No-op when the backend has no
|
|
102
|
+
* relation, the region isn't a dual-role place, or it abstains. The region node's primary role
|
|
103
|
+
* stays `region`; the locality rides alongside.
|
|
104
|
+
*/
|
|
105
|
+
#completeRegionRole(region, regionNode) {
|
|
106
|
+
if (typeof region.id !== "number" || !this.#backend.coincidentLocalitiesFor)
|
|
107
|
+
return;
|
|
108
|
+
const loc = pickCompletion(this.#backend.coincidentLocalitiesFor(region.id));
|
|
109
|
+
if (!loc)
|
|
110
|
+
return;
|
|
111
|
+
const interpretation = {
|
|
112
|
+
tag: "locality",
|
|
113
|
+
placeId: `wof:${loc.id}`,
|
|
114
|
+
sourceId: `${loc.placetype}:${loc.id}`,
|
|
115
|
+
lat: loc.lat,
|
|
116
|
+
lon: loc.lon,
|
|
117
|
+
confidence: 0,
|
|
118
|
+
metadata: { relationship_type: loc.relationshipType, resolver_completed: true, resolver_name: loc.name },
|
|
119
|
+
};
|
|
120
|
+
regionNode.interpretations = [...(regionNode.interpretations ?? []), interpretation];
|
|
121
|
+
}
|
|
43
122
|
async #walk(node, parentResolved, state) {
|
|
44
123
|
// Always clone — never mutate input nodes.
|
|
45
124
|
const decorated = { ...node, children: [] };
|
|
46
125
|
const placetype = state.placetypeMap[node.tag];
|
|
126
|
+
// Track locality presence for hierarchy completion (#405): completion must NOT fire if the parser
|
|
127
|
+
// already emitted a locality node (even one that failed to resolve) — it only fills a genuine
|
|
128
|
+
// gap. Cheap and always-on; only consulted when hierarchyCompletion is set.
|
|
129
|
+
if (placetype === "locality")
|
|
130
|
+
state.localityNodePresent = true;
|
|
47
131
|
let resolved = null;
|
|
48
132
|
if (placetype && state.lookupsRemaining > 0 && node.value.trim().length > 0) {
|
|
49
133
|
const picked = await this.#lookupAndPick(node, placetype, parentResolved, state);
|
|
50
134
|
if (picked) {
|
|
51
135
|
resolved = picked.top;
|
|
52
136
|
decorateNode(decorated, picked.top, picked.alternatives);
|
|
137
|
+
// Lineage attachment (#404): stamp the resolved place's ancestor chain onto metadata. Opt-in
|
|
138
|
+
// + only when the backend supplies it, so the default stays byte-identical (no extra query).
|
|
139
|
+
if (state.includeAncestors && this.#backend.ancestors) {
|
|
140
|
+
decorated.metadata = { ...(decorated.metadata ?? {}), ancestors: this.#backend.ancestors(picked.top.id) };
|
|
141
|
+
}
|
|
142
|
+
// Capture the first resolved region (place + node) for hierarchy completion — the locality
|
|
143
|
+
// interpretation is pushed onto this node in the post-walk pass.
|
|
144
|
+
if (placetype === "region" && state.resolvedRegion === null) {
|
|
145
|
+
state.resolvedRegion = picked.top;
|
|
146
|
+
state.resolvedRegionNode = decorated;
|
|
147
|
+
}
|
|
53
148
|
}
|
|
54
149
|
}
|
|
55
150
|
const carryParent = resolved ?? parentResolved;
|
|
@@ -65,17 +160,34 @@ class WofResolver {
|
|
|
65
160
|
placetype,
|
|
66
161
|
limit: state.candidatesPerLookup,
|
|
67
162
|
};
|
|
68
|
-
// Pass the inherited parent constraint to the backend when available —
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
163
|
+
// Pass the inherited parent constraint to the backend when available — `parentId` scopes to
|
|
164
|
+
// the resolved parent's descendants. For `country`: a resolved parent's country wins, else
|
|
165
|
+
// fall back to the caller's `defaultCountry`. Without this top-level hint a bare "IL" over a
|
|
166
|
+
// multi-country gazetteer fuzzy-matches a foreign place (e.g. a French region) — see the
|
|
167
|
+
// Direction-C resolver eval.
|
|
168
|
+
if (parentResolved && typeof parentResolved.id === "number")
|
|
169
|
+
query.parentId = parentResolved.id;
|
|
170
|
+
const country = parentResolved?.country ?? state.defaultCountry;
|
|
171
|
+
if (country)
|
|
172
|
+
query.country = country;
|
|
173
|
+
// Coordinate-first: hand the sibling postcode to locality lookups so the backend can inject
|
|
174
|
+
// postcode-proximal candidates the name-match would miss. Only for locality (the placetype both
|
|
175
|
+
// `locality` and `dependent_locality` map to); other placetypes ignore it.
|
|
176
|
+
if (placetype === "locality" && state.postcode)
|
|
177
|
+
query.postcode = state.postcode;
|
|
76
178
|
let candidates;
|
|
77
179
|
try {
|
|
78
180
|
candidates = await this.#backend.findPlace(query);
|
|
181
|
+
// Parent soft-gating: `parentId` is a HARD descendant filter in the backend, which wrongly
|
|
182
|
+
// zeroes the result when the parent resolved wrong OR the gazetteer hierarchy is incomplete
|
|
183
|
+
// (a real locality whose `ancestors` chain is missing its region). Rather than turn a
|
|
184
|
+
// resolvable node into an unresolved one, retry once WITHOUT the parent constraint — we
|
|
185
|
+
// prefer a parent-scoped hit but never sacrifice recall. The country constraint is kept, so
|
|
186
|
+
// this still can't wander to a foreign place. Same logical resolution → no extra budget.
|
|
187
|
+
if (candidates.length === 0 && state.parentFallback && query.parentId !== undefined) {
|
|
188
|
+
delete query.parentId;
|
|
189
|
+
candidates = await this.#backend.findPlace(query);
|
|
190
|
+
}
|
|
79
191
|
}
|
|
80
192
|
catch {
|
|
81
193
|
// Defensive: a backend failure should not abort the whole tree walk. Leave the node with
|
|
@@ -84,10 +196,40 @@ class WofResolver {
|
|
|
84
196
|
}
|
|
85
197
|
if (candidates.length === 0)
|
|
86
198
|
return null;
|
|
87
|
-
|
|
199
|
+
// Postcode-anchor re-rank (#369): when a country posterior is supplied (from the address's
|
|
200
|
+
// postcode), boost candidates by `anchorWeight * posterior[candidate.country]` and re-sort, so a
|
|
201
|
+
// postcode that pins the country pulls the right-country place over a higher-BM25 foreign namesake
|
|
202
|
+
// (the "Berlin DE vs Berlin US" class the #59 harness measured). No-op when `anchorPosterior` is
|
|
203
|
+
// undefined (the default) → byte-identical resolution.
|
|
204
|
+
//
|
|
205
|
+
// Applied to BOTH region and locality — the two placetypes that suffer cross-country namesake/
|
|
206
|
+
// abbreviation collisions a country posterior can break. The region case is the one #447's window
|
|
207
|
+
// fix couldn't reach: a bare 2-letter abbreviation is genuinely shared across countries ("VT" is
|
|
208
|
+
// both Vermont and Viterbo; "ME" both Maine and Messina), so with no country signal the score
|
|
209
|
+
// picks the wrong one — and because resolveTree resolves region FIRST and inherits its country
|
|
210
|
+
// down, a wrong region poisons the locality too. The postcode posterior breaks the tie at the
|
|
211
|
+
// region, and the right country then flows to the locality. (Country/macroregion/county are
|
|
212
|
+
// excluded: they don't exhibit this collision class and carry country via `parentId` when nested.)
|
|
213
|
+
//
|
|
214
|
+
// Tier-SAFE ordering: the candidate's exact-match flag is the PRIMARY key, so the country pin
|
|
215
|
+
// never crosses the exact/partial boundary. WITHIN a tier, `score + anchorWeight * posterior`
|
|
216
|
+
// applies the (soft) country boost. So a confident US postcode keeps the US EXACT region
|
|
217
|
+
// ("ME" → Maine) ahead of a more-populous US PARTIAL match (Missouri) AND, within the exact
|
|
218
|
+
// tier, ahead of a foreign exact match (Messina IT); a soft posterior still blends with score.
|
|
219
|
+
// (A plain additive re-rank loses the tier — it isn't encoded in `score` — and flips
|
|
220
|
+
// "ME" → Missouri / "PA" → Alabama. Backends that don't set `exactMatch` degrade to additive.)
|
|
221
|
+
const anchorEligible = placetype === "region" || placetype === "locality";
|
|
222
|
+
let ranked = candidates;
|
|
223
|
+
if (state.anchorPosterior && anchorEligible && candidates.length > 1) {
|
|
224
|
+
const post = state.anchorPosterior;
|
|
225
|
+
const w = state.anchorWeight;
|
|
226
|
+
ranked = [...candidates].sort((a, b) => Number(b.exactMatch ?? false) - Number(a.exactMatch ?? false) ||
|
|
227
|
+
b.score + w * (post[b.country] ?? 0) - (a.score + w * (post[a.country] ?? 0)));
|
|
228
|
+
}
|
|
229
|
+
const top = ranked[0];
|
|
88
230
|
if (top.score < state.minWinningScore)
|
|
89
231
|
return null;
|
|
90
|
-
return { top, alternatives:
|
|
232
|
+
return { top, alternatives: ranked.slice(1) };
|
|
91
233
|
}
|
|
92
234
|
}
|
|
93
235
|
/**
|
|
@@ -111,6 +253,16 @@ function decorateNode(node, resolved, alternatives) {
|
|
|
111
253
|
node.lat = resolved.lat;
|
|
112
254
|
node.lon = resolved.lon;
|
|
113
255
|
node.placeId = `wof:${resolved.id}`; // v1: only WOF resolvers; the URI scheme stays this simple
|
|
256
|
+
// Record the resolver's ranking score AND the resolved place's CANONICAL name. The name is the
|
|
257
|
+
// gazetteer's truth for the place we picked — distinct from `node.value` (the raw input span). It
|
|
258
|
+
// lets consumers display the canonical name and lets the end-to-end eval check the resolver chose
|
|
259
|
+
// the right PLACE (gazetteer-name vs ground-truth) rather than merely echoing the parser's text.
|
|
260
|
+
node.metadata = { ...(node.metadata ?? {}), resolver_score: resolved.score, resolver_name: resolved.name };
|
|
261
|
+
// The postcode/locality conflict flag (the falsehood differentiator): the postcode pointed to a
|
|
262
|
+
// geographically different place than the parsed city name. Surface it so callers can warn rather
|
|
263
|
+
// than silently trust the resolved point.
|
|
264
|
+
if (resolved.mismatch)
|
|
265
|
+
node.metadata["postcode_city_mismatch"] = true;
|
|
114
266
|
if (alternatives.length > 0) {
|
|
115
267
|
node.alternatives = alternatives;
|
|
116
268
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../resolver/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../resolver/resolve.ts"],"names":[],"mappings":"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"}
|
package/out/resolver/types.d.ts
CHANGED
|
@@ -38,6 +38,22 @@ export interface ResolvedPlace {
|
|
|
38
38
|
* defined; callers should treat as ordinal.
|
|
39
39
|
*/
|
|
40
40
|
score: number;
|
|
41
|
+
/**
|
|
42
|
+
* Set by the backend when this candidate is an EXACT name/alias match for the query (vs a partial
|
|
43
|
+
* token match). The postcode-anchor re-rank (#369) uses it as the PRIMARY key so a country
|
|
44
|
+
* posterior can pin the country WITHOUT crossing the exact-match tier: "ME" under a confident US
|
|
45
|
+
* posterior stays Maine (US exact) rather than promoting the more-populous Missouri (US partial),
|
|
46
|
+
* and still beats Messina (IT exact) on the posterior WITHIN the exact tier. Absent → treated as
|
|
47
|
+
* non-exact (backends that don't tier omit it; the re-rank degrades to a plain score+posterior).
|
|
48
|
+
*/
|
|
49
|
+
exactMatch?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Set when the resolver detected that the address's postcode and its parsed locality name point
|
|
52
|
+
* to geographically different places (a transposed / wrong-for-the-city postcode). Surfaced onto
|
|
53
|
+
* the resolved node's metadata as `postcode_city_mismatch` so callers can lower confidence or
|
|
54
|
+
* flag the conflict instead of silently mislocating.
|
|
55
|
+
*/
|
|
56
|
+
mismatch?: boolean;
|
|
41
57
|
}
|
|
42
58
|
/**
|
|
43
59
|
* Pull-based contract for a single resolver query. The resolver knows nothing about `AddressTree` —
|
|
@@ -52,8 +68,52 @@ export interface ResolverBackend {
|
|
|
52
68
|
placetype?: string | string[];
|
|
53
69
|
country?: string;
|
|
54
70
|
parentId?: number | string;
|
|
71
|
+
/**
|
|
72
|
+
* Sibling postcode string, when the address carries one. A coordinate-first backend uses it to
|
|
73
|
+
* inject postcode-proximal locality candidates (the postcode→locality table) and soft-score
|
|
74
|
+
* them against the parsed name — recovering localities the name-match alone misses. Backends
|
|
75
|
+
* without postcode support ignore it.
|
|
76
|
+
*/
|
|
77
|
+
postcode?: string;
|
|
55
78
|
limit?: number;
|
|
56
79
|
}): Promise<ResolvedPlace[]>;
|
|
80
|
+
/**
|
|
81
|
+
* The dual-role locality (or localities) coincident with an admin place id, from the precomputed
|
|
82
|
+
* coincident-roles relation (#403). Drives {@link ResolveOpts.hierarchyCompletion}: when the parse
|
|
83
|
+
* drops the locality of a city-state / capital-seat region, the resolver completes it from here
|
|
84
|
+
* instead of re-querying. OPTIONAL — backends without the relation omit it, and completion
|
|
85
|
+
* no-ops. Synchronous: it's an in-memory map lookup once the relation is loaded.
|
|
86
|
+
*/
|
|
87
|
+
coincidentLocalitiesFor?(adminId: number | string): CoincidentLocality[];
|
|
88
|
+
/**
|
|
89
|
+
* The ancestor lineage of a resolved place — its containment chain (county → region → country),
|
|
90
|
+
* nearest-first. Backs {@link ResolveOpts.includeAncestors} (#404): the Pelias/Nominatim
|
|
91
|
+
* "always-attach-the-hierarchy" enrichment. OPTIONAL — backends without it omit it, and the
|
|
92
|
+
* attachment is skipped. Synchronous: a memoized read of the gazetteer's `ancestors` table.
|
|
93
|
+
*/
|
|
94
|
+
ancestors?(id: number | string): Ancestor[];
|
|
95
|
+
}
|
|
96
|
+
/** One link in a resolved place's containment lineage ({@link ResolverBackend.ancestors}, #404). */
|
|
97
|
+
export interface Ancestor {
|
|
98
|
+
id: number | string;
|
|
99
|
+
placetype: string;
|
|
100
|
+
name: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A dual-role locality returned by {@link ResolverBackend.coincidentLocalitiesFor} — a resolved
|
|
104
|
+
* place (so it can decorate a node directly) plus the relation metadata the completion step
|
|
105
|
+
* disambiguates on.
|
|
106
|
+
*/
|
|
107
|
+
export interface CoincidentLocality extends ResolvedPlace {
|
|
108
|
+
/**
|
|
109
|
+
* `city-state` / `capital-seat` / `consolidated-county` — surfaced as
|
|
110
|
+
* `metadata.relationship_type`.
|
|
111
|
+
*/
|
|
112
|
+
relationshipType: string;
|
|
113
|
+
/** Locality population (0 when unknown) — the PRIMARY disambiguator when an admin has several. */
|
|
114
|
+
population: number;
|
|
115
|
+
/** Centroid distance (km) admin↔locality from the relation — the population tiebreak. */
|
|
116
|
+
distanceKm: number;
|
|
57
117
|
}
|
|
58
118
|
/**
|
|
59
119
|
* Options for `resolveTree`. All optional with sensible defaults.
|
|
@@ -75,6 +135,22 @@ export interface ResolveOpts {
|
|
|
75
135
|
* candidate after post-scoring, but the backend may benefit from over-fetching for ranking.
|
|
76
136
|
*/
|
|
77
137
|
candidatesPerLookup?: number;
|
|
138
|
+
/**
|
|
139
|
+
* Default ISO-3166 alpha-2 country to constrain top-level lookups to, when no resolved parent has
|
|
140
|
+
* supplied a country yet. Without it, a bare component over a multi-country gazetteer (e.g. "IL")
|
|
141
|
+
* can fuzzy-match a foreign place. Callers should set this from the detected locale (the
|
|
142
|
+
* pipeline's locale-gate). A resolved parent's country still overrides it deeper in the tree.
|
|
143
|
+
*/
|
|
144
|
+
defaultCountry?: string;
|
|
145
|
+
/**
|
|
146
|
+
* When a resolved parent constrains a child lookup (`parentId` is passed to the backend as a hard
|
|
147
|
+
* descendant filter) and that filtered lookup returns NOTHING, retry the lookup once without the
|
|
148
|
+
* parent constraint. Guards against an incomplete gazetteer hierarchy (a real locality whose
|
|
149
|
+
* ancestor chain is missing its region) or a mis-resolved parent silently turning a resolvable
|
|
150
|
+
* node unresolved. The country constraint is retained on the retry, so resolution still can't
|
|
151
|
+
* wander cross-border. Default true. Set false to measure the strict-parent baseline.
|
|
152
|
+
*/
|
|
153
|
+
parentFallback?: boolean;
|
|
78
154
|
/**
|
|
79
155
|
* Override the default ComponentTag → resolver-placetype mapping. When set, this map FULLY
|
|
80
156
|
* REPLACES `DEFAULT_PLACETYPE_MAP` — start from the default by spreading it (`{
|
|
@@ -89,6 +165,55 @@ export interface ResolveOpts {
|
|
|
89
165
|
* break when locale-aware resolvers land in 4.4+.
|
|
90
166
|
*/
|
|
91
167
|
locale?: string;
|
|
168
|
+
/**
|
|
169
|
+
* Optional postcode-anchor country posterior (#369) — a `{ countryCode: probability }` map
|
|
170
|
+
* derived from the address's postcode (e.g. `@mailwoman/neural`'s `extractPostcodeAnchors`). When
|
|
171
|
+
* provided, LOCALITY candidates are re-ranked by `score + anchorWeight *
|
|
172
|
+
* posterior[candidate.country]` before the top is picked, so a postcode that pins the country can
|
|
173
|
+
* pull the right-country place over a higher-BM25 foreign namesake (the "Berlin DE vs Berlin US"
|
|
174
|
+
* class the #59 anchor→resolver harness measured). OFF by default — omit it and resolution is
|
|
175
|
+
* byte-identical. Country signal only, so it touches locality lookups only; admin parents already
|
|
176
|
+
* carry country via `parentId`.
|
|
177
|
+
*/
|
|
178
|
+
anchorPosterior?: Record<string, number>;
|
|
179
|
+
/**
|
|
180
|
+
* Weight on the anchor's country posterior in the locality re-rank (#369). Default 2.0 (the value
|
|
181
|
+
* the harness swept). Only consulted when `anchorPosterior` is set.
|
|
182
|
+
*/
|
|
183
|
+
anchorWeight?: number;
|
|
184
|
+
/**
|
|
185
|
+
* Recover the dropped locality in a DUAL-ROLE-place address (#405, epic #402). Many places occupy
|
|
186
|
+
* multiple admin tiers under one name — city-states (Berlin/Hamburg/Bremen = city == state),
|
|
187
|
+
* capital-seat provinces (Milano, Madrid), UK unitary authorities — and in the
|
|
188
|
+
* international-order layout `…, Berlin, Berlin <PC>` the parser labels one token the region and
|
|
189
|
+
* drops the locality entirely, leaving a region but no locality (955/1500 Berlin rows resolved to
|
|
190
|
+
* nothing on v0.9.4).
|
|
191
|
+
*
|
|
192
|
+
* When this is on AND a region resolved AND the tree has NO locality node, the resolver consults
|
|
193
|
+
* the backend's precomputed coincident-roles relation
|
|
194
|
+
* ({@link ResolverBackend.coincidentLocalitiesFor}, #403) for a same-name coincident locality and
|
|
195
|
+
* synthesizes a node from it. The relation is the gazetteer's own structure (same name +
|
|
196
|
+
* descendant + centroid-coincidence, derived at build time), so the runtime is an O(1) membership
|
|
197
|
+
* lookup — no magic distance constant. When an admin maps to several same-name localities, the
|
|
198
|
+
* most populous wins (the principal city), nearest-centroid breaks a population tie, and a
|
|
199
|
+
* genuine tie ABSTAINS (no completion) rather than guess. The synthesized node carries
|
|
200
|
+
* `metadata.resolver_synthesized = true` (+ `relationship_type`) — it has no span in the raw
|
|
201
|
+
* input. ON by default (#402): it only fires for a dual-role region whose locality the parser
|
|
202
|
+
* dropped, and no-ops entirely when the backend has no relation (the browser WASM resolver, or a
|
|
203
|
+
* gazetteer without the `coincident_roles` table). Pass `false` to opt out.
|
|
204
|
+
*/
|
|
205
|
+
hierarchyCompletion?: boolean;
|
|
206
|
+
/** @deprecated Renamed to {@link hierarchyCompletion} (#405 generalized #387). Still honored. */
|
|
207
|
+
cityStateFallback?: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* Attach each resolved node's ancestor lineage (#404) — the containment chain (county → region →
|
|
210
|
+
* country) the backend's {@link ResolverBackend.ancestors} returns — onto `metadata.ancestors`.
|
|
211
|
+
* The Pelias/Nominatim "always-attach-the-hierarchy" enrichment, so a consumer gets the full
|
|
212
|
+
* admin ladder from a single resolved place. OFF by default: omit it and resolution is
|
|
213
|
+
* byte-identical (and there's no extra query). Only attaches to nodes the resolver actually
|
|
214
|
+
* resolved.
|
|
215
|
+
*/
|
|
216
|
+
includeAncestors?: boolean;
|
|
92
217
|
}
|
|
93
218
|
/**
|
|
94
219
|
* Mapping from mailwoman's address-component tags to the resolver's placetype taxonomy. Components
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../resolver/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,wDAAwD;IACxD,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,0FAA0F;IAC1F,SAAS,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../resolver/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC7B,wDAAwD;IACxD,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,0FAA0F;IAC1F,SAAS,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;QAC1B;;;;;WAKG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,KAAK,CAAC,EAAE,MAAM,CAAA;KACd,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IAC5B;;;;;;OAMG;IACH,uBAAuB,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,EAAE,CAAA;IACxE;;;;;OAKG;IACH,SAAS,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAA;CAC3C;AAED,oGAAoG;AACpG,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACZ;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACxD;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAA;IACxB,kGAAkG;IAClG,UAAU,EAAE,MAAM,CAAA;IAClB,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;AAEhE,eAAO,MAAM,qBAAqB,EAAE,YAUnC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CACxE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../resolver/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../resolver/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkOH,MAAM,CAAC,MAAM,qBAAqB,GAAiB;IAClD,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,kBAAkB,EAAE,UAAU;IAC9B,SAAS,EAAE,QAAQ;IACnB,0FAA0F;IAC1F,6FAA6F;IAC7F,2FAA2F;IAC3F,QAAQ,EAAE,YAAY;CACtB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlacetypeDataSource.d.ts","sourceRoot":"","sources":["../../../resources/whosonfirst/PlacetypeDataSource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,kBAAkB,EAClB,KAAK,mBAAmB,EAGxB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAgB,KAAK,mBAAmB,EAAsB,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEtE,MAAM,WAAW,0BAA0B,CAC1C,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,EACrD,CAAC,SAAS,mBAAmB,GAAG,kBAAkB,GAAG,mBAAmB;IAExE,SAAS,EAAE,CAAC,CAAA;IACZ,YAAY,EAAE,CAAC,CAAA;IACf,aAAa,EAAE,eAAe,CAAA;CAC9B;AAED,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,UAAU;;WAGvC,UAAU,CAAC,CAAC,SAAS,oBAAoB,EAAE,CAAC,SAAS,mBAAmB,GAAG,kBAAkB,EAAE,EAC5G,SAAS,EACT,YAAY,EACZ,aAAa,GACb,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,cAAc,GAAG,eAAe,CAAC,GASxE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IAGtC,aAAa,IAAI,IAAI;IAkBrB,cAAc,IAAI,IAAI;gBAejB,YAAY,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"PlacetypeDataSource.d.ts","sourceRoot":"","sources":["../../../resources/whosonfirst/PlacetypeDataSource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,kBAAkB,EAClB,KAAK,mBAAmB,EAGxB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAgB,KAAK,mBAAmB,EAAsB,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEtE,MAAM,WAAW,0BAA0B,CAC1C,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,EACrD,CAAC,SAAS,mBAAmB,GAAG,kBAAkB,GAAG,mBAAmB;IAExE,SAAS,EAAE,CAAC,CAAA;IACZ,YAAY,EAAE,CAAC,CAAA;IACf,aAAa,EAAE,eAAe,CAAA;CAC9B;AAED,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IACV;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,UAAU;;WAGvC,UAAU,CAAC,CAAC,SAAS,oBAAoB,EAAE,CAAC,SAAS,mBAAmB,GAAG,kBAAkB,EAAE,EAC5G,SAAS,EACT,YAAY,EACZ,aAAa,GACb,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,GAAG,cAAc,GAAG,eAAe,CAAC,GASxE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IAGtC,aAAa,IAAI,IAAI;IAkBrB,cAAc,IAAI,IAAI;gBAejB,YAAY,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,mBAAmB;IAcnE,CAAC,MAAM,CAAC,OAAO,CAAC;IAIvB;;OAEG;IAEI,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,cAAc,CAAC,eAAe,CAAC;IAgBhF;;;;OAIG;IACU,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CA+B3D"}
|
|
@@ -50,7 +50,9 @@ export class PlacetypeDataSource {
|
|
|
50
50
|
`);
|
|
51
51
|
}
|
|
52
52
|
constructor(databasePath, dbOptions) {
|
|
53
|
-
this.#db =
|
|
53
|
+
this.#db = dbOptions
|
|
54
|
+
? new DatabaseSync(databasePath.toString(), dbOptions)
|
|
55
|
+
: new DatabaseSync(databasePath.toString());
|
|
54
56
|
// node:sqlite has no .pragma() helper; pragmas are executed as plain SQL.
|
|
55
57
|
this.#db.exec("PRAGMA busy_timeout = 10000");
|
|
56
58
|
this.#db.exec("PRAGMA journal_mode = WAL");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlacetypeDataSource.js","sourceRoot":"","sources":["../../../resources/whosonfirst/PlacetypeDataSource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,kBAAkB,EAElB,eAAe,EACf,qBAAqB,GACrB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAgD,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,WAAW,EAAwB,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAmDrD;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC/B,GAAG,CAAc;IAEV,MAAM,CAAC,UAAU,CAAqF,EAC5G,SAAS,EACT,YAAY,EACZ,aAAa,GAC2E;QACxF,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,YAAY,CAAC;YACjE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC;YACnC,CAAC,CAAC,YAAY,CAAA;QAEf,OAAO,WAAW,CAAC,IAAI,CACtB,aAAa,EACb,SAAS,EACT,GAAG,sBAAsB,KAAK,CACa,CAAA;IAC7C,CAAC;IAEM,aAAa;QACnB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;;;;;;;;;;;;;;GAcvB,CAAC,CAAA;IACH,CAAC;IAEM,cAAc;QACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;;;;;;;;;;;GAWvB,CAAC,CAAA;IACH,CAAC;IAED,YAAY,YAA6B,EAAE,SAA+B;QACzE,IAAI,CAAC,GAAG,GAAG,IAAI,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"PlacetypeDataSource.js","sourceRoot":"","sources":["../../../resources/whosonfirst/PlacetypeDataSource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,kBAAkB,EAElB,eAAe,EACf,qBAAqB,GACrB,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAgD,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,WAAW,EAAwB,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAmDrD;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC/B,GAAG,CAAc;IAEV,MAAM,CAAC,UAAU,CAAqF,EAC5G,SAAS,EACT,YAAY,EACZ,aAAa,GAC2E;QACxF,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,YAAY,CAAC;YACjE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC;YACnC,CAAC,CAAC,YAAY,CAAA;QAEf,OAAO,WAAW,CAAC,IAAI,CACtB,aAAa,EACb,SAAS,EACT,GAAG,sBAAsB,KAAK,CACa,CAAA;IAC7C,CAAC;IAEM,aAAa;QACnB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;;;;;;;;;;;;;;GAcvB,CAAC,CAAA;IACH,CAAC;IAEM,cAAc;QACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;;;;;;;;;;;GAWvB,CAAC,CAAA;IACH,CAAC;IAED,YAAY,YAA6B,EAAE,SAA+B;QACzE,IAAI,CAAC,GAAG,GAAG,SAAS;YACnB,CAAC,CAAC,IAAI,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,SAAS,CAAC;YACtD,CAAC,CAAC,IAAI,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAA;QAE5C,0EAA0E;QAC1E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;QAC5C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;QAC1C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;QAEzC,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,uBAAuB;IACxB,CAAC;IAEM,CAAC,MAAM,CAAC,OAAO,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;IACjB,CAAC;IAED;;OAEG;IAEI,IAAI,CAAC,QAAkC;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;;;WAGpC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;aAC3B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,GAAG,EAAE,CAAC;aAChC,IAAI,CAAC,MAAM,CAAC;GACd,CAAC,CAAA;QAEF,4FAA4F;QAC5F,2DAA2D;QAC3D,OAAO,QAAQ,CAAC,IAAI,CACnB,SAAS,CAAC,OAAO,CAAC,QAAoD,CAAC,CACzB,CAAA;IAChD,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,MAAuB;QAC1C,MAAM,OAAO,GAAG,GAAG,EAAE;YACpB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;IAsB5C,CAAC,CAAA;YAEF,SAAS,CAAC,GAAG,CAAC,MAAkD,CAAC,CAAA;QAClE,CAAC,CAAA;QAED,MAAM,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;IACjC,CAAC;CACD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
import type { PlacetypeRole } from "./definition.js";
|
|
7
|
+
import { Placetype } from "./Placetype.js";
|
|
8
|
+
/**
|
|
9
|
+
* A single node in a placetype graph. One entry per unique placetype name.
|
|
10
|
+
*/
|
|
11
|
+
export interface PlacetypeGraphNode {
|
|
12
|
+
name: string;
|
|
13
|
+
/** Brooklyn Integers ID. */
|
|
14
|
+
id: number;
|
|
15
|
+
role: PlacetypeRole;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A directed parent → child edge. Field names match d3-force / react-flow / cytoscape conventions
|
|
19
|
+
* so the graph drops straight into common viewers.
|
|
20
|
+
*/
|
|
21
|
+
export interface PlacetypeGraphLink {
|
|
22
|
+
source: string;
|
|
23
|
+
target: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Node-link projection of the placetype DAG rooted at a given placetype. Each node and each
|
|
27
|
+
* (parent, child) edge appears exactly once — see {@linkcode generatePlacetypeGraph} for why this is
|
|
28
|
+
* the preferred shape when the root has many shared descendants (e.g. `planet`).
|
|
29
|
+
*/
|
|
30
|
+
export interface PlacetypeGraph {
|
|
31
|
+
root: string;
|
|
32
|
+
nodes: PlacetypeGraphNode[];
|
|
33
|
+
links: PlacetypeGraphLink[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a node-link graph of a placetype and its descendants, optionally filtered by role.
|
|
37
|
+
*
|
|
38
|
+
* Unlike {@linkcode generatePlacetypeTree}, this emits each node and each (parent, child) edge
|
|
39
|
+
* exactly once. WOF placetypes form a DAG with heavy descendant sharing (e.g. `installation` is a
|
|
40
|
+
* leaf reachable from many parents); projecting that DAG to a nested tree duplicates every shared
|
|
41
|
+
* subtree under every parent path and blows up exponentially for roots like `planet` (~165 MB for
|
|
42
|
+
* the full hierarchy). The graph shape stays O(nodes + edges) regardless.
|
|
43
|
+
*
|
|
44
|
+
* Output is well-suited for d3-force, react-flow, cytoscape, and any other HTML graph viewer.
|
|
45
|
+
*/
|
|
46
|
+
export declare function generatePlacetypeGraph(placetype: Placetype, roles?: Iterable<PlacetypeRole> | null): PlacetypeGraph;
|
|
47
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,aAAa,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,kBAAkB,EAAE,CAAA;IAC3B,KAAK,EAAE,kBAAkB,EAAE,CAAA;CAC3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,IAAI,GAAG,cAAc,CAsCnH"}
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAgC1C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAoB,EAAE,KAAsC;IAClG,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAE7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAA;IACnD,MAAM,KAAK,GAAyB,EAAE,CAAA;IACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;IAEhC,MAAM,OAAO,GAAG,CAAC,CAAY,EAAQ,EAAE;QACtC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,OAAM;QAC7B,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,IAAe,EAAQ,EAAE;QACtC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAErB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,CAAA;YAEd,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAA;YAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7B,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBACtB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;YACtD,CAAC;YAED,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAQ;YACpC,IAAI,CAAC,KAAK,CAAC,CAAA;QACZ,CAAC;IACF,CAAC,CAAA;IAED,OAAO,CAAC,SAAS,CAAC,CAAA;IAClB,IAAI,CAAC,SAAS,CAAC,CAAA;IAEf,OAAO;QACN,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,KAAK;KACL,CAAA;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAA;AAC1B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA"}
|
|
@@ -3,18 +3,50 @@
|
|
|
3
3
|
* @license AGPL-3.0
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*/
|
|
6
|
-
import type
|
|
6
|
+
import { type PlacetypeRole } from "./definition.js";
|
|
7
7
|
import { Placetype } from "./Placetype.js";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Hand-tuned default colors for placetype roles. Used when no `interpolator` is passed to
|
|
10
|
+
* {@linkcode generateMermaidMarkup}. Each entry pairs a fill with a darker stroke and a text color
|
|
11
|
+
* chosen for contrast against the fill.
|
|
10
12
|
*/
|
|
11
13
|
export declare const PlacetypeRoleColor: {
|
|
12
14
|
readonly common: "#0066cc";
|
|
13
15
|
readonly common_optional: "#00cc66";
|
|
14
16
|
readonly optional: "#ffcc00";
|
|
15
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* A color interpolator — compatible with d3-scale-chromatic's `interpolate*` functions (e.g.
|
|
20
|
+
* `interpolateViridis`, `interpolateTurbo`). Receives `t ∈ [0, 1]` and returns a CSS color string.
|
|
21
|
+
*/
|
|
22
|
+
export type InterpolateColorCallback = (t: number) => string;
|
|
23
|
+
export interface GenerateMermaidMarkupOptions {
|
|
24
|
+
/** Restrict descendants to the given roles. Default: all roles. */
|
|
25
|
+
roles?: Iterable<PlacetypeRole>;
|
|
26
|
+
/**
|
|
27
|
+
* Edge color interpolator. Each edge is colored by its child node's depth from the root: `t =
|
|
28
|
+
* (childDepth - 1) / (maxDepth - 1)`. This traces a smooth gradient along any lineage path (e.g.
|
|
29
|
+
* `planet → continent → country → …`) and gives a visual cue for how deep an edge sits in the
|
|
30
|
+
* tree.
|
|
31
|
+
*
|
|
32
|
+
* Defaults to d3-scale-chromatic's `interpolateViridis` — perceptually uniform and
|
|
33
|
+
* colorblind-friendly. Node fills/strokes are _not_ affected; they always use the hand-tuned
|
|
34
|
+
* {@linkcode PlacetypeRoleColor} palette, which carries more semantic weight than a sampled
|
|
35
|
+
* gradient for only three categorical role values.
|
|
36
|
+
*/
|
|
37
|
+
edgeInterpolator?: InterpolateColorCallback;
|
|
38
|
+
}
|
|
16
39
|
/**
|
|
17
40
|
* Generate a Mermaid flowchart markup for a placetype and its descendants.
|
|
41
|
+
*
|
|
42
|
+
* The walk is a recursive `findChildren` traversal — every emitted edge is a real direct-parent →
|
|
43
|
+
* direct-child relationship. WOF placetypes form a DAG (e.g. `borough` has both `country` and
|
|
44
|
+
* `macroregion` as parents), so a child can legitimately appear on multiple edges; the `visited`
|
|
45
|
+
* set prevents the subtree below it from being re-emitted.
|
|
46
|
+
*
|
|
47
|
+
* Edges are colored by depth from the root via
|
|
48
|
+
* {@linkcode GenerateMermaidMarkupOptions.edgeInterpolator} (default: viridis), so any lineage path
|
|
49
|
+
* traces a smooth gradient down the chart. Node fills always use the hand-tuned role palette.
|
|
18
50
|
*/
|
|
19
|
-
export declare function generateMermaidMarkup(placetype: Placetype,
|
|
51
|
+
export declare function generateMermaidMarkup(placetype: Placetype, options?: GenerateMermaidMarkupOptions): string;
|
|
20
52
|
//# sourceMappingURL=mermaid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/mermaid.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../../../resources/whosonfirst/placetypes/mermaid.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,iBAAiB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAa1C;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;CAImB,CAAA;AAclD;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;AAE5D,MAAM,WAAW,4BAA4B;IAC5C,mEAAmE;IACnE,KAAK,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;IAC/B;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,wBAAwB,CAAA;CAC3C;AAuCD;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,GAAE,4BAAiC,GAAG,MAAM,CA+C9G"}
|