@welldot/core 0.4.0-next.20261015.d7c7365 → 0.5.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.
Files changed (36) hide show
  1. package/README.md +59 -19
  2. package/dist/index.cjs +344 -178
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +9203 -5704
  5. package/dist/index.d.ts +9203 -5704
  6. package/dist/index.js +334 -178
  7. package/dist/index.js.map +1 -1
  8. package/docs/reference/fgdc-textures.md +15 -0
  9. package/docs/schema/v2/well.schema.json +128 -11
  10. package/docs/spec/v1/well-format.md +26 -0
  11. package/docs/spec/v2/format-reference.md +170 -45
  12. package/docs/spec/v2/interoperability.md +25 -4
  13. package/docs/spec/v2/object-schemas.md +243 -96
  14. package/docs/spec/v2/overview.md +92 -9
  15. package/docs/spec/v2/water-quality.md +26 -3
  16. package/examples/README.md +12 -0
  17. package/examples/belem-pa-condominio-outorga.well +2 -1
  18. package/examples/belem-pa-monitoramento-posto.well +2 -1
  19. package/examples/belem-pa-pirabas-abastecimento.well +2 -2
  20. package/examples/belem-pa-poco-colmatado.well +2 -1
  21. package/examples/belem-pa-poco-raso-abandonado.well +2 -1
  22. package/examples/belem-pa-qualidade-agua-acida.well +2 -1
  23. package/examples/colatina-es-gnaisse-rural.well +2 -2
  24. package/examples/coluna-mg-cristalino-abastecimento.well +2 -2
  25. package/examples/estrela-doeste-sp-bauru-serra-geral.well +2 -1
  26. package/examples/extremoz-rn-barreiras-raso.well +2 -1
  27. package/examples/gastao-vidigal-sp-dados-inconsistentes.well +2 -1
  28. package/examples/irece-ba-carste-bambui.well +2 -1
  29. package/examples/lagoa-santa-mg-carste-abastecimento.well +2 -2
  30. package/examples/minas-novas-mg-cadastro-incompleto.well +2 -1
  31. package/examples/quixeramobim-ce-cristalino-salobro.well +2 -2
  32. package/examples/rinopolis-sp-estratigrafico-guarani.well +2 -1
  33. package/examples/santarem-pa-jorrante-alter-do-chao.well +2 -1
  34. package/examples/sao-gabriel-rs-cacimba.well +2 -1
  35. package/examples/sete-lagoas-mg-carste-industrial.well +2 -1
  36. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,215 @@
1
1
  // src/validators/well.validators.ts
2
2
  import { createDefu } from "defu";
3
3
  import { z } from "zod";
4
+
5
+ // src/utils/timezone.utils.ts
6
+ var IANA_SHAPE = /^[A-Za-z][A-Za-z0-9_+\-/]*$/;
7
+ function isIanaTimeZone(value) {
8
+ if (!IANA_SHAPE.test(value)) return false;
9
+ try {
10
+ new Intl.DateTimeFormat("en-US", { timeZone: value });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ }
16
+
17
+ // src/utils/version.utils.ts
18
+ var WELL_FORMAT_VERSION = "2.4";
19
+ var VERSION_PATTERN = /^(\d+)\.(\d+)$/;
20
+ function parseFormatVersion(value) {
21
+ if (typeof value === "number") {
22
+ return Number.isInteger(value) && value >= 0 ? { major: value, minor: void 0 } : void 0;
23
+ }
24
+ if (typeof value === "string") {
25
+ const match = VERSION_PATTERN.exec(value);
26
+ if (match) return { major: Number(match[1]), minor: Number(match[2]) };
27
+ }
28
+ return void 0;
29
+ }
30
+ function compareFormatVersions(a, b) {
31
+ const pa = parseFormatVersion(a);
32
+ const pb = parseFormatVersion(b);
33
+ if (!pa || pb === void 0 || pa.minor === void 0 || pb.minor === void 0) {
34
+ throw new Error(
35
+ `Malformed .well format version: ${JSON.stringify(pa?.minor === void 0 ? a : b)}`
36
+ );
37
+ }
38
+ return pa.major - pb.major || pa.minor - pb.minor;
39
+ }
40
+
41
+ // src/vocab/closed.vocab.ts
42
+ function closedVocab() {
43
+ return (entries) => entries;
44
+ }
45
+ var valuesOf = (vocab) => vocab.map((entry) => entry.value);
46
+ var WELL_STATUSES = closedVocab()([
47
+ { value: "active", label: { en: "Active", pt: "Ativo" } },
48
+ {
49
+ value: "maintenance",
50
+ label: { en: "Under maintenance", pt: "Em manuten\xE7\xE3o" }
51
+ },
52
+ { value: "inactive", label: { en: "Inactive", pt: "Paralisado" } },
53
+ {
54
+ value: "decommissioned",
55
+ label: { en: "Decommissioned", pt: "Desativado" }
56
+ },
57
+ { value: "abandoned", label: { en: "Abandoned", pt: "Abandonado" } }
58
+ ]);
59
+ var PERMIT_ADMINISTRATIVE_STATUSES = closedVocab()([
60
+ { value: "requested", label: { en: "Requested", pt: "Requerida" } },
61
+ { value: "granted", label: { en: "Granted", pt: "Concedida" } },
62
+ { value: "suspended", label: { en: "Suspended", pt: "Suspensa" } },
63
+ { value: "revoked", label: { en: "Revoked", pt: "Revogada" } },
64
+ { value: "denied", label: { en: "Denied", pt: "Indeferida" } },
65
+ { value: "withdrawn", label: { en: "Withdrawn", pt: "Cancelada" } }
66
+ ]);
67
+ var VOLUME_LIMIT_PERIODS = closedVocab()([
68
+ { value: "daily", label: { en: "Daily", pt: "Di\xE1rio" } },
69
+ { value: "monthly", label: { en: "Monthly", pt: "Mensal" } },
70
+ { value: "annual", label: { en: "Annual", pt: "Anual" } }
71
+ ]);
72
+ var PRODUCTION_ENTRY_TYPES = closedVocab()([
73
+ {
74
+ value: "meter_reading",
75
+ label: { en: "Meter reading", pt: "Leitura de hidr\xF4metro" }
76
+ },
77
+ {
78
+ value: "estimated_volume",
79
+ label: { en: "Estimated volume", pt: "Volume estimado" }
80
+ }
81
+ ]);
82
+ var RESULT_QUALIFIERS = closedVocab()([
83
+ { value: "<", label: { en: "< less than", pt: "< menor que" } },
84
+ { value: ">", label: { en: "> greater than", pt: "> maior que" } },
85
+ { value: "not_detected", label: { en: "Not detected", pt: "N\xE3o detectado" } },
86
+ { value: "estimated", label: { en: "Estimated", pt: "Estimado" } }
87
+ ]);
88
+ var RESULT_FRACTIONS = closedVocab()([
89
+ { value: "total", label: { en: "Total", pt: "Total" } },
90
+ { value: "dissolved", label: { en: "Dissolved", pt: "Dissolvida" } },
91
+ { value: "suspended", label: { en: "Suspended", pt: "Suspensa" } }
92
+ ]);
93
+ var MEASUREMENT_LOCATIONS = closedVocab()([
94
+ { value: "field", label: { en: "Field", pt: "Campo" } },
95
+ { value: "lab", label: { en: "Lab", pt: "Laborat\xF3rio" } }
96
+ ]);
97
+ var VALIDATION_STATUSES = closedVocab()([
98
+ { value: "unvalidated", label: { en: "Unvalidated", pt: "N\xE3o validado" } },
99
+ { value: "validated", label: { en: "Validated", pt: "Validado" } },
100
+ { value: "qualified", label: { en: "Qualified", pt: "Qualificado" } },
101
+ { value: "rejected", label: { en: "Rejected", pt: "Rejeitado" } }
102
+ ]);
103
+ var PARAMETER_GROUPS = closedVocab()([
104
+ {
105
+ value: "physical",
106
+ label: { en: "Physical / field", pt: "F\xEDsico / campo" }
107
+ },
108
+ { value: "aggregate", label: { en: "Aggregate", pt: "Agregados" } },
109
+ { value: "major_ion", label: { en: "Major ions", pt: "\xCDons maiores" } },
110
+ { value: "nutrient", label: { en: "Nutrients", pt: "Nutrientes" } },
111
+ { value: "organic", label: { en: "Organic", pt: "Org\xE2nicos" } },
112
+ { value: "disinfection", label: { en: "Disinfection", pt: "Desinfec\xE7\xE3o" } },
113
+ {
114
+ value: "mining_redox",
115
+ label: { en: "Mining and redox", pt: "Minera\xE7\xE3o e redox" }
116
+ },
117
+ { value: "metal", label: { en: "Metals / trace", pt: "Metais / tra\xE7o" } },
118
+ { value: "microbiology", label: { en: "Microbiology", pt: "Microbiologia" } },
119
+ {
120
+ value: "radioactivity",
121
+ label: { en: "Radioactivity", pt: "Radioatividade" }
122
+ }
123
+ ]);
124
+ var BAROMETRIC_COMPENSATIONS = closedVocab()([
125
+ { value: "barologger", label: { en: "Barologger", pt: "Barologger" } },
126
+ { value: "vented", label: { en: "Vented cable", pt: "Cabo ventilado" } },
127
+ { value: "none", label: { en: "None", pt: "Nenhuma" } }
128
+ ]);
129
+ var READING_AGGREGATIONS = closedVocab()([
130
+ { value: "none", label: { en: "Raw readings", pt: "Leituras brutas" } },
131
+ { value: "hourly", label: { en: "Hourly", pt: "Hor\xE1ria" } },
132
+ { value: "daily", label: { en: "Daily", pt: "Di\xE1ria" } }
133
+ ]);
134
+ var WELL_STATUS_VALUES = valuesOf(WELL_STATUSES);
135
+ var PERMIT_ADMINISTRATIVE_STATUS_VALUES = valuesOf(
136
+ PERMIT_ADMINISTRATIVE_STATUSES
137
+ );
138
+ var QUALIFIER_VALUES = valuesOf(RESULT_QUALIFIERS);
139
+ var FRACTION_VALUES = valuesOf(RESULT_FRACTIONS);
140
+ var MEASURED_IN_VALUES = valuesOf(MEASUREMENT_LOCATIONS);
141
+ var FILTRATION_LOCATION_VALUES = valuesOf(MEASUREMENT_LOCATIONS);
142
+ var VALIDATION_STATUS_VALUES = valuesOf(VALIDATION_STATUSES);
143
+ var PARAMETER_GROUP_VALUES = valuesOf(PARAMETER_GROUPS);
144
+ var BAROMETRIC_COMPENSATION_VALUES = valuesOf(
145
+ BAROMETRIC_COMPENSATIONS
146
+ );
147
+ var READING_AGGREGATION_VALUES = valuesOf(READING_AGGREGATIONS);
148
+ var NUMERIC_QUALIFIERS = [
149
+ "<",
150
+ ">",
151
+ "estimated"
152
+ ];
153
+ var PARENT_SAMPLE_TYPES = [
154
+ "field_duplicate",
155
+ "split_sample"
156
+ ];
157
+ var BLANK_SAMPLE_TYPES = [
158
+ "field_blank",
159
+ "trip_blank",
160
+ "equipment_blank"
161
+ ];
162
+
163
+ // src/vocab/hydrodynamic.vocab.ts
164
+ var HYDRODYNAMIC_EVENT_TYPES = [
165
+ {
166
+ value: "spot_measurement",
167
+ label: { en: "Spot measurement", pt: "Medi\xE7\xE3o pontual" }
168
+ },
169
+ {
170
+ value: "constant_rate",
171
+ label: { en: "Constant rate", pt: "Vaz\xE3o constante" }
172
+ },
173
+ { value: "step_drawdown", label: { en: "Step drawdown", pt: "Escalonada" } },
174
+ { value: "airlift", label: { en: "Air-lift", pt: "Air-lift" } },
175
+ {
176
+ value: "recovery_only",
177
+ label: { en: "Recovery only", pt: "Recupera\xE7\xE3o" }
178
+ },
179
+ {
180
+ value: "logger_series",
181
+ label: { en: "Logger series", pt: "S\xE9rie de datalogger" }
182
+ }
183
+ ];
184
+ var MEASUREMENT_METHODS = [
185
+ {
186
+ value: "electric_probe",
187
+ label: { en: "Electric probe", pt: "Sonda el\xE9trica" }
188
+ },
189
+ {
190
+ value: "pressure_transducer",
191
+ label: { en: "Pressure transducer", pt: "Transdutor de press\xE3o" }
192
+ },
193
+ { value: "air_line", label: { en: "Air line", pt: "Linha de ar" } },
194
+ { value: "tape", label: { en: "Tape", pt: "Trena" } }
195
+ ];
196
+ var AQUIFER_ANALYSIS_METHODS = [
197
+ { value: "cooper_jacob", label: { en: "Cooper-Jacob", pt: "Cooper-Jacob" } },
198
+ { value: "theis", label: { en: "Theis", pt: "Theis" } },
199
+ { value: "neuman", label: { en: "Neuman", pt: "Neuman" } },
200
+ { value: "hantush", label: { en: "Hantush", pt: "Hantush" } },
201
+ {
202
+ value: "birsoy_summers",
203
+ label: { en: "Birsoy-Summers", pt: "Birsoy-Summers" }
204
+ },
205
+ { value: "eden_hazel", label: { en: "Eden-Hazel", pt: "Eden-Hazel" } },
206
+ {
207
+ value: "visual_inspection",
208
+ label: { en: "Visual inspection", pt: "Inspe\xE7\xE3o visual" }
209
+ }
210
+ ];
211
+
212
+ // src/validators/well.validators.ts
4
213
  var mergeWell = createDefu((obj, key, value) => {
5
214
  if (Array.isArray(value)) {
6
215
  obj[key] = value;
@@ -43,7 +252,8 @@ var LocationPropertiesSchema = z.object({
43
252
  lat_precision: z.number().optional(),
44
253
  lng_precision: z.number().optional(),
45
254
  elevation_precision: z.number().optional(),
46
- original_crs: z.string().optional()
255
+ original_crs: z.string().optional(),
256
+ timezone: z.string().refine(isIanaTimeZone, "timezone must be an IANA time zone name").optional()
47
257
  });
48
258
  var LocationSchema = z.object({
49
259
  lat: z.number(),
@@ -134,6 +344,7 @@ var CaveSchema = z.object({
134
344
  });
135
345
  var LevelReadingSchema = z.object({
136
346
  elapsed: z.number(),
347
+ datetime: rfc3339().optional(),
137
348
  depth: z.number(),
138
349
  depth_precision: z.number().optional(),
139
350
  pressure: z.number().optional()
@@ -163,14 +374,16 @@ var SpotMeasurementEventSchema = HydrodynamicEventBaseSchema.extend({
163
374
  static_level: z.number(),
164
375
  static_level_precision: z.number().optional(),
165
376
  measurement_method: z.string().optional(),
166
- steps: z.array(PumpingStepSchema).max(1).optional(),
377
+ // SHOULD carry at most one step; another count is valid (v2.4).
378
+ steps: z.array(PumpingStepSchema).optional(),
167
379
  recovery: RecoveryPhaseSchema.optional()
168
380
  });
169
381
  var ConstantRateEventSchema = HydrodynamicEventBaseSchema.extend({
170
382
  type: z.literal("constant_rate"),
171
383
  static_level: z.number().optional(),
172
384
  static_level_precision: z.number().optional(),
173
- steps: z.tuple([PumpingStepSchema]).optional(),
385
+ // SHOULD carry exactly one step; another count is valid (v2.4).
386
+ steps: z.array(PumpingStepSchema).optional(),
174
387
  recovery: RecoveryPhaseSchema.optional()
175
388
  });
176
389
  var StepDrawdownEventSchema = HydrodynamicEventBaseSchema.extend({
@@ -191,13 +404,62 @@ var RecoveryOnlyEventSchema = HydrodynamicEventBaseSchema.extend({
191
404
  pumping_duration: z.number().optional(),
192
405
  recovery: RecoveryPhaseSchema
193
406
  });
407
+ var LoggerReadingSchema = z.object({
408
+ datetime: rfc3339(),
409
+ elapsed: z.undefined({ message: "logger_series readings use datetime, not elapsed" }).optional(),
410
+ depth: z.number(),
411
+ depth_precision: z.number().optional(),
412
+ pressure: z.number().optional(),
413
+ depth_min: z.number().optional(),
414
+ depth_max: z.number().optional()
415
+ });
416
+ var closedEnum = (values) => z.enum(values);
417
+ var LoggerSeriesEventSchema = HydrodynamicEventBaseSchema.extend({
418
+ type: z.literal("logger_series"),
419
+ measurement_method: z.string().optional(),
420
+ sensor_depth: z.number().optional(),
421
+ interval: z.number().positive().optional(),
422
+ barometric_compensation: closedEnum(
423
+ BAROMETRIC_COMPENSATION_VALUES
424
+ ).optional(),
425
+ aggregation: closedEnum(READING_AGGREGATION_VALUES).optional(),
426
+ readings: z.array(LoggerReadingSchema).min(1),
427
+ steps: z.undefined({ message: "logger_series carries no steps" }).optional(),
428
+ recovery: z.undefined({ message: "logger_series carries no recovery" }).optional()
429
+ });
430
+ var HYDRODYNAMIC_TYPES = HYDRODYNAMIC_EVENT_TYPES.map(
431
+ (t) => t.value
432
+ );
194
433
  var HydrodynamicEventSchema = z.discriminatedUnion("type", [
195
434
  SpotMeasurementEventSchema,
196
435
  ConstantRateEventSchema,
197
436
  StepDrawdownEventSchema,
198
437
  AirliftEventSchema,
199
- RecoveryOnlyEventSchema
200
- ]).or(HydrodynamicEventBaseSchema.passthrough());
438
+ RecoveryOnlyEventSchema,
439
+ LoggerSeriesEventSchema
440
+ ]).or(
441
+ HydrodynamicEventBaseSchema.passthrough().refine(
442
+ (e) => !HYDRODYNAMIC_TYPES.includes(e.type),
443
+ { message: "malformed hydrodynamic event" }
444
+ )
445
+ ).superRefine((e, ctx) => {
446
+ if (e.type !== "logger_series") return;
447
+ const series = e;
448
+ if (series.aggregation !== "hourly" && series.aggregation !== "daily") {
449
+ return;
450
+ }
451
+ series.readings.forEach((r, i) => {
452
+ for (const key of ["depth_min", "depth_max"]) {
453
+ if (r[key] === void 0) {
454
+ ctx.addIssue({
455
+ code: z.ZodIssueCode.custom,
456
+ path: ["readings", i, key],
457
+ message: `${key} is required in an aggregated logger_series`
458
+ });
459
+ }
460
+ }
461
+ });
462
+ });
201
463
  var WellStatusSchema = z.enum([
202
464
  "active",
203
465
  "maintenance",
@@ -239,7 +501,7 @@ var AquiferAnalysisSchema = z.object({
239
501
  max_flow_rate_basis: z.string().optional(),
240
502
  specific_capacity: z.number().optional(),
241
503
  transmissivity: z.number().optional(),
242
- storativity: z.number().nullable().optional(),
504
+ storativity: z.number().optional(),
243
505
  hydraulic_conductivity: z.number().optional(),
244
506
  aquifer_thickness: z.number().optional(),
245
507
  jacob_b: z.number().optional(),
@@ -400,7 +662,7 @@ var OperatingRegimeSchema = z.object({
400
662
  id: z.string(),
401
663
  effective_from: rfc3339(),
402
664
  flow_rate: z.number().nonnegative().optional(),
403
- daily_operating_time: z.number().min(0).max(24).optional(),
665
+ daily_operating_time: z.number().nonnegative().optional(),
404
666
  days_per_week: z.number().int().min(1).max(7).optional(),
405
667
  notes: z.string().optional(),
406
668
  updated_at: rfc3339().optional()
@@ -537,7 +799,10 @@ var WaterSampleSchema = z.object({
537
799
  results: z.array(WaterQualityResultSchema).min(1)
538
800
  });
539
801
  var WellSchema = z.object({
540
- version: z.number().int(),
802
+ version: z.union([
803
+ z.number().int().nonnegative(),
804
+ z.string().regex(/^\d+\.\d+$/, 'version must be "M.m"')
805
+ ]),
541
806
  "@context": z.union([z.string(), z.array(z.unknown()), z.record(z.unknown())]).optional(),
542
807
  well_id: z.array(WellIdSchema).optional(),
543
808
  location: LocationSchema.optional(),
@@ -641,28 +906,39 @@ function normalizeV1Fields(raw) {
641
906
  }
642
907
  function parseWell(json) {
643
908
  const raw = JSON.parse(json);
644
- const version = raw.version;
645
- if (version !== void 0 && typeof version === "number") {
646
- if (version !== 1 && version !== 2) {
647
- throw new Error(`Unsupported .well format version: ${version}`);
909
+ if (raw.version === void 0) {
910
+ raw.version = 2;
911
+ } else {
912
+ const parsed = parseFormatVersion(raw.version);
913
+ if (!parsed) {
914
+ throw new Error(
915
+ `Malformed .well format version: ${JSON.stringify(raw.version)}`
916
+ );
648
917
  }
649
- if (version === 1) {
918
+ if (parsed.major === 1) {
650
919
  const normalized = normalizeV1Fields(raw);
651
920
  return mergeParsed(
652
921
  WellSchema.parse(normalized),
653
922
  normalized
654
923
  );
655
924
  }
656
- } else if (version !== void 0) {
657
- throw new Error(`Unsupported .well format version: ${String(version)}`);
658
- } else {
659
- raw.version = 2;
925
+ if (parsed.major !== 2) {
926
+ throw new Error(
927
+ `Unsupported .well format version: ${JSON.stringify(raw.version)}`
928
+ );
929
+ }
930
+ }
931
+ if (raw.version === 2 && Array.isArray(raw.aquifer_analysis)) {
932
+ for (const item of raw.aquifer_analysis) {
933
+ if (isPlainObject(item) && item.storativity === null) {
934
+ delete item.storativity;
935
+ }
936
+ }
660
937
  }
661
938
  return mergeParsed(WellSchema.parse(raw), raw);
662
939
  }
663
940
 
664
941
  // src/utils/well.utils.ts
665
- var WELL_FORMAT_VERSION = 2;
666
942
  var INCHES_TO_MM = 25.4;
667
943
  var LEGACY_ROOT_KEYS = /* @__PURE__ */ new Set([
668
944
  "lat",
@@ -709,7 +985,7 @@ var VISIBILITY_LEAF_KEYS = SECTION_KEYS.flatMap(
709
985
  (section) => VISIBILITY_TREE[section].length ? VISIBILITY_TREE[section] : [section]
710
986
  );
711
987
  var EMPTY_WELL = {
712
- version: 2,
988
+ version: WELL_FORMAT_VERSION,
713
989
  bore_hole: [],
714
990
  well_case: [],
715
991
  reduction: [],
@@ -805,7 +1081,9 @@ function decodeV2Well(raw) {
805
1081
  const rawScreens = raw.well_screen ?? [];
806
1082
  const decoded = {
807
1083
  ...createEmptyWell(),
808
- ...raw.version !== void 0 && { version: raw.version },
1084
+ ...raw.version !== void 0 && {
1085
+ version: raw.version
1086
+ },
809
1087
  ...raw["@context"] !== void 0 && {
810
1088
  "@context": raw["@context"]
811
1089
  },
@@ -921,6 +1199,19 @@ function unknownRootKeys(well) {
921
1199
  (key) => !(key in WellSchema.shape) && !LEGACY_ROOT_KEYS.has(key)
922
1200
  );
923
1201
  }
1202
+ function omitNulls(value) {
1203
+ if (Array.isArray(value)) return value.map(omitNulls);
1204
+ if (typeof value !== "object" || value === null) return value;
1205
+ const out = {};
1206
+ for (const [key, member] of Object.entries(value)) {
1207
+ if (key.startsWith("x-") || key === "@context") {
1208
+ out[key] = member;
1209
+ } else if (member !== null) {
1210
+ out[key] = omitNulls(member);
1211
+ }
1212
+ }
1213
+ return out;
1214
+ }
924
1215
  function serializeWell(well) {
925
1216
  const payload = {
926
1217
  version: WELL_FORMAT_VERSION,
@@ -977,7 +1268,7 @@ function serializeWell(well) {
977
1268
  const value = well[key];
978
1269
  if (value !== void 0) payload[key] = value;
979
1270
  }
980
- return JSON.stringify(payload);
1271
+ return JSON.stringify(omitNulls(payload));
981
1272
  }
982
1273
  function isWellEmpty(well) {
983
1274
  if (!well) return true;
@@ -1060,10 +1351,18 @@ function deserializeWell(jsonString) {
1060
1351
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
1061
1352
  throw new Error("Invalid profile format");
1062
1353
  }
1063
- if (typeof raw.version === "number") {
1064
- if (raw.version === 2) return withCalculatedWellDepth(decodeV2Well(raw));
1065
- if (raw.version === 1) return withCalculatedWellDepth(decodeV1Well(raw));
1066
- throw new Error(`Unsupported .well format version: ${raw.version}`);
1354
+ if (raw.version !== void 0) {
1355
+ const parsed = parseFormatVersion(raw.version);
1356
+ if (!parsed) {
1357
+ throw new Error(
1358
+ `Malformed .well format version: ${JSON.stringify(raw.version)}`
1359
+ );
1360
+ }
1361
+ if (parsed.major === 2) return withCalculatedWellDepth(decodeV2Well(raw));
1362
+ if (parsed.major === 1) return withCalculatedWellDepth(decodeV1Well(raw));
1363
+ throw new Error(
1364
+ `Unsupported .well format version: ${JSON.stringify(raw.version)}`
1365
+ );
1067
1366
  }
1068
1367
  if (isWellEmpty(raw)) return null;
1069
1368
  const constructiveSource = raw.constructive ?? raw;
@@ -2473,51 +2772,6 @@ var HISTORY_LOG_SEVERITIES = [
2473
2772
  { value: "critical", label: { en: "Critical", pt: "Cr\xEDtica" } }
2474
2773
  ];
2475
2774
 
2476
- // src/vocab/hydrodynamic.vocab.ts
2477
- var HYDRODYNAMIC_EVENT_TYPES = [
2478
- {
2479
- value: "spot_measurement",
2480
- label: { en: "Spot measurement", pt: "Medi\xE7\xE3o pontual" }
2481
- },
2482
- {
2483
- value: "constant_rate",
2484
- label: { en: "Constant rate", pt: "Vaz\xE3o constante" }
2485
- },
2486
- { value: "step_drawdown", label: { en: "Step drawdown", pt: "Escalonada" } },
2487
- { value: "airlift", label: { en: "Air-lift", pt: "Air-lift" } },
2488
- {
2489
- value: "recovery_only",
2490
- label: { en: "Recovery only", pt: "Recupera\xE7\xE3o" }
2491
- }
2492
- ];
2493
- var MEASUREMENT_METHODS = [
2494
- {
2495
- value: "electric_probe",
2496
- label: { en: "Electric probe", pt: "Sonda el\xE9trica" }
2497
- },
2498
- {
2499
- value: "pressure_transducer",
2500
- label: { en: "Pressure transducer", pt: "Transdutor de press\xE3o" }
2501
- },
2502
- { value: "air_line", label: { en: "Air line", pt: "Linha de ar" } },
2503
- { value: "tape", label: { en: "Tape", pt: "Trena" } }
2504
- ];
2505
- var AQUIFER_ANALYSIS_METHODS = [
2506
- { value: "cooper_jacob", label: { en: "Cooper-Jacob", pt: "Cooper-Jacob" } },
2507
- { value: "theis", label: { en: "Theis", pt: "Theis" } },
2508
- { value: "neuman", label: { en: "Neuman", pt: "Neuman" } },
2509
- { value: "hantush", label: { en: "Hantush", pt: "Hantush" } },
2510
- {
2511
- value: "birsoy_summers",
2512
- label: { en: "Birsoy-Summers", pt: "Birsoy-Summers" }
2513
- },
2514
- { value: "eden_hazel", label: { en: "Eden-Hazel", pt: "Eden-Hazel" } },
2515
- {
2516
- value: "visual_inspection",
2517
- label: { en: "Visual inspection", pt: "Inspe\xE7\xE3o visual" }
2518
- }
2519
- ];
2520
-
2521
2775
  // src/vocab/operation.vocab.ts
2522
2776
  var PUMP_TYPES = [
2523
2777
  {
@@ -2728,114 +2982,6 @@ function vocabValues(vocab, { includeDeprecated = false } = {}) {
2728
2982
  return vocab.filter((entry) => includeDeprecated || !entry.deprecated).map((entry) => entry.value);
2729
2983
  }
2730
2984
 
2731
- // src/vocab/closed.vocab.ts
2732
- function closedVocab() {
2733
- return (entries) => entries;
2734
- }
2735
- var valuesOf = (vocab) => vocab.map((entry) => entry.value);
2736
- var WELL_STATUSES = closedVocab()([
2737
- { value: "active", label: { en: "Active", pt: "Ativo" } },
2738
- {
2739
- value: "maintenance",
2740
- label: { en: "Under maintenance", pt: "Em manuten\xE7\xE3o" }
2741
- },
2742
- { value: "inactive", label: { en: "Inactive", pt: "Paralisado" } },
2743
- {
2744
- value: "decommissioned",
2745
- label: { en: "Decommissioned", pt: "Desativado" }
2746
- },
2747
- { value: "abandoned", label: { en: "Abandoned", pt: "Abandonado" } }
2748
- ]);
2749
- var PERMIT_ADMINISTRATIVE_STATUSES = closedVocab()([
2750
- { value: "requested", label: { en: "Requested", pt: "Requerida" } },
2751
- { value: "granted", label: { en: "Granted", pt: "Concedida" } },
2752
- { value: "suspended", label: { en: "Suspended", pt: "Suspensa" } },
2753
- { value: "revoked", label: { en: "Revoked", pt: "Revogada" } },
2754
- { value: "denied", label: { en: "Denied", pt: "Indeferida" } },
2755
- { value: "withdrawn", label: { en: "Withdrawn", pt: "Cancelada" } }
2756
- ]);
2757
- var VOLUME_LIMIT_PERIODS = closedVocab()([
2758
- { value: "daily", label: { en: "Daily", pt: "Di\xE1rio" } },
2759
- { value: "monthly", label: { en: "Monthly", pt: "Mensal" } },
2760
- { value: "annual", label: { en: "Annual", pt: "Anual" } }
2761
- ]);
2762
- var PRODUCTION_ENTRY_TYPES = closedVocab()([
2763
- {
2764
- value: "meter_reading",
2765
- label: { en: "Meter reading", pt: "Leitura de hidr\xF4metro" }
2766
- },
2767
- {
2768
- value: "estimated_volume",
2769
- label: { en: "Estimated volume", pt: "Volume estimado" }
2770
- }
2771
- ]);
2772
- var RESULT_QUALIFIERS = closedVocab()([
2773
- { value: "<", label: { en: "< less than", pt: "< menor que" } },
2774
- { value: ">", label: { en: "> greater than", pt: "> maior que" } },
2775
- { value: "not_detected", label: { en: "Not detected", pt: "N\xE3o detectado" } },
2776
- { value: "estimated", label: { en: "Estimated", pt: "Estimado" } }
2777
- ]);
2778
- var RESULT_FRACTIONS = closedVocab()([
2779
- { value: "total", label: { en: "Total", pt: "Total" } },
2780
- { value: "dissolved", label: { en: "Dissolved", pt: "Dissolvida" } },
2781
- { value: "suspended", label: { en: "Suspended", pt: "Suspensa" } }
2782
- ]);
2783
- var MEASUREMENT_LOCATIONS = closedVocab()([
2784
- { value: "field", label: { en: "Field", pt: "Campo" } },
2785
- { value: "lab", label: { en: "Lab", pt: "Laborat\xF3rio" } }
2786
- ]);
2787
- var VALIDATION_STATUSES = closedVocab()([
2788
- { value: "unvalidated", label: { en: "Unvalidated", pt: "N\xE3o validado" } },
2789
- { value: "validated", label: { en: "Validated", pt: "Validado" } },
2790
- { value: "qualified", label: { en: "Qualified", pt: "Qualificado" } },
2791
- { value: "rejected", label: { en: "Rejected", pt: "Rejeitado" } }
2792
- ]);
2793
- var PARAMETER_GROUPS = closedVocab()([
2794
- {
2795
- value: "physical",
2796
- label: { en: "Physical / field", pt: "F\xEDsico / campo" }
2797
- },
2798
- { value: "aggregate", label: { en: "Aggregate", pt: "Agregados" } },
2799
- { value: "major_ion", label: { en: "Major ions", pt: "\xCDons maiores" } },
2800
- { value: "nutrient", label: { en: "Nutrients", pt: "Nutrientes" } },
2801
- { value: "organic", label: { en: "Organic", pt: "Org\xE2nicos" } },
2802
- { value: "disinfection", label: { en: "Disinfection", pt: "Desinfec\xE7\xE3o" } },
2803
- {
2804
- value: "mining_redox",
2805
- label: { en: "Mining and redox", pt: "Minera\xE7\xE3o e redox" }
2806
- },
2807
- { value: "metal", label: { en: "Metals / trace", pt: "Metais / tra\xE7o" } },
2808
- { value: "microbiology", label: { en: "Microbiology", pt: "Microbiologia" } },
2809
- {
2810
- value: "radioactivity",
2811
- label: { en: "Radioactivity", pt: "Radioatividade" }
2812
- }
2813
- ]);
2814
- var WELL_STATUS_VALUES = valuesOf(WELL_STATUSES);
2815
- var PERMIT_ADMINISTRATIVE_STATUS_VALUES = valuesOf(
2816
- PERMIT_ADMINISTRATIVE_STATUSES
2817
- );
2818
- var QUALIFIER_VALUES = valuesOf(RESULT_QUALIFIERS);
2819
- var FRACTION_VALUES = valuesOf(RESULT_FRACTIONS);
2820
- var MEASURED_IN_VALUES = valuesOf(MEASUREMENT_LOCATIONS);
2821
- var FILTRATION_LOCATION_VALUES = valuesOf(MEASUREMENT_LOCATIONS);
2822
- var VALIDATION_STATUS_VALUES = valuesOf(VALIDATION_STATUSES);
2823
- var PARAMETER_GROUP_VALUES = valuesOf(PARAMETER_GROUPS);
2824
- var NUMERIC_QUALIFIERS = [
2825
- "<",
2826
- ">",
2827
- "estimated"
2828
- ];
2829
- var PARENT_SAMPLE_TYPES = [
2830
- "field_duplicate",
2831
- "split_sample"
2832
- ];
2833
- var BLANK_SAMPLE_TYPES = [
2834
- "field_blank",
2835
- "trip_blank",
2836
- "equipment_blank"
2837
- ];
2838
-
2839
2985
  // src/vocab/waterSample.vocab.ts
2840
2986
  var SAMPLE_TYPES = [
2841
2987
  { value: "routine", label: { en: "Routine", pt: "Rotina" } },
@@ -3100,6 +3246,8 @@ export {
3100
3246
  AirliftEventSchema,
3101
3247
  AquiferAnalysisSchema,
3102
3248
  AttachmentSchema,
3249
+ BAROMETRIC_COMPENSATIONS,
3250
+ BAROMETRIC_COMPENSATION_VALUES,
3103
3251
  BLANK_SAMPLE_TYPES,
3104
3252
  BR_GM_MS_888_2021,
3105
3253
  BoreHoleSchema,
@@ -3135,6 +3283,8 @@ export {
3135
3283
  LithologySchema,
3136
3284
  LocationPropertiesSchema,
3137
3285
  LocationSchema,
3286
+ LoggerReadingSchema,
3287
+ LoggerSeriesEventSchema,
3138
3288
  MAINTENANCE_TYPES,
3139
3289
  MEASURED_IN_VALUES,
3140
3290
  MEASUREMENT_LOCATIONS,
@@ -3169,6 +3319,8 @@ export {
3169
3319
  PurgeReadingSchema,
3170
3320
  PurgeSchema,
3171
3321
  QUALIFIER_VALUES,
3322
+ READING_AGGREGATIONS,
3323
+ READING_AGGREGATION_VALUES,
3172
3324
  READING_SOURCES,
3173
3325
  RESULT_FRACTIONS,
3174
3326
  RESULT_QUALIFIERS,
@@ -3200,6 +3352,7 @@ export {
3200
3352
  WATER_QUALITY_UNITS,
3201
3353
  WATER_QUALITY_VOCABULARY_VERSION,
3202
3354
  WATER_USES,
3355
+ WELL_FORMAT_VERSION,
3203
3356
  WELL_PURPOSES,
3204
3357
  WELL_STATUSES,
3205
3358
  WELL_STATUS_VALUES,
@@ -3214,6 +3367,7 @@ export {
3214
3367
  WellStatusSchema,
3215
3368
  calculatedWellDepth,
3216
3369
  checkIfProfileIsEmpty,
3370
+ compareFormatVersions,
3217
3371
  concentrationFromCanonical,
3218
3372
  concentrationToCanonical,
3219
3373
  convertProfileFromJSON,
@@ -3241,6 +3395,7 @@ export {
3241
3395
  hoursToMinutes,
3242
3396
  hpToKilowatts,
3243
3397
  inchesToMm,
3398
+ isIanaTimeZone,
3244
3399
  isKnownParameter,
3245
3400
  isVocabValue,
3246
3401
  isWellEmpty,
@@ -3257,6 +3412,7 @@ export {
3257
3412
  mmToSlotNumber,
3258
3413
  normalizeColorUnit,
3259
3414
  parameterKey,
3415
+ parseFormatVersion,
3260
3416
  parseWell,
3261
3417
  powerFromCanonical,
3262
3418
  powerToCanonical,