@mailwoman/corpus 5.9.0 → 5.10.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/src/adapter.d.ts +1 -1
- package/out/src/adapters/ban/adapter.d.ts +1 -1
- package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -1
- package/out/src/adapters/geonames/adapter.d.ts +1 -1
- package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
- package/out/src/adapters/gnaf/adapter.d.ts +1 -1
- package/out/src/adapters/index.d.ts +19 -19
- package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
- package/out/src/adapters/overture/adapter.d.ts +1 -1
- package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
- package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
- package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
- package/out/src/adapters/synth-po-box/adapter.d.ts +2 -2
- package/out/src/adapters/tiger/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-nad/adapter.d.ts +2 -2
- package/out/src/adapters/usgov-nad/adapter.js +1 -1
- package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
- package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
- package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
- package/out/src/adapters/wof-admin-json/adapter.d.ts +2 -2
- package/out/src/adapters/wof-postalcode-json/adapter.d.ts +2 -2
- package/out/src/align.d.ts +2 -2
- package/out/src/build.d.ts +4 -4
- package/out/src/index.d.ts +22 -21
- package/out/src/index.d.ts.map +1 -1
- package/out/src/index.js +1 -0
- package/out/src/index.js.map +1 -1
- package/out/src/parquet-wrapper/index.d.ts +3 -3
- package/out/src/parquet-wrapper/reader.d.ts +1 -1
- package/out/src/parquet-wrapper/writer.d.ts +4 -2
- package/out/src/parquet-wrapper/writer.d.ts.map +1 -1
- package/out/src/parquet-wrapper/writer.js +3 -1
- package/out/src/parquet-wrapper/writer.js.map +1 -1
- package/out/src/parquet.d.ts +3 -3
- package/out/src/runner.d.ts +2 -2
- package/out/src/shard-recipes/anchor-absorption.d.ts +1 -1
- package/out/src/shard-recipes/boundary-stress.d.ts +1 -1
- package/out/src/shard-recipes/country-balanced.d.ts +1 -1
- package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts +1 -1
- package/out/src/shard-recipes/fr-admin-split.d.ts +1 -1
- package/out/src/shard-recipes/fr-bare-street.d.ts +1 -1
- package/out/src/shard-recipes/fr-order.d.ts +1 -1
- package/out/src/shard-recipes/german.d.ts +1 -1
- package/out/src/shard-recipes/house-venue.d.ts +1 -1
- package/out/src/shard-recipes/index.d.ts +2 -2
- package/out/src/shard-recipes/intersection.d.ts +1 -1
- package/out/src/shard-recipes/locale.d.ts +2 -2
- package/out/src/shard-recipes/nl-postcode.d.ts +1 -1
- package/out/src/shard-recipes/no-street-led.d.ts +1 -1
- package/out/src/shard-recipes/no-street.d.ts +1 -1
- package/out/src/shard-recipes/po-box-cedex.d.ts +1 -1
- package/out/src/shard-recipes/po-box.d.ts +1 -1
- package/out/src/shard-recipes/si-bare-village.d.ts +1 -1
- package/out/src/shard-recipes/street-affix.d.ts +1 -1
- package/out/src/shard-recipes/street-bare.d.ts +1 -1
- package/out/src/shard-recipes/street.d.ts +1 -1
- package/out/src/shard-recipes/unit.d.ts +1 -1
- package/out/src/split.d.ts +1 -1
- package/out/src/split.js +1 -1
- package/out/src/split.js.map +1 -1
- package/out/src/synthesize-boundary-stress.d.ts +1 -1
- package/out/src/synthesize-german.d.ts +1 -1
- package/out/src/synthesize-house-venue.d.ts +1 -1
- package/out/src/synthesize-intersection.d.ts +1 -1
- package/out/src/synthesize-no-street.d.ts +1 -1
- package/out/src/synthesize-po-box.d.ts +1 -1
- package/out/src/synthesize-street.d.ts +1 -1
- package/out/src/synthesize.d.ts +2 -2
- package/out/src/tools/align-shard.d.ts +8 -0
- package/out/src/tools/align-shard.d.ts.map +1 -0
- package/out/src/tools/align-shard.js +58 -0
- package/out/src/tools/align-shard.js.map +1 -0
- package/out/src/tools/audit.d.ts +28 -0
- package/out/src/tools/audit.d.ts.map +1 -0
- package/out/src/tools/audit.js +273 -0
- package/out/src/tools/audit.js.map +1 -0
- package/out/src/tools/corpus-stats.d.ts +44 -0
- package/out/src/tools/corpus-stats.d.ts.map +1 -0
- package/out/src/tools/corpus-stats.js +151 -0
- package/out/src/tools/corpus-stats.js.map +1 -0
- package/out/src/tools/fetch/ban.d.ts +31 -0
- package/out/src/tools/fetch/ban.d.ts.map +1 -0
- package/out/src/tools/fetch/ban.js +248 -0
- package/out/src/tools/fetch/ban.js.map +1 -0
- package/out/src/tools/fetch/download.d.ts +49 -0
- package/out/src/tools/fetch/download.d.ts.map +1 -0
- package/out/src/tools/fetch/download.js +81 -0
- package/out/src/tools/fetch/download.js.map +1 -0
- package/out/src/tools/fetch/hrsa.d.ts +18 -0
- package/out/src/tools/fetch/hrsa.d.ts.map +1 -0
- package/out/src/tools/fetch/hrsa.js +46 -0
- package/out/src/tools/fetch/hrsa.js.map +1 -0
- package/out/src/tools/fetch/imls-pls.d.ts +25 -0
- package/out/src/tools/fetch/imls-pls.d.ts.map +1 -0
- package/out/src/tools/fetch/imls-pls.js +120 -0
- package/out/src/tools/fetch/imls-pls.js.map +1 -0
- package/out/src/tools/fetch/index.d.ts +118 -0
- package/out/src/tools/fetch/index.d.ts.map +1 -0
- package/out/src/tools/fetch/index.js +117 -0
- package/out/src/tools/fetch/index.js.map +1 -0
- package/out/src/tools/fetch/nad.d.ts +56 -0
- package/out/src/tools/fetch/nad.d.ts.map +1 -0
- package/out/src/tools/fetch/nad.js +225 -0
- package/out/src/tools/fetch/nad.js.map +1 -0
- package/out/src/tools/fetch/nppes.d.ts +26 -0
- package/out/src/tools/fetch/nppes.d.ts.map +1 -0
- package/out/src/tools/fetch/nppes.js +136 -0
- package/out/src/tools/fetch/nppes.js.map +1 -0
- package/out/src/tools/fetch/openaddresses.d.ts +59 -0
- package/out/src/tools/fetch/openaddresses.d.ts.map +1 -0
- package/out/src/tools/fetch/openaddresses.js +307 -0
- package/out/src/tools/fetch/openaddresses.js.map +1 -0
- package/out/src/tools/fetch/state-hi-schools.d.ts +25 -0
- package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -0
- package/out/src/tools/fetch/state-hi-schools.js +171 -0
- package/out/src/tools/fetch/state-hi-schools.js.map +1 -0
- package/out/src/tools/fetch/state-sources.d.ts +22 -0
- package/out/src/tools/fetch/state-sources.d.ts.map +1 -0
- package/out/src/tools/fetch/state-sources.js +110 -0
- package/out/src/tools/fetch/state-sources.js.map +1 -0
- package/out/src/tools/fetch/tiger-full.d.ts +36 -0
- package/out/src/tools/fetch/tiger-full.d.ts.map +1 -0
- package/out/src/tools/fetch/tiger-full.js +239 -0
- package/out/src/tools/fetch/tiger-full.js.map +1 -0
- package/out/src/tools/golden-expand.d.ts +74 -0
- package/out/src/tools/golden-expand.d.ts.map +1 -0
- package/out/src/tools/golden-expand.js +394 -0
- package/out/src/tools/golden-expand.js.map +1 -0
- package/out/src/tools/golden-promote.d.ts +60 -0
- package/out/src/tools/golden-promote.d.ts.map +1 -0
- package/out/src/tools/golden-promote.js +223 -0
- package/out/src/tools/golden-promote.js.map +1 -0
- package/out/src/tools/index.d.ts +24 -0
- package/out/src/tools/index.d.ts.map +1 -0
- package/out/src/tools/index.js +24 -0
- package/out/src/tools/index.js.map +1 -0
- package/out/src/tools/ingest-csv.d.ts +45 -0
- package/out/src/tools/ingest-csv.d.ts.map +1 -0
- package/out/src/tools/ingest-csv.js +309 -0
- package/out/src/tools/ingest-csv.js.map +1 -0
- package/out/src/tools/jsonl-to-parquet.d.ts +49 -0
- package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -0
- package/out/src/tools/jsonl-to-parquet.js +157 -0
- package/out/src/tools/jsonl-to-parquet.js.map +1 -0
- package/out/src/tools/lint-shard-vocab.d.ts +66 -0
- package/out/src/tools/lint-shard-vocab.d.ts.map +1 -0
- package/out/src/tools/lint-shard-vocab.js +266 -0
- package/out/src/tools/lint-shard-vocab.js.map +1 -0
- package/out/src/tools/lint-shard.d.ts +73 -0
- package/out/src/tools/lint-shard.d.ts.map +1 -0
- package/out/src/tools/lint-shard.js +350 -0
- package/out/src/tools/lint-shard.js.map +1 -0
- package/out/src/tools/overlay-manifest.d.ts +35 -0
- package/out/src/tools/overlay-manifest.d.ts.map +1 -0
- package/out/src/tools/overlay-manifest.js +85 -0
- package/out/src/tools/overlay-manifest.js.map +1 -0
- package/out/src/tools/shard-kryptonite.d.ts +28 -0
- package/out/src/tools/shard-kryptonite.d.ts.map +1 -0
- package/out/src/tools/shard-kryptonite.js +101 -0
- package/out/src/tools/shard-kryptonite.js.map +1 -0
- package/out/src/tools/shard-translit.d.ts +42 -0
- package/out/src/tools/shard-translit.d.ts.map +1 -0
- package/out/src/tools/shard-translit.js +196 -0
- package/out/src/tools/shard-translit.js.map +1 -0
- package/package.json +63 -7
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Fetch the US DOT National Address Database (NAD) — ~97 million structured US address-point
|
|
7
|
+
* records aggregated from state and local authorities. Source for the `usgov-nad` adapter (#30).
|
|
8
|
+
* US Public Domain (17 U.S.C. § 105).
|
|
9
|
+
*
|
|
10
|
+
* - Bounded per-chunk page concurrency (4× speedup at safe pressure)
|
|
11
|
+
* - 5× larger page size (5 000 vs. the old bash fetcher's 2 000) — fewer round-trips per chunk
|
|
12
|
+
* - Honest `complete: true` flag: only set when every page in the chunk fetched cleanly
|
|
13
|
+
* - Built-in fetch with gzip/brotli decompression (no curl + Python subprocess tax)
|
|
14
|
+
* - Per-chunk manifest with sha256 + record count + error count
|
|
15
|
+
*
|
|
16
|
+
* ## Source layout
|
|
17
|
+
*
|
|
18
|
+
* The ArcGIS FeatureServer is the only fully-automated path. As of 2026-05:
|
|
19
|
+
*
|
|
20
|
+
* - **`bulk`** mode requires a pre-signed S3 URL (Akamai blocks scripted curl on the DOT page). Pass
|
|
21
|
+
* `--nad-url <presigned>` from a browser visit to
|
|
22
|
+
* [https://www.transportation.gov/gis/national-address-database](https://www.transportation.gov/gis/national-address-database).
|
|
23
|
+
* - **`featureserver`** mode (default) pages the live FeatureService via OBJECTID ranges, writing
|
|
24
|
+
* NDJSON chunks into `<outRoot>/usgov-nad/featureserver/`.
|
|
25
|
+
*
|
|
26
|
+
* ## Usage
|
|
27
|
+
*
|
|
28
|
+
* ```sh
|
|
29
|
+
* mailwoman corpus fetch nad --out-root /mnt/playpen/mailwoman-data/corpus/sources
|
|
30
|
+
*
|
|
31
|
+
* # Resume from an OID
|
|
32
|
+
* mailwoman corpus fetch nad --start-oid 34400001
|
|
33
|
+
*
|
|
34
|
+
* # Increase concurrency on a fast link
|
|
35
|
+
* mailwoman corpus fetch nad --concurrency 8 --page-size 10000
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
import { existsSync, mkdirSync, statSync } from "node:fs";
|
|
39
|
+
import { writeFile } from "node:fs/promises";
|
|
40
|
+
import { join } from "node:path";
|
|
41
|
+
import { sha256File } from "@mailwoman/core/utils";
|
|
42
|
+
import { downloadToFile, readManifest, writeManifest } from "./download.js";
|
|
43
|
+
const SLUG = "usgov-nad";
|
|
44
|
+
const FEATURE_SERVICE_URL = "https://services.arcgis.com/xOi1kZaI0eWDREZv/ArcGIS/rest/services/Address_Points_from_National_Address_Database_view/FeatureServer/0";
|
|
45
|
+
async function fetchPage(startOID, endOID, pageSize) {
|
|
46
|
+
const url = new URL(`${FEATURE_SERVICE_URL}/query`);
|
|
47
|
+
url.searchParams.set("where", `OBJECTID BETWEEN ${startOID} AND ${endOID}`);
|
|
48
|
+
url.searchParams.set("outFields", "*");
|
|
49
|
+
url.searchParams.set("f", "json");
|
|
50
|
+
url.searchParams.set("resultRecordCount", String(pageSize));
|
|
51
|
+
const res = await fetch(url, {
|
|
52
|
+
headers: { "Accept-Encoding": "gzip, br" },
|
|
53
|
+
signal: AbortSignal.timeout(120_000),
|
|
54
|
+
});
|
|
55
|
+
if (!res.ok)
|
|
56
|
+
throw new Error(`HTTP ${res.status} ${res.statusText} on OID ${startOID}-${endOID}`);
|
|
57
|
+
const data = (await res.json());
|
|
58
|
+
if (data.error)
|
|
59
|
+
throw new Error(`ArcGIS error on OID ${startOID}-${endOID}: ${data.error.message}`);
|
|
60
|
+
return (data.features ?? []).map((f) => f.attributes);
|
|
61
|
+
}
|
|
62
|
+
async function discoverTotalCount() {
|
|
63
|
+
const url = new URL(`${FEATURE_SERVICE_URL}/query`);
|
|
64
|
+
url.searchParams.set("where", "1=1");
|
|
65
|
+
url.searchParams.set("returnCountOnly", "true");
|
|
66
|
+
url.searchParams.set("f", "json");
|
|
67
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(30_000) });
|
|
68
|
+
if (!res.ok)
|
|
69
|
+
throw new Error(`Failed to discover NAD record count: HTTP ${res.status}`);
|
|
70
|
+
const data = (await res.json());
|
|
71
|
+
if (typeof data.count !== "number")
|
|
72
|
+
throw new Error("NAD count query returned no count field");
|
|
73
|
+
return data.count;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fetch a single chunk by paging through its OID range with bounded concurrency. Returns the count of records written
|
|
77
|
+
* and the count of pages that errored. The caller decides whether to mark the chunk complete based on errors === 0.
|
|
78
|
+
*
|
|
79
|
+
* NOTE(phase1): this is a JSON API pager, not a file download — the shared `downloadToFile` doesn't apply here.
|
|
80
|
+
*/
|
|
81
|
+
async function fetchChunk(chunkPath, chunkStart, chunkEnd, pageSize, concurrency, report) {
|
|
82
|
+
const pageRanges = [];
|
|
83
|
+
for (let cursor = chunkStart; cursor <= chunkEnd; cursor += pageSize) {
|
|
84
|
+
pageRanges.push([cursor, Math.min(cursor + pageSize - 1, chunkEnd)]);
|
|
85
|
+
}
|
|
86
|
+
// Run bounded-concurrency page fetches. Results indexed by page slot for in-order write.
|
|
87
|
+
const pageResults = pageRanges.map(() => ({
|
|
88
|
+
rows: [],
|
|
89
|
+
error: null,
|
|
90
|
+
}));
|
|
91
|
+
let nextSlot = 0;
|
|
92
|
+
const workers = Array.from({ length: Math.min(concurrency, pageRanges.length) }, async () => {
|
|
93
|
+
while (true) {
|
|
94
|
+
const slot = nextSlot++;
|
|
95
|
+
if (slot >= pageRanges.length)
|
|
96
|
+
return;
|
|
97
|
+
const [s, e] = pageRanges[slot];
|
|
98
|
+
try {
|
|
99
|
+
pageResults[slot].rows = await fetchPage(s, e, pageSize);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
pageResults[slot].error = err;
|
|
103
|
+
report?.(` ✗ page ${s}-${e}: ${err.message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
await Promise.all(workers);
|
|
108
|
+
// Single-writer phase — write all pages in OID order to keep NDJSON deterministic.
|
|
109
|
+
const lines = [];
|
|
110
|
+
let errors = 0;
|
|
111
|
+
for (const { rows, error } of pageResults) {
|
|
112
|
+
if (error) {
|
|
113
|
+
errors++;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
for (const row of rows) {
|
|
117
|
+
lines.push(JSON.stringify(row));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
await writeFile(chunkPath, lines.length === 0 ? "" : lines.join("\n") + "\n");
|
|
121
|
+
return { recordCount: lines.length, errors };
|
|
122
|
+
}
|
|
123
|
+
async function featureserverMode(options, report) {
|
|
124
|
+
const chunkSize = options.chunkSize ?? 100_000;
|
|
125
|
+
const pageSize = options.pageSize ?? 5_000;
|
|
126
|
+
const concurrency = options.concurrency ?? 4;
|
|
127
|
+
const startOID = options.startOID ?? 1;
|
|
128
|
+
const chunkDir = join(options.outRoot, SLUG, "featureserver");
|
|
129
|
+
mkdirSync(chunkDir, { recursive: true });
|
|
130
|
+
report?.(`=== ${SLUG} / featureserver`);
|
|
131
|
+
report?.(` Discovering record count ...`);
|
|
132
|
+
const totalCount = await discoverTotalCount();
|
|
133
|
+
const endOID = options.endOID ?? totalCount;
|
|
134
|
+
report?.(` Total records: ${totalCount.toLocaleString()}`);
|
|
135
|
+
report?.(` OID range: ${startOID.toLocaleString()} .. ${endOID.toLocaleString()}`);
|
|
136
|
+
report?.(` Chunk size: ${chunkSize}, page size: ${pageSize}, concurrency: ${concurrency}`);
|
|
137
|
+
let fetched = 0;
|
|
138
|
+
let skipped = 0;
|
|
139
|
+
let totalRecords = 0;
|
|
140
|
+
let totalErrors = 0;
|
|
141
|
+
const failedCodes = [];
|
|
142
|
+
for (let cursor = startOID; cursor <= endOID; cursor += chunkSize) {
|
|
143
|
+
const chunkEnd = Math.min(cursor + chunkSize - 1, endOID);
|
|
144
|
+
const chunkName = `oids_${cursor}-${chunkEnd}`;
|
|
145
|
+
const chunkPath = join(chunkDir, `${chunkName}.ndjson`);
|
|
146
|
+
const manifestPath = join(chunkDir, `${chunkName}.manifest.json`);
|
|
147
|
+
// Idempotency: skip a chunk only if it's marked complete (the bash version's bug was
|
|
148
|
+
// marking complete on partial-failure runs; we now only set complete after a clean fetch).
|
|
149
|
+
if (existsSync(chunkPath)) {
|
|
150
|
+
const recorded = await readManifest(manifestPath);
|
|
151
|
+
if (recorded?.complete) {
|
|
152
|
+
skipped++;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
report?.(` Fetching ${chunkName} ...`);
|
|
157
|
+
const t0 = Date.now();
|
|
158
|
+
const { recordCount, errors } = await fetchChunk(chunkPath, cursor, chunkEnd, pageSize, concurrency, report);
|
|
159
|
+
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
|
160
|
+
const bytes = statSync(chunkPath).size;
|
|
161
|
+
const sha = await sha256File(chunkPath);
|
|
162
|
+
const manifest = {
|
|
163
|
+
source_url: FEATURE_SERVICE_URL,
|
|
164
|
+
oid_range: [cursor, chunkEnd],
|
|
165
|
+
downloaded_at: new Date().toISOString(),
|
|
166
|
+
filename: `${chunkName}.ndjson`,
|
|
167
|
+
sha256: sha,
|
|
168
|
+
bytes,
|
|
169
|
+
record_count: recordCount,
|
|
170
|
+
page_errors: errors,
|
|
171
|
+
complete: errors === 0,
|
|
172
|
+
};
|
|
173
|
+
await writeManifest(manifestPath, manifest);
|
|
174
|
+
const status = errors === 0 ? "✓" : `⚠ ${errors} page errors`;
|
|
175
|
+
report?.(` ${status} ${recordCount.toLocaleString()} records in ${elapsed}s (${(bytes / 1024 / 1024).toFixed(1)} MB)`);
|
|
176
|
+
fetched++;
|
|
177
|
+
totalRecords += recordCount;
|
|
178
|
+
totalErrors += errors;
|
|
179
|
+
if (errors > 0) {
|
|
180
|
+
failedCodes.push(chunkName);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
report?.(`=== featureserver summary ===`);
|
|
184
|
+
report?.(`chunks fetched: ${fetched} skipped: ${skipped}`);
|
|
185
|
+
report?.(`total records: ${totalRecords.toLocaleString()}`);
|
|
186
|
+
report?.(`page errors: ${totalErrors}`);
|
|
187
|
+
report?.(`output: ${chunkDir}`);
|
|
188
|
+
// `failed` counts page errors (the old exit-1 condition), `failedCodes` names the dirty chunks.
|
|
189
|
+
return { fetched, skipped, failed: totalErrors, failedCodes };
|
|
190
|
+
}
|
|
191
|
+
async function bulkMode(options, report) {
|
|
192
|
+
if (!options.nadURL) {
|
|
193
|
+
throw new Error(`bulk mode requires --nad-url. The DOT page is Akamai-gated; ` +
|
|
194
|
+
`visit https://www.transportation.gov/gis/national-address-database in a browser, ` +
|
|
195
|
+
`accept the disclaimer, and re-run with the pre-signed S3 URL.`);
|
|
196
|
+
}
|
|
197
|
+
const destDir = join(options.outRoot, SLUG);
|
|
198
|
+
mkdirSync(destDir, { recursive: true });
|
|
199
|
+
const filename = new URL(options.nadURL).pathname.split("/").pop() ?? "NAD.zip";
|
|
200
|
+
const destPath = join(destDir, filename);
|
|
201
|
+
report?.(`=== ${SLUG} / ${filename}`);
|
|
202
|
+
report?.(` URL: ${options.nadURL.slice(0, 100)}${options.nadURL.length > 100 ? "…" : ""}`);
|
|
203
|
+
const { bytes } = await downloadToFile({ url: options.nadURL, dest: destPath, timeoutMs: 3 * 3600 * 1000, report });
|
|
204
|
+
const sha = await sha256File(destPath);
|
|
205
|
+
await writeManifest(join(destDir, "MANIFEST.json"), {
|
|
206
|
+
source_url: options.nadURL,
|
|
207
|
+
downloaded_at: new Date().toISOString(),
|
|
208
|
+
filename,
|
|
209
|
+
sha256: sha,
|
|
210
|
+
bytes,
|
|
211
|
+
});
|
|
212
|
+
report?.(` ✓ ${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB sha256=${sha}`);
|
|
213
|
+
return { fetched: 1, skipped: 0, failed: 0, failedCodes: [] };
|
|
214
|
+
}
|
|
215
|
+
export async function fetchNAD(options, report) {
|
|
216
|
+
const mode = options.mode ?? "featureserver";
|
|
217
|
+
if (mode === "featureserver") {
|
|
218
|
+
return featureserverMode(options, report);
|
|
219
|
+
}
|
|
220
|
+
if (mode === "bulk") {
|
|
221
|
+
return bulkMode(options, report);
|
|
222
|
+
}
|
|
223
|
+
throw new Error(`unknown mode "${String(mode)}" (expected featureserver|bulk)`);
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=nad.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nad.js","sourceRoot":"","sources":["../../../../src/tools/fetch/nad.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Re-fetch the NPPES (National Plan and Provider Enumeration System) full monthly data
|
|
7
|
+
* dissemination file. ~7M provider rows with venue+address data. Source for the `usgov-nppes`
|
|
8
|
+
* adapter. US Public Domain.
|
|
9
|
+
*
|
|
10
|
+
* The file is published monthly by CMS. This module discovers the current filename by scraping the
|
|
11
|
+
* NPI_Files.html index, then downloads the ZIP and extracts only the main registry CSV
|
|
12
|
+
* (npidata_pfile_*.csv). The smaller endpoint/othername/pl files stay zipped — we don't need them.
|
|
13
|
+
*
|
|
14
|
+
* Uses Node's built-in fetch (gzip/brotli) to parse the HTML index and download the ZIP, and
|
|
15
|
+
* streaming sha256 instead of sha256sum. The ZIP is unpacked with the `unzip` binary via
|
|
16
|
+
* `node:child_process` (no clean Node equivalent for member listing + selective extraction). NOTE:
|
|
17
|
+
* the old bash fetcher used `curl --continue-at -` to resume a partial download; native fetch has
|
|
18
|
+
* no resume, so a partial run re-downloads from the start.
|
|
19
|
+
*
|
|
20
|
+
* Invoke via `mailwoman corpus fetch nppes --out-root <path>`. Idempotent: if dest CSV exists and
|
|
21
|
+
* sha256 matches MANIFEST, skips download.
|
|
22
|
+
*/
|
|
23
|
+
import type { BaseFetchOptions, FetchSummary } from "./download.ts";
|
|
24
|
+
export type FetchNPPESOptions = BaseFetchOptions;
|
|
25
|
+
export declare function fetchNPPES(options: FetchNPPESOptions, report?: (line: string) => void): Promise<FetchSummary>;
|
|
26
|
+
//# sourceMappingURL=nppes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nppes.d.ts","sourceRoot":"","sources":["../../../../src/tools/fetch/nppes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AASnE,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAA;AA6ChD,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CA2FnH"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Re-fetch the NPPES (National Plan and Provider Enumeration System) full monthly data
|
|
7
|
+
* dissemination file. ~7M provider rows with venue+address data. Source for the `usgov-nppes`
|
|
8
|
+
* adapter. US Public Domain.
|
|
9
|
+
*
|
|
10
|
+
* The file is published monthly by CMS. This module discovers the current filename by scraping the
|
|
11
|
+
* NPI_Files.html index, then downloads the ZIP and extracts only the main registry CSV
|
|
12
|
+
* (npidata_pfile_*.csv). The smaller endpoint/othername/pl files stay zipped — we don't need them.
|
|
13
|
+
*
|
|
14
|
+
* Uses Node's built-in fetch (gzip/brotli) to parse the HTML index and download the ZIP, and
|
|
15
|
+
* streaming sha256 instead of sha256sum. The ZIP is unpacked with the `unzip` binary via
|
|
16
|
+
* `node:child_process` (no clean Node equivalent for member listing + selective extraction). NOTE:
|
|
17
|
+
* the old bash fetcher used `curl --continue-at -` to resume a partial download; native fetch has
|
|
18
|
+
* no resume, so a partial run re-downloads from the start.
|
|
19
|
+
*
|
|
20
|
+
* Invoke via `mailwoman corpus fetch nppes --out-root <path>`. Idempotent: if dest CSV exists and
|
|
21
|
+
* sha256 matches MANIFEST, skips download.
|
|
22
|
+
*/
|
|
23
|
+
import { execFile } from "node:child_process";
|
|
24
|
+
import { existsSync, mkdirSync, statSync } from "node:fs";
|
|
25
|
+
import { rm } from "node:fs/promises";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { promisify } from "node:util";
|
|
28
|
+
import { sha256File } from "@mailwoman/core/utils";
|
|
29
|
+
import { downloadToFile, readManifest, writeManifest } from "./download.js";
|
|
30
|
+
const execFileAsync = promisify(execFile);
|
|
31
|
+
const INDEX_URL = "https://download.cms.gov/nppes/NPI_Files.html";
|
|
32
|
+
const BASE_URL = "https://download.cms.gov/nppes";
|
|
33
|
+
const SLUG = "usgov-nppes";
|
|
34
|
+
/**
|
|
35
|
+
* Scrape the NPI_Files.html index for the latest full monthly ZIP. Full-replacement files match
|
|
36
|
+
* `NPPES_Data_Dissemination_<Month>_<Year>*.zip`; weekly files carry a `MMDDYY_MMDDYY` date range, which we exclude.
|
|
37
|
+
*/
|
|
38
|
+
async function discoverLatestZip() {
|
|
39
|
+
const res = await fetch(INDEX_URL, {
|
|
40
|
+
headers: { "Accept-Encoding": "gzip, br" },
|
|
41
|
+
signal: AbortSignal.timeout(60_000),
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok)
|
|
44
|
+
throw new Error(`HTTP ${res.status} ${res.statusText} on ${INDEX_URL}`);
|
|
45
|
+
const html = await res.text();
|
|
46
|
+
for (const match of html.matchAll(/NPPES_Data_Dissemination_[A-Za-z]+_\d{4}[^"]*\.zip/g)) {
|
|
47
|
+
const name = match[0];
|
|
48
|
+
if (name && !/\d{6}_\d{6}/.test(name))
|
|
49
|
+
return name;
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
/** Extract the main registry CSV name (npidata_pfile_*.csv) from a ZIP's `unzip -l` listing. */
|
|
54
|
+
async function findNpidataCSV(zipPath) {
|
|
55
|
+
const listing = await execFileAsync("unzip", ["-l", zipPath]);
|
|
56
|
+
for (const line of listing.stdout.split("\n")) {
|
|
57
|
+
const match = /npidata_pfile\S+\.csv/i.exec(line);
|
|
58
|
+
if (match?.[0])
|
|
59
|
+
return match[0];
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
export async function fetchNPPES(options, report) {
|
|
64
|
+
const destDir = join(options.outRoot, SLUG);
|
|
65
|
+
mkdirSync(destDir, { recursive: true });
|
|
66
|
+
const manifestPath = join(destDir, "MANIFEST.json");
|
|
67
|
+
report?.(`=== ${SLUG}`);
|
|
68
|
+
report?.(` Discovering latest full-replacement ZIP from ${INDEX_URL} ...`);
|
|
69
|
+
const zipFilename = await discoverLatestZip();
|
|
70
|
+
if (!zipFilename) {
|
|
71
|
+
report?.(` ✗ Could not discover ZIP filename from ${INDEX_URL}`);
|
|
72
|
+
return { fetched: 0, skipped: 0, failed: 1, failedCodes: [SLUG] };
|
|
73
|
+
}
|
|
74
|
+
const zipURL = `${BASE_URL}/${zipFilename}`;
|
|
75
|
+
const zipDest = join(destDir, zipFilename);
|
|
76
|
+
report?.(` Latest full file: ${zipFilename}`);
|
|
77
|
+
// ------------------------------------------------------------------
|
|
78
|
+
// Idempotency check: if the main CSV already exists and sha matches,
|
|
79
|
+
// skip re-download.
|
|
80
|
+
// ------------------------------------------------------------------
|
|
81
|
+
const recorded = await readManifest(manifestPath);
|
|
82
|
+
if (recorded?.sha256 && recorded.filename) {
|
|
83
|
+
const recordedPath = join(destDir, recorded.filename);
|
|
84
|
+
if (existsSync(recordedPath) && (await sha256File(recordedPath)) === recorded.sha256) {
|
|
85
|
+
report?.(" ✓ Already current (sha256 matches MANIFEST) — skipping download.");
|
|
86
|
+
return { fetched: 0, skipped: 1, failed: 0, failedCodes: [] };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ------------------------------------------------------------------
|
|
90
|
+
// Download ZIP (large; 60-minute timeout)
|
|
91
|
+
// ------------------------------------------------------------------
|
|
92
|
+
report?.(` Downloading ${zipURL} ...`);
|
|
93
|
+
const { bytes: zipSize } = await downloadToFile({
|
|
94
|
+
url: zipURL,
|
|
95
|
+
dest: zipDest,
|
|
96
|
+
timeoutMs: 3_600_000,
|
|
97
|
+
headers: { "Accept-Encoding": "gzip, br" },
|
|
98
|
+
report,
|
|
99
|
+
});
|
|
100
|
+
report?.(` Downloaded: ${(zipSize / 1024 / 1024).toFixed(1)} MB`);
|
|
101
|
+
// ------------------------------------------------------------------
|
|
102
|
+
// Extract only the main registry CSV (npidata_pfile_*.csv)
|
|
103
|
+
// ------------------------------------------------------------------
|
|
104
|
+
report?.(" Extracting npidata_pfile CSV from ZIP ...");
|
|
105
|
+
const csvName = await findNpidataCSV(zipDest);
|
|
106
|
+
if (!csvName) {
|
|
107
|
+
report?.(" ✗ Could not find npidata_pfile CSV inside ZIP");
|
|
108
|
+
return { fetched: 0, skipped: 0, failed: 1, failedCodes: [SLUG] };
|
|
109
|
+
}
|
|
110
|
+
report?.(` Extracting: ${csvName}`);
|
|
111
|
+
await execFileAsync("unzip", ["-o", "-j", zipDest, csvName, "-d", destDir]);
|
|
112
|
+
const csvDest = join(destDir, csvName);
|
|
113
|
+
const csvSize = statSync(csvDest).size;
|
|
114
|
+
const csvSha = await sha256File(csvDest);
|
|
115
|
+
report?.(` CSV size: ${(csvSize / 1024 / 1024).toFixed(1)} MB`);
|
|
116
|
+
// ------------------------------------------------------------------
|
|
117
|
+
// Remove the ZIP to reclaim ~1 GB (the CSV is what adapters consume)
|
|
118
|
+
// ------------------------------------------------------------------
|
|
119
|
+
await rm(zipDest, { force: true });
|
|
120
|
+
report?.(" Removed ZIP (CSV kept)");
|
|
121
|
+
// ------------------------------------------------------------------
|
|
122
|
+
// Write MANIFEST (records the extracted CSV, not the ZIP)
|
|
123
|
+
// ------------------------------------------------------------------
|
|
124
|
+
const manifest = {
|
|
125
|
+
source_url: zipURL,
|
|
126
|
+
downloaded_at: new Date().toISOString(),
|
|
127
|
+
filename: csvName,
|
|
128
|
+
sha256: csvSha,
|
|
129
|
+
bytes: csvSize,
|
|
130
|
+
};
|
|
131
|
+
await writeManifest(manifestPath, manifest);
|
|
132
|
+
report?.(` ✓ ${(csvSize / 1024 / 1024).toFixed(1)} MB sha256=${csvSha}`);
|
|
133
|
+
report?.(` MANIFEST written to ${manifestPath}`);
|
|
134
|
+
return { fetched: 1, skipped: 0, failed: 0, failedCodes: [] };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=nppes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nppes.js","sourceRoot":"","sources":["../../../../src/tools/fetch/nppes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGlD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE3E,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AAEzC,MAAM,SAAS,GAAG,+CAA+C,CAAA;AACjE,MAAM,QAAQ,GAAG,gCAAgC,CAAA;AACjD,MAAM,IAAI,GAAG,aAAa,CAAA;AAY1B;;;GAGG;AACH,KAAK,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,EAAE;QAClC,OAAO,EAAE,EAAE,iBAAiB,EAAE,UAAU,EAAE;QAC1C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACnC,CAAC,CAAA;IAEF,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,OAAO,SAAS,EAAE,CAAC,CAAA;IACpF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;IAE7B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,qDAAqD,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAErB,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAA;IACnD,CAAC;IAED,OAAO,SAAS,CAAA;AACjB,CAAC;AAED,gGAAgG;AAChG,KAAK,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;IAE7D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEjD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IAChC,CAAC;IAED,OAAO,SAAS,CAAA;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B,EAAE,MAA+B;IAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC3C,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;IAEnD,MAAM,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;IACvB,MAAM,EAAE,CAAC,kDAAkD,SAAS,MAAM,CAAC,CAAA;IAE3E,MAAM,WAAW,GAAG,MAAM,iBAAiB,EAAE,CAAA;IAE7C,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,EAAE,CAAC,4CAA4C,SAAS,EAAE,CAAC,CAAA;QAEjE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;IAClE,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,QAAQ,IAAI,WAAW,EAAE,CAAA;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;IAC1C,MAAM,EAAE,CAAC,uBAAuB,WAAW,EAAE,CAAC,CAAA;IAE9C,qEAAqE;IACrE,qEAAqE;IACrE,oBAAoB;IACpB,qEAAqE;IACrE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAA0B,YAAY,CAAC,CAAA;IAE1E,IAAI,QAAQ,EAAE,MAAM,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAErD,IAAI,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,YAAY,CAAC,CAAC,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;YACtF,MAAM,EAAE,CAAC,oEAAoE,CAAC,CAAA;YAE9E,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAA;QAC9D,CAAC;IACF,CAAC;IAED,qEAAqE;IACrE,0CAA0C;IAC1C,qEAAqE;IACrE,MAAM,EAAE,CAAC,iBAAiB,MAAM,MAAM,CAAC,CAAA;IACvC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC;QAC/C,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,OAAO;QACb,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,EAAE,iBAAiB,EAAE,UAAU,EAAE;QAC1C,MAAM;KACN,CAAC,CAAA;IACF,MAAM,EAAE,CAAC,iBAAiB,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAElE,qEAAqE;IACrE,2DAA2D;IAC3D,qEAAqE;IACrE,MAAM,EAAE,CAAC,6CAA6C,CAAC,CAAA;IACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAA;IAE7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,EAAE,CAAC,iDAAiD,CAAC,CAAA;QAE3D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,CAAA;IAClE,CAAC;IAED,MAAM,EAAE,CAAC,iBAAiB,OAAO,EAAE,CAAC,CAAA;IACpC,MAAM,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;IAE3E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAA;IACtC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAA;IACxC,MAAM,EAAE,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAEhE,qEAAqE;IACrE,qEAAqE;IACrE,qEAAqE;IACrE,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAClC,MAAM,EAAE,CAAC,0BAA0B,CAAC,CAAA;IAEpC,qEAAqE;IACrE,0DAA0D;IAC1D,qEAAqE;IACrE,MAAM,QAAQ,GAAmB;QAChC,UAAU,EAAE,MAAM;QAClB,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACvC,QAAQ,EAAE,OAAO;QACjB,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,OAAO;KACd,CAAA;IACD,MAAM,aAAa,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAA;IAE3C,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,MAAM,EAAE,CAAC,CAAA;IAC1E,MAAM,EAAE,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAA;IAEjD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAA;AAC9D,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Fetch an OpenAddresses country collection from batch.openaddresses.io.
|
|
7
|
+
*
|
|
8
|
+
* Source: https://batch.openaddresses.io
|
|
9
|
+
* License: MIXED — OpenAddresses aggregates hundreds of upstream sources with per-source licenses
|
|
10
|
+
* (CC-BY, CC0, PDDL, ODbL, CC-BY-SA, and proprietary attribution-only). The per-row LICENSE filter
|
|
11
|
+
* in the openaddresses adapter is essential for proprietary-weights training: Tier-C rows (ODbL,
|
|
12
|
+
* CC-BY-SA, CC-SA) are dropped at ingest by default. This module downloads the raw collection; the
|
|
13
|
+
* adapter does the license gating.
|
|
14
|
+
*
|
|
15
|
+
* Native `fetch` streams the download to disk (no curl + Python subprocess tax);
|
|
16
|
+
* `node:child_process` keeps the genuine shell ops it still needs (`file` magic detection +
|
|
17
|
+
* `gunzip` decompression, both nice/ionice-deprioritized).
|
|
18
|
+
*
|
|
19
|
+
* ## Authentication note (2026-05-18)
|
|
20
|
+
*
|
|
21
|
+
* The batch.openaddresses.io download endpoint now requires a registered account. Downloads are
|
|
22
|
+
* still free at the "basic" tier (GeoJSON+LD output).
|
|
23
|
+
*
|
|
24
|
+
* 1. Register at https://batch.openaddresses.io/register
|
|
25
|
+
* 2. Log in and go to Profile → "Create Token"
|
|
26
|
+
* 3. Export the token: `export OA_BATCH_TOKEN=<your-token>`
|
|
27
|
+
* 4. Re-run the command.
|
|
28
|
+
*
|
|
29
|
+
* The collection URL pattern (verified 2026-05-18):
|
|
30
|
+
*
|
|
31
|
+
* - `POST /api/login {username, password}` → `{token}`
|
|
32
|
+
* - `GET /api/job/{job_id}/output/source.geojson.gz?token={token}`
|
|
33
|
+
*
|
|
34
|
+
* Collections are downloaded as a combined GeoJSON.gz via:
|
|
35
|
+
*
|
|
36
|
+
* - `GET /api/collections/{collection_id}/download` (returns a redirect to S3)
|
|
37
|
+
*
|
|
38
|
+
* Collection IDs discovered from `/api/collections`:
|
|
39
|
+
*
|
|
40
|
+
* - `id=6 name="ca" size=2044467556` (~1.9 GiB uncompressed, verified 2026-05-18)
|
|
41
|
+
*
|
|
42
|
+
* ## Usage
|
|
43
|
+
*
|
|
44
|
+
* ```sh
|
|
45
|
+
* # With token (preferred). Default country: ca. Supports any OA country code (us-west, fr, …)
|
|
46
|
+
* OA_BATCH_TOKEN=<token> mailwoman corpus fetch openaddresses --country ca \
|
|
47
|
+
* --out-root /mnt/playpen/mailwoman-data/corpus/sources
|
|
48
|
+
*
|
|
49
|
+
* # Without token (will detect + print instructions, then report the failure):
|
|
50
|
+
* mailwoman corpus fetch openaddresses --country ca
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
import type { BaseFetchOptions, FetchSummary } from "./download.ts";
|
|
54
|
+
export interface FetchOpenAddressesOptions extends BaseFetchOptions {
|
|
55
|
+
/** OA country collection code. Default `ca`. */
|
|
56
|
+
country?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function fetchOpenAddresses(options: FetchOpenAddressesOptions, report?: (line: string) => void): Promise<FetchSummary>;
|
|
59
|
+
//# sourceMappingURL=openaddresses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openaddresses.d.ts","sourceRoot":"","sources":["../../../../src/tools/fetch/openaddresses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAaH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAoBnE,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IAClE,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAkGD,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,yBAAyB,EAClC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC7B,OAAO,CAAC,YAAY,CAAC,CA+LvB"}
|