@urbankitstudio/atlas 0.5.2 → 0.6.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 +36 -0
- package/data/california.json +22 -2
- package/dist/index.cjs +37 -2
- package/dist/index.d.cts +111 -1
- package/dist/index.d.ts +111 -1
- package/dist/index.js +35 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -92,6 +92,42 @@ atlas.totals; // { states, counties, endpoints }
|
|
|
92
92
|
atlas.byStateSlug; // Map<stateSlug, StateFile>
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
## `status` is a publish-time claim, not a live signal
|
|
96
|
+
|
|
97
|
+
This package ships static JSON and makes no network calls, so `status` and
|
|
98
|
+
`lastVerified` on every endpoint describe what was true **when the version you
|
|
99
|
+
installed was published**. `status: "live"` means a check passed before publish —
|
|
100
|
+
not that the endpoint is up right now. A county can go down the day after a
|
|
101
|
+
release and every installed copy keeps saying `"live"` until the next one.
|
|
102
|
+
|
|
103
|
+
The distinction is not hypothetical: on 2026-08-04 a county was being served as
|
|
104
|
+
`"live"` from its registry entry while the liveness probe had it down that same
|
|
105
|
+
afternoon.
|
|
106
|
+
|
|
107
|
+
For the current answer, ask the health endpoint — no API key, refreshed every
|
|
108
|
+
two hours:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { LIVE_STATUS_URL } from "@urbankitstudio/atlas";
|
|
112
|
+
|
|
113
|
+
const res = await fetch(`${LIVE_STATUS_URL}?fips=17089`);
|
|
114
|
+
const health = await res.json();
|
|
115
|
+
// { ok: true, found: true, county_fips: "17089",
|
|
116
|
+
// status: "ok" | "degraded" | "down" | "unknown",
|
|
117
|
+
// consecutive_failures, last_ok_at, checked_at }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Two cases to handle rather than ignore:
|
|
121
|
+
|
|
122
|
+
- **`found: false`** means no observation exists — the county may be untracked or
|
|
123
|
+
never probed. It is *not* a statement that the endpoint is healthy.
|
|
124
|
+
- **A `503`** means the health store itself was unreachable. Also not a health
|
|
125
|
+
claim.
|
|
126
|
+
|
|
127
|
+
Treat both as *unknown*. Neither should render as "up".
|
|
128
|
+
|
|
129
|
+
Omit `?fips=` to get every tracked county in one call.
|
|
130
|
+
|
|
95
131
|
## Coverage today
|
|
96
132
|
|
|
97
133
|
The atlas currently bundles **155 counties across all 50 US states**, covering the largest counties in each. Call `listStates()` to enumerate the full set; every state is now populated with at least one verified county endpoint.
|
package/data/california.json
CHANGED
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"url": "https://egis-lacounty.hub.arcgis.com/",
|
|
45
45
|
"email": null
|
|
46
46
|
},
|
|
47
|
-
"notes": "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name),
|
|
47
|
+
"notes": "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name), because the county does not publish an owner column on this layer. California Government Code 7928.205 is often cited for this, but that section protects the home address of elected and appointed officials rather than owner data generally, and California counties differ: San Diego publishes owner names on its public layer while San Bernardino returns a redaction notice in every row. For ownership data, use the LA County Assessor's portal at assessor.lacounty.gov; the Assessor's office manages roughly 2.5 million parcels and publishes annual assessment rolls. Re-verified live 2026-06-04, a sample AIN query returned a real parcel. The EGIS open-data hub at egis-lacounty.hub.arcgis.com has downloadable parcel shapefiles. AIN queries use exact match: AIN='4321002009' (no dashes)."
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"id": "ca-sacramento",
|
|
@@ -205,7 +205,27 @@
|
|
|
205
205
|
"url": "https://data-sbcounty.opendata.arcgis.com/",
|
|
206
206
|
"email": null
|
|
207
207
|
},
|
|
208
|
-
"notes": "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com."
|
|
208
|
+
"notes": "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com.",
|
|
209
|
+
"ownerFieldNote": {
|
|
210
|
+
"body": "San Bernardino County's public parcel layer returns an OwnerName field, but every row's value is the literal string \"Protected Per CA Gov Code 7928.205\" rather than a name. The redaction is applied server-side to the whole layer, so no query can retrieve ownership here. Parcel number, land and improvement value, zoning, and acreage are unredacted and searchable; ownership by APN is available from the county Assessor's own portal.",
|
|
211
|
+
"source": {
|
|
212
|
+
"label": "San Bernardino County Assessor property information",
|
|
213
|
+
"url": "https://arc.sbcounty.gov/property-information/"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"capabilityOverrides": {
|
|
217
|
+
"owner_name": {
|
|
218
|
+
"status": "restricted",
|
|
219
|
+
"basis": {
|
|
220
|
+
"type": "county_cited_statute",
|
|
221
|
+
"note": "Every row's OwnerName value is the literal string \"Protected Per CA Gov Code 7928.205\" rather than a name. The county applies the redaction server-side to the whole layer and cites that section itself. The section protects the home address of elected and appointed officials, so this is the county's own reading applied to every parcel, not a statewide rule: San Diego County publishes owner names on its public layer.",
|
|
222
|
+
"citation": "Cal. Gov. Code 7928.205",
|
|
223
|
+
"attributedTo": "San Bernardino County",
|
|
224
|
+
"sourceUrl": "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=7928.205&lawCode=GOV"
|
|
225
|
+
},
|
|
226
|
+
"lawfulAlternativeUrl": "https://arc.sbcounty.gov/property-information/"
|
|
227
|
+
}
|
|
228
|
+
}
|
|
209
229
|
},
|
|
210
230
|
{
|
|
211
231
|
"id": "ca-san-diego",
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/capability.ts
|
|
4
|
+
function reviewedCapability(county, field) {
|
|
5
|
+
return county.capabilityOverrides?.[field] ?? null;
|
|
6
|
+
}
|
|
7
|
+
function isReviewedUnservable(county, field) {
|
|
8
|
+
const reviewed = reviewedCapability(county, field);
|
|
9
|
+
return reviewed?.status === "restricted" || reviewed?.status === "not_published";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/types.ts
|
|
13
|
+
var LIVE_STATUS_URL = "https://urbankitstudio.com/api/atlas/status";
|
|
14
|
+
|
|
3
15
|
// data/index.json
|
|
4
16
|
var data_default = {
|
|
5
17
|
version: "0.3.0",
|
|
@@ -913,7 +925,7 @@ var california_default = {
|
|
|
913
925
|
url: "https://egis-lacounty.hub.arcgis.com/",
|
|
914
926
|
email: null
|
|
915
927
|
},
|
|
916
|
-
notes: "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name),
|
|
928
|
+
notes: "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name), because the county does not publish an owner column on this layer. California Government Code 7928.205 is often cited for this, but that section protects the home address of elected and appointed officials rather than owner data generally, and California counties differ: San Diego publishes owner names on its public layer while San Bernardino returns a redaction notice in every row. For ownership data, use the LA County Assessor's portal at assessor.lacounty.gov; the Assessor's office manages roughly 2.5 million parcels and publishes annual assessment rolls. Re-verified live 2026-06-04, a sample AIN query returned a real parcel. The EGIS open-data hub at egis-lacounty.hub.arcgis.com has downloadable parcel shapefiles. AIN queries use exact match: AIN='4321002009' (no dashes)."
|
|
917
929
|
},
|
|
918
930
|
{
|
|
919
931
|
id: "ca-sacramento",
|
|
@@ -1074,7 +1086,27 @@ var california_default = {
|
|
|
1074
1086
|
url: "https://data-sbcounty.opendata.arcgis.com/",
|
|
1075
1087
|
email: null
|
|
1076
1088
|
},
|
|
1077
|
-
notes: "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com."
|
|
1089
|
+
notes: "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com.",
|
|
1090
|
+
ownerFieldNote: {
|
|
1091
|
+
body: `San Bernardino County's public parcel layer returns an OwnerName field, but every row's value is the literal string "Protected Per CA Gov Code 7928.205" rather than a name. The redaction is applied server-side to the whole layer, so no query can retrieve ownership here. Parcel number, land and improvement value, zoning, and acreage are unredacted and searchable; ownership by APN is available from the county Assessor's own portal.`,
|
|
1092
|
+
source: {
|
|
1093
|
+
label: "San Bernardino County Assessor property information",
|
|
1094
|
+
url: "https://arc.sbcounty.gov/property-information/"
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
capabilityOverrides: {
|
|
1098
|
+
owner_name: {
|
|
1099
|
+
status: "restricted",
|
|
1100
|
+
basis: {
|
|
1101
|
+
type: "county_cited_statute",
|
|
1102
|
+
note: `Every row's OwnerName value is the literal string "Protected Per CA Gov Code 7928.205" rather than a name. The county applies the redaction server-side to the whole layer and cites that section itself. The section protects the home address of elected and appointed officials, so this is the county's own reading applied to every parcel, not a statewide rule: San Diego County publishes owner names on its public layer.`,
|
|
1103
|
+
citation: "Cal. Gov. Code 7928.205",
|
|
1104
|
+
attributedTo: "San Bernardino County",
|
|
1105
|
+
sourceUrl: "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=7928.205&lawCode=GOV"
|
|
1106
|
+
},
|
|
1107
|
+
lawfulAlternativeUrl: "https://arc.sbcounty.gov/property-information/"
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1078
1110
|
},
|
|
1079
1111
|
{
|
|
1080
1112
|
id: "ca-san-diego",
|
|
@@ -8225,6 +8257,7 @@ function countyPath(stateSlug, countySlug) {
|
|
|
8225
8257
|
return `/parcel-atlas/${stateSlug}/${countySlug}`;
|
|
8226
8258
|
}
|
|
8227
8259
|
|
|
8260
|
+
exports.LIVE_STATUS_URL = LIVE_STATUS_URL;
|
|
8228
8261
|
exports.atlas = atlas;
|
|
8229
8262
|
exports.atlasIndex = atlasIndex;
|
|
8230
8263
|
exports.buildParcelLookupDeepLink = buildParcelLookupDeepLink;
|
|
@@ -8233,7 +8266,9 @@ exports.countySlugFromName = countySlugFromName;
|
|
|
8233
8266
|
exports.findCounty = findCounty;
|
|
8234
8267
|
exports.findCountyByFips = findCountyByFips;
|
|
8235
8268
|
exports.findState = findState;
|
|
8269
|
+
exports.isReviewedUnservable = isReviewedUnservable;
|
|
8236
8270
|
exports.listCountiesByState = listCountiesByState;
|
|
8237
8271
|
exports.listStates = listStates;
|
|
8272
|
+
exports.reviewedCapability = reviewedCapability;
|
|
8238
8273
|
exports.slugify = slugify;
|
|
8239
8274
|
exports.statePath = statePath;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
type ServiceType = "FeatureServer" | "MapServer";
|
|
2
2
|
type LicenseType = "public" | "open-data" | "restricted" | "unknown";
|
|
3
|
+
/**
|
|
4
|
+
* The registry's curation stamp for an endpoint, AS OF THE MOMENT THIS PACKAGE
|
|
5
|
+
* WAS PUBLISHED. It is not a live signal and cannot be — this package ships
|
|
6
|
+
* static JSON and makes no network calls.
|
|
7
|
+
*
|
|
8
|
+
* So `"live"` here means "a check passed before publish", not "this endpoint is
|
|
9
|
+
* up right now". A county can go down the day after a release and every
|
|
10
|
+
* installed copy will keep reporting `"live"` until the next one.
|
|
11
|
+
*
|
|
12
|
+
* For the current answer, query the public health endpoint, which reports what
|
|
13
|
+
* the liveness probe last observed (every two hours) and requires no API key:
|
|
14
|
+
*
|
|
15
|
+
* GET https://urbankitstudio.com/api/atlas/status?fips=17089
|
|
16
|
+
*
|
|
17
|
+
* A `found: false` there means no observation exists — which is not the same as
|
|
18
|
+
* healthy. See LIVE_STATUS_URL below.
|
|
19
|
+
*/
|
|
3
20
|
type EndpointStatus = "live" | "stale" | "unreachable" | "unverified";
|
|
4
21
|
type VerifiedBy = "manual" | "arcgis-hub-seed" | "automated";
|
|
22
|
+
/**
|
|
23
|
+
* Where to ask whether an endpoint is actually up right now. Keyless.
|
|
24
|
+
* Omit the query string for every tracked county.
|
|
25
|
+
*/
|
|
26
|
+
declare const LIVE_STATUS_URL = "https://urbankitstudio.com/api/atlas/status";
|
|
5
27
|
interface SearchField {
|
|
6
28
|
name: string;
|
|
7
29
|
label: string;
|
|
@@ -18,7 +40,10 @@ interface EndpointRecord {
|
|
|
18
40
|
sampleQuery: string | null;
|
|
19
41
|
license: LicenseType;
|
|
20
42
|
licenseUrl: string | null;
|
|
43
|
+
/** Publish-time claim, NOT live. See {@link EndpointStatus}. */
|
|
21
44
|
status: EndpointStatus;
|
|
45
|
+
/** ISO date this entry was last verified before publish — a human curation
|
|
46
|
+
* date, not a probe result, and always at least as old as this release. */
|
|
22
47
|
lastVerified: string;
|
|
23
48
|
verifiedBy: VerifiedBy;
|
|
24
49
|
}
|
|
@@ -27,6 +52,58 @@ interface ContactInfo {
|
|
|
27
52
|
url: string | null;
|
|
28
53
|
email: string | null;
|
|
29
54
|
}
|
|
55
|
+
/** A short curated caveat about a county, written by a human. */
|
|
56
|
+
interface CountyAdvisory {
|
|
57
|
+
body: string;
|
|
58
|
+
source?: {
|
|
59
|
+
label: string;
|
|
60
|
+
url: string;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** The fields a caller can ask a county about. */
|
|
64
|
+
type CapabilityField = "apn" | "owner_name" | "owner_mailing_address" | "situs_address" | "geometry" | "land_use" | "zoning";
|
|
65
|
+
type CapabilityStatus = "available" | "not_published" | "restricted" | "unverified";
|
|
66
|
+
/**
|
|
67
|
+
* Where a non-available status comes from. The type matters more than the
|
|
68
|
+
* prose, because it tells you whether you are reading a fact about a service, a
|
|
69
|
+
* claim the COUNTY makes, or a claim we make.
|
|
70
|
+
*
|
|
71
|
+
* `county_cited_statute` is the one to read carefully. It means the county
|
|
72
|
+
* publishes that citation as its own reason, reported here attributed to them
|
|
73
|
+
* rather than adopted as our reading of the law. San Bernardino County returns
|
|
74
|
+
* the literal string "Protected Per CA Gov Code 7928.205" in every owner-name
|
|
75
|
+
* row; that section protects the home address of elected and appointed
|
|
76
|
+
* officials, and San Diego County publishes owner names on its public layer.
|
|
77
|
+
* One statute, different county behaviour, so the attribution is not a
|
|
78
|
+
* formality.
|
|
79
|
+
*/
|
|
80
|
+
type CapabilityBasisType = "endpoint_schema" | "county_cited_statute" | "statute" | "county_policy";
|
|
81
|
+
interface CapabilityBasis {
|
|
82
|
+
type: CapabilityBasisType;
|
|
83
|
+
/** One sentence you could show a user without editing. */
|
|
84
|
+
note: string;
|
|
85
|
+
citation?: string;
|
|
86
|
+
sourceUrl?: string;
|
|
87
|
+
/** Who makes the claim, when it is not us. Always set for county_cited_statute. */
|
|
88
|
+
attributedTo?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* REVIEWED capability assertions, per field. Only entries a human entered and
|
|
92
|
+
* checked appear here, which is exactly the knowledge you cannot compute from
|
|
93
|
+
* the bundled data yourself.
|
|
94
|
+
*
|
|
95
|
+
* What is NOT here is the mechanical half. Whether a field is simply absent
|
|
96
|
+
* from an endpoint's documented `searchFields` is derivable, and this package
|
|
97
|
+
* deliberately does not derive it: a second implementation of that
|
|
98
|
+
* classification would drift from the one the API bills against, and you would
|
|
99
|
+
* have no way to tell which was right. Read `endpoints[].searchFields` for the
|
|
100
|
+
* mechanical answer, and treat an entry here as outranking it.
|
|
101
|
+
*/
|
|
102
|
+
type CapabilityOverrides = Partial<Record<CapabilityField, {
|
|
103
|
+
status: CapabilityStatus;
|
|
104
|
+
basis: CapabilityBasis;
|
|
105
|
+
lawfulAlternativeUrl?: string | null;
|
|
106
|
+
}>>;
|
|
30
107
|
interface CountyRecord {
|
|
31
108
|
id: string;
|
|
32
109
|
state: string;
|
|
@@ -39,6 +116,14 @@ interface CountyRecord {
|
|
|
39
116
|
contact: ContactInfo | null;
|
|
40
117
|
hasPublicRest: boolean;
|
|
41
118
|
notes: string | null;
|
|
119
|
+
/** Curated caveat about owner data on this county's public layer. */
|
|
120
|
+
ownerFieldNote?: CountyAdvisory | null;
|
|
121
|
+
/** Curated caveat about how old the county's published data is. */
|
|
122
|
+
dataVintage?: CountyAdvisory | null;
|
|
123
|
+
/** Reviewed, per-field capability assertions. See {@link CapabilityOverrides}. */
|
|
124
|
+
capabilityOverrides?: CapabilityOverrides | null;
|
|
125
|
+
relatedZoningCitySlug?: string | null;
|
|
126
|
+
relatedPropertyCitySlug?: string | null;
|
|
42
127
|
}
|
|
43
128
|
interface StateFile {
|
|
44
129
|
stateSlug: string;
|
|
@@ -66,6 +151,31 @@ interface AtlasIndex {
|
|
|
66
151
|
};
|
|
67
152
|
}
|
|
68
153
|
|
|
154
|
+
/**
|
|
155
|
+
* The reviewed capability assertion for one field, or null when none exists.
|
|
156
|
+
*
|
|
157
|
+
* Null is the common answer and it is not a failure: it means nobody has had to
|
|
158
|
+
* write anything down about that field for that county, so the ordinary rules
|
|
159
|
+
* apply. Read `county.endpoints[].searchFields` to see what the layer actually
|
|
160
|
+
* documents.
|
|
161
|
+
*
|
|
162
|
+
* A non-null answer is the part worth branching on. It was entered by a human
|
|
163
|
+
* who checked something a field list cannot show, and it outranks whatever the
|
|
164
|
+
* field list implies. The clearest case: San Bernardino County publishes an
|
|
165
|
+
* `OwnerName` column, so the field list says owner names are available, and
|
|
166
|
+
* every row's value is the literal string "Protected Per CA Gov Code 7928.205".
|
|
167
|
+
* Only the reviewed record can tell you that.
|
|
168
|
+
*/
|
|
169
|
+
declare function reviewedCapability(county: Pick<CountyRecord, "capabilityOverrides">, field: CapabilityField): NonNullable<CapabilityOverrides[CapabilityField]> | null;
|
|
170
|
+
/**
|
|
171
|
+
* True when a reviewed record says this field cannot be served, whatever the
|
|
172
|
+
* reason. Use it to decide whether to promise a user the field at all.
|
|
173
|
+
*
|
|
174
|
+
* False does NOT mean "available". It means no reviewed record says otherwise,
|
|
175
|
+
* so fall back to the endpoint's documented `searchFields`.
|
|
176
|
+
*/
|
|
177
|
+
declare function isReviewedUnservable(county: Pick<CountyRecord, "capabilityOverrides">, field: CapabilityField): boolean;
|
|
178
|
+
|
|
69
179
|
/**
|
|
70
180
|
* Look up a county by state slug and county slug.
|
|
71
181
|
* Returns undefined if the state isn't populated yet or the county doesn't exist.
|
|
@@ -121,4 +231,4 @@ interface Atlas {
|
|
|
121
231
|
}
|
|
122
232
|
declare const atlas: Atlas;
|
|
123
233
|
|
|
124
|
-
export { type Atlas, type AtlasIndex, type ContactInfo, type CountyRecord, type EndpointRecord, type EndpointStatus, type LicenseType, type SearchField, type ServiceType, type StateFile, type StateIndexEntry, type VerifiedBy, atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, listCountiesByState, listStates, slugify, statePath };
|
|
234
|
+
export { type Atlas, type AtlasIndex, type CapabilityBasis, type CapabilityBasisType, type CapabilityField, type CapabilityOverrides, type CapabilityStatus, type ContactInfo, type CountyAdvisory, type CountyRecord, type EndpointRecord, type EndpointStatus, LIVE_STATUS_URL, type LicenseType, type SearchField, type ServiceType, type StateFile, type StateIndexEntry, type VerifiedBy, atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, isReviewedUnservable, listCountiesByState, listStates, reviewedCapability, slugify, statePath };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
type ServiceType = "FeatureServer" | "MapServer";
|
|
2
2
|
type LicenseType = "public" | "open-data" | "restricted" | "unknown";
|
|
3
|
+
/**
|
|
4
|
+
* The registry's curation stamp for an endpoint, AS OF THE MOMENT THIS PACKAGE
|
|
5
|
+
* WAS PUBLISHED. It is not a live signal and cannot be — this package ships
|
|
6
|
+
* static JSON and makes no network calls.
|
|
7
|
+
*
|
|
8
|
+
* So `"live"` here means "a check passed before publish", not "this endpoint is
|
|
9
|
+
* up right now". A county can go down the day after a release and every
|
|
10
|
+
* installed copy will keep reporting `"live"` until the next one.
|
|
11
|
+
*
|
|
12
|
+
* For the current answer, query the public health endpoint, which reports what
|
|
13
|
+
* the liveness probe last observed (every two hours) and requires no API key:
|
|
14
|
+
*
|
|
15
|
+
* GET https://urbankitstudio.com/api/atlas/status?fips=17089
|
|
16
|
+
*
|
|
17
|
+
* A `found: false` there means no observation exists — which is not the same as
|
|
18
|
+
* healthy. See LIVE_STATUS_URL below.
|
|
19
|
+
*/
|
|
3
20
|
type EndpointStatus = "live" | "stale" | "unreachable" | "unverified";
|
|
4
21
|
type VerifiedBy = "manual" | "arcgis-hub-seed" | "automated";
|
|
22
|
+
/**
|
|
23
|
+
* Where to ask whether an endpoint is actually up right now. Keyless.
|
|
24
|
+
* Omit the query string for every tracked county.
|
|
25
|
+
*/
|
|
26
|
+
declare const LIVE_STATUS_URL = "https://urbankitstudio.com/api/atlas/status";
|
|
5
27
|
interface SearchField {
|
|
6
28
|
name: string;
|
|
7
29
|
label: string;
|
|
@@ -18,7 +40,10 @@ interface EndpointRecord {
|
|
|
18
40
|
sampleQuery: string | null;
|
|
19
41
|
license: LicenseType;
|
|
20
42
|
licenseUrl: string | null;
|
|
43
|
+
/** Publish-time claim, NOT live. See {@link EndpointStatus}. */
|
|
21
44
|
status: EndpointStatus;
|
|
45
|
+
/** ISO date this entry was last verified before publish — a human curation
|
|
46
|
+
* date, not a probe result, and always at least as old as this release. */
|
|
22
47
|
lastVerified: string;
|
|
23
48
|
verifiedBy: VerifiedBy;
|
|
24
49
|
}
|
|
@@ -27,6 +52,58 @@ interface ContactInfo {
|
|
|
27
52
|
url: string | null;
|
|
28
53
|
email: string | null;
|
|
29
54
|
}
|
|
55
|
+
/** A short curated caveat about a county, written by a human. */
|
|
56
|
+
interface CountyAdvisory {
|
|
57
|
+
body: string;
|
|
58
|
+
source?: {
|
|
59
|
+
label: string;
|
|
60
|
+
url: string;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** The fields a caller can ask a county about. */
|
|
64
|
+
type CapabilityField = "apn" | "owner_name" | "owner_mailing_address" | "situs_address" | "geometry" | "land_use" | "zoning";
|
|
65
|
+
type CapabilityStatus = "available" | "not_published" | "restricted" | "unverified";
|
|
66
|
+
/**
|
|
67
|
+
* Where a non-available status comes from. The type matters more than the
|
|
68
|
+
* prose, because it tells you whether you are reading a fact about a service, a
|
|
69
|
+
* claim the COUNTY makes, or a claim we make.
|
|
70
|
+
*
|
|
71
|
+
* `county_cited_statute` is the one to read carefully. It means the county
|
|
72
|
+
* publishes that citation as its own reason, reported here attributed to them
|
|
73
|
+
* rather than adopted as our reading of the law. San Bernardino County returns
|
|
74
|
+
* the literal string "Protected Per CA Gov Code 7928.205" in every owner-name
|
|
75
|
+
* row; that section protects the home address of elected and appointed
|
|
76
|
+
* officials, and San Diego County publishes owner names on its public layer.
|
|
77
|
+
* One statute, different county behaviour, so the attribution is not a
|
|
78
|
+
* formality.
|
|
79
|
+
*/
|
|
80
|
+
type CapabilityBasisType = "endpoint_schema" | "county_cited_statute" | "statute" | "county_policy";
|
|
81
|
+
interface CapabilityBasis {
|
|
82
|
+
type: CapabilityBasisType;
|
|
83
|
+
/** One sentence you could show a user without editing. */
|
|
84
|
+
note: string;
|
|
85
|
+
citation?: string;
|
|
86
|
+
sourceUrl?: string;
|
|
87
|
+
/** Who makes the claim, when it is not us. Always set for county_cited_statute. */
|
|
88
|
+
attributedTo?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* REVIEWED capability assertions, per field. Only entries a human entered and
|
|
92
|
+
* checked appear here, which is exactly the knowledge you cannot compute from
|
|
93
|
+
* the bundled data yourself.
|
|
94
|
+
*
|
|
95
|
+
* What is NOT here is the mechanical half. Whether a field is simply absent
|
|
96
|
+
* from an endpoint's documented `searchFields` is derivable, and this package
|
|
97
|
+
* deliberately does not derive it: a second implementation of that
|
|
98
|
+
* classification would drift from the one the API bills against, and you would
|
|
99
|
+
* have no way to tell which was right. Read `endpoints[].searchFields` for the
|
|
100
|
+
* mechanical answer, and treat an entry here as outranking it.
|
|
101
|
+
*/
|
|
102
|
+
type CapabilityOverrides = Partial<Record<CapabilityField, {
|
|
103
|
+
status: CapabilityStatus;
|
|
104
|
+
basis: CapabilityBasis;
|
|
105
|
+
lawfulAlternativeUrl?: string | null;
|
|
106
|
+
}>>;
|
|
30
107
|
interface CountyRecord {
|
|
31
108
|
id: string;
|
|
32
109
|
state: string;
|
|
@@ -39,6 +116,14 @@ interface CountyRecord {
|
|
|
39
116
|
contact: ContactInfo | null;
|
|
40
117
|
hasPublicRest: boolean;
|
|
41
118
|
notes: string | null;
|
|
119
|
+
/** Curated caveat about owner data on this county's public layer. */
|
|
120
|
+
ownerFieldNote?: CountyAdvisory | null;
|
|
121
|
+
/** Curated caveat about how old the county's published data is. */
|
|
122
|
+
dataVintage?: CountyAdvisory | null;
|
|
123
|
+
/** Reviewed, per-field capability assertions. See {@link CapabilityOverrides}. */
|
|
124
|
+
capabilityOverrides?: CapabilityOverrides | null;
|
|
125
|
+
relatedZoningCitySlug?: string | null;
|
|
126
|
+
relatedPropertyCitySlug?: string | null;
|
|
42
127
|
}
|
|
43
128
|
interface StateFile {
|
|
44
129
|
stateSlug: string;
|
|
@@ -66,6 +151,31 @@ interface AtlasIndex {
|
|
|
66
151
|
};
|
|
67
152
|
}
|
|
68
153
|
|
|
154
|
+
/**
|
|
155
|
+
* The reviewed capability assertion for one field, or null when none exists.
|
|
156
|
+
*
|
|
157
|
+
* Null is the common answer and it is not a failure: it means nobody has had to
|
|
158
|
+
* write anything down about that field for that county, so the ordinary rules
|
|
159
|
+
* apply. Read `county.endpoints[].searchFields` to see what the layer actually
|
|
160
|
+
* documents.
|
|
161
|
+
*
|
|
162
|
+
* A non-null answer is the part worth branching on. It was entered by a human
|
|
163
|
+
* who checked something a field list cannot show, and it outranks whatever the
|
|
164
|
+
* field list implies. The clearest case: San Bernardino County publishes an
|
|
165
|
+
* `OwnerName` column, so the field list says owner names are available, and
|
|
166
|
+
* every row's value is the literal string "Protected Per CA Gov Code 7928.205".
|
|
167
|
+
* Only the reviewed record can tell you that.
|
|
168
|
+
*/
|
|
169
|
+
declare function reviewedCapability(county: Pick<CountyRecord, "capabilityOverrides">, field: CapabilityField): NonNullable<CapabilityOverrides[CapabilityField]> | null;
|
|
170
|
+
/**
|
|
171
|
+
* True when a reviewed record says this field cannot be served, whatever the
|
|
172
|
+
* reason. Use it to decide whether to promise a user the field at all.
|
|
173
|
+
*
|
|
174
|
+
* False does NOT mean "available". It means no reviewed record says otherwise,
|
|
175
|
+
* so fall back to the endpoint's documented `searchFields`.
|
|
176
|
+
*/
|
|
177
|
+
declare function isReviewedUnservable(county: Pick<CountyRecord, "capabilityOverrides">, field: CapabilityField): boolean;
|
|
178
|
+
|
|
69
179
|
/**
|
|
70
180
|
* Look up a county by state slug and county slug.
|
|
71
181
|
* Returns undefined if the state isn't populated yet or the county doesn't exist.
|
|
@@ -121,4 +231,4 @@ interface Atlas {
|
|
|
121
231
|
}
|
|
122
232
|
declare const atlas: Atlas;
|
|
123
233
|
|
|
124
|
-
export { type Atlas, type AtlasIndex, type ContactInfo, type CountyRecord, type EndpointRecord, type EndpointStatus, type LicenseType, type SearchField, type ServiceType, type StateFile, type StateIndexEntry, type VerifiedBy, atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, listCountiesByState, listStates, slugify, statePath };
|
|
234
|
+
export { type Atlas, type AtlasIndex, type CapabilityBasis, type CapabilityBasisType, type CapabilityField, type CapabilityOverrides, type CapabilityStatus, type ContactInfo, type CountyAdvisory, type CountyRecord, type EndpointRecord, type EndpointStatus, LIVE_STATUS_URL, type LicenseType, type SearchField, type ServiceType, type StateFile, type StateIndexEntry, type VerifiedBy, atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, isReviewedUnservable, listCountiesByState, listStates, reviewedCapability, slugify, statePath };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
// src/capability.ts
|
|
2
|
+
function reviewedCapability(county, field) {
|
|
3
|
+
return county.capabilityOverrides?.[field] ?? null;
|
|
4
|
+
}
|
|
5
|
+
function isReviewedUnservable(county, field) {
|
|
6
|
+
const reviewed = reviewedCapability(county, field);
|
|
7
|
+
return reviewed?.status === "restricted" || reviewed?.status === "not_published";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/types.ts
|
|
11
|
+
var LIVE_STATUS_URL = "https://urbankitstudio.com/api/atlas/status";
|
|
12
|
+
|
|
1
13
|
// data/index.json
|
|
2
14
|
var data_default = {
|
|
3
15
|
version: "0.3.0",
|
|
@@ -911,7 +923,7 @@ var california_default = {
|
|
|
911
923
|
url: "https://egis-lacounty.hub.arcgis.com/",
|
|
912
924
|
email: null
|
|
913
925
|
},
|
|
914
|
-
notes: "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name),
|
|
926
|
+
notes: "Los Angeles County is the most populous US county (pop. 10M+) and contains 88 incorporated cities plus a large unincorporated area. The Assessor Identification Number (AIN) is a 10-digit numeric code unique to each parcel. The public LACounty_Cache/LACounty_Parcel MapServer layer exposes AIN, APN, and SitusFullAddress (no owner name), because the county does not publish an owner column on this layer. California Government Code 7928.205 is often cited for this, but that section protects the home address of elected and appointed officials rather than owner data generally, and California counties differ: San Diego publishes owner names on its public layer while San Bernardino returns a redaction notice in every row. For ownership data, use the LA County Assessor's portal at assessor.lacounty.gov; the Assessor's office manages roughly 2.5 million parcels and publishes annual assessment rolls. Re-verified live 2026-06-04, a sample AIN query returned a real parcel. The EGIS open-data hub at egis-lacounty.hub.arcgis.com has downloadable parcel shapefiles. AIN queries use exact match: AIN='4321002009' (no dashes)."
|
|
915
927
|
},
|
|
916
928
|
{
|
|
917
929
|
id: "ca-sacramento",
|
|
@@ -1072,7 +1084,27 @@ var california_default = {
|
|
|
1072
1084
|
url: "https://data-sbcounty.opendata.arcgis.com/",
|
|
1073
1085
|
email: null
|
|
1074
1086
|
},
|
|
1075
|
-
notes: "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com."
|
|
1087
|
+
notes: "San Bernardino County is the largest county by land area in the contiguous United States (20,000+ sq mi, extending from the Inland Empire to the Nevada and Arizona borders), with a population of approximately 2.2M. 21 fields confirmed including ParcelNumber (the APN), OwnerName, LandValue, ImprovementValue, PersonalPropertyValue, ExemptionValue, HomeOwnerExemption, Acreage, TaxStatus, TaxRateArea, Zoning, ZoningDescription, Jurisdiction. Critical limitation: the OwnerName field exists in the schema and is returned in query results, but its value is redacted to the string 'Protected Per CA Gov Code 7928.205' on every public record. This is a deliberate redaction applied server-side under California Assembly Bill 1785 (effective January 2023), not a field that varies by parcel. ParcelNumber, LandValue, ImprovementValue, Zoning, and Acreage remain accessible and unredacted. Hosted on ArcGIS Online (services.arcgis.com/aA3snZwJfFkVyDuP). The county Assessor portal at arc.sbcounty.gov/property-information/ provides ownership data by APN. The Geographic Information Management Systems (GIMS) division manages the spatial data. Open-data hub: data-sbcounty.opendata.arcgis.com.",
|
|
1088
|
+
ownerFieldNote: {
|
|
1089
|
+
body: `San Bernardino County's public parcel layer returns an OwnerName field, but every row's value is the literal string "Protected Per CA Gov Code 7928.205" rather than a name. The redaction is applied server-side to the whole layer, so no query can retrieve ownership here. Parcel number, land and improvement value, zoning, and acreage are unredacted and searchable; ownership by APN is available from the county Assessor's own portal.`,
|
|
1090
|
+
source: {
|
|
1091
|
+
label: "San Bernardino County Assessor property information",
|
|
1092
|
+
url: "https://arc.sbcounty.gov/property-information/"
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
capabilityOverrides: {
|
|
1096
|
+
owner_name: {
|
|
1097
|
+
status: "restricted",
|
|
1098
|
+
basis: {
|
|
1099
|
+
type: "county_cited_statute",
|
|
1100
|
+
note: `Every row's OwnerName value is the literal string "Protected Per CA Gov Code 7928.205" rather than a name. The county applies the redaction server-side to the whole layer and cites that section itself. The section protects the home address of elected and appointed officials, so this is the county's own reading applied to every parcel, not a statewide rule: San Diego County publishes owner names on its public layer.`,
|
|
1101
|
+
citation: "Cal. Gov. Code 7928.205",
|
|
1102
|
+
attributedTo: "San Bernardino County",
|
|
1103
|
+
sourceUrl: "https://leginfo.legislature.ca.gov/faces/codes_displaySection.xhtml?sectionNum=7928.205&lawCode=GOV"
|
|
1104
|
+
},
|
|
1105
|
+
lawfulAlternativeUrl: "https://arc.sbcounty.gov/property-information/"
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1076
1108
|
},
|
|
1077
1109
|
{
|
|
1078
1110
|
id: "ca-san-diego",
|
|
@@ -8223,4 +8255,4 @@ function countyPath(stateSlug, countySlug) {
|
|
|
8223
8255
|
return `/parcel-atlas/${stateSlug}/${countySlug}`;
|
|
8224
8256
|
}
|
|
8225
8257
|
|
|
8226
|
-
export { atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, listCountiesByState, listStates, slugify, statePath };
|
|
8258
|
+
export { LIVE_STATUS_URL, atlas, atlasIndex, buildParcelLookupDeepLink, countyPath, countySlugFromName, findCounty, findCountyByFips, findState, isReviewedUnservable, listCountiesByState, listStates, reviewedCapability, slugify, statePath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@urbankitstudio/atlas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "JS SDK for the UrbanKit County Parcel REST API Atlas — public ArcGIS REST endpoints for US county parcel data, with searchable field metadata, sample queries, and license info.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"parcel",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"tsup": "^8.3.5",
|
|
59
59
|
"typescript": "^5.8.3",
|
|
60
|
-
"vitest": "^
|
|
60
|
+
"vitest": "^4.1.10"
|
|
61
61
|
},
|
|
62
62
|
"publishConfig": {
|
|
63
63
|
"access": "public"
|