@o3co/ts.hocon 1.14.0 → 1.14.1

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,64 @@
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 {
31
+ throw new z.ZodError(refused);
32
+ }
33
+ if (result.success) throw new z.ZodError(refused);
34
+ throw new z.ZodError([...refused, ...withoutPrototypeKeyIssues(result.error.issues)]);
35
+ }
36
+ function withoutPrototypeKeyIssues(issues) {
37
+ return issues.filter((issue) => !issue.path.some((seg) => typeof seg === "string" && PROTOTYPE_KEYS.has(seg))).map(
38
+ (issue) => issue.code === "invalid_union" ? { ...issue, errors: issue.errors.map(withoutPrototypeKeyIssues) } : issue
39
+ );
28
40
  }
29
41
  function requireResolved(config, path) {
30
42
  config.getValue(path);
31
43
  }
32
44
  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
- }
45
+ function dropPrototypeKeys(value, path, issues) {
46
+ if (Array.isArray(value)) return value.map((item, i) => dropPrototypeKeys(item, [...path, i], issues));
47
+ if (typeof value !== "object" || value === null) return value;
48
+ const kept = {};
49
+ for (const [key, item] of Object.entries(value)) {
50
+ if (PROTOTYPE_KEYS.has(key)) {
51
+ issues.push({
52
+ code: "custom",
53
+ path,
54
+ message: `key ${JSON.stringify(key)} names an object's prototype`,
55
+ params: { key }
56
+ });
57
+ } else {
58
+ kept[key] = dropPrototypeKeys(item, [...path, key], issues);
53
59
  }
54
60
  }
61
+ return kept;
55
62
  }
56
63
  function unitMarker(what, read) {
57
64
  return z.transform((input, ctx) => {
@@ -62,18 +69,23 @@ function unitMarker(what, read) {
62
69
  const text = typeof input === "string" ? input : String(input);
63
70
  const reading = read(text);
64
71
  if (reading.ok) return reading.value;
65
- ctx.issues.push({ code: "custom", message: unitProblemMessage(what, reading.problem, text), input });
72
+ ctx.issues.push({
73
+ code: "custom",
74
+ message: unitProblemMessage(what, reading.problem),
75
+ input,
76
+ params: { problem: reading.problem }
77
+ });
66
78
  return z.NEVER;
67
79
  });
68
80
  }
69
- function unitProblemMessage(what, problem, text) {
81
+ function unitProblemMessage(what, problem) {
70
82
  switch (problem) {
71
83
  case "invalid":
72
- return `invalid ${what}: ${JSON.stringify(text)}`;
84
+ return `not a ${what}`;
73
85
  case "negative":
74
- return `${what} must be non-negative: ${JSON.stringify(text)}`;
86
+ return `${what} must be non-negative`;
75
87
  case "overflow":
76
- return `${what} overflows the representable range: ${JSON.stringify(text)}`;
88
+ return `${what} overflows the representable range`;
77
89
  }
78
90
  }
79
91
  function describeInput(input) {
@@ -116,6 +128,9 @@ function getDefType(schema) {
116
128
  const zod = schema._zod;
117
129
  return zod?.def?.type;
118
130
  }
131
+ function getDef(schema) {
132
+ return schema._zod?.def;
133
+ }
119
134
  function getInnerSchema(schema) {
120
135
  const def = schema._zod?.def;
121
136
  return def?.innerType ?? def?.schema;
@@ -124,6 +139,9 @@ function getObjectShape(schema) {
124
139
  const shape = schema._zod?.def?.shape;
125
140
  return typeof shape === "object" && shape !== null ? shape : void 0;
126
141
  }
142
+ function getPropValues(schema) {
143
+ return schema._zod?.propValues;
144
+ }
127
145
  function getArrayElement(schema) {
128
146
  return schema._zod?.def?.element;
129
147
  }
@@ -152,6 +170,10 @@ function coerceValue(value, schema) {
152
170
  return coerced !== void 0 ? coerced : value;
153
171
  }
154
172
  return value;
173
+ case "literal": {
174
+ const values = getDef(schema)?.values;
175
+ return values ? coerceToLiteral(value, new Set(values)) : value;
176
+ }
155
177
  case "object": {
156
178
  if (typeof value !== "object" || Array.isArray(value)) return value;
157
179
  const shape = getObjectShape(schema);
@@ -171,9 +193,39 @@ function coerceValue(value, schema) {
171
193
  if (!elementSchema) return value;
172
194
  return value.map((item) => coerceValue(item, elementSchema));
173
195
  }
196
+ case "record": {
197
+ if (typeof value !== "object" || Array.isArray(value)) return value;
198
+ const valueSchema = getDef(schema)?.valueType;
199
+ if (!valueSchema) return value;
200
+ const result = {};
201
+ for (const [key, item] of Object.entries(value)) result[key] = coerceValue(item, valueSchema);
202
+ return result;
203
+ }
204
+ case "tuple": {
205
+ if (!Array.isArray(value)) return value;
206
+ const def = getDef(schema);
207
+ const items = def?.items ?? [];
208
+ const rest = def?.rest;
209
+ return value.map((item, i) => {
210
+ const itemSchema = i < items.length ? items[i] : rest;
211
+ return itemSchema ? coerceValue(item, itemSchema) : item;
212
+ });
213
+ }
214
+ case "union":
215
+ return coerceUnion(value, schema);
216
+ case "pipe": {
217
+ const input = getDef(schema)?.in;
218
+ return input ? coerceValue(value, input) : value;
219
+ }
220
+ case "lazy": {
221
+ const getter = getDef(schema)?.getter;
222
+ return getter ? coerceValue(value, getter()) : value;
223
+ }
174
224
  case "optional":
175
225
  case "nullable":
176
226
  case "default":
227
+ case "prefault":
228
+ case "nonoptional":
177
229
  case "catch":
178
230
  case "readonly": {
179
231
  const inner = getInnerSchema(schema);
@@ -183,6 +235,42 @@ function coerceValue(value, schema) {
183
235
  return value;
184
236
  }
185
237
  }
238
+ function coerceUnion(value, schema) {
239
+ const def = getDef(schema);
240
+ const options = def?.options ?? [];
241
+ const discriminator = def?.discriminator;
242
+ if (discriminator !== void 0) {
243
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
244
+ const tag = Object.prototype.hasOwnProperty.call(value, discriminator) ? value[discriminator] : void 0;
245
+ const tagsOf = (o) => getPropValues(o)?.[discriminator];
246
+ const option = options.find((o) => tagsOf(o)?.has(tag)) ?? options.find((o) => {
247
+ const tags = tagsOf(o);
248
+ return tags !== void 0 && tags.has(coerceToLiteral(tag, tags));
249
+ });
250
+ return option ? coerceValue(value, option) : value;
251
+ }
252
+ if (options.some((option) => accepts(option, value))) return value;
253
+ for (const option of options) {
254
+ const coerced = coerceValue(value, option);
255
+ if (accepts(option, coerced)) return coerced;
256
+ }
257
+ return value;
258
+ }
259
+ function coerceToLiteral(value, literals) {
260
+ if (typeof value !== "string" || literals.has(value)) return value;
261
+ const n = coerceNumber(value);
262
+ if (n !== void 0 && literals.has(n)) return n;
263
+ const b = coerceBoolean(value);
264
+ if (b !== void 0 && literals.has(b)) return b;
265
+ return value;
266
+ }
267
+ function accepts(schema, value) {
268
+ try {
269
+ return schema.safeParse(value).success;
270
+ } catch {
271
+ return false;
272
+ }
273
+ }
186
274
  export {
187
275
  getValidated,
188
276
  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.1",
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
  },