@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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./build-bdc.ts";
|
|
2
|
+
export * from "./buildings.ts";
|
|
3
|
+
export * from "./client.ts";
|
|
4
|
+
export * from "./common.ts";
|
|
5
|
+
export * from "./data-collection.ts";
|
|
6
|
+
export * from "./download.ts";
|
|
7
|
+
export * from "./filing-dates.ts";
|
|
8
|
+
export * from "./filing-landscape.ts";
|
|
9
|
+
export * from "./list-files.ts";
|
|
10
|
+
export * from "./location.ts";
|
|
11
|
+
export * from "./nearest-infrastructure.ts";
|
|
12
|
+
export * from "./parsing.ts";
|
|
13
|
+
export * from "./plausibility.ts";
|
|
14
|
+
export * from "./technologies.ts";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../sdk/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA"}
|
package/out/sdk/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./build-bdc.js";
|
|
2
|
+
export * from "./buildings.js";
|
|
3
|
+
export * from "./client.js";
|
|
4
|
+
export * from "./common.js";
|
|
5
|
+
export * from "./data-collection.js";
|
|
6
|
+
export * from "./download.js";
|
|
7
|
+
export * from "./filing-dates.js";
|
|
8
|
+
export * from "./filing-landscape.js";
|
|
9
|
+
export * from "./list-files.js";
|
|
10
|
+
export * from "./location.js";
|
|
11
|
+
export * from "./nearest-infrastructure.js";
|
|
12
|
+
export * from "./parsing.js";
|
|
13
|
+
export * from "./plausibility.js";
|
|
14
|
+
export * from "./technologies.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../sdk/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,6BAA6B,CAAA;AAC3C,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file FCC BDC availability-file listing.
|
|
6
|
+
*
|
|
7
|
+
* Re-homed from Nexus's `sync/fcc/bdc/list-files.ts` (relicense-by-copy, no provenance headers):
|
|
8
|
+
* the `URLRoutePattern`-compiled route → a plain template literal (this port has no routing
|
|
9
|
+
* dependency), the `$BCDClient`-bound `retrieveAvailabilityFiles()` → a plain function taking a
|
|
10
|
+
* {@linkcode BDCClient}. Raw entries are parsed via Task 4's `parseRawBDCFile` and returned sorted
|
|
11
|
+
* ascending by revision (`compareRevisionAsc`) rather than in API order.
|
|
12
|
+
*/
|
|
13
|
+
import type { BDCClient } from "./client.ts";
|
|
14
|
+
import { type BDCFile, type BDCFileCategory, type BDCProviderSubCategory, type BDCStateSubCategory, type BDCSummarySubCategory } from "./common.ts";
|
|
15
|
+
export interface RetrieveProviderAvailabilityFilesParams {
|
|
16
|
+
/**
|
|
17
|
+
* The filing's `as_of_date`, e.g. from {@linkcode file://./filing-dates.ts#resolveLatestVintage}.
|
|
18
|
+
*/
|
|
19
|
+
asOfDate: string;
|
|
20
|
+
category: typeof BDCFileCategory.Provider;
|
|
21
|
+
subcategory: BDCProviderSubCategory;
|
|
22
|
+
}
|
|
23
|
+
export interface RetrieveStateAvailabilityFilesParams {
|
|
24
|
+
asOfDate: string;
|
|
25
|
+
category: typeof BDCFileCategory.State;
|
|
26
|
+
subcategory: BDCStateSubCategory;
|
|
27
|
+
}
|
|
28
|
+
export interface RetrieveSummaryAvailabilityFilesParams {
|
|
29
|
+
asOfDate: string;
|
|
30
|
+
category: typeof BDCFileCategory.Summary;
|
|
31
|
+
subcategory: BDCSummarySubCategory;
|
|
32
|
+
}
|
|
33
|
+
export type RetrieveAvailabilityFilesParams = RetrieveProviderAvailabilityFilesParams | RetrieveStateAvailabilityFilesParams | RetrieveSummaryAvailabilityFilesParams;
|
|
34
|
+
/**
|
|
35
|
+
* List the BDC availability files for a given `as_of_date`/category/subcategory, parsed into {@linkcode BDCFile}
|
|
36
|
+
* records and sorted ascending by revision date ({@linkcode compareRevisionAsc}).
|
|
37
|
+
*/
|
|
38
|
+
export declare function retrieveAvailabilityFiles(client: BDCClient, { asOfDate, category, subcategory }: RetrieveAvailabilityFilesParams): Promise<BDCFile[]>;
|
|
39
|
+
//# sourceMappingURL=list-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-files.d.ts","sourceRoot":"","sources":["../../sdk/list-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAGN,KAAK,OAAO,EACZ,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAE1B,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,uCAAuC;IACvD;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,eAAe,CAAC,QAAQ,CAAA;IACzC,WAAW,EAAE,sBAAsB,CAAA;CACnC;AAED,MAAM,WAAW,oCAAoC;IACpD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,eAAe,CAAC,KAAK,CAAA;IACtC,WAAW,EAAE,mBAAmB,CAAA;CAChC;AAED,MAAM,WAAW,sCAAsC;IACtD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,eAAe,CAAC,OAAO,CAAA;IACxC,WAAW,EAAE,qBAAqB,CAAA;CAClC;AAED,MAAM,MAAM,+BAA+B,GACxC,uCAAuC,GACvC,oCAAoC,GACpC,sCAAsC,CAAA;AAMzC;;;GAGG;AACH,wBAAsB,yBAAyB,CAC9C,MAAM,EAAE,SAAS,EACjB,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,+BAA+B,GAClE,OAAO,CAAC,OAAO,EAAE,CAAC,CASpB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file FCC BDC availability-file listing.
|
|
6
|
+
*
|
|
7
|
+
* Re-homed from Nexus's `sync/fcc/bdc/list-files.ts` (relicense-by-copy, no provenance headers):
|
|
8
|
+
* the `URLRoutePattern`-compiled route → a plain template literal (this port has no routing
|
|
9
|
+
* dependency), the `$BCDClient`-bound `retrieveAvailabilityFiles()` → a plain function taking a
|
|
10
|
+
* {@linkcode BDCClient}. Raw entries are parsed via Task 4's `parseRawBDCFile` and returned sorted
|
|
11
|
+
* ascending by revision (`compareRevisionAsc`) rather than in API order.
|
|
12
|
+
*/
|
|
13
|
+
import { compareRevisionAsc, parseRawBDCFile, } from "./common.js";
|
|
14
|
+
/**
|
|
15
|
+
* List the BDC availability files for a given `as_of_date`/category/subcategory, parsed into {@linkcode BDCFile}
|
|
16
|
+
* records and sorted ascending by revision date ({@linkcode compareRevisionAsc}).
|
|
17
|
+
*/
|
|
18
|
+
export async function retrieveAvailabilityFiles(client, { asOfDate, category, subcategory }) {
|
|
19
|
+
const pathname = `/map/downloads/listAvailabilityData/${encodeURIComponent(asOfDate)}`;
|
|
20
|
+
const body = await client.get(pathname, {
|
|
21
|
+
category,
|
|
22
|
+
subcategory,
|
|
23
|
+
});
|
|
24
|
+
return body.data.map(parseRawBDCFile).toSorted(compareRevisionAsc);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=list-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-files.js","sourceRoot":"","sources":["../../sdk/list-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EACN,kBAAkB,EAClB,eAAe,GAOf,MAAM,aAAa,CAAA;AAgCpB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,MAAiB,EACjB,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAmC;IAEpE,MAAM,QAAQ,GAAG,uCAAuC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAA;IAEtF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAmC,QAAQ,EAAE;QACzE,QAAQ;QACR,WAAW;KACX,CAAC,CAAA;IAEF,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;AACnE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
import type { Tagged } from "type-fest";
|
|
7
|
+
/**
|
|
8
|
+
* Matches a 10-digit FCC Broadband Serviceable Location ID, leading zeros included.
|
|
9
|
+
*
|
|
10
|
+
* @see {@linkcode isBroadbandServicableLocationID} for the type-predicate that uses this.
|
|
11
|
+
*/
|
|
12
|
+
export declare const BROADBAND_SERVICABLE_LOCATION_INPUT_PATTERN: RegExp;
|
|
13
|
+
/**
|
|
14
|
+
* Unique ID for the Fabric location.
|
|
15
|
+
*
|
|
16
|
+
* The BSL ID remains persistent version to version when newer evidence indicates the position of the serviceable
|
|
17
|
+
* location or the presence of a serviceable location on a single location parcel is not significantly changed as
|
|
18
|
+
* compared to the prior version.
|
|
19
|
+
*
|
|
20
|
+
* - While IDs persist across Fabric versions does not mean that the latitude and longitude are unchanged.
|
|
21
|
+
* - An ID will remain consistent across versions when a different building is selected on a single parcel.
|
|
22
|
+
*
|
|
23
|
+
* Typed as a `string`, not a `number` — the FCC's own IDs are 10-digit zero-padded strings, and leading zeros make
|
|
24
|
+
* integer storage lossy.
|
|
25
|
+
*
|
|
26
|
+
* @type string
|
|
27
|
+
* @title Broadband Servicable Location ID
|
|
28
|
+
* @pattern ^\d{10}$
|
|
29
|
+
*/
|
|
30
|
+
export type BroadbandServicableLocationID = Tagged<string, "BroadbandServicableLocationID">;
|
|
31
|
+
/**
|
|
32
|
+
* Type-predicate for checking if a value appears to be a valid Broadband Servicable Location ID.
|
|
33
|
+
*
|
|
34
|
+
* Accepts only a 10-digit string. A `number` input is always rejected, even if its digits would otherwise match —
|
|
35
|
+
* numeric storage would silently drop meaningful leading zeros.
|
|
36
|
+
*
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export declare function isBroadbandServicableLocationID(input: unknown): input is BroadbandServicableLocationID;
|
|
40
|
+
//# sourceMappingURL=location.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../sdk/location.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC;;;;GAIG;AACH,eAAO,MAAM,2CAA2C,QAAa,CAAA;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,6BAA6B,GAAG,MAAM,CAAC,MAAM,EAAE,+BAA+B,CAAC,CAAA;AAE3F;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,6BAA6B,CAEtG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Matches a 10-digit FCC Broadband Serviceable Location ID, leading zeros included.
|
|
8
|
+
*
|
|
9
|
+
* @see {@linkcode isBroadbandServicableLocationID} for the type-predicate that uses this.
|
|
10
|
+
*/
|
|
11
|
+
export const BROADBAND_SERVICABLE_LOCATION_INPUT_PATTERN = /^\d{10}$/;
|
|
12
|
+
/**
|
|
13
|
+
* Type-predicate for checking if a value appears to be a valid Broadband Servicable Location ID.
|
|
14
|
+
*
|
|
15
|
+
* Accepts only a 10-digit string. A `number` input is always rejected, even if its digits would otherwise match —
|
|
16
|
+
* numeric storage would silently drop meaningful leading zeros.
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export function isBroadbandServicableLocationID(input) {
|
|
21
|
+
return typeof input === "string" && BROADBAND_SERVICABLE_LOCATION_INPUT_PATTERN.test(input);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=location.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"location.js","sourceRoot":"","sources":["../../sdk/location.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,2CAA2C,GAAG,UAAU,CAAA;AAqBrE;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAAc;IAC7D,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,2CAA2C,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAC5F,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `nearestInfrastructure` — a coverage-paired k-nearest read over the telecom-infrastructure POI
|
|
7
|
+
* categories (`telecom_exchange`/`tower_comms`, poi-taxonomy task 1 + the `--source osm` extractor,
|
|
8
|
+
* 2b tasks 1–2) that a caller can join against ANY layer's own `layer_coverage` survey-completeness
|
|
9
|
+
* table (2b task 4, decision 7). Typical caller: a BDC filing scorer that wants "what's the nearest
|
|
10
|
+
* real infrastructure to this claimed Broadband Serviceable Location, and does OUR layer even have
|
|
11
|
+
* survey evidence for that area" in one call.
|
|
12
|
+
*
|
|
13
|
+
* Two deviations from the task brief's literal sketch, both forced by what `poi-lookup.ts` and
|
|
14
|
+
* `@mailwoman/core/layers` actually expose (documented per the brief's "implementer picks and
|
|
15
|
+
* documents" instruction):
|
|
16
|
+
*
|
|
17
|
+
* - **`poiLookup` is an already-open {@link POILookup}, not a `POILookupOpts` this function
|
|
18
|
+
* constructs itself.** `POILookup`'s constructor eagerly loads the poi-taxonomy category dictionary
|
|
19
|
+
* and prepares three statements (see `poi-lookup.ts`) — reconstructing that per call would mean
|
|
20
|
+
* re-opening the SQLite handle and re-running the dictionary `SELECT` on every single
|
|
21
|
+
* `nearestInfrastructure` invocation. A scorer calling this once per filing candidate wants to open
|
|
22
|
+
* `poi.db` ONCE and reuse the same `POILookup` — this wrapper takes that shape: the caller owns
|
|
23
|
+
* `POILookup`'s open/dispose lifecycle (`using poiLookup = new POILookup(...)`), we just call
|
|
24
|
+
* `.search()` on it.
|
|
25
|
+
* - **`nearestInfrastructure` is `async`, not the brief's sync sketch.** `readLayerCoverage`
|
|
26
|
+
* (`@mailwoman/core/layers`) is `Promise`-returning — every layer-contract read in this codebase is
|
|
27
|
+
* (`readLayerManifest`, `filingLandscape` itself) — so pairing each POI hit with its coverage cell
|
|
28
|
+
* means awaiting one `readLayerCoverage` call per hit. A sync signature can't await that.
|
|
29
|
+
*
|
|
30
|
+
* {@link res9ShortCellToRes6Parent} (exported by `filing-landscape.ts`; see that file's docstring for
|
|
31
|
+
* why the res-9 → res-6 reconstruction is a straight concatenation, not `@mailwoman/spatial`'s
|
|
32
|
+
* `expandH3Cell`) turns each hit's res-9 cell into the res-6 cell every layer in this repo aggregates
|
|
33
|
+
* coverage at (poi.db's own convention; `bdc.db`'s `BDC_COVERAGE_H3_RESOLUTION` matches it
|
|
34
|
+
* deliberately — see `schema.ts`). `POI_H3_RESOLUTION` (`poi-lookup.ts`) is ALSO 9, so the two layers'
|
|
35
|
+
* spines agree without this module hardcoding a resolution of its own.
|
|
36
|
+
*/
|
|
37
|
+
import type { DatabaseClient } from "@mailwoman/core/kysley/client";
|
|
38
|
+
import { type CoverageCell, type LayerContractDatabase } from "@mailwoman/core/layers";
|
|
39
|
+
import { type POILookup } from "@mailwoman/resolver-wof-sqlite/poi-lookup";
|
|
40
|
+
import { type PointLiteral } from "@mailwoman/spatial";
|
|
41
|
+
/**
|
|
42
|
+
* Ring budget default for {@link nearestInfrastructure} — wider than `POILookup`'s own internal `DEFAULT_MAX_RINGS`
|
|
43
|
+
* (16, ≈5.4 km) because telecom infrastructure (central offices, comm towers) is sparser per-area than poi.db's dense
|
|
44
|
+
* categories (cafes, etc.): 32 res-9 rings ≈ 11 km, a BDC-block-scale search radius that gives real infrastructure room
|
|
45
|
+
* to be found without over-restricting callers who DO want a tighter budget via `options.maxRings`.
|
|
46
|
+
*/
|
|
47
|
+
export declare const NEAREST_INFRASTRUCTURE_DEFAULT_MAX_RINGS = 32;
|
|
48
|
+
/**
|
|
49
|
+
* One k-nearest telecom-infrastructure hit, paired with the res-6 coverage cell it falls in. `coverage: undefined`
|
|
50
|
+
* means `contractDB`'s layer has never surveyed that area (the meaning-of-zero rule; see `@mailwoman/core/layers`) —
|
|
51
|
+
* never conflate it with a covered-but-empty cell.
|
|
52
|
+
*/
|
|
53
|
+
export interface InfrastructureHit {
|
|
54
|
+
categoryID: string;
|
|
55
|
+
name: string | null;
|
|
56
|
+
distanceM: number;
|
|
57
|
+
/**
|
|
58
|
+
* Res-9 short H3 cell of the hit ITSELF — not the (coarser) coverage cell; see `coverage.h3Cell` for that.
|
|
59
|
+
*/
|
|
60
|
+
h3Cell: number;
|
|
61
|
+
coverage: CoverageCell | undefined;
|
|
62
|
+
}
|
|
63
|
+
export interface NearestInfrastructureOptions {
|
|
64
|
+
center: PointLiteral;
|
|
65
|
+
/**
|
|
66
|
+
* Poi-taxonomy category ids to search — fans out to `POILookup.search`'s `categoryIDs` (union across every resolved
|
|
67
|
+
* leaf, nearest-first). Typically `["telecom_exchange", "tower_comms"]`.
|
|
68
|
+
*/
|
|
69
|
+
categoryIDs: string[];
|
|
70
|
+
limit?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Ring budget. Default {@link NEAREST_INFRASTRUCTURE_DEFAULT_MAX_RINGS} (32) — NOT `POILookup`'s own internal default
|
|
73
|
+
* (16); see this module's docstring.
|
|
74
|
+
*/
|
|
75
|
+
maxRings?: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* K-nearest telecom-infrastructure POIs from `options.center`, each paired with the coverage cell it falls in per
|
|
79
|
+
* `contractDB`'s own `layer_coverage` table. Never throws on a sparse result — no infrastructure within `maxRings`, or
|
|
80
|
+
* every `categoryIDs` entry unresolvable against `poiLookup`'s dictionary — returns `[]`, the same discipline
|
|
81
|
+
* `POILookup.search` itself follows.
|
|
82
|
+
*/
|
|
83
|
+
export declare function nearestInfrastructure(poiLookup: POILookup, contractDB: DatabaseClient<LayerContractDatabase>, options: NearestInfrastructureOptions): Promise<InfrastructureHit[]>;
|
|
84
|
+
//# sourceMappingURL=nearest-infrastructure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nearest-infrastructure.d.ts","sourceRoot":"","sources":["../../sdk/nearest-infrastructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,EAAqB,KAAK,YAAY,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AACzG,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,2CAA2C,CAAA;AAC7F,OAAO,EAA+B,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKnF;;;;;GAKG;AACH,eAAO,MAAM,wCAAwC,KAAK,CAAA;AAE1D;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,YAAY,GAAG,SAAS,CAAA;CAClC;AAED,MAAM,WAAW,4BAA4B;IAC5C,MAAM,EAAE,YAAY,CAAA;IACpB;;;OAGG;IACH,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAC1C,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,cAAc,CAAC,qBAAqB,CAAC,EACjD,OAAO,EAAE,4BAA4B,GACnC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAkC9B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* `nearestInfrastructure` — a coverage-paired k-nearest read over the telecom-infrastructure POI
|
|
7
|
+
* categories (`telecom_exchange`/`tower_comms`, poi-taxonomy task 1 + the `--source osm` extractor,
|
|
8
|
+
* 2b tasks 1–2) that a caller can join against ANY layer's own `layer_coverage` survey-completeness
|
|
9
|
+
* table (2b task 4, decision 7). Typical caller: a BDC filing scorer that wants "what's the nearest
|
|
10
|
+
* real infrastructure to this claimed Broadband Serviceable Location, and does OUR layer even have
|
|
11
|
+
* survey evidence for that area" in one call.
|
|
12
|
+
*
|
|
13
|
+
* Two deviations from the task brief's literal sketch, both forced by what `poi-lookup.ts` and
|
|
14
|
+
* `@mailwoman/core/layers` actually expose (documented per the brief's "implementer picks and
|
|
15
|
+
* documents" instruction):
|
|
16
|
+
*
|
|
17
|
+
* - **`poiLookup` is an already-open {@link POILookup}, not a `POILookupOpts` this function
|
|
18
|
+
* constructs itself.** `POILookup`'s constructor eagerly loads the poi-taxonomy category dictionary
|
|
19
|
+
* and prepares three statements (see `poi-lookup.ts`) — reconstructing that per call would mean
|
|
20
|
+
* re-opening the SQLite handle and re-running the dictionary `SELECT` on every single
|
|
21
|
+
* `nearestInfrastructure` invocation. A scorer calling this once per filing candidate wants to open
|
|
22
|
+
* `poi.db` ONCE and reuse the same `POILookup` — this wrapper takes that shape: the caller owns
|
|
23
|
+
* `POILookup`'s open/dispose lifecycle (`using poiLookup = new POILookup(...)`), we just call
|
|
24
|
+
* `.search()` on it.
|
|
25
|
+
* - **`nearestInfrastructure` is `async`, not the brief's sync sketch.** `readLayerCoverage`
|
|
26
|
+
* (`@mailwoman/core/layers`) is `Promise`-returning — every layer-contract read in this codebase is
|
|
27
|
+
* (`readLayerManifest`, `filingLandscape` itself) — so pairing each POI hit with its coverage cell
|
|
28
|
+
* means awaiting one `readLayerCoverage` call per hit. A sync signature can't await that.
|
|
29
|
+
*
|
|
30
|
+
* {@link res9ShortCellToRes6Parent} (exported by `filing-landscape.ts`; see that file's docstring for
|
|
31
|
+
* why the res-9 → res-6 reconstruction is a straight concatenation, not `@mailwoman/spatial`'s
|
|
32
|
+
* `expandH3Cell`) turns each hit's res-9 cell into the res-6 cell every layer in this repo aggregates
|
|
33
|
+
* coverage at (poi.db's own convention; `bdc.db`'s `BDC_COVERAGE_H3_RESOLUTION` matches it
|
|
34
|
+
* deliberately — see `schema.ts`). `POI_H3_RESOLUTION` (`poi-lookup.ts`) is ALSO 9, so the two layers'
|
|
35
|
+
* spines agree without this module hardcoding a resolution of its own.
|
|
36
|
+
*/
|
|
37
|
+
import { readLayerCoverage } from "@mailwoman/core/layers";
|
|
38
|
+
import { POI_H3_RESOLUTION } from "@mailwoman/resolver-wof-sqlite/poi-lookup";
|
|
39
|
+
import { shortCellToInt } from "@mailwoman/spatial";
|
|
40
|
+
import { latLngToCell } from "h3-js";
|
|
41
|
+
import { res9ShortCellToRes6Parent } from "./filing-landscape.js";
|
|
42
|
+
/**
|
|
43
|
+
* Ring budget default for {@link nearestInfrastructure} — wider than `POILookup`'s own internal `DEFAULT_MAX_RINGS`
|
|
44
|
+
* (16, ≈5.4 km) because telecom infrastructure (central offices, comm towers) is sparser per-area than poi.db's dense
|
|
45
|
+
* categories (cafes, etc.): 32 res-9 rings ≈ 11 km, a BDC-block-scale search radius that gives real infrastructure room
|
|
46
|
+
* to be found without over-restricting callers who DO want a tighter budget via `options.maxRings`.
|
|
47
|
+
*/
|
|
48
|
+
export const NEAREST_INFRASTRUCTURE_DEFAULT_MAX_RINGS = 32;
|
|
49
|
+
/**
|
|
50
|
+
* K-nearest telecom-infrastructure POIs from `options.center`, each paired with the coverage cell it falls in per
|
|
51
|
+
* `contractDB`'s own `layer_coverage` table. Never throws on a sparse result — no infrastructure within `maxRings`, or
|
|
52
|
+
* every `categoryIDs` entry unresolvable against `poiLookup`'s dictionary — returns `[]`, the same discipline
|
|
53
|
+
* `POILookup.search` itself follows.
|
|
54
|
+
*/
|
|
55
|
+
export async function nearestInfrastructure(poiLookup, contractDB, options) {
|
|
56
|
+
const [longitude, latitude] = options.center.coordinates;
|
|
57
|
+
const hits = poiLookup.search({
|
|
58
|
+
categoryIDs: options.categoryIDs,
|
|
59
|
+
center: { latitude, longitude },
|
|
60
|
+
limit: options.limit,
|
|
61
|
+
maxRings: options.maxRings ?? NEAREST_INFRASTRUCTURE_DEFAULT_MAX_RINGS,
|
|
62
|
+
});
|
|
63
|
+
const infrastructureHits = [];
|
|
64
|
+
for (const hit of hits) {
|
|
65
|
+
if (hit.categoryID === null) {
|
|
66
|
+
// `categoryIDs` above always constrains the k-ring probe to real (non-zero) category ids (see
|
|
67
|
+
// POILookup#searchKRing), so a hit here always carries the category it was found under — this
|
|
68
|
+
// can't happen without a corrupted poi.db. Guard rather than silently coerce to "".
|
|
69
|
+
throw new Error(`nearestInfrastructure: hit ${JSON.stringify(hit.name)} has no categoryID`);
|
|
70
|
+
}
|
|
71
|
+
const h3Cell = shortCellToInt(latLngToCell(hit.latitude, hit.longitude, POI_H3_RESOLUTION));
|
|
72
|
+
const coverage = await readLayerCoverage(contractDB, res9ShortCellToRes6Parent(h3Cell));
|
|
73
|
+
infrastructureHits.push({
|
|
74
|
+
categoryID: hit.categoryID,
|
|
75
|
+
name: hit.name,
|
|
76
|
+
// `center` is always supplied above, so POILookup.search always attaches distanceM.
|
|
77
|
+
distanceM: hit.distanceM,
|
|
78
|
+
h3Cell,
|
|
79
|
+
coverage,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return infrastructureHits;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=nearest-infrastructure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nearest-infrastructure.js","sourceRoot":"","sources":["../../sdk/nearest-infrastructure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EAAE,iBAAiB,EAAiD,MAAM,wBAAwB,CAAA;AACzG,OAAO,EAAE,iBAAiB,EAAkB,MAAM,2CAA2C,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAkC,MAAM,oBAAoB,CAAA;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAEpC,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAEjE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wCAAwC,GAAG,EAAE,CAAA;AAiC1D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,SAAoB,EACpB,UAAiD,EACjD,OAAqC;IAErC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAA;IAExD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC;QAC7B,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE;QAC/B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,wCAAwC;KACtE,CAAC,CAAA;IAEF,MAAM,kBAAkB,GAAwB,EAAE,CAAA;IAElD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC7B,8FAA8F;YAC9F,8FAA8F;YAC9F,oFAAoF;YACpF,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;QAC5F,CAAC;QAED,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAAW,CAAC,CAAA;QACrG,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,UAAU,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAA;QAEvF,kBAAkB,CAAC,IAAI,CAAC;YACvB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,oFAAoF;YACpF,SAAS,EAAE,GAAG,CAAC,SAAU;YACzB,MAAM;YACN,QAAQ;SACR,CAAC,CAAA;IACH,CAAC;IAED,OAAO,kBAAkB,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file FCC BDC availability CSV byte-level parser.
|
|
6
|
+
*
|
|
7
|
+
* Re-homed from Nexus's `sync/fcc/bdc/parsing.ts` (relicense-by-copy, no provenance headers): the same
|
|
8
|
+
* byte-scanning generator over the FCC's 12-column availability CSV — see the Nexus `RawBSLAvailabilityRow`
|
|
9
|
+
* tuple (`sync/fcc/bdc/block-aggregator.ts`) for the column order this scan assumes: frn, provider_id,
|
|
10
|
+
* brand_name, location_id, technology, max_advertised_download_speed, max_advertised_upload_speed,
|
|
11
|
+
* low_latency, business_residential_code, state_usps, block_geoid, h3_res8_id. Changed only where the
|
|
12
|
+
* pre-registered 2a decisions require: `geoid` (column 10, `block_geoid`) decodes to an ASCII string
|
|
13
|
+
* instead of staying a raw `Uint8Array` slice (decision 3), and `location_id` (column 3) stays a string
|
|
14
|
+
* instead of `parseInt`ing it, preserving leading zeros (decision 1). `business_residential_code` is
|
|
15
|
+
* likewise decoded to its ASCII string here — the Nexus original kept only the field's first raw byte as
|
|
16
|
+
* a bare `number`, which this port's `BDCAvailabilityRow` shape doesn't call for.
|
|
17
|
+
*
|
|
18
|
+
* Columns 0-2 (frn, provider_id, brand_name) and 9, 11 (state_usps, h3_res8_id) are scanned over but
|
|
19
|
+
* never sliced into the output record: `provider_id` comes from the `providerID` parameter instead (the
|
|
20
|
+
* FCC partitions availability files per provider, so the caller already knows it), and FRN/brand/state/H3
|
|
21
|
+
* join concerns are out of scope for 2a (decision 8 — provider identity is a 2c registry-join seam).
|
|
22
|
+
*/
|
|
23
|
+
import type { ProviderID } from "./common.ts";
|
|
24
|
+
/**
|
|
25
|
+
* A single parsed row of FCC BDC availability data.
|
|
26
|
+
*
|
|
27
|
+
* @see {@linkcode takeAvailabilityLine}
|
|
28
|
+
*/
|
|
29
|
+
export interface BDCAvailabilityRow {
|
|
30
|
+
provider_id: number;
|
|
31
|
+
/**
|
|
32
|
+
* Kept as a string — the FCC's `location_id` values are zero-padded 10-digit strings; `parseInt`ing would lose
|
|
33
|
+
* leading zeros (2a decision 1).
|
|
34
|
+
*/
|
|
35
|
+
location_id: string;
|
|
36
|
+
technology_code: number;
|
|
37
|
+
max_advertised_download_speed: number;
|
|
38
|
+
max_advertised_upload_speed: number;
|
|
39
|
+
low_latency: 0 | 1;
|
|
40
|
+
business_residential_code: string;
|
|
41
|
+
/**
|
|
42
|
+
* Decoded to an ASCII string at the parse boundary (2a decision 3) — joins `TIGERBlockTable.GEOID` (note: uppercase
|
|
43
|
+
* column on that side).
|
|
44
|
+
*/
|
|
45
|
+
geoid: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Given a buffer containing FCC BDC availability CSV data, yield each data row (the header row is skipped) as a
|
|
49
|
+
* {@linkcode BDCAvailabilityRow}.
|
|
50
|
+
*
|
|
51
|
+
* A byte-level scan, not a general CSV parser: it tracks comma/newline byte positions directly and only toggles
|
|
52
|
+
* quote-awareness via a running double-quote count (an odd count means the scanner is currently inside a quoted field,
|
|
53
|
+
* so a comma there isn't a column delimiter) — matching the Nexus original's approach for this specific, known-shaped
|
|
54
|
+
* 12-column file rather than reaching for a general CSV library.
|
|
55
|
+
*/
|
|
56
|
+
export declare function takeAvailabilityLine(csvBuffer: Buffer, providerID: ProviderID): Iterable<BDCAvailabilityRow>;
|
|
57
|
+
//# sourceMappingURL=parsing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsing.d.ts","sourceRoot":"","sources":["../../sdk/parsing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAgB7C;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,6BAA6B,EAAE,MAAM,CAAA;IACrC,2BAA2B,EAAE,MAAM,CAAA;IACnC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAA;IAClB,yBAAyB,EAAE,MAAM,CAAA;IACjC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;GAQG;AACH,wBAAiB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAmD7G"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
* @file FCC BDC availability CSV byte-level parser.
|
|
6
|
+
*
|
|
7
|
+
* Re-homed from Nexus's `sync/fcc/bdc/parsing.ts` (relicense-by-copy, no provenance headers): the same
|
|
8
|
+
* byte-scanning generator over the FCC's 12-column availability CSV — see the Nexus `RawBSLAvailabilityRow`
|
|
9
|
+
* tuple (`sync/fcc/bdc/block-aggregator.ts`) for the column order this scan assumes: frn, provider_id,
|
|
10
|
+
* brand_name, location_id, technology, max_advertised_download_speed, max_advertised_upload_speed,
|
|
11
|
+
* low_latency, business_residential_code, state_usps, block_geoid, h3_res8_id. Changed only where the
|
|
12
|
+
* pre-registered 2a decisions require: `geoid` (column 10, `block_geoid`) decodes to an ASCII string
|
|
13
|
+
* instead of staying a raw `Uint8Array` slice (decision 3), and `location_id` (column 3) stays a string
|
|
14
|
+
* instead of `parseInt`ing it, preserving leading zeros (decision 1). `business_residential_code` is
|
|
15
|
+
* likewise decoded to its ASCII string here — the Nexus original kept only the field's first raw byte as
|
|
16
|
+
* a bare `number`, which this port's `BDCAvailabilityRow` shape doesn't call for.
|
|
17
|
+
*
|
|
18
|
+
* Columns 0-2 (frn, provider_id, brand_name) and 9, 11 (state_usps, h3_res8_id) are scanned over but
|
|
19
|
+
* never sliced into the output record: `provider_id` comes from the `providerID` parameter instead (the
|
|
20
|
+
* FCC partitions availability files per provider, so the caller already knows it), and FRN/brand/state/H3
|
|
21
|
+
* join concerns are out of scope for 2a (decision 8 — provider identity is a 2c registry-join seam).
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Byte values this scanner switches on.
|
|
25
|
+
*
|
|
26
|
+
* Local to this file — no generic newline-delimited-file utility exists elsewhere in the repo to import. Nexus's
|
|
27
|
+
* equivalent (`LineDelimitedCharacter`) lived in `@isp.nexus/sdk/files`, a workspace this port doesn't carry over, and
|
|
28
|
+
* repo convention forbids TS `enum` anyway (`erasableSyntaxOnly`).
|
|
29
|
+
*/
|
|
30
|
+
const CSVByte = {
|
|
31
|
+
Newline: 10,
|
|
32
|
+
Comma: 44,
|
|
33
|
+
DoubleQuote: 34,
|
|
34
|
+
One: 49,
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Given a buffer containing FCC BDC availability CSV data, yield each data row (the header row is skipped) as a
|
|
38
|
+
* {@linkcode BDCAvailabilityRow}.
|
|
39
|
+
*
|
|
40
|
+
* A byte-level scan, not a general CSV parser: it tracks comma/newline byte positions directly and only toggles
|
|
41
|
+
* quote-awareness via a running double-quote count (an odd count means the scanner is currently inside a quoted field,
|
|
42
|
+
* so a comma there isn't a column delimiter) — matching the Nexus original's approach for this specific, known-shaped
|
|
43
|
+
* 12-column file rather than reaching for a general CSV library.
|
|
44
|
+
*/
|
|
45
|
+
export function* takeAvailabilityLine(csvBuffer, providerID) {
|
|
46
|
+
// Skip the header row.
|
|
47
|
+
let byteIndex = csvBuffer.indexOf(CSVByte.Newline) + 1;
|
|
48
|
+
const contentDelimiters = new Uint32Array(12); // 12 columns
|
|
49
|
+
contentDelimiters[0] = byteIndex;
|
|
50
|
+
let delimiterIndex = 1;
|
|
51
|
+
let doubleQuoteCount = 0;
|
|
52
|
+
while (byteIndex < csvBuffer.length) {
|
|
53
|
+
const byte = csvBuffer[byteIndex];
|
|
54
|
+
if (byte === CSVByte.DoubleQuote) {
|
|
55
|
+
doubleQuoteCount++;
|
|
56
|
+
}
|
|
57
|
+
if (byte === CSVByte.Comma && doubleQuoteCount % 2 === 0) {
|
|
58
|
+
contentDelimiters[delimiterIndex] = byteIndex;
|
|
59
|
+
delimiterIndex++;
|
|
60
|
+
}
|
|
61
|
+
if (byte === CSVByte.Newline) {
|
|
62
|
+
contentDelimiters[delimiterIndex] = CSVByte.Newline;
|
|
63
|
+
const slices = [];
|
|
64
|
+
// Skip columns 0-2 (frn, provider_id, brand_name) — see the file header for why.
|
|
65
|
+
for (let i = 3; i < contentDelimiters.length; i++) {
|
|
66
|
+
const start = contentDelimiters[i] + 1;
|
|
67
|
+
const end = contentDelimiters[i + 1];
|
|
68
|
+
slices.push(csvBuffer.subarray(start, end));
|
|
69
|
+
}
|
|
70
|
+
const record = {
|
|
71
|
+
provider_id: providerID,
|
|
72
|
+
location_id: slices[0].toString("ascii"),
|
|
73
|
+
technology_code: Number.parseInt(slices[1].toString(), 10),
|
|
74
|
+
max_advertised_download_speed: Number.parseInt(slices[2].toString(), 10),
|
|
75
|
+
max_advertised_upload_speed: Number.parseInt(slices[3].toString(), 10),
|
|
76
|
+
low_latency: slices[4][0] === CSVByte.One ? 1 : 0,
|
|
77
|
+
business_residential_code: slices[5].toString("ascii"),
|
|
78
|
+
geoid: slices[7].toString("ascii"),
|
|
79
|
+
};
|
|
80
|
+
yield record;
|
|
81
|
+
delimiterIndex = 1;
|
|
82
|
+
doubleQuoteCount = 0;
|
|
83
|
+
}
|
|
84
|
+
byteIndex++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=parsing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parsing.js","sourceRoot":"","sources":["../../sdk/parsing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH;;;;;;GAMG;AACH,MAAM,OAAO,GAAG;IACf,OAAO,EAAE,EAAE;IACX,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,EAAE;IACf,GAAG,EAAE,EAAE;CACE,CAAA;AA0BV;;;;;;;;GAQG;AACH,MAAM,SAAS,CAAC,CAAC,oBAAoB,CAAC,SAAiB,EAAE,UAAsB;IAC9E,uBAAuB;IACvB,IAAI,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACtD,MAAM,iBAAiB,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAA,CAAC,aAAa;IAC3D,iBAAiB,CAAC,CAAC,CAAC,GAAG,SAAS,CAAA;IAChC,IAAI,cAAc,GAAG,CAAC,CAAA;IACtB,IAAI,gBAAgB,GAAG,CAAC,CAAA;IAExB,OAAO,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;QAEjC,IAAI,IAAI,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC;YAClC,gBAAgB,EAAE,CAAA;QACnB,CAAC;QAED,IAAI,IAAI,KAAK,OAAO,CAAC,KAAK,IAAI,gBAAgB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,iBAAiB,CAAC,cAAc,CAAC,GAAG,SAAS,CAAA;YAE7C,cAAc,EAAE,CAAA;QACjB,CAAC;QAED,IAAI,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9B,iBAAiB,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,OAAO,CAAA;YACnD,MAAM,MAAM,GAAa,EAAE,CAAA;YAE3B,iFAAiF;YACjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAE,GAAG,CAAC,CAAA;gBACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;gBAEpC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;YAC5C,CAAC;YAED,MAAM,MAAM,GAAuB;gBAClC,WAAW,EAAE,UAAU;gBACvB,WAAW,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACzC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;gBAC3D,6BAA6B,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;gBACzE,2BAA2B,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;gBACvE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClD,yBAAyB,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACvD,KAAK,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;aACnC,CAAA;YAED,MAAM,MAAM,CAAA;YACZ,cAAc,GAAG,CAAC,CAAA;YAClB,gBAAgB,GAAG,CAAC,CAAA;QACrB,CAAC;QAED,SAAS,EAAE,CAAA;IACZ,CAAC;AACF,CAAC"}
|