@mailwoman/corpus 8.6.0 → 9.0.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 (310) hide show
  1. package/README.md +1 -1
  2. package/out/src/adapter.d.ts +41 -0
  3. package/out/src/adapter.d.ts.map +1 -1
  4. package/out/src/adapter.js +46 -1
  5. package/out/src/adapter.js.map +1 -1
  6. package/out/src/adapters/ban/adapter.d.ts +4 -3
  7. package/out/src/adapters/ban/adapter.d.ts.map +1 -1
  8. package/out/src/adapters/ban/adapter.js +60 -67
  9. package/out/src/adapters/ban/adapter.js.map +1 -1
  10. package/out/src/adapters/ban/street-decompose.d.ts.map +1 -1
  11. package/out/src/adapters/ban/street-decompose.js +18 -25
  12. package/out/src/adapters/ban/street-decompose.js.map +1 -1
  13. package/out/src/adapters/fcc-bdc/adapter.d.ts +0 -6
  14. package/out/src/adapters/fcc-bdc/adapter.d.ts.map +1 -1
  15. package/out/src/adapters/fcc-bdc/adapter.js +2 -24
  16. package/out/src/adapters/fcc-bdc/adapter.js.map +1 -1
  17. package/out/src/adapters/geonames/adapter.d.ts.map +1 -1
  18. package/out/src/adapters/geonames/adapter.js +70 -76
  19. package/out/src/adapters/geonames/adapter.js.map +1 -1
  20. package/out/src/adapters/geonames-postal/adapter.d.ts.map +1 -1
  21. package/out/src/adapters/geonames-postal/adapter.js +44 -49
  22. package/out/src/adapters/geonames-postal/adapter.js.map +1 -1
  23. package/out/src/adapters/gnaf/adapter.d.ts.map +1 -1
  24. package/out/src/adapters/gnaf/adapter.js +4 -7
  25. package/out/src/adapters/gnaf/adapter.js.map +1 -1
  26. package/out/src/adapters/gnaf/assemble.d.ts.map +1 -1
  27. package/out/src/adapters/gnaf/assemble.js +6 -11
  28. package/out/src/adapters/gnaf/assemble.js.map +1 -1
  29. package/out/src/adapters/openaddresses/adapter.d.ts.map +1 -1
  30. package/out/src/adapters/openaddresses/adapter.js +2 -7
  31. package/out/src/adapters/openaddresses/adapter.js.map +1 -1
  32. package/out/src/adapters/overture/adapter.d.ts.map +1 -1
  33. package/out/src/adapters/overture/adapter.js +3 -7
  34. package/out/src/adapters/overture/adapter.js.map +1 -1
  35. package/out/src/adapters/state-hi-schools/adapter.d.ts.map +1 -1
  36. package/out/src/adapters/state-hi-schools/adapter.js +55 -73
  37. package/out/src/adapters/state-hi-schools/adapter.js.map +1 -1
  38. package/out/src/adapters/state-ia-contractors/adapter.d.ts.map +1 -1
  39. package/out/src/adapters/state-ia-contractors/adapter.js +58 -76
  40. package/out/src/adapters/state-ia-contractors/adapter.js.map +1 -1
  41. package/out/src/adapters/state-ny-notaries/adapter.d.ts.map +1 -1
  42. package/out/src/adapters/state-ny-notaries/adapter.js +67 -85
  43. package/out/src/adapters/state-ny-notaries/adapter.js.map +1 -1
  44. package/out/src/adapters/state-tx-notaries/adapter.d.ts.map +1 -1
  45. package/out/src/adapters/state-tx-notaries/adapter.js +69 -87
  46. package/out/src/adapters/state-tx-notaries/adapter.js.map +1 -1
  47. package/out/src/adapters/synth-po-box/adapter.d.ts.map +1 -1
  48. package/out/src/adapters/synth-po-box/adapter.js +7 -15
  49. package/out/src/adapters/synth-po-box/adapter.js.map +1 -1
  50. package/out/src/adapters/tiger/street-decompose.d.ts.map +1 -1
  51. package/out/src/adapters/tiger/street-decompose.js +18 -27
  52. package/out/src/adapters/tiger/street-decompose.js.map +1 -1
  53. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts +3 -3
  54. package/out/src/adapters/usgov-hrsa-fqhc/adapter.d.ts.map +1 -1
  55. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js +62 -80
  56. package/out/src/adapters/usgov-hrsa-fqhc/adapter.js.map +1 -1
  57. package/out/src/adapters/usgov-imls-pls/adapter.d.ts.map +1 -1
  58. package/out/src/adapters/usgov-imls-pls/adapter.js +60 -82
  59. package/out/src/adapters/usgov-imls-pls/adapter.js.map +1 -1
  60. package/out/src/adapters/usgov-irs-bmf/adapter.d.ts.map +1 -1
  61. package/out/src/adapters/usgov-irs-bmf/adapter.js +58 -65
  62. package/out/src/adapters/usgov-irs-bmf/adapter.js.map +1 -1
  63. package/out/src/adapters/usgov-nad/adapter.d.ts.map +1 -1
  64. package/out/src/adapters/usgov-nad/adapter.js +5 -8
  65. package/out/src/adapters/usgov-nad/adapter.js.map +1 -1
  66. package/out/src/adapters/usgov-nppes/adapter.d.ts.map +1 -1
  67. package/out/src/adapters/usgov-nppes/adapter.js +58 -76
  68. package/out/src/adapters/usgov-nppes/adapter.js.map +1 -1
  69. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.d.ts.map +1 -1
  70. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js +51 -71
  71. package/out/src/adapters/usgov-samhsa-treatment-locator/adapter.js.map +1 -1
  72. package/out/src/adapters/wof-admin-jp/adapter.d.ts.map +1 -1
  73. package/out/src/adapters/wof-admin-jp/adapter.js +24 -6
  74. package/out/src/adapters/wof-admin-jp/adapter.js.map +1 -1
  75. package/out/src/build.d.ts.map +1 -1
  76. package/out/src/build.js +2 -1
  77. package/out/src/build.js.map +1 -1
  78. package/out/src/golden.d.ts +5 -0
  79. package/out/src/golden.d.ts.map +1 -1
  80. package/out/src/golden.js +23 -9
  81. package/out/src/golden.js.map +1 -1
  82. package/out/src/parquet-wrapper/reader.d.ts +8 -0
  83. package/out/src/parquet-wrapper/reader.d.ts.map +1 -1
  84. package/out/src/parquet-wrapper/reader.js +16 -0
  85. package/out/src/parquet-wrapper/reader.js.map +1 -1
  86. package/out/src/parquet-wrapper/schema.d.ts +4 -0
  87. package/out/src/parquet-wrapper/schema.d.ts.map +1 -1
  88. package/out/src/parquet-wrapper/schema.js.map +1 -1
  89. package/out/src/parquet.d.ts.map +1 -1
  90. package/out/src/parquet.js +2 -13
  91. package/out/src/parquet.js.map +1 -1
  92. package/out/src/shard-recipes/anchor-absorption.d.ts.map +1 -1
  93. package/out/src/shard-recipes/anchor-absorption.js +2 -1
  94. package/out/src/shard-recipes/anchor-absorption.js.map +1 -1
  95. package/out/src/shard-recipes/country-balanced.d.ts.map +1 -1
  96. package/out/src/shard-recipes/country-balanced.js +68 -60
  97. package/out/src/shard-recipes/country-balanced.js.map +1 -1
  98. package/out/src/shard-recipes/fr-fragment.d.ts.map +1 -1
  99. package/out/src/shard-recipes/fr-fragment.js +8 -5
  100. package/out/src/shard-recipes/fr-fragment.js.map +1 -1
  101. package/out/src/shard-recipes/fr-order.d.ts.map +1 -1
  102. package/out/src/shard-recipes/fr-order.js +14 -58
  103. package/out/src/shard-recipes/fr-order.js.map +1 -1
  104. package/out/src/shard-recipes/german.d.ts.map +1 -1
  105. package/out/src/shard-recipes/german.js +11 -58
  106. package/out/src/shard-recipes/german.js.map +1 -1
  107. package/out/src/shard-recipes/index.d.ts.map +1 -1
  108. package/out/src/shard-recipes/index.js +2 -0
  109. package/out/src/shard-recipes/index.js.map +1 -1
  110. package/out/src/shard-recipes/intersection.d.ts +2 -2
  111. package/out/src/shard-recipes/intersection.d.ts.map +1 -1
  112. package/out/src/shard-recipes/intersection.js +24 -62
  113. package/out/src/shard-recipes/intersection.js.map +1 -1
  114. package/out/src/shard-recipes/locale.d.ts.map +1 -1
  115. package/out/src/shard-recipes/locale.js +14 -16
  116. package/out/src/shard-recipes/locale.js.map +1 -1
  117. package/out/src/shard-recipes/no-fragment.d.ts.map +1 -1
  118. package/out/src/shard-recipes/no-fragment.js +8 -5
  119. package/out/src/shard-recipes/no-fragment.js.map +1 -1
  120. package/out/src/shard-recipes/no-street-led.d.ts.map +1 -1
  121. package/out/src/shard-recipes/no-street-led.js +8 -5
  122. package/out/src/shard-recipes/no-street-led.js.map +1 -1
  123. package/out/src/shard-recipes/po-box-cedex.d.ts +3 -3
  124. package/out/src/shard-recipes/po-box-cedex.d.ts.map +1 -1
  125. package/out/src/shard-recipes/po-box-cedex.js +51 -94
  126. package/out/src/shard-recipes/po-box-cedex.js.map +1 -1
  127. package/out/src/shard-recipes/scaffold.d.ts +59 -9
  128. package/out/src/shard-recipes/scaffold.d.ts.map +1 -1
  129. package/out/src/shard-recipes/scaffold.js +51 -30
  130. package/out/src/shard-recipes/scaffold.js.map +1 -1
  131. package/out/src/shard-recipes/street-affix.d.ts.map +1 -1
  132. package/out/src/shard-recipes/street-affix.js +56 -82
  133. package/out/src/shard-recipes/street-affix.js.map +1 -1
  134. package/out/src/shard-recipes/sub-venue-sources.d.ts +231 -0
  135. package/out/src/shard-recipes/sub-venue-sources.d.ts.map +1 -0
  136. package/out/src/shard-recipes/sub-venue-sources.js +669 -0
  137. package/out/src/shard-recipes/sub-venue-sources.js.map +1 -0
  138. package/out/src/shard-recipes/sub-venue.d.ts +269 -0
  139. package/out/src/shard-recipes/sub-venue.d.ts.map +1 -0
  140. package/out/src/shard-recipes/sub-venue.js +709 -0
  141. package/out/src/shard-recipes/sub-venue.js.map +1 -0
  142. package/out/src/shard-recipes/unit.d.ts +1 -1
  143. package/out/src/shard-recipes/unit.d.ts.map +1 -1
  144. package/out/src/shard-recipes/unit.js +22 -64
  145. package/out/src/shard-recipes/unit.js.map +1 -1
  146. package/out/src/split.d.ts +7 -0
  147. package/out/src/split.d.ts.map +1 -1
  148. package/out/src/split.js +7 -0
  149. package/out/src/split.js.map +1 -1
  150. package/out/src/synthesize.d.ts.map +1 -1
  151. package/out/src/synthesize.js +1 -12
  152. package/out/src/synthesize.js.map +1 -1
  153. package/out/src/tools/align-shard.d.ts.map +1 -1
  154. package/out/src/tools/align-shard.js +3 -7
  155. package/out/src/tools/align-shard.js.map +1 -1
  156. package/out/src/tools/audit.d.ts.map +1 -1
  157. package/out/src/tools/audit.js +4 -4
  158. package/out/src/tools/audit.js.map +1 -1
  159. package/out/src/tools/corpus-stats.d.ts +2 -2
  160. package/out/src/tools/corpus-stats.d.ts.map +1 -1
  161. package/out/src/tools/corpus-stats.js +18 -31
  162. package/out/src/tools/corpus-stats.js.map +1 -1
  163. package/out/src/tools/fetch/download.d.ts.map +1 -1
  164. package/out/src/tools/fetch/download.js +5 -6
  165. package/out/src/tools/fetch/download.js.map +1 -1
  166. package/out/src/tools/fetch/imls-pls.d.ts.map +1 -1
  167. package/out/src/tools/fetch/imls-pls.js +2 -2
  168. package/out/src/tools/fetch/imls-pls.js.map +1 -1
  169. package/out/src/tools/fetch/index.d.ts +14 -1
  170. package/out/src/tools/fetch/index.d.ts.map +1 -1
  171. package/out/src/tools/fetch/index.js +14 -1
  172. package/out/src/tools/fetch/index.js.map +1 -1
  173. package/out/src/tools/fetch/nad.d.ts +1 -1
  174. package/out/src/tools/fetch/nad.js +1 -1
  175. package/out/src/tools/fetch/nppes.d.ts.map +1 -1
  176. package/out/src/tools/fetch/nppes.js +2 -1
  177. package/out/src/tools/fetch/nppes.js.map +1 -1
  178. package/out/src/tools/fetch/openaddresses.d.ts +1 -1
  179. package/out/src/tools/fetch/openaddresses.js +1 -1
  180. package/out/src/tools/fetch/ourairports.d.ts +45 -0
  181. package/out/src/tools/fetch/ourairports.d.ts.map +1 -0
  182. package/out/src/tools/fetch/ourairports.js +123 -0
  183. package/out/src/tools/fetch/ourairports.js.map +1 -0
  184. package/out/src/tools/fetch/wikidata-subvenue.d.ts +171 -0
  185. package/out/src/tools/fetch/wikidata-subvenue.d.ts.map +1 -0
  186. package/out/src/tools/fetch/wikidata-subvenue.js +275 -0
  187. package/out/src/tools/fetch/wikidata-subvenue.js.map +1 -0
  188. package/out/src/tools/golden-expand.d.ts.map +1 -1
  189. package/out/src/tools/golden-expand.js +18 -16
  190. package/out/src/tools/golden-expand.js.map +1 -1
  191. package/out/src/tools/golden-promote.d.ts.map +1 -1
  192. package/out/src/tools/golden-promote.js +12 -6
  193. package/out/src/tools/golden-promote.js.map +1 -1
  194. package/out/src/tools/golden-relabel-street.d.ts +196 -0
  195. package/out/src/tools/golden-relabel-street.d.ts.map +1 -0
  196. package/out/src/tools/golden-relabel-street.js +513 -0
  197. package/out/src/tools/golden-relabel-street.js.map +1 -0
  198. package/out/src/tools/index.d.ts +4 -0
  199. package/out/src/tools/index.d.ts.map +1 -1
  200. package/out/src/tools/index.js +4 -0
  201. package/out/src/tools/index.js.map +1 -1
  202. package/out/src/tools/jsonl-to-parquet.d.ts.map +1 -1
  203. package/out/src/tools/jsonl-to-parquet.js +3 -2
  204. package/out/src/tools/jsonl-to-parquet.js.map +1 -1
  205. package/out/src/tools/lint-shard-vocab.d.ts.map +1 -1
  206. package/out/src/tools/lint-shard-vocab.js +3 -2
  207. package/out/src/tools/lint-shard-vocab.js.map +1 -1
  208. package/out/src/tools/lint-shard.d.ts +3 -3
  209. package/out/src/tools/lint-shard.d.ts.map +1 -1
  210. package/out/src/tools/lint-shard.js +23 -32
  211. package/out/src/tools/lint-shard.js.map +1 -1
  212. package/out/src/tools/overlay-manifest.d.ts.map +1 -1
  213. package/out/src/tools/overlay-manifest.js +2 -1
  214. package/out/src/tools/overlay-manifest.js.map +1 -1
  215. package/out/src/tools/overture-subvenue.d.ts +112 -0
  216. package/out/src/tools/overture-subvenue.d.ts.map +1 -0
  217. package/out/src/tools/overture-subvenue.js +144 -0
  218. package/out/src/tools/overture-subvenue.js.map +1 -0
  219. package/out/src/tools/shard-kryptonite.d.ts +1 -1
  220. package/out/src/tools/shard-kryptonite.d.ts.map +1 -1
  221. package/out/src/tools/shard-kryptonite.js +5 -4
  222. package/out/src/tools/shard-kryptonite.js.map +1 -1
  223. package/out/src/tools/shard-translit.d.ts +6 -3
  224. package/out/src/tools/shard-translit.d.ts.map +1 -1
  225. package/out/src/tools/shard-translit.js +8 -6
  226. package/out/src/tools/shard-translit.js.map +1 -1
  227. package/out/src/tools/sub-venue-lexicon.d.ts +507 -0
  228. package/out/src/tools/sub-venue-lexicon.d.ts.map +1 -0
  229. package/out/src/tools/sub-venue-lexicon.js +817 -0
  230. package/out/src/tools/sub-venue-lexicon.js.map +1 -0
  231. package/out/src/tools/sub-venue-promotions.d.ts +94 -0
  232. package/out/src/tools/sub-venue-promotions.d.ts.map +1 -0
  233. package/out/src/tools/sub-venue-promotions.js +266 -0
  234. package/out/src/tools/sub-venue-promotions.js.map +1 -0
  235. package/out/src/wof-json.d.ts +2 -2
  236. package/out/src/wof-json.d.ts.map +1 -1
  237. package/out/src/wof-json.js +5 -8
  238. package/out/src/wof-json.js.map +1 -1
  239. package/package.json +8 -8
  240. package/src/adapter.ts +58 -1
  241. package/src/adapters/ban/adapter.ts +55 -65
  242. package/src/adapters/ban/street-decompose.ts +17 -25
  243. package/src/adapters/fcc-bdc/adapter.ts +2 -33
  244. package/src/adapters/geonames/adapter.ts +64 -72
  245. package/src/adapters/geonames-postal/adapter.ts +42 -50
  246. package/src/adapters/gnaf/adapter.ts +4 -7
  247. package/src/adapters/gnaf/assemble.ts +6 -10
  248. package/src/adapters/openaddresses/adapter.ts +2 -7
  249. package/src/adapters/overture/adapter.ts +3 -6
  250. package/src/adapters/state-hi-schools/adapter.ts +50 -73
  251. package/src/adapters/state-ia-contractors/adapter.ts +52 -76
  252. package/src/adapters/state-ny-notaries/adapter.ts +61 -85
  253. package/src/adapters/state-tx-notaries/adapter.ts +60 -84
  254. package/src/adapters/synth-po-box/adapter.ts +7 -17
  255. package/src/adapters/tiger/street-decompose.ts +21 -31
  256. package/src/adapters/usgov-hrsa-fqhc/adapter.ts +61 -84
  257. package/src/adapters/usgov-imls-pls/adapter.ts +54 -82
  258. package/src/adapters/usgov-irs-bmf/adapter.ts +53 -63
  259. package/src/adapters/usgov-nad/adapter.ts +5 -8
  260. package/src/adapters/usgov-nppes/adapter.ts +51 -75
  261. package/src/adapters/usgov-samhsa-treatment-locator/adapter.ts +45 -71
  262. package/src/adapters/wof-admin-jp/adapter.ts +34 -8
  263. package/src/build.ts +2 -1
  264. package/src/golden.ts +24 -9
  265. package/src/parquet-wrapper/reader.ts +19 -0
  266. package/src/parquet-wrapper/schema.ts +4 -0
  267. package/src/parquet.ts +3 -16
  268. package/src/shard-recipes/anchor-absorption.ts +2 -1
  269. package/src/shard-recipes/country-balanced.ts +69 -70
  270. package/src/shard-recipes/fr-fragment.ts +10 -7
  271. package/src/shard-recipes/fr-order.ts +13 -63
  272. package/src/shard-recipes/german.ts +12 -65
  273. package/src/shard-recipes/index.ts +2 -0
  274. package/src/shard-recipes/intersection.ts +32 -60
  275. package/src/shard-recipes/locale.ts +14 -16
  276. package/src/shard-recipes/no-fragment.ts +10 -7
  277. package/src/shard-recipes/no-street-led.ts +10 -7
  278. package/src/shard-recipes/po-box-cedex.ts +68 -119
  279. package/src/shard-recipes/scaffold.ts +82 -28
  280. package/src/shard-recipes/street-affix.ts +58 -95
  281. package/src/shard-recipes/sub-venue-sources.ts +895 -0
  282. package/src/shard-recipes/sub-venue.ts +982 -0
  283. package/src/shard-recipes/unit.ts +22 -70
  284. package/src/split.ts +7 -0
  285. package/src/synthesize.ts +1 -15
  286. package/src/tools/align-shard.ts +3 -6
  287. package/src/tools/audit.ts +6 -5
  288. package/src/tools/corpus-stats.ts +25 -33
  289. package/src/tools/fetch/download.ts +7 -5
  290. package/src/tools/fetch/imls-pls.ts +2 -2
  291. package/src/tools/fetch/index.ts +14 -1
  292. package/src/tools/fetch/nad.ts +1 -1
  293. package/src/tools/fetch/nppes.ts +2 -1
  294. package/src/tools/fetch/openaddresses.ts +1 -1
  295. package/src/tools/fetch/ourairports.ts +166 -0
  296. package/src/tools/fetch/wikidata-subvenue.ts +386 -0
  297. package/src/tools/golden-expand.ts +18 -13
  298. package/src/tools/golden-promote.ts +15 -6
  299. package/src/tools/golden-relabel-street.ts +748 -0
  300. package/src/tools/index.ts +4 -0
  301. package/src/tools/jsonl-to-parquet.ts +3 -2
  302. package/src/tools/lint-shard-vocab.ts +3 -2
  303. package/src/tools/lint-shard.ts +33 -36
  304. package/src/tools/overlay-manifest.ts +2 -1
  305. package/src/tools/overture-subvenue.ts +215 -0
  306. package/src/tools/shard-kryptonite.ts +5 -4
  307. package/src/tools/shard-translit.ts +12 -7
  308. package/src/tools/sub-venue-lexicon.ts +1250 -0
  309. package/src/tools/sub-venue-promotions.ts +330 -0
  310. package/src/wof-json.ts +5 -8
@@ -36,6 +36,7 @@
36
36
  * for non-US locales where district names DO appear on the envelope.
37
37
  */
38
38
 
39
+ import { tryParsingJSON } from "@mailwoman/core/objects"
39
40
  import { TextSpliterator } from "spliterator"
40
41
 
41
42
  import { stableSourceID } from "../../adapter.ts"
@@ -96,13 +97,7 @@ function parseFeatureLine(line: string): OaProperties | null {
96
97
  const trimmed = line.trim()
97
98
 
98
99
  if (!trimmed || trimmed.startsWith("#")) return null
99
- let parsed: unknown
100
-
101
- try {
102
- parsed = JSON.parse(trimmed)
103
- } catch {
104
- return null
105
- }
100
+ const parsed = tryParsingJSON(trimmed)
106
101
 
107
102
  if (!parsed || typeof parsed !== "object") return null
108
103
  const obj = parsed as { type?: string; properties?: unknown }
@@ -30,6 +30,7 @@
30
30
  * `postcode` | | `locality`| `locality` (Overture address_levels municipality, or postal_city) |
31
31
  */
32
32
 
33
+ import { tryParsingJSON } from "@mailwoman/core/objects"
33
34
  import { TextSpliterator } from "spliterator"
34
35
 
35
36
  import { stableSourceID } from "../../adapter.ts"
@@ -63,13 +64,9 @@ function parseLine(line: string): OvertureCorpusRow | null {
63
64
 
64
65
  if (!t || t.startsWith("#")) return null
65
66
 
66
- try {
67
- const o = JSON.parse(t)
67
+ const o = tryParsingJSON(t)
68
68
 
69
- return o && typeof o === "object" ? (o as OvertureCorpusRow) : null
70
- } catch {
71
- return null
72
- }
69
+ return o && typeof o === "object" ? (o as OvertureCorpusRow) : null
73
70
  }
74
71
 
75
72
  export function createOvertureAdapter(): CorpusAdapter {
@@ -29,11 +29,9 @@
29
29
  * License: stamped `"Public Domain"` per Hawaii state government open-data terms.
30
30
  */
31
31
 
32
- import { createReadStream } from "node:fs"
32
+ import { CSVSpliterator } from "spliterator"
33
33
 
34
- import { parse as csvParse } from "csv-parse"
35
-
36
- import { stableSourceID } from "../../adapter.ts"
34
+ import { splitStreetLine, stableSourceID } from "../../adapter.ts"
37
35
  import { lookupStateAbbreviation } from "../../codex/us-fips-state.ts"
38
36
  import { reconcileComponents } from "../../format.ts"
39
37
  import type { AdapterOptions, CanonicalRow, CorpusAdapter } from "../../types.ts"
@@ -49,7 +47,6 @@ export const STATE_HI_SCHOOLS_ADAPTER_ID = "state-hi-schools"
49
47
  */
50
48
  export const STATE_HI_SCHOOLS_DEFAULT_LICENSE = "Public Domain"
51
49
 
52
- const HOUSE_NUMBER_PREFIX = /^(\d+(?:-\d+)?[A-Za-z]?)\s+(.+)$/
53
50
  const HI_STATE_ABBR = "HI"
54
51
 
55
52
  interface HiSchoolRow {
@@ -60,17 +57,6 @@ interface HiSchoolRow {
60
57
  zip: string
61
58
  }
62
59
 
63
- function splitAddress(address: string): { house_number?: string; street: string } | null {
64
- const trimmed = address.trim()
65
-
66
- if (!trimmed) return null
67
- const m = HOUSE_NUMBER_PREFIX.exec(trimmed)
68
-
69
- if (m) return { house_number: m[1], street: m[2]!.trim() }
70
-
71
- return { street: trimmed }
72
- }
73
-
74
60
  function normalizeZip(raw: string): string {
75
61
  const trimmed = raw.trim()
76
62
 
@@ -95,16 +81,11 @@ export function createStateHiSchoolsAdapter(): CorpusAdapter {
95
81
  throw new Error(`state-hi-schools adapter: only US supported, got country=${opts.country}`)
96
82
  }
97
83
 
98
- const stream = createReadStream(opts.inputPath, { encoding: "utf8" })
99
-
100
- const parser = stream.pipe(
101
- csvParse({
102
- columns: true,
103
- skip_empty_lines: true,
104
- relax_quotes: true,
105
- relax_column_count: true,
106
- })
107
- )
84
+ const rows = CSVSpliterator.fromAsync(opts.inputPath, {
85
+ mode: "object",
86
+ normalizeKeys: false,
87
+ enableQuoteHandling: true,
88
+ })
108
89
 
109
90
  const state = lookupStateAbbreviation(HI_STATE_ABBR)
110
91
 
@@ -114,67 +95,63 @@ export function createStateHiSchoolsAdapter(): CorpusAdapter {
114
95
 
115
96
  let emitted = 0
116
97
 
117
- try {
118
- for await (const record of parser as AsyncIterable<HiSchoolRow>) {
119
- if (opts.signal?.aborted) break
120
-
121
- if (opts.limit !== undefined && emitted >= opts.limit) break
98
+ for await (const record of rows as AsyncIterable<HiSchoolRow>) {
99
+ if (opts.signal?.aborted) break
122
100
 
123
- const name = (record.name ?? "").trim()
124
- const address = (record.address ?? "").trim()
125
- const city = (record.city ?? "").trim()
126
- const zip = normalizeZip(record.zip ?? "")
101
+ if (opts.limit !== undefined && emitted >= opts.limit) break
127
102
 
128
- if (!name || !address || !city || !zip) continue
103
+ const name = (record.name ?? "").trim()
104
+ const address = (record.address ?? "").trim()
105
+ const city = (record.city ?? "").trim()
106
+ const zip = normalizeZip(record.zip ?? "")
129
107
 
130
- const split = splitAddress(address)
108
+ if (!name || !address || !city || !zip) continue
131
109
 
132
- if (!split) continue
110
+ const split = splitStreetLine(address)
133
111
 
134
- const components: CanonicalRow["components"] = {
135
- venue: name,
136
- ...(split.house_number ? { house_number: split.house_number } : {}),
137
- street: split.street,
138
- locality: city,
139
- region: state.abbreviation,
140
- postcode: zip,
141
- }
112
+ if (!split) continue
142
113
 
143
- const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
114
+ const components: CanonicalRow["components"] = {
115
+ venue: name,
116
+ ...(split.house_number ? { house_number: split.house_number } : {}),
117
+ street: split.street,
118
+ locality: city,
119
+ region: state.abbreviation,
120
+ postcode: zip,
121
+ }
144
122
 
145
- const raw = [
146
- name,
147
- streetPart,
148
- [city, [HI_STATE_ABBR, zip].filter(Boolean).join(" ")].filter(Boolean).join(", "),
149
- ]
150
- .filter(Boolean)
151
- .join(", ")
123
+ const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
152
124
 
153
- const aligned = reconcileComponents(components, raw)
125
+ const raw = [
126
+ name,
127
+ streetPart,
128
+ [city, [HI_STATE_ABBR, zip].filter(Boolean).join(" ")].filter(Boolean).join(", "),
129
+ ]
130
+ .filter(Boolean)
131
+ .join(", ")
154
132
 
155
- if (Object.keys(aligned).length <= 2) continue
133
+ const aligned = reconcileComponents(components, raw)
156
134
 
157
- const code = (record.code ?? "").toString().trim()
135
+ if (Object.keys(aligned).length <= 2) continue
158
136
 
159
- const sourceID = code
160
- ? `${STATE_HI_SCHOOLS_ADAPTER_ID}-${code}`
161
- : stableSourceID(STATE_HI_SCHOOLS_ADAPTER_ID, aligned)
137
+ const code = (record.code ?? "").toString().trim()
162
138
 
163
- yield {
164
- raw,
165
- components: aligned,
166
- country: "US",
167
- locale: "en-US",
168
- source: STATE_HI_SCHOOLS_ADAPTER_ID,
169
- source_id: sourceID,
170
- corpus_version: "",
171
- license: STATE_HI_SCHOOLS_DEFAULT_LICENSE,
172
- }
139
+ const sourceID = code
140
+ ? `${STATE_HI_SCHOOLS_ADAPTER_ID}-${code}`
141
+ : stableSourceID(STATE_HI_SCHOOLS_ADAPTER_ID, aligned)
173
142
 
174
- emitted++
143
+ yield {
144
+ raw,
145
+ components: aligned,
146
+ country: "US",
147
+ locale: "en-US",
148
+ source: STATE_HI_SCHOOLS_ADAPTER_ID,
149
+ source_id: sourceID,
150
+ corpus_version: "",
151
+ license: STATE_HI_SCHOOLS_DEFAULT_LICENSE,
175
152
  }
176
- } finally {
177
- stream.destroy()
153
+
154
+ emitted++
178
155
  }
179
156
  },
180
157
  }
@@ -16,11 +16,9 @@
16
16
  * License: stamped `"Public Domain"` per Iowa state government open-data terms.
17
17
  */
18
18
 
19
- import { createReadStream } from "node:fs"
19
+ import { CSVSpliterator } from "spliterator"
20
20
 
21
- import { parse as csvParse } from "csv-parse"
22
-
23
- import { stableSourceID } from "../../adapter.ts"
21
+ import { splitStreetLine, stableSourceID } from "../../adapter.ts"
24
22
  import { lookupStateAbbreviation } from "../../codex/us-fips-state.ts"
25
23
  import { reconcileComponents } from "../../format.ts"
26
24
  import type { AdapterOptions, CanonicalRow, CorpusAdapter } from "../../types.ts"
@@ -36,8 +34,6 @@ export const STATE_IA_CONTRACTORS_ADAPTER_ID = "state-ia-contractors"
36
34
  */
37
35
  export const STATE_IA_CONTRACTORS_DEFAULT_LICENSE = "Public Domain"
38
36
 
39
- const HOUSE_NUMBER_PREFIX = /^(\d+(?:-\d+)?[A-Za-z]?)\s+(.+)$/
40
-
41
37
  interface IaContractorRow {
42
38
  "Registration #": string
43
39
  "Business Name": string
@@ -50,17 +46,6 @@ interface IaContractorRow {
50
46
  "Last Name": string
51
47
  }
52
48
 
53
- function splitAddress(address: string): { house_number?: string; street: string } | null {
54
- const trimmed = address.trim()
55
-
56
- if (!trimmed) return null
57
- const m = HOUSE_NUMBER_PREFIX.exec(trimmed)
58
-
59
- if (m) return { house_number: m[1], street: m[2]!.trim() }
60
-
61
- return { street: trimmed }
62
- }
63
-
64
49
  export function createStateIaContractorsAdapter(): CorpusAdapter {
65
50
  return {
66
51
  id: STATE_IA_CONTRACTORS_ADAPTER_ID,
@@ -73,85 +58,76 @@ export function createStateIaContractorsAdapter(): CorpusAdapter {
73
58
  throw new Error(`state-ia-contractors adapter: only US supported, got country=${opts.country}`)
74
59
  }
75
60
 
76
- const stream = createReadStream(opts.inputPath, { encoding: "utf8" })
77
-
78
- const parser = stream.pipe(
79
- csvParse({
80
- columns: true,
81
- skip_empty_lines: true,
82
- relax_quotes: true,
83
- relax_column_count: true,
84
- })
85
- )
61
+ const rows = CSVSpliterator.fromAsync(opts.inputPath, {
62
+ mode: "object",
63
+ normalizeKeys: false,
64
+ enableQuoteHandling: true,
65
+ })
86
66
 
87
67
  let emitted = 0
88
68
 
89
- try {
90
- for await (const record of parser as AsyncIterable<IaContractorRow>) {
91
- if (opts.signal?.aborted) break
92
-
93
- if (opts.limit !== undefined && emitted >= opts.limit) break
69
+ for await (const record of rows as AsyncIterable<IaContractorRow>) {
70
+ if (opts.signal?.aborted) break
94
71
 
95
- const businessName = (record["Business Name"] ?? "").trim()
96
- const address1 = (record["Address 1"] ?? "").trim()
97
- const address2 = (record["Address 2"] ?? "").trim()
98
- const city = (record.City ?? "").trim()
99
- const stateAbbr = (record.State ?? "").trim()
100
- const zip = (record["Zip Code"] ?? "").trim()
72
+ if (opts.limit !== undefined && emitted >= opts.limit) break
101
73
 
102
- if (!city || !zip) continue
74
+ const businessName = (record["Business Name"] ?? "").trim()
75
+ const address1 = (record["Address 1"] ?? "").trim()
76
+ const address2 = (record["Address 2"] ?? "").trim()
77
+ const city = (record.City ?? "").trim()
78
+ const stateAbbr = (record.State ?? "").trim()
79
+ const zip = (record["Zip Code"] ?? "").trim()
103
80
 
104
- const state = lookupStateAbbreviation(stateAbbr)
81
+ if (!city || !zip) continue
105
82
 
106
- if (!state) continue
83
+ const state = lookupStateAbbreviation(stateAbbr)
107
84
 
108
- const fullAddress = [address1, address2].filter(Boolean).join(" ")
109
- const split = splitAddress(fullAddress)
85
+ if (!state) continue
110
86
 
111
- if (!split) continue
87
+ const fullAddress = [address1, address2].filter(Boolean).join(" ")
88
+ const split = splitStreetLine(fullAddress)
112
89
 
113
- const venue = businessName || undefined
90
+ if (!split) continue
114
91
 
115
- const components: CanonicalRow["components"] = {
116
- ...(venue ? { venue } : {}),
117
- ...(split.house_number ? { house_number: split.house_number } : {}),
118
- street: split.street,
119
- locality: city,
120
- region: state.abbreviation,
121
- postcode: zip,
122
- }
92
+ const venue = businessName || undefined
123
93
 
124
- const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
94
+ const components: CanonicalRow["components"] = {
95
+ ...(venue ? { venue } : {}),
96
+ ...(split.house_number ? { house_number: split.house_number } : {}),
97
+ street: split.street,
98
+ locality: city,
99
+ region: state.abbreviation,
100
+ postcode: zip,
101
+ }
125
102
 
126
- const raw = [venue, streetPart, [city, [stateAbbr, zip].filter(Boolean).join(" ")].filter(Boolean).join(", ")]
127
- .filter(Boolean)
128
- .join(", ")
103
+ const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
129
104
 
130
- const aligned = reconcileComponents(components, raw)
105
+ const raw = [venue, streetPart, [city, [stateAbbr, zip].filter(Boolean).join(" ")].filter(Boolean).join(", ")]
106
+ .filter(Boolean)
107
+ .join(", ")
131
108
 
132
- if (Object.keys(aligned).length <= 2) continue
109
+ const aligned = reconcileComponents(components, raw)
133
110
 
134
- const regNum = (record["Registration #"] ?? "").trim()
111
+ if (Object.keys(aligned).length <= 2) continue
135
112
 
136
- const sourceID = regNum
137
- ? `${STATE_IA_CONTRACTORS_ADAPTER_ID}-${regNum}`
138
- : stableSourceID(STATE_IA_CONTRACTORS_ADAPTER_ID, aligned)
113
+ const regNum = (record["Registration #"] ?? "").trim()
139
114
 
140
- yield {
141
- raw,
142
- components: aligned,
143
- country: "US",
144
- locale: "en-US",
145
- source: STATE_IA_CONTRACTORS_ADAPTER_ID,
146
- source_id: sourceID,
147
- corpus_version: "",
148
- license: STATE_IA_CONTRACTORS_DEFAULT_LICENSE,
149
- }
115
+ const sourceID = regNum
116
+ ? `${STATE_IA_CONTRACTORS_ADAPTER_ID}-${regNum}`
117
+ : stableSourceID(STATE_IA_CONTRACTORS_ADAPTER_ID, aligned)
150
118
 
151
- emitted++
119
+ yield {
120
+ raw,
121
+ components: aligned,
122
+ country: "US",
123
+ locale: "en-US",
124
+ source: STATE_IA_CONTRACTORS_ADAPTER_ID,
125
+ source_id: sourceID,
126
+ corpus_version: "",
127
+ license: STATE_IA_CONTRACTORS_DEFAULT_LICENSE,
152
128
  }
153
- } finally {
154
- stream.destroy()
129
+
130
+ emitted++
155
131
  }
156
132
  },
157
133
  }
@@ -14,11 +14,9 @@
14
14
  * License: stamped `"Public Domain"` per New York state government open-data terms.
15
15
  */
16
16
 
17
- import { createReadStream } from "node:fs"
17
+ import { CSVSpliterator } from "spliterator"
18
18
 
19
- import { parse as csvParse } from "csv-parse"
20
-
21
- import { stableSourceID } from "../../adapter.ts"
19
+ import { splitStreetLine, stableSourceID } from "../../adapter.ts"
22
20
  import { lookupStateAbbreviation } from "../../codex/us-fips-state.ts"
23
21
  import { reconcileComponents } from "../../format.ts"
24
22
  import type { AdapterOptions, CanonicalRow, CorpusAdapter } from "../../types.ts"
@@ -34,8 +32,6 @@ export const STATE_NY_NOTARIES_ADAPTER_ID = "state-ny-notaries"
34
32
  */
35
33
  export const STATE_NY_NOTARIES_DEFAULT_LICENSE = "Public Domain"
36
34
 
37
- const HOUSE_NUMBER_PREFIX = /^(\d+(?:-\d+)?[A-Za-z]?)\s+(.+)$/
38
-
39
35
  interface NyNotaryRow {
40
36
  "Commission Holder Name": string
41
37
  "Commission Number (UID)": string
@@ -48,17 +44,6 @@ interface NyNotaryRow {
48
44
  "Commissioned County": string
49
45
  }
50
46
 
51
- function splitAddress(address: string): { house_number?: string; street: string } | null {
52
- const trimmed = address.trim()
53
-
54
- if (!trimmed) return null
55
- const m = HOUSE_NUMBER_PREFIX.exec(trimmed)
56
-
57
- if (m) return { house_number: m[1], street: m[2]!.trim() }
58
-
59
- return { street: trimmed }
60
- }
61
-
62
47
  const RAW_NY_COLUMNS = [
63
48
  "Commission Holder Name",
64
49
  "Commission Number (UID)",
@@ -82,97 +67,88 @@ export function createStateNyNotariesAdapter(): CorpusAdapter {
82
67
  throw new Error(`state-ny-notaries adapter: only US supported, got country=${opts.country}`)
83
68
  }
84
69
 
85
- const stream = createReadStream(opts.inputPath, { encoding: "utf8" })
86
-
87
- const parser = stream.pipe(
88
- csvParse({
89
- columns: true,
90
- skip_empty_lines: true,
91
- relax_quotes: true,
92
- relax_column_count: true,
93
- })
94
- )
70
+ const rows = CSVSpliterator.fromAsync(opts.inputPath, {
71
+ mode: "object",
72
+ normalizeKeys: false,
73
+ enableQuoteHandling: true,
74
+ })
95
75
 
96
76
  let emitted = 0
97
77
 
98
- try {
99
- for await (const rawRecord of parser as AsyncIterable<Record<string, string>>) {
100
- if (opts.signal?.aborted) break
101
-
102
- if (opts.limit !== undefined && emitted >= opts.limit) break
78
+ for await (const rawRecord of rows as AsyncIterable<Record<string, string>>) {
79
+ if (opts.signal?.aborted) break
103
80
 
104
- // NY CSV has columns with leading spaces, so we normalize by trimming keys.
105
- const record: Record<string, string> = {}
81
+ if (opts.limit !== undefined && emitted >= opts.limit) break
106
82
 
107
- for (const key of Object.keys(rawRecord)) {
108
- record[key.trim()] = rawRecord[key] ?? ""
109
- }
83
+ // NY CSV has columns with leading spaces, so we normalize by trimming keys.
84
+ const record: Record<string, string> = {}
110
85
 
111
- const holderName = (record["Commission Holder Name"] ?? "").trim()
112
- const businessName = (record["Business Name (if available)"] ?? "").trim()
113
- const address1 = (record["Business Address 1 (if available)"] ?? "").trim()
114
- const address2 = (record["Business Address 2 (if available)"] ?? "").trim()
115
- const city = (record["Business City (if available)"] ?? "").trim()
116
- const stateAbbr = (record["Business State (if available)"] ?? "").trim()
117
- const zip = (record["Business Zip (if available)"] ?? "").trim()
118
- const county = (record["Commissioned County"] ?? "").trim()
86
+ for (const key of Object.keys(rawRecord)) {
87
+ record[key.trim()] = rawRecord[key] ?? ""
88
+ }
119
89
 
120
- if (!city || !stateAbbr || !zip) continue
90
+ const holderName = (record["Commission Holder Name"] ?? "").trim()
91
+ const businessName = (record["Business Name (if available)"] ?? "").trim()
92
+ const address1 = (record["Business Address 1 (if available)"] ?? "").trim()
93
+ const address2 = (record["Business Address 2 (if available)"] ?? "").trim()
94
+ const city = (record["Business City (if available)"] ?? "").trim()
95
+ const stateAbbr = (record["Business State (if available)"] ?? "").trim()
96
+ const zip = (record["Business Zip (if available)"] ?? "").trim()
97
+ const county = (record["Commissioned County"] ?? "").trim()
121
98
 
122
- if (!address1 && !address2) continue
99
+ if (!city || !stateAbbr || !zip) continue
123
100
 
124
- const state = lookupStateAbbreviation(stateAbbr)
101
+ if (!address1 && !address2) continue
125
102
 
126
- if (!state) continue
103
+ const state = lookupStateAbbreviation(stateAbbr)
127
104
 
128
- const fullAddress = [address1, address2].filter(Boolean).join(" ")
129
- const split = splitAddress(fullAddress)
105
+ if (!state) continue
130
106
 
131
- if (!split) continue
107
+ const fullAddress = [address1, address2].filter(Boolean).join(" ")
108
+ const split = splitStreetLine(fullAddress)
132
109
 
133
- const venue = businessName || holderName || undefined
110
+ if (!split) continue
134
111
 
135
- const components: CanonicalRow["components"] = {
136
- ...(venue ? { venue } : {}),
137
- ...(split.house_number ? { house_number: split.house_number } : {}),
138
- street: split.street,
139
- locality: city,
140
- region: state.abbreviation,
141
- postcode: zip,
142
- ...(county ? { subregion: county } : {}),
143
- }
112
+ const venue = businessName || holderName || undefined
144
113
 
145
- const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
114
+ const components: CanonicalRow["components"] = {
115
+ ...(venue ? { venue } : {}),
116
+ ...(split.house_number ? { house_number: split.house_number } : {}),
117
+ street: split.street,
118
+ locality: city,
119
+ region: state.abbreviation,
120
+ postcode: zip,
121
+ ...(county ? { subregion: county } : {}),
122
+ }
146
123
 
147
- const raw = [venue, streetPart, [city, [stateAbbr, zip].filter(Boolean).join(" ")].filter(Boolean).join(", ")]
148
- .filter(Boolean)
149
- .join(", ")
124
+ const streetPart = [split.house_number, split.street].filter(Boolean).join(" ").trim()
150
125
 
151
- const aligned = reconcileComponents(components, raw)
126
+ const raw = [venue, streetPart, [city, [stateAbbr, zip].filter(Boolean).join(" ")].filter(Boolean).join(", ")]
127
+ .filter(Boolean)
128
+ .join(", ")
152
129
 
153
- if (Object.keys(aligned).length <= 2) continue
130
+ const aligned = reconcileComponents(components, raw)
154
131
 
155
- const commNum = (record["Commission Number (UID)"] ?? "").trim()
132
+ if (Object.keys(aligned).length <= 2) continue
156
133
 
157
- const sourceID = commNum
158
- ? `${STATE_NY_NOTARIES_ADAPTER_ID}-${commNum}`
159
- : stableSourceID(STATE_NY_NOTARIES_ADAPTER_ID, aligned)
134
+ const commNum = (record["Commission Number (UID)"] ?? "").trim()
160
135
 
161
- yield {
162
- raw,
163
- components: aligned,
164
- country: "US",
165
- locale: "en-US",
166
- source: STATE_NY_NOTARIES_ADAPTER_ID,
167
- source_id: sourceID,
168
- corpus_version: "",
169
- license: STATE_NY_NOTARIES_DEFAULT_LICENSE,
170
- }
136
+ const sourceID = commNum
137
+ ? `${STATE_NY_NOTARIES_ADAPTER_ID}-${commNum}`
138
+ : stableSourceID(STATE_NY_NOTARIES_ADAPTER_ID, aligned)
171
139
 
172
- emitted++
140
+ yield {
141
+ raw,
142
+ components: aligned,
143
+ country: "US",
144
+ locale: "en-US",
145
+ source: STATE_NY_NOTARIES_ADAPTER_ID,
146
+ source_id: sourceID,
147
+ corpus_version: "",
148
+ license: STATE_NY_NOTARIES_DEFAULT_LICENSE,
173
149
  }
174
- } finally {
175
- stream.destroy()
150
+
151
+ emitted++
176
152
  }
177
153
  },
178
154
  }