@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.
Files changed (169) hide show
  1. package/out/src/adapter.d.ts +1 -1
  2. package/out/src/adapters/ban/adapter.d.ts +1 -1
  3. package/out/src/adapters/fcc-bdc/adapter.d.ts +1 -1
  4. package/out/src/adapters/geonames/adapter.d.ts +1 -1
  5. package/out/src/adapters/geonames-postal/adapter.d.ts +1 -1
  6. package/out/src/adapters/gnaf/adapter.d.ts +1 -1
  7. package/out/src/adapters/index.d.ts +19 -19
  8. package/out/src/adapters/openaddresses/adapter.d.ts +1 -1
  9. package/out/src/adapters/overture/adapter.d.ts +1 -1
  10. package/out/src/adapters/state-hi-schools/adapter.d.ts +1 -1
  11. package/out/src/adapters/state-ia-contractors/adapter.d.ts +1 -1
  12. package/out/src/adapters/state-ny-notaries/adapter.d.ts +1 -1
  13. package/out/src/adapters/state-tx-notaries/adapter.d.ts +1 -1
  14. package/out/src/adapters/synth-po-box/adapter.d.ts +2 -2
  15. package/out/src/adapters/tiger/adapter.d.ts +1 -1
  16. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +1 -1
  17. package/out/src/adapters/usgov-imls-pls/adapter.d.ts +1 -1
  18. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts +1 -1
  19. package/out/src/adapters/usgov-nad/adapter.d.ts +2 -2
  20. package/out/src/adapters/usgov-nad/adapter.js +1 -1
  21. package/out/src/adapters/usgov-nppes/adapter.d.ts +1 -1
  22. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts +1 -1
  23. package/out/src/adapters/wof-admin-jp/adapter.d.ts +1 -1
  24. package/out/src/adapters/wof-admin-json/adapter.d.ts +2 -2
  25. package/out/src/adapters/wof-postalcode-json/adapter.d.ts +2 -2
  26. package/out/src/align.d.ts +2 -2
  27. package/out/src/build.d.ts +4 -4
  28. package/out/src/index.d.ts +22 -21
  29. package/out/src/index.d.ts.map +1 -1
  30. package/out/src/index.js +1 -0
  31. package/out/src/index.js.map +1 -1
  32. package/out/src/parquet-wrapper/index.d.ts +3 -3
  33. package/out/src/parquet-wrapper/reader.d.ts +1 -1
  34. package/out/src/parquet-wrapper/writer.d.ts +4 -2
  35. package/out/src/parquet-wrapper/writer.d.ts.map +1 -1
  36. package/out/src/parquet-wrapper/writer.js +3 -1
  37. package/out/src/parquet-wrapper/writer.js.map +1 -1
  38. package/out/src/parquet.d.ts +3 -3
  39. package/out/src/runner.d.ts +2 -2
  40. package/out/src/shard-recipes/anchor-absorption.d.ts +1 -1
  41. package/out/src/shard-recipes/boundary-stress.d.ts +1 -1
  42. package/out/src/shard-recipes/country-balanced.d.ts +1 -1
  43. package/out/src/shard-recipes/cz-pcfirst-preposition.d.ts +1 -1
  44. package/out/src/shard-recipes/fr-admin-split.d.ts +1 -1
  45. package/out/src/shard-recipes/fr-bare-street.d.ts +1 -1
  46. package/out/src/shard-recipes/fr-order.d.ts +1 -1
  47. package/out/src/shard-recipes/german.d.ts +1 -1
  48. package/out/src/shard-recipes/house-venue.d.ts +1 -1
  49. package/out/src/shard-recipes/index.d.ts +2 -2
  50. package/out/src/shard-recipes/intersection.d.ts +1 -1
  51. package/out/src/shard-recipes/locale.d.ts +2 -2
  52. package/out/src/shard-recipes/nl-postcode.d.ts +1 -1
  53. package/out/src/shard-recipes/no-street-led.d.ts +1 -1
  54. package/out/src/shard-recipes/no-street.d.ts +1 -1
  55. package/out/src/shard-recipes/po-box-cedex.d.ts +1 -1
  56. package/out/src/shard-recipes/po-box.d.ts +1 -1
  57. package/out/src/shard-recipes/si-bare-village.d.ts +1 -1
  58. package/out/src/shard-recipes/street-affix.d.ts +1 -1
  59. package/out/src/shard-recipes/street-bare.d.ts +1 -1
  60. package/out/src/shard-recipes/street.d.ts +1 -1
  61. package/out/src/shard-recipes/unit.d.ts +1 -1
  62. package/out/src/split.d.ts +1 -1
  63. package/out/src/split.js +1 -1
  64. package/out/src/split.js.map +1 -1
  65. package/out/src/synthesize-boundary-stress.d.ts +1 -1
  66. package/out/src/synthesize-german.d.ts +1 -1
  67. package/out/src/synthesize-house-venue.d.ts +1 -1
  68. package/out/src/synthesize-intersection.d.ts +1 -1
  69. package/out/src/synthesize-no-street.d.ts +1 -1
  70. package/out/src/synthesize-po-box.d.ts +1 -1
  71. package/out/src/synthesize-street.d.ts +1 -1
  72. package/out/src/synthesize.d.ts +2 -2
  73. package/out/src/tools/align-shard.d.ts +8 -0
  74. package/out/src/tools/align-shard.d.ts.map +1 -0
  75. package/out/src/tools/align-shard.js +58 -0
  76. package/out/src/tools/align-shard.js.map +1 -0
  77. package/out/src/tools/audit.d.ts +28 -0
  78. package/out/src/tools/audit.d.ts.map +1 -0
  79. package/out/src/tools/audit.js +273 -0
  80. package/out/src/tools/audit.js.map +1 -0
  81. package/out/src/tools/corpus-stats.d.ts +44 -0
  82. package/out/src/tools/corpus-stats.d.ts.map +1 -0
  83. package/out/src/tools/corpus-stats.js +151 -0
  84. package/out/src/tools/corpus-stats.js.map +1 -0
  85. package/out/src/tools/fetch/ban.d.ts +31 -0
  86. package/out/src/tools/fetch/ban.d.ts.map +1 -0
  87. package/out/src/tools/fetch/ban.js +248 -0
  88. package/out/src/tools/fetch/ban.js.map +1 -0
  89. package/out/src/tools/fetch/download.d.ts +49 -0
  90. package/out/src/tools/fetch/download.d.ts.map +1 -0
  91. package/out/src/tools/fetch/download.js +81 -0
  92. package/out/src/tools/fetch/download.js.map +1 -0
  93. package/out/src/tools/fetch/hrsa.d.ts +18 -0
  94. package/out/src/tools/fetch/hrsa.d.ts.map +1 -0
  95. package/out/src/tools/fetch/hrsa.js +46 -0
  96. package/out/src/tools/fetch/hrsa.js.map +1 -0
  97. package/out/src/tools/fetch/imls-pls.d.ts +25 -0
  98. package/out/src/tools/fetch/imls-pls.d.ts.map +1 -0
  99. package/out/src/tools/fetch/imls-pls.js +120 -0
  100. package/out/src/tools/fetch/imls-pls.js.map +1 -0
  101. package/out/src/tools/fetch/index.d.ts +118 -0
  102. package/out/src/tools/fetch/index.d.ts.map +1 -0
  103. package/out/src/tools/fetch/index.js +117 -0
  104. package/out/src/tools/fetch/index.js.map +1 -0
  105. package/out/src/tools/fetch/nad.d.ts +56 -0
  106. package/out/src/tools/fetch/nad.d.ts.map +1 -0
  107. package/out/src/tools/fetch/nad.js +225 -0
  108. package/out/src/tools/fetch/nad.js.map +1 -0
  109. package/out/src/tools/fetch/nppes.d.ts +26 -0
  110. package/out/src/tools/fetch/nppes.d.ts.map +1 -0
  111. package/out/src/tools/fetch/nppes.js +136 -0
  112. package/out/src/tools/fetch/nppes.js.map +1 -0
  113. package/out/src/tools/fetch/openaddresses.d.ts +59 -0
  114. package/out/src/tools/fetch/openaddresses.d.ts.map +1 -0
  115. package/out/src/tools/fetch/openaddresses.js +307 -0
  116. package/out/src/tools/fetch/openaddresses.js.map +1 -0
  117. package/out/src/tools/fetch/state-hi-schools.d.ts +25 -0
  118. package/out/src/tools/fetch/state-hi-schools.d.ts.map +1 -0
  119. package/out/src/tools/fetch/state-hi-schools.js +171 -0
  120. package/out/src/tools/fetch/state-hi-schools.js.map +1 -0
  121. package/out/src/tools/fetch/state-sources.d.ts +22 -0
  122. package/out/src/tools/fetch/state-sources.d.ts.map +1 -0
  123. package/out/src/tools/fetch/state-sources.js +110 -0
  124. package/out/src/tools/fetch/state-sources.js.map +1 -0
  125. package/out/src/tools/fetch/tiger-full.d.ts +36 -0
  126. package/out/src/tools/fetch/tiger-full.d.ts.map +1 -0
  127. package/out/src/tools/fetch/tiger-full.js +239 -0
  128. package/out/src/tools/fetch/tiger-full.js.map +1 -0
  129. package/out/src/tools/golden-expand.d.ts +74 -0
  130. package/out/src/tools/golden-expand.d.ts.map +1 -0
  131. package/out/src/tools/golden-expand.js +394 -0
  132. package/out/src/tools/golden-expand.js.map +1 -0
  133. package/out/src/tools/golden-promote.d.ts +60 -0
  134. package/out/src/tools/golden-promote.d.ts.map +1 -0
  135. package/out/src/tools/golden-promote.js +223 -0
  136. package/out/src/tools/golden-promote.js.map +1 -0
  137. package/out/src/tools/index.d.ts +24 -0
  138. package/out/src/tools/index.d.ts.map +1 -0
  139. package/out/src/tools/index.js +24 -0
  140. package/out/src/tools/index.js.map +1 -0
  141. package/out/src/tools/ingest-csv.d.ts +45 -0
  142. package/out/src/tools/ingest-csv.d.ts.map +1 -0
  143. package/out/src/tools/ingest-csv.js +309 -0
  144. package/out/src/tools/ingest-csv.js.map +1 -0
  145. package/out/src/tools/jsonl-to-parquet.d.ts +49 -0
  146. package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -0
  147. package/out/src/tools/jsonl-to-parquet.js +157 -0
  148. package/out/src/tools/jsonl-to-parquet.js.map +1 -0
  149. package/out/src/tools/lint-shard-vocab.d.ts +66 -0
  150. package/out/src/tools/lint-shard-vocab.d.ts.map +1 -0
  151. package/out/src/tools/lint-shard-vocab.js +266 -0
  152. package/out/src/tools/lint-shard-vocab.js.map +1 -0
  153. package/out/src/tools/lint-shard.d.ts +73 -0
  154. package/out/src/tools/lint-shard.d.ts.map +1 -0
  155. package/out/src/tools/lint-shard.js +350 -0
  156. package/out/src/tools/lint-shard.js.map +1 -0
  157. package/out/src/tools/overlay-manifest.d.ts +35 -0
  158. package/out/src/tools/overlay-manifest.d.ts.map +1 -0
  159. package/out/src/tools/overlay-manifest.js +85 -0
  160. package/out/src/tools/overlay-manifest.js.map +1 -0
  161. package/out/src/tools/shard-kryptonite.d.ts +28 -0
  162. package/out/src/tools/shard-kryptonite.d.ts.map +1 -0
  163. package/out/src/tools/shard-kryptonite.js +101 -0
  164. package/out/src/tools/shard-kryptonite.js.map +1 -0
  165. package/out/src/tools/shard-translit.d.ts +42 -0
  166. package/out/src/tools/shard-translit.d.ts.map +1 -0
  167. package/out/src/tools/shard-translit.js +196 -0
  168. package/out/src/tools/shard-translit.js.map +1 -0
  169. package/package.json +63 -7
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/tools/audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Pre-compute corpus-wide token + bigram label distributions for the corpus linter.
7
+ *
8
+ * Reads one or more Parquet shards, builds per-(token, label) and per-(bigram, label-bigram)
9
+ * histograms, and serializes them as JSON. The output file is consumed by `lint-corpus-shard.ts`
10
+ * as the baseline against which a new shard is compared.
11
+ *
12
+ * Stats are cheap to compute (~5–30s per 100K rows) but expensive enough that we cache them between
13
+ * linter invocations. Re-run this script whenever the corpus changes substantially (a new
14
+ * mainline shard added, a source-pool re-weighted, etc.).
15
+ *
16
+ * Output schema:
17
+ *
18
+ * ```ts
19
+ * interface CorpusStats {
20
+ * row_count: number
21
+ * shard_paths: string[]
22
+ * tokens: { [token: string]: { [label: string]: number } }
23
+ * bigrams: { [token_bigram: string]: { [label_bigram: string]: number } }
24
+ * // token_bigram = "tok1tok2" (US sep), label_bigram = "lab1lab2"
25
+ * // For memory: only keep bigrams with count >= MIN_BIGRAM_COUNT (2).
26
+ * }
27
+ * ```
28
+ *
29
+ * Usage: node scripts/build-corpus-stats.ts\
30
+ * --shards <glob-pattern-or-dir>\
31
+ * --output <stats.json>
32
+ *
33
+ * For a quick local-corpus baseline (limited but useful for linter testing): node
34
+ * scripts/build-corpus-stats.ts\
35
+ * --shards /mnt/playpen/mailwoman-data/corpus/versioned/v0.4.0/corpus-v0.4.0/train/\
36
+ * --output /tmp/corpus-stats-local.json
37
+ */
38
+ export interface CorpusStatsOptions {
39
+ shardsArg: string;
40
+ outputPath: string;
41
+ limitPerShard?: number;
42
+ }
43
+ export declare function buildCorpusStats(args: CorpusStatsOptions): void;
44
+ //# sourceMappingURL=corpus-stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"corpus-stats.d.ts","sourceRoot":"","sources":["../../../src/tools/corpus-stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AASH,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB;AA8CD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAuF/D"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Pre-compute corpus-wide token + bigram label distributions for the corpus linter.
7
+ *
8
+ * Reads one or more Parquet shards, builds per-(token, label) and per-(bigram, label-bigram)
9
+ * histograms, and serializes them as JSON. The output file is consumed by `lint-corpus-shard.ts`
10
+ * as the baseline against which a new shard is compared.
11
+ *
12
+ * Stats are cheap to compute (~5–30s per 100K rows) but expensive enough that we cache them between
13
+ * linter invocations. Re-run this script whenever the corpus changes substantially (a new
14
+ * mainline shard added, a source-pool re-weighted, etc.).
15
+ *
16
+ * Output schema:
17
+ *
18
+ * ```ts
19
+ * interface CorpusStats {
20
+ * row_count: number
21
+ * shard_paths: string[]
22
+ * tokens: { [token: string]: { [label: string]: number } }
23
+ * bigrams: { [token_bigram: string]: { [label_bigram: string]: number } }
24
+ * // token_bigram = "tok1tok2" (US sep), label_bigram = "lab1lab2"
25
+ * // For memory: only keep bigrams with count >= MIN_BIGRAM_COUNT (2).
26
+ * }
27
+ * ```
28
+ *
29
+ * Usage: node scripts/build-corpus-stats.ts\
30
+ * --shards <glob-pattern-or-dir>\
31
+ * --output <stats.json>
32
+ *
33
+ * For a quick local-corpus baseline (limited but useful for linter testing): node
34
+ * scripts/build-corpus-stats.ts\
35
+ * --shards /mnt/playpen/mailwoman-data/corpus/versioned/v0.4.0/corpus-v0.4.0/train/\
36
+ * --output /tmp/corpus-stats-local.json
37
+ */
38
+ import { execSync } from "node:child_process";
39
+ import { readdirSync, statSync, writeFileSync } from "node:fs";
40
+ import { join } from "node:path";
41
+ const SEP = "";
42
+ const MIN_BIGRAM_COUNT = 2;
43
+ function discoverShards(shardsArg) {
44
+ const stat = statSync(shardsArg);
45
+ if (stat.isDirectory()) {
46
+ return readdirSync(shardsArg)
47
+ .filter((f) => f.endsWith(".parquet"))
48
+ .map((f) => join(shardsArg, f));
49
+ }
50
+ if (stat.isFile() && shardsArg.endsWith(".parquet"))
51
+ return [shardsArg];
52
+ // Otherwise treat as a literal path list (one per line if it's stdin-friendly).
53
+ return [shardsArg];
54
+ }
55
+ /**
56
+ * Use a Python subprocess to read parquet (pyarrow is heavier than parquet-wasm but already on the path here, and we
57
+ * have nothing in the JS ecosystem that reads parquet cleanly at this scale). Emits one JSON object per line: `{tokens:
58
+ * [...], labels: [...]}`.
59
+ */
60
+ function streamShardRows(shardPath, limit) {
61
+ // Pipe the python script via stdin instead of `-c` to preserve newlines verbatim
62
+ // (JSON-encoding the script for -c collapses real newlines into literal `\n`).
63
+ const py = `
64
+ import pyarrow.parquet as pq
65
+ import json, sys
66
+ t = pq.read_table(${JSON.stringify(shardPath)}, columns=['tokens', 'labels'])
67
+ tokens_col = t['tokens'].to_pylist()
68
+ labels_col = t['labels'].to_pylist()
69
+ n = min(len(tokens_col), ${limit ?? "len(tokens_col)"})
70
+ for i in range(n):
71
+ sys.stdout.write(json.dumps({"tokens": tokens_col[i], "labels": labels_col[i]}) + "\\n")
72
+ `;
73
+ const buf = execSync(`python3`, { input: py, maxBuffer: 1024 * 1024 * 1024 });
74
+ const rows = [];
75
+ for (const line of buf.toString("utf8").split("\n")) {
76
+ if (!line)
77
+ continue;
78
+ rows.push(JSON.parse(line));
79
+ }
80
+ return rows;
81
+ }
82
+ export function buildCorpusStats(args) {
83
+ const shardPaths = discoverShards(args.shardsArg);
84
+ console.error(`Discovered ${shardPaths.length} parquet shard(s)`);
85
+ const tokenStats = new Map();
86
+ const bigramStats = new Map();
87
+ let totalRows = 0;
88
+ for (const path of shardPaths) {
89
+ console.error(`Reading ${path}...`);
90
+ const rows = streamShardRows(path, args.limitPerShard);
91
+ totalRows += rows.length;
92
+ for (const row of rows) {
93
+ const { tokens, labels } = row;
94
+ if (tokens.length !== labels.length)
95
+ continue;
96
+ // skip malformed
97
+ for (let i = 0; i < tokens.length; i++) {
98
+ const tk = tokens[i];
99
+ const lb = labels[i];
100
+ let labelMap = tokenStats.get(tk);
101
+ if (!labelMap) {
102
+ labelMap = new Map();
103
+ tokenStats.set(tk, labelMap);
104
+ }
105
+ labelMap.set(lb, (labelMap.get(lb) ?? 0) + 1);
106
+ if (i + 1 < tokens.length) {
107
+ const bigramKey = tk + SEP + tokens[i + 1];
108
+ const bigramLabel = lb + SEP + labels[i + 1];
109
+ let bMap = bigramStats.get(bigramKey);
110
+ if (!bMap) {
111
+ bMap = new Map();
112
+ bigramStats.set(bigramKey, bMap);
113
+ }
114
+ bMap.set(bigramLabel, (bMap.get(bigramLabel) ?? 0) + 1);
115
+ }
116
+ }
117
+ }
118
+ console.error(` ${rows.length} rows; running totals: ${tokenStats.size} unique tokens, ${bigramStats.size} unique bigrams`);
119
+ }
120
+ // Prune bigrams below MIN_BIGRAM_COUNT to keep the output file size sane. Token stats
121
+ // stay complete — they're cheap and we need accuracy at the long tail for label-vacuum
122
+ // detection.
123
+ let prunedBigrams = 0;
124
+ for (const [k, labelMap] of bigramStats) {
125
+ let total = 0;
126
+ for (const v of labelMap.values()) {
127
+ total += v;
128
+ }
129
+ if (total < MIN_BIGRAM_COUNT) {
130
+ bigramStats.delete(k);
131
+ prunedBigrams++;
132
+ }
133
+ }
134
+ console.error(`Pruned ${prunedBigrams} singleton bigrams; ${bigramStats.size} remain`);
135
+ const out = {
136
+ row_count: totalRows,
137
+ shard_paths: shardPaths,
138
+ tokens: {},
139
+ bigrams: {},
140
+ };
141
+ for (const [tk, labelMap] of tokenStats) {
142
+ out.tokens[tk] = Object.fromEntries(labelMap);
143
+ }
144
+ for (const [k, labelMap] of bigramStats) {
145
+ out.bigrams[k] = Object.fromEntries(labelMap);
146
+ }
147
+ writeFileSync(args.outputPath, JSON.stringify(out));
148
+ const sizeMB = (Buffer.byteLength(JSON.stringify(out)) / 1024 / 1024).toFixed(1);
149
+ console.error(`Wrote ${args.outputPath} (${sizeMB} MB) — ${totalRows} rows, ${tokenStats.size} tokens, ${bigramStats.size} bigrams`);
150
+ }
151
+ //# sourceMappingURL=corpus-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"corpus-stats.js","sourceRoot":"","sources":["../../../src/tools/corpus-stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Fetch the full French BAN (Base Adresse Nationale) — all metropolitan départements (01-95, 2A,
7
+ * 2B) plus 5 overseas DOM/TOM (971-976 excl. 975).
8
+ *
9
+ * Source: https://adresse.data.gouv.fr/data/ban/adresses/latest/csv/
10
+ * Licence: Licence Ouverte 2.0 (attribution required — Tier B).
11
+ *
12
+ * Files already present with matching sha256 are skipped (re-runnable). Downloads `.csv.gz`,
13
+ * decompresses to `.csv`, deletes the `.gz` artifact. One shared `MANIFEST.json` at
14
+ * `<outRoot>/ban/MANIFEST.json` covers all codes.
15
+ *
16
+ * Invoke via `mailwoman corpus fetch ban --out-root <path>`. Built-in `fetch` with gzip/brotli
17
+ * decompression replaces curl; native `node:zlib` gunzip replaces the `gunzip` subprocess; no
18
+ * Python.
19
+ */
20
+ import type { BaseFetchOptions, FetchSummary } from "./download.ts";
21
+ export interface BanManifestEntry {
22
+ dept_code: string;
23
+ filename: string;
24
+ source_url: string;
25
+ downloaded_at: string;
26
+ sha256: string;
27
+ bytes: number;
28
+ }
29
+ export type FetchBanOptions = BaseFetchOptions;
30
+ export declare function fetchBan(options: FetchBanOptions, report?: (line: string) => void): Promise<FetchSummary>;
31
+ //# sourceMappingURL=ban.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ban.d.ts","sourceRoot":"","sources":["../../../../src/tools/fetch/ban.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAiHnE,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAmB9C,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAsH/G"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Fetch the full French BAN (Base Adresse Nationale) — all metropolitan départements (01-95, 2A,
7
+ * 2B) plus 5 overseas DOM/TOM (971-976 excl. 975).
8
+ *
9
+ * Source: https://adresse.data.gouv.fr/data/ban/adresses/latest/csv/
10
+ * Licence: Licence Ouverte 2.0 (attribution required — Tier B).
11
+ *
12
+ * Files already present with matching sha256 are skipped (re-runnable). Downloads `.csv.gz`,
13
+ * decompresses to `.csv`, deletes the `.gz` artifact. One shared `MANIFEST.json` at
14
+ * `<outRoot>/ban/MANIFEST.json` covers all codes.
15
+ *
16
+ * Invoke via `mailwoman corpus fetch ban --out-root <path>`. Built-in `fetch` with gzip/brotli
17
+ * decompression replaces curl; native `node:zlib` gunzip replaces the `gunzip` subprocess; no
18
+ * Python.
19
+ */
20
+ import { existsSync, mkdirSync, statSync } from "node:fs";
21
+ import { readFile, unlink, writeFile } from "node:fs/promises";
22
+ import { join } from "node:path";
23
+ import { setTimeout as sleep } from "node:timers/promises";
24
+ import { gunzipSync } from "node:zlib";
25
+ import { sha256File } from "@mailwoman/core/utils";
26
+ import { downloadToFile, loadManifestEntries, writeManifest } from "./download.js";
27
+ const BASE_URL = "https://adresse.data.gouv.fr/data/ban/adresses/latest/csv";
28
+ /**
29
+ * All département codes — metropolitan 01-95 (with 2A/2B for Corsica instead of 20) plus overseas DOM/TOM. Codes do not
30
+ * change.
31
+ */
32
+ const DEPT_CODES = [
33
+ "01",
34
+ "02",
35
+ "03",
36
+ "04",
37
+ "05",
38
+ "06",
39
+ "07",
40
+ "08",
41
+ "09",
42
+ "10",
43
+ "11",
44
+ "12",
45
+ "13",
46
+ "14",
47
+ "15",
48
+ "16",
49
+ "17",
50
+ "18",
51
+ "19",
52
+ "21",
53
+ "22",
54
+ "23",
55
+ "24",
56
+ "25",
57
+ "26",
58
+ "27",
59
+ "28",
60
+ "29",
61
+ "2A",
62
+ "2B",
63
+ "30",
64
+ "31",
65
+ "32",
66
+ "33",
67
+ "34",
68
+ "35",
69
+ "36",
70
+ "37",
71
+ "38",
72
+ "39",
73
+ "40",
74
+ "41",
75
+ "42",
76
+ "43",
77
+ "44",
78
+ "45",
79
+ "46",
80
+ "47",
81
+ "48",
82
+ "49",
83
+ "50",
84
+ "51",
85
+ "52",
86
+ "53",
87
+ "54",
88
+ "55",
89
+ "56",
90
+ "57",
91
+ "58",
92
+ "59",
93
+ "60",
94
+ "61",
95
+ "62",
96
+ "63",
97
+ "64",
98
+ "65",
99
+ "66",
100
+ "67",
101
+ "68",
102
+ "69",
103
+ "70",
104
+ "71",
105
+ "72",
106
+ "73",
107
+ "74",
108
+ "75",
109
+ "76",
110
+ "77",
111
+ "78",
112
+ "79",
113
+ "80",
114
+ "81",
115
+ "82",
116
+ "83",
117
+ "84",
118
+ "85",
119
+ "86",
120
+ "87",
121
+ "88",
122
+ "89",
123
+ "90",
124
+ "91",
125
+ "92",
126
+ "93",
127
+ "94",
128
+ "95",
129
+ "971",
130
+ "972",
131
+ "973",
132
+ "974",
133
+ "976",
134
+ ];
135
+ /** Mimic `numfmt --to=iec` for a friendly byte-size log line. */
136
+ function iec(bytes) {
137
+ if (bytes < 1024)
138
+ return String(bytes);
139
+ const units = ["K", "M", "G", "T", "P"];
140
+ let value = bytes / 1024;
141
+ let i = 0;
142
+ while (value >= 1024 && i < units.length - 1) {
143
+ value /= 1024;
144
+ i++;
145
+ }
146
+ const rounded = value < 10 ? value.toFixed(1) : Math.round(value).toString();
147
+ return `${rounded}${units[i] ?? ""}`;
148
+ }
149
+ export async function fetchBan(options, report) {
150
+ const banDir = join(options.outRoot, "ban");
151
+ const manifestPath = join(banDir, "MANIFEST.json");
152
+ mkdirSync(banDir, { recursive: true });
153
+ // Load existing entries (code -> entry): skip detection + preservation of untouched codes.
154
+ const entries = await loadManifestEntries(manifestPath, (entry) => entry.dept_code);
155
+ let fetched = 0;
156
+ let skipped = 0;
157
+ let failed = 0;
158
+ const failedCodes = [];
159
+ for (const code of DEPT_CODES) {
160
+ const filename = `adresses-${code}.csv`;
161
+ const gzFile = join(banDir, `${filename}.gz`);
162
+ const csvFile = join(banDir, filename);
163
+ const url = `${BASE_URL}/adresses-${code}.csv.gz`;
164
+ report?.(`=== dept ${code}`);
165
+ // If the CSV already exists, compare its sha256 against the manifest.
166
+ if (existsSync(csvFile)) {
167
+ const existingSha = await sha256File(csvFile);
168
+ const recordedSha = entries.get(code)?.sha256;
169
+ if (recordedSha && existingSha === recordedSha) {
170
+ report?.(` → already present + sha matches — skipping`);
171
+ skipped++;
172
+ continue;
173
+ }
174
+ report?.(` → present but sha mismatch or no manifest entry — re-fetching`);
175
+ await unlink(csvFile);
176
+ }
177
+ // Download the gzipped CSV.
178
+ try {
179
+ await downloadToFile({
180
+ url,
181
+ dest: gzFile,
182
+ timeoutMs: 600_000,
183
+ headers: { "Accept-Encoding": "gzip, br" },
184
+ report,
185
+ });
186
+ }
187
+ catch (err) {
188
+ report?.(` ✗ download failed: ${url} (${err.message})`);
189
+ failed++;
190
+ failedCodes.push(code);
191
+ continue;
192
+ }
193
+ // Guard against truncated 404/error pages.
194
+ const gzSize = statSync(gzFile).size;
195
+ if (gzSize < 1024) {
196
+ report?.(` ✗ response too small (${gzSize} bytes) — probable 404 / error page`);
197
+ await unlink(gzFile);
198
+ failed++;
199
+ failedCodes.push(code);
200
+ continue;
201
+ }
202
+ // Decompress in-place; delete the .gz.
203
+ try {
204
+ await writeFile(csvFile, gunzipSync(await readFile(gzFile)));
205
+ }
206
+ catch (err) {
207
+ report?.(` ✗ decompress failed: ${err.message}`);
208
+ await unlink(gzFile);
209
+ failed++;
210
+ failedCodes.push(code);
211
+ continue;
212
+ }
213
+ await unlink(gzFile);
214
+ if (!existsSync(csvFile)) {
215
+ report?.(` ✗ decompressed file not found at ${csvFile}`);
216
+ failed++;
217
+ failedCodes.push(code);
218
+ continue;
219
+ }
220
+ const bytes = statSync(csvFile).size;
221
+ const sha = await sha256File(csvFile);
222
+ entries.set(code, {
223
+ dept_code: code,
224
+ filename,
225
+ source_url: url,
226
+ downloaded_at: new Date().toISOString(),
227
+ sha256: sha,
228
+ bytes,
229
+ });
230
+ report?.(` ✓ ${iec(bytes)} sha256=${sha}`);
231
+ fetched++;
232
+ // Be a polite citizen — short pause between requests.
233
+ await sleep(200);
234
+ }
235
+ // Write the consolidated MANIFEST.json (entries sorted by dept_code, codepoint order).
236
+ const sorted = [...entries.values()].sort((a, b) => a.dept_code < b.dept_code ? -1 : a.dept_code > b.dept_code ? 1 : 0);
237
+ await writeManifest(manifestPath, sorted);
238
+ report?.(`Wrote ${manifestPath} with ${sorted.length} entries.`);
239
+ report?.(`=== summary ===`);
240
+ report?.(`fetched: ${fetched}`);
241
+ report?.(`skipped: ${skipped} (already present + sha matched)`);
242
+ report?.(`failed: ${failed}`);
243
+ if (failedCodes.length > 0) {
244
+ report?.(`failed codes: ${failedCodes.join(" ")}`);
245
+ }
246
+ return { fetched, skipped, failed, failedCodes };
247
+ }
248
+ //# sourceMappingURL=ban.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ban.js","sourceRoot":"","sources":["../../../../src/tools/fetch/ban.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Download + manifest plumbing for the `mailwoman corpus fetch <source>` family — one download-with-retry and
7
+ * one MANIFEST.json idiom instead of the per-script clones the 2026-07-09 dedupe survey counted
8
+ * (6× `downloadToFile`, 2× `isTransientStatus`, 9× manifest writes).
9
+ */
10
+ /** The option base every `mailwoman corpus fetch <source>` module extends. */
11
+ export interface BaseFetchOptions {
12
+ /** Destination root for downloaded source data. Each source writes its own subdirectory. */
13
+ outRoot: string;
14
+ }
15
+ /** The per-run result every fetch module returns; the command maps `failed > 0` to exit code 1. */
16
+ export interface FetchSummary {
17
+ fetched: number;
18
+ skipped: number;
19
+ failed: number;
20
+ failedCodes: string[];
21
+ }
22
+ /** A status worth retrying: rate limiting or a server-side failure. */
23
+ export declare function isTransientStatus(status: number): boolean;
24
+ export interface DownloadOptions {
25
+ url: string;
26
+ dest: string;
27
+ /** Per-attempt timeout. Default 10 minutes — these are multi-GB government dumps. */
28
+ timeoutMs?: number;
29
+ /** Extra attempts after the first, taken only on transient statuses or network errors. Default 0. */
30
+ retries?: number;
31
+ /** Delay between attempts. Default 5s. */
32
+ retryDelayMs?: number;
33
+ headers?: Record<string, string>;
34
+ report?: (line: string) => void;
35
+ }
36
+ /**
37
+ * Download `url` to `dest` with per-attempt timeout and transient-status retry. Throws on a non-transient HTTP status
38
+ * or once retries are exhausted. Returns the byte count written.
39
+ */
40
+ export declare function downloadToFile(options: DownloadOptions): Promise<{
41
+ bytes: number;
42
+ }>;
43
+ /** Read a MANIFEST.json; `null` when missing or corrupt (callers re-fetch from scratch). */
44
+ export declare function readManifest<T>(path: string): Promise<T | null>;
45
+ /** Load manifest entries into a map so untouched keys survive a partial re-fetch. */
46
+ export declare function loadManifestEntries<T>(path: string, key: (entry: T) => string): Promise<Map<string, T>>;
47
+ /** Write a MANIFEST.json in the house shape: pretty-printed, trailing newline. */
48
+ export declare function writeManifest(path: string, manifest: unknown): Promise<void>;
49
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../../src/tools/fetch/download.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,8EAA8E;AAC9E,MAAM,WAAW,gBAAgB;IAChC,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAA;CACf;AAED,mGAAmG;AACnG,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qGAAqG;IACrG,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCzF;AAED,4FAA4F;AAC5F,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAQrE;AAED,qFAAqF;AACrF,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAS7G;AAED,kFAAkF;AAClF,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Download + manifest plumbing for the `mailwoman corpus fetch <source>` family — one download-with-retry and
7
+ * one MANIFEST.json idiom instead of the per-script clones the 2026-07-09 dedupe survey counted
8
+ * (6× `downloadToFile`, 2× `isTransientStatus`, 9× manifest writes).
9
+ */
10
+ import { existsSync } from "node:fs";
11
+ import { readFile, writeFile } from "node:fs/promises";
12
+ import { setTimeout as sleep } from "node:timers/promises";
13
+ /** A status worth retrying: rate limiting or a server-side failure. */
14
+ export function isTransientStatus(status) {
15
+ return status === 429 || (status >= 500 && status <= 599);
16
+ }
17
+ /**
18
+ * Download `url` to `dest` with per-attempt timeout and transient-status retry. Throws on a non-transient HTTP status
19
+ * or once retries are exhausted. Returns the byte count written.
20
+ */
21
+ export async function downloadToFile(options) {
22
+ const { url, dest, timeoutMs = 600_000, retries = 0, retryDelayMs = 5_000, headers, report } = options;
23
+ let lastError;
24
+ for (let attempt = 0; attempt <= retries; attempt++) {
25
+ if (attempt > 0) {
26
+ report?.(`retry ${attempt}/${retries} after ${retryDelayMs}ms — ${url}`);
27
+ await sleep(retryDelayMs);
28
+ }
29
+ let res;
30
+ try {
31
+ res = await fetch(url, { headers, signal: AbortSignal.timeout(timeoutMs) });
32
+ }
33
+ catch (error) {
34
+ // AbortSignal timeouts and network-level failures are retryable.
35
+ lastError = error;
36
+ continue;
37
+ }
38
+ if (!res.ok) {
39
+ const error = new Error(`HTTP ${res.status} ${res.statusText} — ${url}`);
40
+ if (!isTransientStatus(res.status))
41
+ throw error;
42
+ lastError = error;
43
+ continue;
44
+ }
45
+ try {
46
+ const buffer = Buffer.from(await res.arrayBuffer());
47
+ await writeFile(dest, buffer);
48
+ return { bytes: buffer.byteLength };
49
+ }
50
+ catch (error) {
51
+ // A mid-stream abort while reading the body is retryable too.
52
+ lastError = error;
53
+ }
54
+ }
55
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
56
+ }
57
+ /** Read a MANIFEST.json; `null` when missing or corrupt (callers re-fetch from scratch). */
58
+ export async function readManifest(path) {
59
+ if (!existsSync(path))
60
+ return null;
61
+ try {
62
+ return JSON.parse(await readFile(path, "utf8"));
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ /** Load manifest entries into a map so untouched keys survive a partial re-fetch. */
69
+ export async function loadManifestEntries(path, key) {
70
+ const entries = new Map();
71
+ const parsed = await readManifest(path);
72
+ for (const entry of parsed ?? []) {
73
+ entries.set(key(entry), entry);
74
+ }
75
+ return entries;
76
+ }
77
+ /** Write a MANIFEST.json in the house shape: pretty-printed, trailing newline. */
78
+ export async function writeManifest(path, manifest) {
79
+ await writeFile(path, JSON.stringify(manifest, null, 2) + "\n");
80
+ }
81
+ //# sourceMappingURL=download.js.map