@welldot/core 0.3.0 → 0.4.0-next.20261014.26249fd

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 CHANGED
@@ -15,11 +15,16 @@ TypeScript types, Zod validators, and serialization utilities for the `.well` op
15
15
  - **Administrative metadata** — well identity, construction type and purpose (`well_type`, `well_purpose`), authority-scoped IDs (`well_id`), driller, construction date, and geographic coordinates with explicit CRS
16
16
  - **Hydrodynamic events** — append-only ledger of static level readings, pumping tests (constant-rate, step-drawdown, airlift), and recovery phases
17
17
  - **Aquifer analysis** — interpreted parameter sets: transmissivity, specific capacity, storativity, and Jacob loss coefficients
18
- - **Operational history** — timestamped log of maintenance, inspections, and incidents with HTTPS attachment references
18
+ - **Operational history** — timestamped log of maintenance, inspections, incidents, status changes and permit condition fulfillment, with HTTPS attachment references
19
+ - **Pump installations** — installation history of the well's pumps: nameplate data, intake depth, riser and electrical data (v2.3)
20
+ - **Permits** — legal instruments governing abstraction (outorgas): validity, granted flow and daily operating time, volume limits, monthly schedule, and conditions (condicionantes) whose deadlines are derived from ISO 8601 date durations, with their fulfillments, an administrative status (requested, suspended…) and an administrative history (v2.3)
21
+ - **Meters, production and operating regime** — totalizer (hidrômetro) installation history, an append-only production ledger of meter readings and declared volumes (volumes are derived, never stored as totals), and the declared operating regime in force from a given instant (v2.3)
22
+ - **Water quality** — a `water_samples` ledger of samples, each with its field and laboratory results, sampling point and depth, purge and stabilization readings, laboratory and chain of custody, field QA/QC (duplicates, splits, blanks), per-result filtration, lab flags and data validation. Parameters are identified by `{ code, vocabulary }` against a versioned vocabulary of 98 `welldot` codes (plus CAS numbers and `x-` codes), and units come from the code. Limits are never stored in the file (v2.3)
23
+ - **Attachments** — HTTPS-referenced files typed by `document_type`: a root-level `attachments` array for general files about the well (e.g. the drilling report), plus per-record attachments on pumps, events, analyses and log entries. The root array does not collect the per-record ones (v2.3)
19
24
 
20
25
  The format is designed for three use cases: visualization of technical well profiles, registration with regulatory bodies, and hydrogeological research.
21
26
 
22
- See the [v2 format specification](./docs/spec/v2/overview.md) (current revision: v2.1) for the complete schema reference and design rationale. The [v1 spec](./docs/spec/v1/well-format.md) remains available for reference.
27
+ See the [v2 format specification](./docs/spec/v2/overview.md) (current revision: v2.3) for the complete schema reference and design rationale. The [v1 spec](./docs/spec/v1/well-format.md) remains available for reference.
23
28
 
24
29
  ## Installation
25
30
 
@@ -70,81 +75,145 @@ const empty = isWellEmpty(well);
70
75
 
71
76
  All types are exported as TypeScript type-only exports (zero runtime cost).
72
77
 
73
- | Type | Description |
74
- | ----------------------- | ------------------------------------------------------------------------------- |
75
- | `Well` | Complete static record of a water well (v2) |
76
- | `BoreHole` | A drilled interval with diameter and optional drilling method |
77
- | `WellCase` | Steel or plastic casing installed in the borehole |
78
- | `Reduction` | Transition piece between different casing diameters |
79
- | `WellScreen` | Slotted screen section for water intake (`screen_slot` in mm) |
80
- | `SurfaceCase` | Protective casing near the surface |
81
- | `HoleFill` | Annular fill material (`gravel_pack` or `seal`) |
82
- | `CementPad` | Concrete wellhead pad dimensions |
83
- | `Centralizer` | Casing/screen centralizers over a depth interval with spacing (v2.1) |
84
- | `Lithology` | Geological description of a depth interval |
85
- | `Texture` | `{ code: string \| number; vocabulary?: string }` — lithology texture reference |
86
- | `Fracture` | A discrete fracture or fracture zone |
87
- | `Cave` | A cavity or void zone |
88
- | `Constructive` | Grouped type: borehole + casings + screens + fills |
89
- | `Geologic` | Grouped type: lithology + fractures + caves |
90
- | `WellId` | Authority-scoped well identifier `{ authority, id, primary? }` |
91
- | `Location` | Geographic location with optional elevation and CRS properties |
92
- | `LocationProperties` | CRS, datum, and precision metadata for a `Location` |
93
- | `LevelReading` | A single depth/time reading during a pumping or recovery phase |
94
- | `RecoveryPhase` | Time-series of level readings after pump shutdown |
95
- | `PumpingStep` | One flow-rate step in a pumping test |
96
- | `HydrodynamicEventBase` | Common fields shared by all hydrodynamic event types |
97
- | `SpotMeasurementEvent` | A single static water level reading |
98
- | `ConstantRateEvent` | A constant-rate pumping test |
99
- | `StepDrawdownEvent` | A step-drawdown pumping test |
100
- | `AirliftEvent` | An air-lift development or test |
101
- | `RecoveryOnlyEvent` | Recovery measurements without drawdown data |
102
- | `HydrodynamicEvent` | Discriminated union of all event types + x- custom events |
103
- | `AquiferAnalysis` | An interpreted set of aquifer parameters |
104
- | `Attachment` | An HTTPS-referenced file attached to a history log entry |
105
- | `HistoryLogEntry` | One entry in the operational history log |
106
- | `Units` | `{ length: 'm' \| 'ft'; diameter: 'mm' \| 'inches' }` |
107
- | `LengthUnits` | `'m' \| 'ft'` |
108
- | `DiameterUnits` | `'mm' \| 'inches'` |
109
- | `UnitsTypes` | `'metric' \| 'imperial'` |
110
- | `TextureType` | `{ code: TextureCode; label: string }` — a single FGDC texture entry (lookup) |
111
- | `TextureCode` | `number \| string` — numeric FGDC code or custom string code |
78
+ | Type | Description |
79
+ | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
80
+ | `Well` | Complete static record of a water well (v2) |
81
+ | `BoreHole` | A drilled interval with diameter and optional drilling method |
82
+ | `WellCase` | Steel or plastic casing installed in the borehole |
83
+ | `Reduction` | Transition piece between different casing diameters |
84
+ | `WellScreen` | Slotted screen section for water intake (`screen_slot` in mm) |
85
+ | `WellStatus` | Closed `status_change` vocabulary: `active`, `maintenance`, `inactive`, `decommissioned`, `abandoned` (v2.3) |
86
+ | `SurfaceCase` | Protective casing near the surface |
87
+ | `HoleFill` | Annular fill material (`gravel_pack` or `seal`) |
88
+ | `CementPad` | Concrete wellhead pad dimensions |
89
+ | `Centralizer` | Casing/screen centralizers over a depth interval with spacing (v2.1) |
90
+ | `Lithology` | Geological description of a depth interval |
91
+ | `Texture` | `{ code: string \| number; vocabulary?: string }` — lithology texture reference |
92
+ | `Fracture` | A discrete fracture or fracture zone |
93
+ | `Cave` | A cavity or void zone |
94
+ | `Constructive` | Grouped type: borehole + casings + screens + fills |
95
+ | `Geologic` | Grouped type: lithology + fractures + caves |
96
+ | `WellId` | Authority-scoped well identifier `{ authority, id, primary? }` |
97
+ | `Location` | Geographic location with optional elevation and CRS properties |
98
+ | `LocationProperties` | CRS, datum, and precision metadata for a `Location` |
99
+ | `LevelReading` | A single depth/time reading during a pumping or recovery phase |
100
+ | `RecoveryPhase` | Time-series of level readings after pump shutdown |
101
+ | `PumpingStep` | One flow-rate step in a pumping test |
102
+ | `HydrodynamicEventBase` | Common fields shared by all hydrodynamic event types |
103
+ | `SpotMeasurementEvent` | A single static water level reading |
104
+ | `ConstantRateEvent` | A constant-rate pumping test |
105
+ | `StepDrawdownEvent` | A step-drawdown pumping test |
106
+ | `AirliftEvent` | An air-lift development or test |
107
+ | `RecoveryOnlyEvent` | Recovery measurements without drawdown data |
108
+ | `HydrodynamicEvent` | Discriminated union of all event types + x- custom events |
109
+ | `AquiferAnalysis` | An interpreted set of aquifer parameters |
110
+ | `Attachment` | An HTTPS-referenced document, typed by `document_type` (common type since v2.3) |
111
+ | `PumpInstallation` | One installation of a pump in the well (v2.3) |
112
+ | `PumpElectrical` | Electrical data of a pump installation (v2.3) |
113
+ | `Permit` | A legal instrument governing abstraction — outorga, dispensa, cadastro (v2.3) |
114
+ | `PermitAdministrativeStatus` | `'requested' \| 'granted' \| 'suspended' \| 'revoked' \| 'denied' \| 'withdrawn'` (v2.3) |
115
+ | `PermitHistoryEntry` | One administrative step of a permit: filing, process, notification, fee (v2.3) |
116
+ | `PermitCondition` | An obligation (condicionante) of a permit, with derived deadlines and its `fulfillments` (v2.3) |
117
+ | `ConditionFulfillment` | The record of one condition deadline being met (v2.3) |
118
+ | `VolumeLimit` | A volume stated in a permit for a daily, monthly or annual period (v2.3) |
119
+ | `MonthlyGrant` | One month of a permit's month-by-month grant (v2.3) |
120
+ | `Meter` | One installation of a totalizer (hidrômetro) in the well (v2.3) |
121
+ | `ProductionEntryBase` | Common fields of every `production` ledger entry (v2.3) |
122
+ | `MeterReading` | A totalizer register value in m³ (`type: 'meter_reading'`) (v2.3) |
123
+ | `EstimatedVolume` | A volume estimated for a period, without a meter (`type: 'estimated_volume'`) (v2.3) |
124
+ | `ProductionEntry` | `MeterReading \| EstimatedVolume` — one entry of the `production` ledger (v2.3) |
125
+ | `OperatingRegime` | Declared flow rate, daily operating time and days per week from `effective_from` (v2.3) |
126
+ | `WaterSample` | One water sample and its results; `water_samples` is a ledger corrected with `corrects` (v2.3) |
127
+ | `SamplingPoint` | Where the sample was taken: `type`, point `depth` or `from`/`to` interval, `device`, `pump_installation_id` (v2.3) |
128
+ | `Purge` | Purge before collection: duration, volume, flow rate, stabilization and readings (v2.3) |
129
+ | `PurgeReading` | One stabilization reading during the purge (v2.3) |
130
+ | `Laboratory` | Laboratory, accreditation, report number, batch, receipt instant and temperature (v2.3) |
131
+ | `WaterQualityResult` | One result: exactly one of `value`, `presence` or `text`, plus qualifier, limits, fraction, validation (v2.3) |
132
+ | `ResultQualifier` | `'<' \| '>' \| 'not_detected' \| 'estimated'` (v2.3) |
133
+ | `Parameter` | `{ code; vocabulary }` — `welldot`, `cas` or `x-…` parameter identity (v2.3) |
134
+ | `Filtration` | Filter `pore_size` (µm) and `location` (`field` \| `lab`) (v2.3) |
135
+ | `ResultValidation` | Reviewer validation: `status` (`unvalidated`, `validated`, `qualified`, `rejected`), qualifier, guideline (v2.3) |
136
+ | `TimeResolution` | `'day'` — marks an instant known only by its date (`*_resolution` fields) (v2.3) |
137
+ | `HistoryLogEntry` | One entry in the operational history log (incl. `maintenance` and `status_change` fields, and `hydrodynamic_event_ids` / `sample_ids` links) |
138
+ | `Units` | `{ length; diameter; flow?; power?; volume? }` — display/input unit preferences |
139
+ | `LengthUnits` | `'m' \| 'ft'` |
140
+ | `DiameterUnits` | `'mm' \| 'inches'` |
141
+ | `FlowUnits` | `'m3/h' \| 'L/s' \| 'gpm'` |
142
+ | `PowerUnits` | `'kW' \| 'cv' \| 'hp'` |
143
+ | `VolumeUnits` | `'m3' \| 'L' \| 'ft3' \| 'gal'` (`gal` is the US gallon) |
144
+ | `UnitsTypes` | `'metric' \| 'imperial'` |
145
+ | `TextureType` | `{ code: TextureCode; label: string }` — a single FGDC texture entry (lookup) |
146
+ | `TextureCode` | `number \| string` — numeric FGDC code or custom string code |
147
+ | `SectionKey` | Section of a well for share visibility / redaction (includes `'water_quality'` since v2.3) |
148
+ | `ParameterDefinition` | One vocabulary entry: code, group, EN label, translations, unit, value form, CAS, molar mass, charge (v2.3) |
149
+ | `ParameterGroup` | Vocabulary group (`physical`, `major_ion`, `metal`, `microbiology`, …) (v2.3) |
150
+ | `ParameterForm` | `'value' \| 'presence' \| 'text'` (v2.3) |
151
+ | `ParameterUnit` | `{ symbol; ucum? }` — canonical unit of a parameter (v2.3) |
152
+ | `LimitSet`, `Limit`, `LimitBasis` | A jurisdiction limit set and its per-code limits (v2.3) |
153
+ | `ConcentrationUnits` | `'mg/L' \| 'ug/L' \| 'ng/L' \| 'g/L'` (v2.3) |
112
154
 
113
155
  ### Validators
114
156
 
115
157
  Each schema validates its corresponding type at runtime. All schemas are Zod objects and compose with standard Zod methods (`.parse`, `.safeParse`, `.extend`, etc.).
116
158
 
117
- | Export | Validates |
118
- | ----------------------------- | ----------------------------------------------------------------------- |
119
- | `WellSchema` | `Well` (the complete document; `.passthrough()` preserves unknown keys) |
120
- | `BoreHoleSchema` | `BoreHole` |
121
- | `WellCaseSchema` | `WellCase` |
122
- | `ReductionSchema` | `Reduction` |
123
- | `WellScreenSchema` | `WellScreen` |
124
- | `SurfaceCaseSchema` | `SurfaceCase` |
125
- | `HoleFillSchema` | `HoleFill` |
126
- | `CementPadSchema` | `CementPad` |
127
- | `CentralizerSchema` | `Centralizer` |
128
- | `LithologySchema` | `Lithology` |
129
- | `TextureSchema` | `Texture` |
130
- | `FractureSchema` | `Fracture` |
131
- | `CaveSchema` | `Cave` |
132
- | `WellIdSchema` | `WellId` |
133
- | `LocationPropertiesSchema` | `LocationProperties` |
134
- | `LocationSchema` | `Location` |
135
- | `LevelReadingSchema` | `LevelReading` |
136
- | `RecoveryPhaseSchema` | `RecoveryPhase` |
137
- | `PumpingStepSchema` | `PumpingStep` |
138
- | `HydrodynamicEventBaseSchema` | `HydrodynamicEventBase` |
139
- | `SpotMeasurementEventSchema` | `SpotMeasurementEvent` |
140
- | `ConstantRateEventSchema` | `ConstantRateEvent` |
141
- | `StepDrawdownEventSchema` | `StepDrawdownEvent` |
142
- | `AirliftEventSchema` | `AirliftEvent` |
143
- | `RecoveryOnlyEventSchema` | `RecoveryOnlyEvent` |
144
- | `HydrodynamicEventSchema` | `HydrodynamicEvent` (discriminated union + x- passthrough) |
145
- | `AquiferAnalysisSchema` | `AquiferAnalysis` |
146
- | `AttachmentSchema` | `Attachment` |
147
- | `HistoryLogEntrySchema` | `HistoryLogEntry` |
159
+ | Export | Validates |
160
+ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
161
+ | `WellSchema` | `Well` (the complete document; `.passthrough()` preserves unknown keys) |
162
+ | `BoreHoleSchema` | `BoreHole` |
163
+ | `WellCaseSchema` | `WellCase` |
164
+ | `ReductionSchema` | `Reduction` |
165
+ | `WellScreenSchema` | `WellScreen` |
166
+ | `WellStatusSchema` | `WellStatus` (z.enum — any other value is rejected) |
167
+ | `SurfaceCaseSchema` | `SurfaceCase` |
168
+ | `HoleFillSchema` | `HoleFill` |
169
+ | `CementPadSchema` | `CementPad` |
170
+ | `CentralizerSchema` | `Centralizer` |
171
+ | `LithologySchema` | `Lithology` |
172
+ | `TextureSchema` | `Texture` |
173
+ | `FractureSchema` | `Fracture` |
174
+ | `CaveSchema` | `Cave` |
175
+ | `WellIdSchema` | `WellId` |
176
+ | `LocationPropertiesSchema` | `LocationProperties` |
177
+ | `LocationSchema` | `Location` |
178
+ | `LevelReadingSchema` | `LevelReading` |
179
+ | `RecoveryPhaseSchema` | `RecoveryPhase` |
180
+ | `PumpingStepSchema` | `PumpingStep` |
181
+ | `HydrodynamicEventBaseSchema` | `HydrodynamicEventBase` |
182
+ | `SpotMeasurementEventSchema` | `SpotMeasurementEvent` |
183
+ | `ConstantRateEventSchema` | `ConstantRateEvent` |
184
+ | `StepDrawdownEventSchema` | `StepDrawdownEvent` |
185
+ | `AirliftEventSchema` | `AirliftEvent` |
186
+ | `RecoveryOnlyEventSchema` | `RecoveryOnlyEvent` |
187
+ | `HydrodynamicEventSchema` | `HydrodynamicEvent` (discriminated union + x- passthrough) |
188
+ | `AquiferAnalysisSchema` | `AquiferAnalysis` |
189
+ | `AttachmentSchema` | `Attachment` |
190
+ | `PumpInstallationSchema` | `PumpInstallation` |
191
+ | `PumpElectricalSchema` | `PumpElectrical` |
192
+ | `PermitSchema` | `Permit` |
193
+ | `PermitConditionSchema` | `PermitCondition` |
194
+ | `ConditionFulfillmentSchema` | `ConditionFulfillment` |
195
+ | `PermitHistoryEntrySchema` | `PermitHistoryEntry` |
196
+ | `PermitAdministrativeStatusSchema` | `PermitAdministrativeStatus` |
197
+ | `VolumeLimitSchema` | `VolumeLimit` |
198
+ | `MonthlyGrantSchema` | `MonthlyGrant` |
199
+ | `MeterSchema` | `Meter` (`max_reading` > 0) |
200
+ | `ProductionEntryBaseSchema` | `ProductionEntryBase` |
201
+ | `MeterReadingSchema` | `MeterReading` |
202
+ | `EstimatedVolumeSchema` | `EstimatedVolume` |
203
+ | `ProductionEntrySchema` | `ProductionEntry` (discriminated union + x- passthrough; a known type missing required fields is rejected) |
204
+ | `OperatingRegimeSchema` | `OperatingRegime` (`daily_operating_time` 0–24, integer `days_per_week` 1–7) |
205
+ | `HistoryLogEntrySchema` | `HistoryLogEntry` |
206
+ | `WaterSampleSchema` | `WaterSample` (`results` must have at least one entry) |
207
+ | `SamplingPointSchema` | `SamplingPoint` (`depth` and `from`/`to` are mutually exclusive) |
208
+ | `PurgeSchema` | `Purge` |
209
+ | `PurgeReadingSchema` | `PurgeReading` |
210
+ | `LaboratorySchema` | `Laboratory` |
211
+ | `WaterQualityResultSchema` | `WaterQualityResult` (exactly one value form except `not_detected`; `<`/`>`/`estimated` need `value`; `unit` required for `x-` and forbidden for `welldot`/`cas`) |
212
+ | `ResultQualifierSchema` | `ResultQualifier` (z.enum) |
213
+ | `ParameterSchema` | `Parameter` (`vocabulary` must be `welldot`, `cas` or `x-…`) |
214
+ | `FiltrationSchema` | `Filtration` |
215
+ | `ResultValidationSchema` | `ResultValidation` (closed `status` enum) |
216
+ | `TimeResolutionSchema` | `TimeResolution` (`z.literal('day')`) |
148
217
 
149
218
  ### Functions
150
219
 
@@ -172,6 +241,140 @@ Returns `null` if the parsed data is empty. Throws on unrecognized version numbe
172
241
 
173
242
  Returns `true` when all constructive and geologic arrays are empty. Accepts `null` and `undefined` (both treated as empty).
174
243
 
244
+ #### `calculatedWellDepth(well: Well): number`
245
+
246
+ Deepest `to` across the constructive arrays (bore hole, casings, screens, reductions, hole fill), ignoring geology. `0` without constructive data. Used as the fallback for a missing `well_depth`.
247
+
248
+ #### `redactWell(well: Well, visibility: WellVisibility): Well`
249
+
250
+ Copy of `well` with hidden parts emptied (arrays become `[]`, optional fields are removed), so the result stays schema-valid. `visibility` keys are the 7 `SECTION_KEYS` and/or the fields of `VISIBILITY_TREE` (e.g. `meters`, `permits`, `location`); `false` hides, missing keys are visible, and a hidden section hides all its fields. `VISIBILITY_LEAF_KEYS` lists the finest toggles. References from visible records to hidden ones are left as-is.
251
+
252
+ ```typescript
253
+ redactWell(well, { operation: false }); // whole section
254
+ redactWell(well, { meters: false, location: false }); // single fields
255
+ ```
256
+
257
+ #### Unit conversion
258
+
259
+ `.well` files always store canonical SI units; these helpers convert for display and input.
260
+
261
+ | Quantity | Functions |
262
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
263
+ | Length | `metersToFeet`, `feetToMeters` |
264
+ | Diameter | `mmToInches`, `inchesToMm`, `slotNumberToMm`, `mmToSlotNumber` |
265
+ | Flow | `cubicMeterPerHourToLitersPerSecond`, `litersPerSecondToCubicMeterPerHour`, `cubicMeterPerHourToUsGallonsPerMinute`, `usGallonsPerMinuteToCubicMeterPerHour`, `flowFromCanonical`, `flowToCanonical` |
266
+ | Power | `cvToKilowatts`, `kilowattsToCv`, `hpToKilowatts`, `kilowattsToHp`, `powerFromCanonical`, `powerToCanonical` |
267
+ | Volume | `litersToCubicMeters`, `cubicMetersToLiters`, `cubicMetersToCubicFeet`, `cubicFeetToCubicMeters`, `cubicMetersToUsGallons`, `usGallonsToCubicMeters`, `volumeFromCanonical`, `volumeToCanonical` |
268
+ | Time | `minutesToHours`, `hoursToMinutes` |
269
+ | Pressure | `kilopascalToPsi`, `psiToKilopascal` |
270
+ | Transmissivity | `squareMeterPerSecondToSquareMeterPerDay`, `squareMeterPerDayToSquareMeterPerSecond` |
271
+ | Coordinates | `decimalDegreesToDms`, `dmsToDecimalDegrees` (`DmsCoordinate`) |
272
+ | Concentration | `concentrationToCanonical`, `concentrationFromCanonical` (`ConcentrationUnits`: mg/L, µg/L, ng/L, g/L ↔ canonical mg/L) (v2.3) |
273
+ | Conductivity | `milliSiemensPerMeterToMicroSiemensPerCm` (×10), `milliSiemensPerCmToMicroSiemensPerCm` (×1000) (v2.3) |
274
+ | Lab report import | `turbidityCodeForUnit` (NTU/FNU/FAU/FTU/uT → turbidity code), `normalizeColorUnit` (mg Pt-Co/L, PCU, TCU → `uH`), `expandedToStandardUncertainty` (U / k → one-sigma `value_precision`) (v2.3) |
275
+
276
+ `*FromCanonical(value, unit)` converts from the canonical unit (m³/h, kW, m³) to the given display unit; `*ToCanonical(value, unit)` converts back.
277
+
278
+ ## Water Quality Vocabulary and Limit Sets _(v2.3)_
279
+
280
+ The `welldot` water quality parameter vocabulary is published as versioned data. Each `ParameterDefinition` carries the code, group, canonical English label, translations (`labels.pt`), canonical unit (display symbol and UCUM code), value form (`value`, `presence` or `text`), the CAS equivalence when one exists, and molar mass and charge for ions used in ion balance and hydrochemical diagrams.
281
+
282
+ | Export | Description |
283
+ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
284
+ | `WATER_QUALITY_PARAMETERS` | The 98 `welldot` parameter definitions |
285
+ | `WATER_QUALITY_VOCABULARY_VERSION` | Version of the published vocabulary |
286
+ | `WATER_QUALITY_UNITS` | Canonical units used by the vocabulary (`mg/L`, `µS/cm`, `°C`, `mV`, NTU/FNU/FAU/FTU, `uH`, MPN/CFU counts, `Bq/L`) |
287
+ | `getParameterDefinition(param)` | Looks up a `{ code, vocabulary }`; a `cas` code resolves through the published equivalences to its `welldot` entry |
288
+ | `parameterKey(param)` | Canonical identity — a `welldot` code and its CAS equivalent produce the same key (duplicate detection, grouping) |
289
+ | `isKnownParameter(param)` | `false` only for a `welldot` code unknown to this vocabulary version (`cas` and `x-` are always accepted) |
290
+ | `WHO_GDWQ_2022` | WHO Guidelines for Drinking-water Quality (2022) |
291
+ | `BR_GM_MS_888_2021` | Brasil — Portaria GM/MS 888/2021 |
292
+ | `EU_2020_2184` | EU Drinking Water Directive 2020/2184 |
293
+ | `WATER_QUALITY_LIMIT_SETS` | All bundled limit sets, in display order |
294
+ | `getLimitSet(id)` | Finds a bundled limit set by `id` (`who_gdwq_2022`, `br_gm_ms_888_2021`, `eu_2020_2184`) |
295
+ | `NEPHELOMETRIC_TURBIDITY_CODES` | `turbidity`, `turbidity_ntu`, `turbidity_fnu` — compared with nephelometric limits; `turbidity_fau` never is |
296
+
297
+ ```typescript
298
+ import {
299
+ getLimitSet,
300
+ getParameterDefinition,
301
+ parameterKey,
302
+ } from '@welldot/core';
303
+
304
+ getParameterDefinition({ code: '14808-79-8', vocabulary: 'cas' })?.code; // 'sulfate'
305
+ parameterKey({ code: 'sulfate', vocabulary: 'welldot' }); // 'sulfate'
306
+ getLimitSet('who_gdwq_2022')?.limits.find(l => l.code === 'arsenic');
307
+ ```
308
+
309
+ Limits are never written to `.well` files (jurisdiction neutrality): consumers pick a set at display time and compare results with the derivation helpers of `@welldot/utils`. **The bundled limit values are transcribed from the cited sources and must be verified against the official documents before any regulatory use.**
310
+
311
+ ## Recommended Vocabularies _(v2.3)_
312
+
313
+ Many `.well` string fields are **open**: any value (or an `x-` extension) is valid, but the spec recommends a vocabulary. Each one is exported as data, with display labels keyed by BCP 47 language tag (`en` and `pt` always present). Field types use `OpenVocab<T>` (`T | (string & {})`), so the recommended values autocomplete while any string still type-checks.
314
+
315
+ | Vocabulary | Field |
316
+ | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
317
+ | `WELL_TYPES` | `well_type` (`artesian` is `deprecated`) |
318
+ | `WELL_PURPOSES` | `well_purpose[]` |
319
+ | `DRILLING_METHODS` | `bore_hole[].drilling_method` |
320
+ | `CONSTRUCTION_MATERIALS` | `well_case[].type`, `well_screen[].type`, `reduction[].type`, `pump_installations[].riser_material` |
321
+ | `SCREEN_SLOT_TYPES` | `well_screen[].slot_type` |
322
+ | `CENTRALIZER_TYPES` | `centralizers[].type` |
323
+ | `CEMENT_PAD_TYPES` | `cement_pad.type` |
324
+ | `PUMP_TYPES`, `POWER_SOURCES` | `pump_installations[].type`, `.power_source` |
325
+ | `METER_TYPES` | `meters[].type` |
326
+ | `READING_SOURCES`, `ESTIMATION_METHODS` | `production[].source`, `production[].method` |
327
+ | `PERMIT_TYPES`, `WATER_USES` | `permits[].type`, `permits[].water_use[]` |
328
+ | `CONDITION_CATEGORIES` | `permits[].conditions[].category` |
329
+ | `PERMIT_HISTORY_TYPES` | `permits[].history[].type` |
330
+ | `HISTORY_LOG_CATEGORIES`, `HISTORY_LOG_SEVERITIES`, `MAINTENANCE_TYPES` | `history_logs[].category`, `.severity`, `.maintenance_type` |
331
+ | `HYDRODYNAMIC_EVENT_TYPES`, `MEASUREMENT_METHODS` | `hydrodynamic_events[].type`, `.measurement_method` |
332
+ | `AQUIFER_ANALYSIS_METHODS` | `aquifer_analysis[].method` |
333
+ | `DOCUMENT_TYPES`, `DOCUMENT_TYPE_SUGGESTIONS` | `attachments[].document_type` (and per-context suggestion order) |
334
+ | `SAMPLE_TYPES`, `SAMPLING_METHODS`, `SAMPLING_POINT_TYPES`, `SAMPLING_DEVICES` | `water_samples[]` sampling fields |
335
+
336
+ Labels are `LanguageText<'en' | 'pt'>`. `LanguageText<L>` is the general localized-text type (`Record<string, string>` keyed by BCP 47 tag), where `L` lists the tags that must be present — `LanguageText` alone requires none. `LanguageTextInput` adds the plain-string, JSON-string and `null`/`undefined` forms accepted by `resolveLanguageText`.
337
+
338
+ | Helper | Description |
339
+ | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
340
+ | `getVocabLabel(vocab, value, locale)` | Label in `locale` (`pt-BR` → `pt` → `en`); free-text and `x-` values are returned as-is |
341
+ | `resolveLanguageText(text, locale)` | Resolves a `LanguageTextInput` with the same fallback: a `LanguageText` object, a plain string (returned as-is), a JSON object string (parsed; malformed JSON stays a plain string) or `null`/`undefined` (`''`); empty labels count as missing |
342
+ | `getVocabEntry` / `isVocabValue` | Looks up a value's entry / checks whether it is recommended |
343
+ | `vocabValues(vocab, { includeDeprecated })` | The recommended values, deprecated ones left out by default |
344
+ | `formatVocabList(vocab, values, locale)` | Comma-separated labels of a multi-valued field (e.g. `well_purpose`), unknown values kept as-is |
345
+
346
+ ```typescript
347
+ import {
348
+ CONSTRUCTION_MATERIALS,
349
+ PERMIT_TYPES,
350
+ getVocabLabel,
351
+ type OpenVocab,
352
+ type PermitType,
353
+ } from '@welldot/core';
354
+
355
+ const type: OpenVocab<PermitType> = 'abstraction_permit'; // or any string
356
+ getVocabLabel(PERMIT_TYPES, type, 'pt'); // 'Outorga de direito de uso'
357
+ getVocabLabel(PERMIT_TYPES, 'x-special', 'pt'); // 'x-special'
358
+ ```
359
+
360
+ ### Closed vocabularies
361
+
362
+ Fields whose values the schema fixes (no free text, no `x-`) ship in the same shape as the open vocabularies — `VocabEntry` lists with `en`/`pt` labels — so `getVocabLabel` labels any value without consumer translations. Each list is checked at compile time against its type, so it cannot drift from the schema. The `*_VALUES` lists are the bare values.
363
+
364
+ | Vocabulary | Field |
365
+ | -------------------------------------------------- | --------------------------------------------- |
366
+ | `WELL_STATUSES` (`WELL_STATUS_VALUES`) | `history_logs[].status` (`status_change`) |
367
+ | `PERMIT_ADMINISTRATIVE_STATUSES` | `permits[].status` |
368
+ | `VOLUME_LIMIT_PERIODS` | `permits[].volume_limits[].period` |
369
+ | `PRODUCTION_ENTRY_TYPES` | `production[].type` |
370
+ | `RESULT_QUALIFIERS` (`QUALIFIER_VALUES`) | result `qualifier` |
371
+ | `RESULT_FRACTIONS` (`FRACTION_VALUES`) | result `fraction` |
372
+ | `MEASUREMENT_LOCATIONS` | result `measured_in`, `filtration.location` |
373
+ | `VALIDATION_STATUSES` (`VALIDATION_STATUS_VALUES`) | result `validation.status` |
374
+ | `PARAMETER_GROUPS` (`PARAMETER_GROUP_VALUES`) | parameter vocabulary groups, in display order |
375
+
376
+ Value rules without labels: `NUMERIC_QUALIFIERS`, `PARENT_SAMPLE_TYPES`, `BLANK_SAMPLE_TYPES`. Parameter names: `getParameterLabel(parameter, locale)` (CAS numbers resolve through the published equivalences; unknown codes are returned as-is).
377
+
175
378
  ## FGDC Texture Patterns
176
379
 
177
380
  `FGDC_TEXTURES_OPTIONS` is a typed array of 284 texture pattern entries drawn from the **FGDC Digital Cartographic Standard for Geologic Map Symbolization (FGDC-STD-013-2006)**. Assign a `code` to the `texture` field of a `Lithology` record to attach a standardized fill pattern to a depth interval.