@mailwoman/bdc 8.3.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/README.md +7 -0
- package/index.ts +2 -0
- package/out/index.d.ts +3 -0
- package/out/index.d.ts.map +1 -0
- package/out/index.js +3 -0
- package/out/index.js.map +1 -0
- package/out/schema.d.ts +138 -0
- package/out/schema.d.ts.map +1 -0
- package/out/schema.js +88 -0
- package/out/schema.js.map +1 -0
- package/out/sdk/build-bdc.d.ts +214 -0
- package/out/sdk/build-bdc.d.ts.map +1 -0
- package/out/sdk/build-bdc.js +500 -0
- package/out/sdk/build-bdc.js.map +1 -0
- package/out/sdk/buildings.d.ts +84 -0
- package/out/sdk/buildings.d.ts.map +1 -0
- package/out/sdk/buildings.js +75 -0
- package/out/sdk/buildings.js.map +1 -0
- package/out/sdk/client.d.ts +237 -0
- package/out/sdk/client.d.ts.map +1 -0
- package/out/sdk/client.js +430 -0
- package/out/sdk/client.js.map +1 -0
- package/out/sdk/common.d.ts +279 -0
- package/out/sdk/common.d.ts.map +1 -0
- package/out/sdk/common.js +162 -0
- package/out/sdk/common.js.map +1 -0
- package/out/sdk/data-collection.d.ts +244 -0
- package/out/sdk/data-collection.d.ts.map +1 -0
- package/out/sdk/data-collection.js +50 -0
- package/out/sdk/data-collection.js.map +1 -0
- package/out/sdk/download.d.ts +36 -0
- package/out/sdk/download.d.ts.map +1 -0
- package/out/sdk/download.js +76 -0
- package/out/sdk/download.js.map +1 -0
- package/out/sdk/filing-dates.d.ts +57 -0
- package/out/sdk/filing-dates.d.ts.map +1 -0
- package/out/sdk/filing-dates.js +50 -0
- package/out/sdk/filing-dates.js.map +1 -0
- package/out/sdk/filing-landscape.d.ts +124 -0
- package/out/sdk/filing-landscape.d.ts.map +1 -0
- package/out/sdk/filing-landscape.js +216 -0
- package/out/sdk/filing-landscape.js.map +1 -0
- package/out/sdk/index.d.ts +15 -0
- package/out/sdk/index.d.ts.map +1 -0
- package/out/sdk/index.js +15 -0
- package/out/sdk/index.js.map +1 -0
- package/out/sdk/list-files.d.ts +39 -0
- package/out/sdk/list-files.d.ts.map +1 -0
- package/out/sdk/list-files.js +26 -0
- package/out/sdk/list-files.js.map +1 -0
- package/out/sdk/location.d.ts +40 -0
- package/out/sdk/location.d.ts.map +1 -0
- package/out/sdk/location.js +23 -0
- package/out/sdk/location.js.map +1 -0
- package/out/sdk/nearest-infrastructure.d.ts +84 -0
- package/out/sdk/nearest-infrastructure.d.ts.map +1 -0
- package/out/sdk/nearest-infrastructure.js +84 -0
- package/out/sdk/nearest-infrastructure.js.map +1 -0
- package/out/sdk/parsing.d.ts +57 -0
- package/out/sdk/parsing.d.ts.map +1 -0
- package/out/sdk/parsing.js +87 -0
- package/out/sdk/parsing.js.map +1 -0
- package/out/sdk/plausibility.d.ts +256 -0
- package/out/sdk/plausibility.d.ts.map +1 -0
- package/out/sdk/plausibility.js +334 -0
- package/out/sdk/plausibility.js.map +1 -0
- package/out/sdk/technologies.d.ts +229 -0
- package/out/sdk/technologies.d.ts.map +1 -0
- package/out/sdk/technologies.js +217 -0
- package/out/sdk/technologies.js.map +1 -0
- package/package.json +97 -0
- package/schema.ts +172 -0
- package/sdk/build-bdc.ts +810 -0
- package/sdk/buildings.ts +87 -0
- package/sdk/client.ts +643 -0
- package/sdk/common.ts +363 -0
- package/sdk/data-collection.ts +268 -0
- package/sdk/download.ts +91 -0
- package/sdk/filing-dates.ts +88 -0
- package/sdk/filing-landscape.ts +287 -0
- package/sdk/index.ts +14 -0
- package/sdk/list-files.ts +72 -0
- package/sdk/location.ts +45 -0
- package/sdk/nearest-infrastructure.ts +129 -0
- package/sdk/parsing.ts +124 -0
- package/sdk/plausibility.ts +512 -0
- package/sdk/technologies.ts +258 -0
package/schema.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Typed schema for bdc.db — the FCC Broadband Data Collection availability read-side layer (2a
|
|
7
|
+
* decisions 4, 8). `bdc_availability` holds, in the default (non-`includeLocationIDs`) build mode, one
|
|
8
|
+
* row per DISTINCT (geoid, provider_id, technology_code, max_advertised_download_speed,
|
|
9
|
+
* max_advertised_upload_speed, low_latency, business_residential_code) tuple parsed from the FCC's
|
|
10
|
+
* per-provider CSV (see `sdk/parsing.ts`) — NOT one row per (block, provider, technology) triple: when
|
|
11
|
+
* two Broadband Serviceable Locations in the same block file different speeds/flags for the same
|
|
12
|
+
* provider/technology, both rows survive `build-bdc.ts`'s materialize-time collapse (see that file's
|
|
13
|
+
* docstring; accepted FCC filing behavior, not a bug). `bdc_provider` is a small dictionary
|
|
14
|
+
* keyed on `provider_id`, populated by a later registry-join task — decision 8 keeps FRN/brand/
|
|
15
|
+
* holding-company resolution out of 2a's scope. The DB also embeds the layer-contract tables from
|
|
16
|
+
* `@mailwoman/core/layers` (manifest tier `shipped`, license `public-domain` — FCC BDC block-level
|
|
17
|
+
* availability data, at the granularity this layer ships, is US government public-domain data, not
|
|
18
|
+
* redistribution-restricted; the CostQuest Fabric boundary this workspace never crosses is the
|
|
19
|
+
* licensing edge, see `bdc/README.md` — spine `h3` res 9 for availability rows, res 6 for coverage
|
|
20
|
+
* cells, matching poi.db's convention).
|
|
21
|
+
*
|
|
22
|
+
* Clustering decision (implementer's pick — the brief allows either): a PLAIN rowid table, NOT
|
|
23
|
+
* `WITHOUT ROWID`, and NOT a composite `(h3_cell, provider_id, technology_code)` primary key.
|
|
24
|
+
* `WITHOUT ROWID` earns its keep on small, PK-probed rows — poi.db's clustered key and
|
|
25
|
+
* `layer_coverage`'s per-cell probe both read by their exact PK and nothing else, so folding the row
|
|
26
|
+
* into the B-tree removes a second lookup. `bdc_availability` doesn't fit that shape: it's a wider,
|
|
27
|
+
* 10-column row read two different ways — an h3-range scan ("everything near this cell", the
|
|
28
|
+
* coverage/overlay path) and a geoid point lookup (the public spatial join key TIGER and callers
|
|
29
|
+
* actually probe by) — never a single composite-key point probe. Clustering the full row under a
|
|
30
|
+
* composite PK would also force the bulk loader to sort-then-insert in that exact key order across
|
|
31
|
+
* millions of rows spread over per-provider, per-state source files, for a locality win a plain
|
|
32
|
+
* index already delivers without constraining ingest order. So: a regular rowid table, an index on
|
|
33
|
+
* `h3_cell` bundled into {@link createBDCAvailabilityTable} (every reader depends on it, same as the
|
|
34
|
+
* table itself), and {@link createBDCGeoidIndex} as a separate, callable-after-bulk-load secondary
|
|
35
|
+
* index for the geoid path — the index-after-load discipline used elsewhere in this repo (see
|
|
36
|
+
* poi-schema.ts's name_key/brand indexes).
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import type { LayerContractDatabase } from "@mailwoman/core/layers"
|
|
40
|
+
import type { Kysely } from "kysely"
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* One availability row from the FCC's per-provider BDC CSV. In the default build mode this is one row per DISTINCT
|
|
44
|
+
* (geoid, provider_id, technology_code, speeds, low_latency, business_residential_code) tuple — NOT one row per (block,
|
|
45
|
+
* provider, technology) triple; a triple whose BSLs carry differing speed tiers keeps multiple rows here (see
|
|
46
|
+
* `build-bdc.ts`'s docstring).
|
|
47
|
+
*/
|
|
48
|
+
export interface BDCAvailabilityTable {
|
|
49
|
+
/**
|
|
50
|
+
* Res-9 integer short H3 cell of the block centroid (spine).
|
|
51
|
+
*/
|
|
52
|
+
h3_cell: number
|
|
53
|
+
/**
|
|
54
|
+
* 15-char census block GEOID (public spatial key).
|
|
55
|
+
*/
|
|
56
|
+
geoid: string
|
|
57
|
+
/**
|
|
58
|
+
* Block-centroid PIP at build time (spine).
|
|
59
|
+
*/
|
|
60
|
+
wof_id: number | null
|
|
61
|
+
provider_id: number
|
|
62
|
+
technology_code: number
|
|
63
|
+
max_advertised_download_speed: number
|
|
64
|
+
max_advertised_upload_speed: number
|
|
65
|
+
low_latency: 0 | 1
|
|
66
|
+
business_residential_code: string
|
|
67
|
+
/**
|
|
68
|
+
* Opaque BSL join key — NEVER resolved (spec §2.2); null unless `--include-location-ids`.
|
|
69
|
+
*/
|
|
70
|
+
location_id: string | null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Provider dictionary keyed on `provider_id`. Populated by a later registry-join task (2a decision 8) — that task is 3a
|
|
75
|
+
* Task 8's optional `BuildBDCOptions.providers` (`bdc/sdk/build-bdc.ts`'s `populateBDCProviderTable`); when that option
|
|
76
|
+
* is omitted (the default), this table stays empty, exactly as it did before Task 8. No FK constraint against
|
|
77
|
+
* `bdc_availability.provider_id` — SQLite doesn't enforce FKs without `PRAGMA foreign_keys`, and the join happens at
|
|
78
|
+
* read time, not write time.
|
|
79
|
+
*
|
|
80
|
+
* **Decision 6 — this table is an explicitly LOSSY denormalization, not the source of truth.** `provider_id` is the PK
|
|
81
|
+
* (one row per provider), but the FCC's BDC provider list lets one `provider_id` carry MULTIPLE `frn` values — and
|
|
82
|
+
* conflicting `holding_company` strings — across its rows (Task 3's `parseProviderList` preserves every one of them;
|
|
83
|
+
* see `filer/sdk/provider-list.ts`). A single-row-per-provider table cannot express that cardinality. `filer.db`
|
|
84
|
+
* (`@mailwoman/filer`) is the source of truth: it retains every `provider_id`↔`frn` (and
|
|
85
|
+
* `provider_id`↔`holding_company_name`) edge, never folded or last-wins. When `bdc.db` is built with
|
|
86
|
+
* `BuildBDCOptions.providers` supplied:
|
|
87
|
+
*
|
|
88
|
+
* - `frn` holds only the PRIMARY FRN — the one carrying the most recent Form 499 filing date, per
|
|
89
|
+
* `@mailwoman/filer/sdk`'s `readFRNFilingCandidates` + `pickPrimaryFRN` (imported into `build-bdc.ts`, never
|
|
90
|
+
* reimplemented — Task 7's review found and fixed a temporal bug in that exact query, one a fresh implementation
|
|
91
|
+
* would reintroduce). Every OTHER FRN that `provider_id` carries is discarded here but stays fully recoverable from
|
|
92
|
+
* `filer.db`.
|
|
93
|
+
* - `holding_company` gets the SAME single-distinct-value shortcut `frn` gets (review fix round 1, IMPORTANT-3): when a
|
|
94
|
+
* `provider_id`'s rows carry exactly one distinct non-null `holding_company` string, there is no conflict to resolve,
|
|
95
|
+
* so it's populated directly — no rule needed, same as a single-FRN provider needs no `filerDB` query. When they
|
|
96
|
+
* carry MORE than one distinct value, that ambiguity is the real conflict decision 6 refuses to paper over with
|
|
97
|
+
* last-wins (`holding_company` has no most-recent-filing-date rule the way `frn` does), so it stays NULL and every
|
|
98
|
+
* discarded value remains recoverable from `filer.db`'s `holding_company_name` edges — the identical discipline
|
|
99
|
+
* `frn`'s primary pick already applies.
|
|
100
|
+
* - `brand_name` stays NULL unconditionally: the provider list carries no brand-name column at all, primary or otherwise,
|
|
101
|
+
* so there is nothing to populate it from.
|
|
102
|
+
*/
|
|
103
|
+
export interface BDCProviderTable {
|
|
104
|
+
/**
|
|
105
|
+
* PK.
|
|
106
|
+
*/
|
|
107
|
+
provider_id: number
|
|
108
|
+
frn: string | null
|
|
109
|
+
brand_name: string | null
|
|
110
|
+
holding_company: string | null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface BDCDatabase extends LayerContractDatabase {
|
|
114
|
+
bdc_availability: BDCAvailabilityTable
|
|
115
|
+
bdc_provider: BDCProviderTable
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* H3 resolution for `bdc_availability.h3_cell` — the block-centroid spine resolution.
|
|
120
|
+
*/
|
|
121
|
+
export const BDC_H3_RESOLUTION = 9
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* H3 resolution for `layer_coverage.h3_cell` in bdc.db — coarser than the availability spine, matching poi.db's res-6
|
|
125
|
+
* coverage-cell convention.
|
|
126
|
+
*/
|
|
127
|
+
export const BDC_COVERAGE_H3_RESOLUTION = 6
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Create `bdc_availability` as a plain rowid table, plus the `h3_cell` range-scan index (bundled here since every
|
|
131
|
+
* reader depends on it — see the file header for the clustering rationale). Call {@link createBDCGeoidIndex}
|
|
132
|
+
* separately, after bulk load, for the geoid point-lookup path.
|
|
133
|
+
*/
|
|
134
|
+
export async function createBDCAvailabilityTable(db: Kysely<BDCDatabase>): Promise<void> {
|
|
135
|
+
await db.schema
|
|
136
|
+
.createTable("bdc_availability")
|
|
137
|
+
.addColumn("h3_cell", "integer", (c) => c.notNull())
|
|
138
|
+
.addColumn("geoid", "text", (c) => c.notNull())
|
|
139
|
+
.addColumn("wof_id", "integer")
|
|
140
|
+
.addColumn("provider_id", "integer", (c) => c.notNull())
|
|
141
|
+
.addColumn("technology_code", "integer", (c) => c.notNull())
|
|
142
|
+
.addColumn("max_advertised_download_speed", "integer", (c) => c.notNull())
|
|
143
|
+
.addColumn("max_advertised_upload_speed", "integer", (c) => c.notNull())
|
|
144
|
+
.addColumn("low_latency", "integer", (c) => c.notNull())
|
|
145
|
+
.addColumn("business_residential_code", "text", (c) => c.notNull())
|
|
146
|
+
.addColumn("location_id", "text")
|
|
147
|
+
.execute()
|
|
148
|
+
|
|
149
|
+
await db.schema.createIndex("bdc_availability_h3_cell").on("bdc_availability").column("h3_cell").execute()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create `bdc_provider`. A single-column INTEGER PRIMARY KEY is already the SQLite rowid alias, so there's no `WITHOUT
|
|
154
|
+
* ROWID` win here — that modifier only pays off clustering a composite or non-integer PK.
|
|
155
|
+
*/
|
|
156
|
+
export async function createBDCProviderTable(db: Kysely<BDCDatabase>): Promise<void> {
|
|
157
|
+
await db.schema
|
|
158
|
+
.createTable("bdc_provider")
|
|
159
|
+
.addColumn("provider_id", "integer", (c) => c.primaryKey())
|
|
160
|
+
.addColumn("frn", "text")
|
|
161
|
+
.addColumn("brand_name", "text")
|
|
162
|
+
.addColumn("holding_company", "text")
|
|
163
|
+
.execute()
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Secondary index for the geoid point-lookup path (the public spatial join key). Call AFTER the bulk materialize
|
|
168
|
+
* (index-after-load), same discipline as poi.db's secondary indexes.
|
|
169
|
+
*/
|
|
170
|
+
export async function createBDCGeoidIndex(db: Kysely<BDCDatabase>): Promise<void> {
|
|
171
|
+
await db.schema.createIndex("bdc_availability_geoid").on("bdc_availability").column("geoid").execute()
|
|
172
|
+
}
|