@o3co/ts.hocon 1.14.0 → 1.14.2

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/dist/zod.js CHANGED
@@ -1,57 +1,67 @@
1
1
  import {
2
2
  parse,
3
3
  parseFile
4
- } from "./chunk-XWKO4JM3.js";
4
+ } from "./chunk-JVABBNF5.js";
5
5
  import {
6
6
  coerceBoolean,
7
7
  coerceNumber,
8
8
  readBytes,
9
9
  readDuration,
10
10
  readPeriod
11
- } from "./chunk-WTXULUZS.js";
11
+ } from "./chunk-GOXMKYWS.js";
12
12
 
13
13
  // src/zod.ts
14
14
  import { z } from "zod";
15
15
  function validate(config, schema) {
16
16
  requireResolved(config, "");
17
- const plain = config.toObject();
18
- refusePrototypeKeys(plain);
19
- const coerced = coerceValue(plain, schema);
20
- return schema.parse(coerced);
17
+ return parseValue(config.toObject(), schema);
21
18
  }
22
19
  function getValidated(config, path, schema) {
23
20
  requireResolved(config, path);
24
- const val = config.get(path);
25
- refusePrototypeKeys(val);
26
- const coerced = coerceValue(val, schema);
27
- return schema.parse(coerced);
21
+ return parseValue(config.get(path), schema);
22
+ }
23
+ function parseValue(value, schema) {
24
+ const refused = [];
25
+ const coerced = coerceValue(dropPrototypeKeys(value, [], refused), schema);
26
+ if (refused.length === 0) return schema.parse(coerced);
27
+ let result;
28
+ try {
29
+ result = schema.safeParse(coerced);
30
+ } catch (err) {
31
+ if (err instanceof z.core.$ZodAsyncError || err?.constructor?.name === "$ZodAsyncError") {
32
+ throw new z.ZodError(refused);
33
+ }
34
+ throw err;
35
+ }
36
+ if (result.success) throw new z.ZodError(refused);
37
+ throw new z.ZodError([...refused, ...withoutPrototypeKeyIssues(result.error.issues)]);
38
+ }
39
+ function withoutPrototypeKeyIssues(issues) {
40
+ return issues.filter((issue) => !issue.path.some((seg) => typeof seg === "string" && PROTOTYPE_KEYS.has(seg))).map(
41
+ (issue) => issue.code === "invalid_union" ? { ...issue, errors: issue.errors.map(withoutPrototypeKeyIssues) } : issue
42
+ );
28
43
  }
29
44
  function requireResolved(config, path) {
30
45
  config.getValue(path);
31
46
  }
32
47
  var PROTOTYPE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
33
- function refusePrototypeKeys(value) {
34
- const issues = [];
35
- collectPrototypeKeys(value, [], issues);
36
- if (issues.length > 0) throw new z.ZodError(issues);
37
- }
38
- function collectPrototypeKeys(value, path, issues) {
39
- if (Array.isArray(value)) {
40
- value.forEach((item, i) => collectPrototypeKeys(item, [...path, i], issues));
41
- } else if (typeof value === "object" && value !== null) {
42
- for (const [key, item] of Object.entries(value)) {
43
- if (PROTOTYPE_KEYS.has(key)) {
44
- issues.push({
45
- code: "custom",
46
- path,
47
- message: `key ${JSON.stringify(key)} names an object's prototype`,
48
- params: { key }
49
- });
50
- } else {
51
- collectPrototypeKeys(item, [...path, key], issues);
52
- }
48
+ function dropPrototypeKeys(value, path, issues) {
49
+ if (Array.isArray(value)) return value.map((item, i) => dropPrototypeKeys(item, [...path, i], issues));
50
+ if (typeof value !== "object" || value === null) return value;
51
+ const kept = {};
52
+ for (const [key, item] of Object.entries(value)) {
53
+ if (PROTOTYPE_KEYS.has(key)) {
54
+ issues.push({
55
+ code: "custom",
56
+ path,
57
+ message: `key ${JSON.stringify(key)} names an object's prototype`,
58
+ params: { key }
59
+ });
60
+ } else {
61
+ kept[key] = dropPrototypeKeys(item, [...path, key], issues);
53
62
  }
54
63
  }
64
+ return kept;
55
65
  }
56
66
  function unitMarker(what, read) {
57
67
  return z.transform((input, ctx) => {
@@ -62,18 +72,23 @@ function unitMarker(what, read) {
62
72
  const text = typeof input === "string" ? input : String(input);
63
73
  const reading = read(text);
64
74
  if (reading.ok) return reading.value;
65
- ctx.issues.push({ code: "custom", message: unitProblemMessage(what, reading.problem, text), input });
75
+ ctx.issues.push({
76
+ code: "custom",
77
+ message: unitProblemMessage(what, reading.problem),
78
+ input,
79
+ params: { problem: reading.problem }
80
+ });
66
81
  return z.NEVER;
67
82
  });
68
83
  }
69
- function unitProblemMessage(what, problem, text) {
84
+ function unitProblemMessage(what, problem) {
70
85
  switch (problem) {
71
86
  case "invalid":
72
- return `invalid ${what}: ${JSON.stringify(text)}`;
87
+ return `not a ${what}`;
73
88
  case "negative":
74
- return `${what} must be non-negative: ${JSON.stringify(text)}`;
89
+ return `${what} must be non-negative`;
75
90
  case "overflow":
76
- return `${what} overflows the representable range: ${JSON.stringify(text)}`;
91
+ return `${what} overflows the representable range`;
77
92
  }
78
93
  }
79
94
  function describeInput(input) {
@@ -116,6 +131,9 @@ function getDefType(schema) {
116
131
  const zod = schema._zod;
117
132
  return zod?.def?.type;
118
133
  }
134
+ function getDef(schema) {
135
+ return schema._zod?.def;
136
+ }
119
137
  function getInnerSchema(schema) {
120
138
  const def = schema._zod?.def;
121
139
  return def?.innerType ?? def?.schema;
@@ -124,6 +142,9 @@ function getObjectShape(schema) {
124
142
  const shape = schema._zod?.def?.shape;
125
143
  return typeof shape === "object" && shape !== null ? shape : void 0;
126
144
  }
145
+ function getPropValues(schema) {
146
+ return schema._zod?.propValues;
147
+ }
127
148
  function getArrayElement(schema) {
128
149
  return schema._zod?.def?.element;
129
150
  }
@@ -152,6 +173,14 @@ function coerceValue(value, schema) {
152
173
  return coerced !== void 0 ? coerced : value;
153
174
  }
154
175
  return value;
176
+ case "enum": {
177
+ const values = schema._zod.values;
178
+ return coerceToLiteral(value, values);
179
+ }
180
+ case "literal": {
181
+ const values = getDef(schema)?.values;
182
+ return values ? coerceToLiteral(value, new Set(values)) : value;
183
+ }
155
184
  case "object": {
156
185
  if (typeof value !== "object" || Array.isArray(value)) return value;
157
186
  const shape = getObjectShape(schema);
@@ -163,17 +192,63 @@ function coerceValue(value, schema) {
163
192
  result[key] = coerceValue(obj[key], shape[key]);
164
193
  }
165
194
  }
195
+ const catchall = getDef(schema)?.catchall;
196
+ if (catchall) {
197
+ for (const key of Object.keys(obj)) {
198
+ if (!Object.prototype.hasOwnProperty.call(shape, key)) result[key] = coerceValue(obj[key], catchall);
199
+ }
200
+ }
166
201
  return result;
167
202
  }
203
+ case "intersection": {
204
+ if (accepts(schema, value)) return value;
205
+ const def = getDef(schema);
206
+ const forLeft = coerceValue(value, def.left);
207
+ if (accepts(schema, forLeft)) return forLeft;
208
+ const forRight = coerceValue(value, def.right);
209
+ if (accepts(schema, forRight)) return forRight;
210
+ return coerceValue(forLeft, def.right);
211
+ }
168
212
  case "array": {
169
213
  if (!Array.isArray(value)) return value;
170
214
  const elementSchema = getArrayElement(schema);
171
215
  if (!elementSchema) return value;
172
216
  return value.map((item) => coerceValue(item, elementSchema));
173
217
  }
218
+ case "record": {
219
+ if (typeof value !== "object" || Array.isArray(value)) return value;
220
+ const valueSchema = getDef(schema)?.valueType;
221
+ if (!valueSchema) return value;
222
+ const result = {};
223
+ for (const [key, item] of Object.entries(value)) result[key] = coerceValue(item, valueSchema);
224
+ return result;
225
+ }
226
+ case "tuple": {
227
+ if (!Array.isArray(value)) return value;
228
+ const def = getDef(schema);
229
+ const items = def?.items ?? [];
230
+ const rest = def?.rest;
231
+ return value.map((item, i) => {
232
+ const itemSchema = i < items.length ? items[i] : rest;
233
+ return itemSchema ? coerceValue(item, itemSchema) : item;
234
+ });
235
+ }
236
+ case "union":
237
+ return coerceUnion(value, schema);
238
+ case "pipe": {
239
+ const input = getDef(schema)?.in;
240
+ return input ? coerceValue(value, input) : value;
241
+ }
242
+ case "lazy": {
243
+ const getter = getDef(schema)?.getter;
244
+ return getter ? coerceValue(value, getter()) : value;
245
+ }
174
246
  case "optional":
175
247
  case "nullable":
176
248
  case "default":
249
+ case "prefault":
250
+ case "nonoptional":
251
+ case "success":
177
252
  case "catch":
178
253
  case "readonly": {
179
254
  const inner = getInnerSchema(schema);
@@ -183,6 +258,42 @@ function coerceValue(value, schema) {
183
258
  return value;
184
259
  }
185
260
  }
261
+ function coerceUnion(value, schema) {
262
+ const def = getDef(schema);
263
+ const options = def?.options ?? [];
264
+ const discriminator = def?.discriminator;
265
+ if (discriminator !== void 0) {
266
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
267
+ const tag = Object.prototype.hasOwnProperty.call(value, discriminator) ? value[discriminator] : void 0;
268
+ const tagsOf = (o) => getPropValues(o)?.[discriminator];
269
+ const option = options.find((o) => tagsOf(o)?.has(tag)) ?? options.find((o) => {
270
+ const tags = tagsOf(o);
271
+ return tags !== void 0 && tags.has(coerceToLiteral(tag, tags));
272
+ });
273
+ return option ? coerceValue(value, option) : value;
274
+ }
275
+ if (options.some((option) => accepts(option, value))) return value;
276
+ for (const option of options) {
277
+ const coerced = coerceValue(value, option);
278
+ if (accepts(option, coerced)) return coerced;
279
+ }
280
+ return value;
281
+ }
282
+ function coerceToLiteral(value, literals) {
283
+ if (typeof value !== "string" || literals.has(value)) return value;
284
+ const n = coerceNumber(value);
285
+ if (n !== void 0 && literals.has(n)) return n;
286
+ const b = coerceBoolean(value);
287
+ if (b !== void 0 && literals.has(b)) return b;
288
+ return value;
289
+ }
290
+ function accepts(schema, value) {
291
+ try {
292
+ return schema.safeParse(value).success;
293
+ } catch {
294
+ return false;
295
+ }
296
+ }
186
297
  export {
187
298
  getValidated,
188
299
  hocon,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3co/ts.hocon",
3
- "version": "1.14.0",
3
+ "version": "1.14.2",
4
4
  "description": "Full Lightbend HOCON spec-compliant parser and config library for TypeScript",
5
5
  "keywords": [
6
6
  "hocon",
@@ -118,13 +118,13 @@
118
118
  "devDependencies": {
119
119
  "@types/js-yaml": "^4.0.9",
120
120
  "@types/node": "^25.9.5",
121
- "@vitest/coverage-v8": "4.1.10",
122
- "js-yaml": "^4.3.1",
123
- "smol-toml": "^1.7.0",
121
+ "@vitest/coverage-v8": "4.1.11",
122
+ "js-yaml": "^4.3.2",
123
+ "smol-toml": "^1.9.0",
124
124
  "tsup": "^8.5.1",
125
125
  "typedoc": "^0.28.20",
126
126
  "typescript": "^5.9.3",
127
- "vitest": "4.1.10",
127
+ "vitest": "4.1.11",
128
128
  "yaml": "^2.9.0",
129
129
  "zod": "^4.4.3"
130
130
  },