/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * Shared utilities for the `wof-admin` / `wof-postalcode` GeoJSON-bundle adapters. * * The Phase 1.5.1 pivot moved both adapters off the SpatiaLite distribution (dead mirror, empty * `names` table) and onto the per-record GeoJSON bundles published as * `github.com/whosonfirst-data/whosonfirst-data-{admin,postalcode}-` repos. Each repo carries * a tree of `data/<3>/<3>/<3>/.geojson` files plus alternate-geometry siblings like * `-alt-quattroshapes.geojson`. The adapter only consumes the canonical record (no `-alt-` * files); the alternate geometries are irrelevant to the name/hierarchy concerns Phase 1 cares * about. * * This module provides: * * - `WOFRecord`: the lightweight per-feature shape both adapters carry in their ancestry index. * - `walkFeatures`: streaming directory walk → parsed `WOFRecord`s (skips alt files, bad JSON, * deprecated records). * - `buildAncestryIndex`: in-memory ancestry chain construction (`Map`). * - `extractNameVariants`: pulls `name:*` localized name lists off a feature's properties. * - `normalizeNameKey`: turns `"name:eng_x_colloquial"` into `"name-eng-x-colloquial"` for safe use * in `source_id` suffixes. * * `is_current` semantics follow WOF + Pelias: `mz:is_current` ∈ {`1`, `-1`} are live; `0` is * superseded. WOF's official postalcode distribution stamps every row with `-1` ("unknown but * treated as active"), which is why the previous SpatiaLite adapter's `is_current = 1` filter * silently emitted zero rows from the real corpus. */ /** * A WOF GeoJSON feature, as published by the per-record bundles. */ export interface WOFFeature { type?: string; id?: number | string; properties?: Record | null; } /** * Lightweight in-memory shape both adapters keep per record. Geometry is intentionally dropped — it's 95% of the file * weight and the adapters never consult it. */ export interface WOFRecord { id: number; parent_id: number | null; /** * Canonical `wof:name` of the record. */ name: string; placetype: string; /** * ISO 3166-1 alpha-2 from `wof:country`. */ country: string; /** * Localized name variants from `name:*` properties. * * Keys are the raw `name:eng_x_preferred` form; values are the first non-empty string from the underlying array (WOF * stores variants as arrays even when only one form is present). The canonical `wof:name` is NOT included here — * adapters add a synthetic `"default"` slot for it. */ nameVariants: Map; } /** * `mz:is_current` ∈ {`1`, `-1`} → keep. `0` → drop. * * Real WOF postalcode distros tag every row `-1` ("unknown but treated as active"); the Pelias importer accepts `-1` * alongside `1`. Tightening the predicate to `= 1` is the trap: the postalcode distros then contribute ZERO rows to the * corpus, silently, with nothing raised to notice it by. */ export declare function isCurrentFeature(props: Record): boolean; /** * Pull `name:*` localized variants off a WOF feature's properties. WOF stores variants as arrays (`["Saint * Petersburg"]`); we lift the first non-empty string. Multiple-value variants (rare; usually historical aliases) are * not split into separate rows by this helper — adapters can opt in by iterating the underlying array if they need it. */ export declare function extractNameVariants(props: Record): Map; /** * Turn a `name:*` property key into a hyphen-safe suffix fragment for `source_id`. * * `"name:eng_x_colloquial"` → `"name-eng-x-colloquial"`. `:` and `_` both become `-` because both collide with the * existing source_id separator vocabulary and downstream consumers split on `-`. */ export declare function normalizeNameKey(rawKey: string): string; /** * Stream every canonical GeoJSON file under `repoDir` and yield parsed `WOFRecord`s. * * `repoDir` may point at a single cloned `whosonfirst-data-*` repo OR at a parent directory holding several such repos * (the corpus pipeline clones all four into a shared `wof/repos/` root and runs the adapter against that root). * `**\/*.geojson` walks the whole tree; `-alt-` siblings are skipped since they're alternate-geometry exports, not new * records. * * Errors per-file (unreadable, malformed JSON, missing properties) are swallowed so one bad file doesn't poison a 3 GB * walk. Adapters can add stricter validation downstream if they need it. */ export declare function walkFeatures(repoDir: string, opts?: { signal?: AbortSignal; }): AsyncIterable; /** * Build an in-memory ancestry index: `Map` walking `parent_id` upward and stopping * at the first missing link. A cycle guard halts at any re-visit (defensive — WOF data is acyclic by construction but * corrupt fixtures shouldn't infinite-loop the adapter). * * Records whose ancestors aren't in `byID` (e.g. an FR locality whose region wasn't included in the cloned repo set) * get a shorter chain; the variant emission gracefully degrades. */ export type AncestryIndex = Map; export declare function buildAncestryIndex(byID: Map): AncestryIndex; //# sourceMappingURL=wof-json.d.ts.map