@mailwoman/tiger 4.16.1 → 5.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.
- package/block-group.ts +2 -3
- package/class-code.ts +268 -318
- package/constants.ts +2 -4
- package/county-subdivision.ts +3 -4
- package/county.ts +2 -3
- package/files.ts +1 -0
- package/functional-status.ts +4 -6
- package/geoid.ts +20 -18
- package/legal-statistical-area.ts +4 -6
- package/out/block-group.d.ts +2 -3
- package/out/block-group.d.ts.map +1 -1
- package/out/class-code.d.ts +268 -318
- package/out/class-code.d.ts.map +1 -1
- package/out/class-code.js +268 -318
- package/out/class-code.js.map +1 -1
- package/out/constants.d.ts +2 -4
- package/out/constants.d.ts.map +1 -1
- package/out/county-subdivision.d.ts +3 -4
- package/out/county-subdivision.d.ts.map +1 -1
- package/out/county.d.ts +2 -3
- package/out/county.d.ts.map +1 -1
- package/out/county.js.map +1 -1
- package/out/files.d.ts.map +1 -1
- package/out/files.js.map +1 -1
- package/out/functional-status.d.ts +4 -6
- package/out/functional-status.d.ts.map +1 -1
- package/out/functional-status.js +4 -6
- package/out/functional-status.js.map +1 -1
- package/out/geoid.d.ts +15 -15
- package/out/geoid.d.ts.map +1 -1
- package/out/geoid.js +3 -4
- package/out/geoid.js.map +1 -1
- package/out/legal-statistical-area.d.ts +4 -6
- package/out/legal-statistical-area.d.ts.map +1 -1
- package/out/legal-statistical-area.js +4 -6
- package/out/legal-statistical-area.js.map +1 -1
- package/out/sdk/fetch.d.ts +3 -6
- package/out/sdk/fetch.d.ts.map +1 -1
- package/out/sdk/fetch.js +3 -4
- package/out/sdk/fetch.js.map +1 -1
- package/out/sdk/redistricting.d.ts +1 -2
- package/out/sdk/redistricting.d.ts.map +1 -1
- package/out/sdk/redistricting.js +3 -4
- package/out/sdk/redistricting.js.map +1 -1
- package/out/sdk/schema.d.ts +12 -12
- package/out/sdk/schema.js +9 -9
- package/out/sdk/state/block-operations.d.ts +1 -2
- package/out/sdk/state/block-operations.d.ts.map +1 -1
- package/out/sdk/state/block-operations.js +1 -2
- package/out/sdk/state/block-operations.js.map +1 -1
- package/out/state.d.ts +10 -12
- package/out/state.d.ts.map +1 -1
- package/out/state.js +8 -10
- package/out/state.js.map +1 -1
- package/out/tabulation-block.d.ts +2 -2
- package/out/tabulation-block.d.ts.map +1 -1
- package/out/tabulation-block.js.map +1 -1
- package/out/tract.d.ts +2 -2
- package/out/tract.d.ts.map +1 -1
- package/out/tract.js.map +1 -1
- package/out/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -18
- package/sdk/fetch.ts +21 -8
- package/sdk/redistricting.ts +14 -4
- package/sdk/schema.ts +12 -12
- package/sdk/state/block-operations.ts +1 -2
- package/state.ts +11 -12
- package/tabulation-block.ts +3 -2
- package/tract.ts +3 -2
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/tiger",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "US Census TIGER/Line data processing and analysis.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"census",
|
|
7
|
+
"geospatial",
|
|
8
|
+
"tiger"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/sister-software/mailwoman",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/sister-software/mailwoman/issues"
|
|
13
|
+
},
|
|
5
14
|
"license": "AGPL-3.0-only",
|
|
6
15
|
"contributors": [
|
|
7
16
|
{
|
|
@@ -14,13 +23,6 @@
|
|
|
14
23
|
"url": "https://github.com/sister-software/mailwoman.git",
|
|
15
24
|
"directory": "tiger"
|
|
16
25
|
},
|
|
17
|
-
"bugs": {
|
|
18
|
-
"url": "https://github.com/sister-software/mailwoman/issues"
|
|
19
|
-
},
|
|
20
|
-
"homepage": "https://github.com/sister-software/mailwoman",
|
|
21
|
-
"scripts": {
|
|
22
|
-
"test": "node ./out/sdk/TIGERService.test.js"
|
|
23
|
-
},
|
|
24
26
|
"type": "module",
|
|
25
27
|
"exports": {
|
|
26
28
|
"./package.json": "./package.json",
|
|
@@ -29,9 +31,15 @@
|
|
|
29
31
|
"./sdk": "./out/sdk/index.js",
|
|
30
32
|
".": "./out/index.js"
|
|
31
33
|
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "node ./out/sdk/TIGERService.test.js"
|
|
39
|
+
},
|
|
32
40
|
"dependencies": {
|
|
33
|
-
"@mailwoman/core": "
|
|
34
|
-
"@mailwoman/spatial": "
|
|
41
|
+
"@mailwoman/core": "5.0.0",
|
|
42
|
+
"@mailwoman/spatial": "5.0.0",
|
|
35
43
|
"@turf/boolean-contains": "^7.3.5",
|
|
36
44
|
"kysely": "^0.29.2",
|
|
37
45
|
"shapefile-parser": "^1.0.3",
|
|
@@ -39,13 +47,5 @@
|
|
|
39
47
|
},
|
|
40
48
|
"engines": {
|
|
41
49
|
"node": ">=24.18.0"
|
|
42
|
-
},
|
|
43
|
-
"keywords": [
|
|
44
|
-
"census",
|
|
45
|
-
"tiger",
|
|
46
|
-
"geospatial"
|
|
47
|
-
],
|
|
48
|
-
"publishConfig": {
|
|
49
|
-
"access": "public"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/sdk/fetch.ts
CHANGED
|
@@ -24,8 +24,6 @@
|
|
|
24
24
|
* inserts. Re-running a state replaces its rows.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import { DatabaseClient } from "@mailwoman/core/kysley/client"
|
|
28
|
-
import { mailwomanDataRoot } from "@mailwoman/core/utils"
|
|
29
27
|
import { spawn } from "node:child_process"
|
|
30
28
|
import { createWriteStream, existsSync } from "node:fs"
|
|
31
29
|
import { mkdir, rename } from "node:fs/promises"
|
|
@@ -34,6 +32,10 @@ import { createInterface } from "node:readline"
|
|
|
34
32
|
import { DatabaseSync } from "node:sqlite"
|
|
35
33
|
import { Readable } from "node:stream"
|
|
36
34
|
import { pipeline } from "node:stream/promises"
|
|
35
|
+
|
|
36
|
+
import { DatabaseClient } from "@mailwoman/core/kysley/client"
|
|
37
|
+
import { mailwomanDataRoot } from "@mailwoman/core/utils"
|
|
38
|
+
|
|
37
39
|
import type { TIGERBlockTable, TIGERDatabase, TIGERPlaceTable, TIGERStreetTable } from "./schema.js"
|
|
38
40
|
import { initializeTIGERSchema, TIGER_PRAGMAS } from "./schema.js"
|
|
39
41
|
|
|
@@ -41,8 +43,7 @@ const CENSUS_HOST = "https://www2.census.gov"
|
|
|
41
43
|
const DEFAULT_DATA_ROOT = mailwomanDataRoot()
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
|
-
* Supported TIGER levels. `tabblock20` is per state + carries geometry; `place`/`addrfeat` are
|
|
45
|
-
* attribute-only.
|
|
46
|
+
* Supported TIGER levels. `tabblock20` is per state + carries geometry; `place`/`addrfeat` are attribute-only.
|
|
46
47
|
*/
|
|
47
48
|
export type TIGERFetchLevel = "tabblock20" | "place" | "addrfeat"
|
|
48
49
|
|
|
@@ -65,8 +66,7 @@ export interface FetchTIGEROptions {
|
|
|
65
66
|
/** Vintage. Default 2020 for blocks (matches the 2020 P.L.), 2024 for place/addrfeat (current). */
|
|
66
67
|
vintage?: number
|
|
67
68
|
/**
|
|
68
|
-
* Output SQLite path. Default `<dataRoot>/tiger/tiger.db` (the name the corpus `tiger` adapter
|
|
69
|
-
* reads).
|
|
69
|
+
* Output SQLite path. Default `<dataRoot>/tiger/tiger.db` (the name the corpus `tiger` adapter reads).
|
|
70
70
|
*/
|
|
71
71
|
outPath?: string
|
|
72
72
|
/** Download cache + default output root. */
|
|
@@ -91,6 +91,7 @@ export interface FetchTIGERResult {
|
|
|
91
91
|
/** The isp-nexus column map for `tabblock20`. Geometry rides along implicitly. */
|
|
92
92
|
function blockSelectSQL(layer: string, county?: string): string {
|
|
93
93
|
const where = county ? ` WHERE COUNTYFP20 = '${county}'` : ""
|
|
94
|
+
|
|
94
95
|
return (
|
|
95
96
|
`SELECT GEOID20 AS GEOID, STATEFP20 AS state_code, COUNTYFP20 AS county_code, ` +
|
|
96
97
|
`SUBSTR(GEOID20, 6, 6) AS tract_code, ` +
|
|
@@ -171,6 +172,7 @@ async function downloadIfNeeded(url: string, dest: string): Promise<boolean> {
|
|
|
171
172
|
if (existsSync(dest)) {
|
|
172
173
|
try {
|
|
173
174
|
await runCapture("unzip", ["-tq", dest])
|
|
175
|
+
|
|
174
176
|
return true
|
|
175
177
|
} catch {
|
|
176
178
|
// corrupt cache — re-download
|
|
@@ -178,26 +180,30 @@ async function downloadIfNeeded(url: string, dest: string): Promise<boolean> {
|
|
|
178
180
|
}
|
|
179
181
|
const tmp = dest + ".tmp"
|
|
180
182
|
const res = await fetch(url, { redirect: "follow" })
|
|
183
|
+
|
|
181
184
|
if (!res.ok || !res.body) throw new Error(`HTTP ${res.status} fetching ${url}`)
|
|
182
185
|
await pipeline(Readable.fromWeb(res.body as Parameters<typeof Readable.fromWeb>[0]), createWriteStream(tmp))
|
|
183
186
|
await rename(tmp, dest)
|
|
187
|
+
|
|
184
188
|
return false
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
/** Scrape the ADDRFEAT directory listing for a state's county FIPS codes. */
|
|
188
192
|
async function discoverCounties(state: string, vintage: number): Promise<string[]> {
|
|
189
193
|
const res = await fetch(`${CENSUS_HOST}/geo/tiger/TIGER${vintage}/ADDRFEAT/`, { redirect: "follow" })
|
|
194
|
+
|
|
190
195
|
if (!res.ok) throw new Error(`HTTP ${res.status} listing ADDRFEAT for vintage ${vintage}`)
|
|
191
196
|
const html = await res.text()
|
|
192
197
|
const re = new RegExp(`tl_${vintage}_${state}(\\d{3})_addrfeat\\.zip`, "g")
|
|
193
198
|
const counties = new Set<string>()
|
|
199
|
+
|
|
194
200
|
for (let m = re.exec(html); m; m = re.exec(html)) counties.add(m[1]!)
|
|
201
|
+
|
|
195
202
|
return [...counties].sort()
|
|
196
203
|
}
|
|
197
204
|
|
|
198
205
|
/**
|
|
199
|
-
* Fetch one state's TIGER data at `level` into a SQLite DB. Yields progress; returns the final
|
|
200
|
-
* tally.
|
|
206
|
+
* Fetch one state's TIGER data at `level` into a SQLite DB. Yields progress; returns the final tally.
|
|
201
207
|
*/
|
|
202
208
|
export async function* fetchTIGER(options: FetchTIGEROptions): AsyncGenerator<FetchTIGEREvent, FetchTIGERResult> {
|
|
203
209
|
const level = options.level ?? "tabblock20"
|
|
@@ -218,6 +224,7 @@ export async function* fetchTIGER(options: FetchTIGEROptions): AsyncGenerator<Fe
|
|
|
218
224
|
|
|
219
225
|
// Source units: one (per-state) for block/place; one per county for addrfeat.
|
|
220
226
|
const geoCodes = level === "addrfeat" ? await discoverCounties(state, vintage) : [""]
|
|
227
|
+
|
|
221
228
|
if (level === "addrfeat" && geoCodes.length === 0) {
|
|
222
229
|
throw new Error(`No ADDRFEAT counties found for state ${state} vintage ${vintage}`)
|
|
223
230
|
}
|
|
@@ -296,14 +303,18 @@ export async function* fetchTIGER(options: FetchTIGEROptions): AsyncGenerator<Fe
|
|
|
296
303
|
for await (const line of createInterface({ input: child.stdout, crlfDelay: Infinity })) {
|
|
297
304
|
if (!line) continue
|
|
298
305
|
let feat: { properties?: Record<string, unknown>; geometry?: unknown }
|
|
306
|
+
|
|
299
307
|
try {
|
|
300
308
|
feat = JSON.parse(line)
|
|
301
309
|
} catch {
|
|
302
310
|
continue
|
|
303
311
|
}
|
|
312
|
+
|
|
304
313
|
if (!feat.properties) continue
|
|
314
|
+
|
|
305
315
|
if (level === "tabblock20" && !feat.geometry) continue
|
|
306
316
|
batch.push(buildRow(level, feat.properties, feat.geometry, state))
|
|
317
|
+
|
|
307
318
|
if (batch.length >= batchSize) {
|
|
308
319
|
await flush()
|
|
309
320
|
yield { phase: "load", inserted, total: 0 }
|
|
@@ -312,11 +323,13 @@ export async function* fetchTIGER(options: FetchTIGEROptions): AsyncGenerator<Fe
|
|
|
312
323
|
await flush()
|
|
313
324
|
|
|
314
325
|
const code = await exited
|
|
326
|
+
|
|
315
327
|
if (code !== 0) throw new Error(`ogr2ogr exited ${code} on ${layer}: ${stderr.slice(0, 500)}`)
|
|
316
328
|
yield { phase: "load", inserted, total: 0 }
|
|
317
329
|
}
|
|
318
330
|
|
|
319
331
|
db.exec("PRAGMA wal_checkpoint(TRUNCATE);")
|
|
332
|
+
|
|
320
333
|
return { outPath, table, inserted }
|
|
321
334
|
} finally {
|
|
322
335
|
await kdb.destroy()
|
package/sdk/redistricting.ts
CHANGED
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
* https://www2.census.gov/programs-surveys/decennial/2020/data/01-Redistricting_File--PL_94-171/
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { DatabaseClient } from "@mailwoman/core/kysley/client"
|
|
20
|
-
import { mailwomanDataRoot } from "@mailwoman/core/utils"
|
|
21
19
|
import { spawn } from "node:child_process"
|
|
22
20
|
import { createReadStream, createWriteStream, existsSync } from "node:fs"
|
|
23
21
|
import { mkdir, rename } from "node:fs/promises"
|
|
@@ -26,6 +24,10 @@ import { createInterface } from "node:readline"
|
|
|
26
24
|
import { DatabaseSync } from "node:sqlite"
|
|
27
25
|
import { Readable } from "node:stream"
|
|
28
26
|
import { pipeline } from "node:stream/promises"
|
|
27
|
+
|
|
28
|
+
import { DatabaseClient } from "@mailwoman/core/kysley/client"
|
|
29
|
+
import { mailwomanDataRoot } from "@mailwoman/core/utils"
|
|
30
|
+
|
|
29
31
|
import { AdminLevel1CodeToAbbreviation, StateName, type AdminLevel1Code } from "../state.js"
|
|
30
32
|
import { initializeTIGERSchema, TIGER_PRAGMAS, type PLBlockTable, type TIGERDatabase } from "./schema.js"
|
|
31
33
|
|
|
@@ -100,6 +102,7 @@ async function downloadIfNeeded(url: string, dest: string): Promise<boolean> {
|
|
|
100
102
|
if (existsSync(dest)) {
|
|
101
103
|
try {
|
|
102
104
|
await runCapture("unzip", ["-tq", dest])
|
|
105
|
+
|
|
103
106
|
return true
|
|
104
107
|
} catch {
|
|
105
108
|
// corrupt cache — re-download
|
|
@@ -107,9 +110,11 @@ async function downloadIfNeeded(url: string, dest: string): Promise<boolean> {
|
|
|
107
110
|
}
|
|
108
111
|
const tmp = dest + ".tmp"
|
|
109
112
|
const res = await fetch(url, { redirect: "follow" })
|
|
113
|
+
|
|
110
114
|
if (!res.ok || !res.body) throw new Error(`HTTP ${res.status} fetching ${url}`)
|
|
111
115
|
await pipeline(Readable.fromWeb(res.body as Parameters<typeof Readable.fromWeb>[0]), createWriteStream(tmp))
|
|
112
116
|
await rename(tmp, dest)
|
|
117
|
+
|
|
113
118
|
return false
|
|
114
119
|
}
|
|
115
120
|
|
|
@@ -120,8 +125,7 @@ async function eachLine(path: string, fn: (line: string) => void): Promise<void>
|
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
/**
|
|
123
|
-
* Fetch one state's P.L. 94-171 block race counts into `pl_block`. Yields progress; returns the
|
|
124
|
-
* tally.
|
|
128
|
+
* Fetch one state's P.L. 94-171 block race counts into `pl_block`. Yields progress; returns the tally.
|
|
125
129
|
*/
|
|
126
130
|
export async function* fetchRedistricting(
|
|
127
131
|
options: FetchRedistrictingOptions
|
|
@@ -132,6 +136,7 @@ export async function* fetchRedistricting(
|
|
|
132
136
|
const state = options.stateFIPS
|
|
133
137
|
|
|
134
138
|
const abbr = AdminLevel1CodeToAbbreviation[state as AdminLevel1Code]
|
|
139
|
+
|
|
135
140
|
if (!abbr) throw new Error(`Unknown state FIPS "${state}"`)
|
|
136
141
|
const stateName = StateName[abbr as keyof typeof StateName]
|
|
137
142
|
const dirName = stateName.replace(/ /g, "_")
|
|
@@ -160,8 +165,10 @@ export async function* fetchRedistricting(
|
|
|
160
165
|
const logToGeoid = new Map<string, string>()
|
|
161
166
|
await eachLine(geoPath, (line) => {
|
|
162
167
|
const f = line.split("|")
|
|
168
|
+
|
|
163
169
|
if (f[GEO_SUMLEV] !== "750") return
|
|
164
170
|
const geoid = f[GEO_GEOCODE] ?? ""
|
|
171
|
+
|
|
165
172
|
if (!geoid.startsWith(prefix)) return
|
|
166
173
|
logToGeoid.set(f[GEO_LOGRECNO] ?? "", geoid)
|
|
167
174
|
})
|
|
@@ -195,6 +202,7 @@ export async function* fetchRedistricting(
|
|
|
195
202
|
if (!line) continue
|
|
196
203
|
const f = line.split("|")
|
|
197
204
|
const geoid = logToGeoid.get(f[SEG_LOGRECNO] ?? "")
|
|
205
|
+
|
|
198
206
|
if (!geoid) continue
|
|
199
207
|
batch.push({
|
|
200
208
|
GEOID: geoid,
|
|
@@ -208,6 +216,7 @@ export async function* fetchRedistricting(
|
|
|
208
216
|
other: Number(f[CATEGORY_INDEX.other] ?? 0),
|
|
209
217
|
multi: Number(f[CATEGORY_INDEX.multi] ?? 0),
|
|
210
218
|
})
|
|
219
|
+
|
|
211
220
|
if (batch.length >= batchSize) {
|
|
212
221
|
await flush()
|
|
213
222
|
yield { phase: "load", inserted, total }
|
|
@@ -217,6 +226,7 @@ export async function* fetchRedistricting(
|
|
|
217
226
|
|
|
218
227
|
yield { phase: "load", inserted, total }
|
|
219
228
|
db.exec("PRAGMA wal_checkpoint(TRUNCATE);")
|
|
229
|
+
|
|
220
230
|
return { outPath, table: "pl_block", inserted }
|
|
221
231
|
} finally {
|
|
222
232
|
await kdb.destroy()
|
package/sdk/schema.ts
CHANGED
|
@@ -30,9 +30,9 @@ export interface TIGERBlockTable {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Kysely row type for `pl_block` — Census 2020 P.L. 94-171 table P2 (Hispanic-or-Latino by race),
|
|
34
|
-
*
|
|
35
|
-
*
|
|
33
|
+
* Kysely row type for `pl_block` — Census 2020 P.L. 94-171 table P2 (Hispanic-or-Latino by race), one row per
|
|
34
|
+
* tabulation block, keyed on the same 15-char `GEOID` as {@link TIGERBlockTable}. The eight category columns partition
|
|
35
|
+
* `pop_total`.
|
|
36
36
|
*/
|
|
37
37
|
export interface PLBlockTable {
|
|
38
38
|
GEOID: string
|
|
@@ -78,9 +78,9 @@ export interface TIGERDatabase {
|
|
|
78
78
|
export type { Generated }
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
|
-
* Build-tuning PRAGMAs, run raw before any table is created (`page_size`/`auto_vacuum` only take
|
|
82
|
-
*
|
|
83
|
-
*
|
|
81
|
+
* Build-tuning PRAGMAs, run raw before any table is created (`page_size`/`auto_vacuum` only take effect on an empty DB,
|
|
82
|
+
* and PRAGMA has no Kysely builder). The consumer execs this, then calls {@link initializeTIGERSchema} for the tables +
|
|
83
|
+
* indexes.
|
|
84
84
|
*/
|
|
85
85
|
export const TIGER_PRAGMAS = /* sql */ `
|
|
86
86
|
PRAGMA auto_vacuum = INCREMENTAL;
|
|
@@ -90,13 +90,13 @@ PRAGMA journal_mode = WAL;
|
|
|
90
90
|
`
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
|
-
* Create the TIGER tables + indexes via the Kysely schema-builder (the house idiom). Idempotent
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
93
|
+
* Create the TIGER tables + indexes via the Kysely schema-builder (the house idiom). Idempotent (`IF NOT EXISTS`). Pass
|
|
94
|
+
* a {@link DatabaseClient} (or any `Kysely`) over the TIGER DB; run {@link TIGER_PRAGMAS} first. `us_state`/`tract`
|
|
95
|
+
* aren't in {@link TIGERDatabase} (created here but not queried via Kysely) — `createTable` takes any table name, so
|
|
96
|
+
* that's fine.
|
|
97
97
|
*
|
|
98
|
-
* The `text(N)` length hints in the prior raw DDL were documentary only (SQLite uses TEXT affinity
|
|
99
|
-
*
|
|
98
|
+
* The `text(N)` length hints in the prior raw DDL were documentary only (SQLite uses TEXT affinity regardless); the
|
|
99
|
+
* lengths live on the {@link TIGERBlockTable} interface instead.
|
|
100
100
|
*/
|
|
101
101
|
export async function initializeTIGERSchema(db: Kysely<TIGERDatabase>): Promise<void> {
|
|
102
102
|
await db.schema
|
|
@@ -51,8 +51,7 @@ export function parseTIGERBlockFromRow({ serializedGeometry, ...properties }: TI
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* Given a collection of rows from the TIGER tabulated block table, parses them into a GeoJSON
|
|
55
|
-
* feature collection.
|
|
54
|
+
* Given a collection of rows from the TIGER tabulated block table, parses them into a GeoJSON feature collection.
|
|
56
55
|
*
|
|
57
56
|
* @internal
|
|
58
57
|
*/
|
package/state.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { GeoFeature, MultiPolygonLiteral } from "@mailwoman/spatial"
|
|
8
|
+
|
|
8
9
|
import { GeoIDPart } from "./geoid.js"
|
|
9
10
|
import type { TIGERTabulatedBlockProperties } from "./tabulation-block.js"
|
|
10
11
|
|
|
@@ -180,10 +181,10 @@ export enum FIPSStateCode {
|
|
|
180
181
|
* @category FIPS
|
|
181
182
|
* @category Territories
|
|
182
183
|
* @category Census
|
|
183
|
-
* @see {@linkcode FIPSStateCode} for states.
|
|
184
|
-
* @see {@linkcode AdminLevel1Code} for a combined set of states and territories.
|
|
185
184
|
* @minLength 2
|
|
186
185
|
* @maxLength 2
|
|
186
|
+
* @see {@linkcode FIPSStateCode} for states.
|
|
187
|
+
* @see {@linkcode AdminLevel1Code} for a combined set of states and territories.
|
|
187
188
|
*/
|
|
188
189
|
export enum FIPSTerritoryCode {
|
|
189
190
|
/**
|
|
@@ -214,11 +215,11 @@ export enum FIPSTerritoryCode {
|
|
|
214
215
|
* @category States
|
|
215
216
|
* @category Territories
|
|
216
217
|
* @category Census
|
|
217
|
-
* @see {@linkcode FIPSStateCode} for states.
|
|
218
|
-
* @see {@linkcode FIPSTerritoryCode} for territories.
|
|
219
218
|
* @minLength 2
|
|
220
219
|
* @maxLength 2
|
|
221
220
|
* @public
|
|
221
|
+
* @see {@linkcode FIPSStateCode} for states.
|
|
222
|
+
* @see {@linkcode FIPSTerritoryCode} for territories.
|
|
222
223
|
*/
|
|
223
224
|
export const AdminLevel1Code = {
|
|
224
225
|
...FIPSStateCode,
|
|
@@ -434,8 +435,8 @@ export enum StateName {
|
|
|
434
435
|
//#region State Utilities
|
|
435
436
|
|
|
436
437
|
/**
|
|
437
|
-
* Predicate for checking if a string is a proper abbreviation for a US State or territory, rather
|
|
438
|
-
*
|
|
438
|
+
* Predicate for checking if a string is a proper abbreviation for a US State or territory, rather than a random
|
|
439
|
+
* 2-letter string.
|
|
439
440
|
*
|
|
440
441
|
* @see {@link isStateAbbreviation} for a specific check for US States.
|
|
441
442
|
* @see {@link isStateTerritoryAbbreviation} for a specific check for US Territories.
|
|
@@ -447,8 +448,7 @@ export function isStateLevelAbbreviation(input: unknown): input is AdminLevel1Ab
|
|
|
447
448
|
}
|
|
448
449
|
|
|
449
450
|
/**
|
|
450
|
-
* Predicate for checking if a string is a proper abbreviation for a US State, rather than a random
|
|
451
|
-
* 2-letter string.
|
|
451
|
+
* Predicate for checking if a string is a proper abbreviation for a US State, rather than a random 2-letter string.
|
|
452
452
|
*
|
|
453
453
|
* @see {@link isStateLevelAbbreviation} for a general check for US States and Territories.
|
|
454
454
|
* @see {@link isStateTerritoryAbbreviation} for a specific check for US Territories.
|
|
@@ -460,8 +460,7 @@ export function isStateAbbreviation(input: unknown): input is StateAbbreviation
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
/**
|
|
463
|
-
* Predicate for checking if a string is a proper abbreviation for a US Territory, rather than a
|
|
464
|
-
* random 2-letter string.
|
|
463
|
+
* Predicate for checking if a string is a proper abbreviation for a US Territory, rather than a random 2-letter string.
|
|
465
464
|
*
|
|
466
465
|
* @see {@link isStateLevelAbbreviation} for a general check for US States and Territories.
|
|
467
466
|
* @see {@link isStateAbbreviation} for a specific check for US States.
|
|
@@ -540,8 +539,8 @@ export interface TIGERState {
|
|
|
540
539
|
[GeoIDPart.State]: AdminLevel1Code
|
|
541
540
|
|
|
542
541
|
/**
|
|
543
|
-
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks
|
|
544
|
-
*
|
|
542
|
+
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks with holes, or
|
|
543
|
+
* islands.
|
|
545
544
|
*
|
|
546
545
|
* @title Geometry
|
|
547
546
|
*/
|
package/tabulation-block.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { type MultiPolygonLiteral } from "@mailwoman/spatial"
|
|
8
|
+
|
|
8
9
|
import { TIGERProperty, type TIGERPropertyRecord } from "./constants.js"
|
|
9
10
|
import { GeoIDPart, type FIPSBlockGeoID, type ParsedGeoIDBlockLevel } from "./geoid.js"
|
|
10
11
|
|
|
@@ -59,8 +60,8 @@ export interface TIGERTabulatedBlock extends ParsedGeoIDBlockLevel, TIGERTabulat
|
|
|
59
60
|
GEOID: FIPSBlockGeoID
|
|
60
61
|
|
|
61
62
|
/**
|
|
62
|
-
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks
|
|
63
|
-
*
|
|
63
|
+
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks with holes, or
|
|
64
|
+
* islands.
|
|
64
65
|
*
|
|
65
66
|
* @title Geometry
|
|
66
67
|
*/
|
package/tract.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { type GeoFeature, type MultiPolygonLiteral } from "@mailwoman/spatial"
|
|
8
|
+
|
|
8
9
|
import { TIGERProperty, type TIGERPropertyRecord } from "./constants.js"
|
|
9
10
|
import type { FIPSTractGeoID, GeoIDPart, ParsedGeoIDTractLevel } from "./geoid.js"
|
|
10
11
|
|
|
@@ -21,8 +22,8 @@ export interface TIGERTract extends ParsedGeoIDTractLevel {
|
|
|
21
22
|
GEOID: FIPSTractGeoID
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks
|
|
25
|
-
*
|
|
25
|
+
* The geometry of the tabulated block, typically a polygon, but may be a multi-polygon for blocks with holes, or
|
|
26
|
+
* islands.
|
|
26
27
|
*
|
|
27
28
|
* @title Geometry
|
|
28
29
|
*/
|