@o3co/ts.hocon 1.14.2 → 1.14.3

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.
@@ -265,6 +265,19 @@ function readBytes(text, outputUnit) {
265
265
  if (value < 0) return { ok: false, problem: "negative" };
266
266
  return { ok: true, value };
267
267
  }
268
+ function namesMagnitudeUnit(text) {
269
+ const split = splitUnitText(text);
270
+ return split !== void 0 && split.unit !== "";
271
+ }
272
+ function namesPeriodUnit(text) {
273
+ return splitPeriodText(text).unit !== "";
274
+ }
275
+ function splitPeriodText(text) {
276
+ const trimmed = trimHoconWs(text);
277
+ let i = 0;
278
+ while (i < trimmed.length && "+-0123456789".includes(trimmed[i])) i++;
279
+ return { digits: trimmed.slice(0, i), unit: trimHoconWs(trimmed.slice(i)) };
280
+ }
268
281
  var PERIOD_UNITS = /* @__PURE__ */ new Map([
269
282
  ["", { field: "days", factor: 1 }],
270
283
  ["d", { field: "days", factor: 1 }],
@@ -284,11 +297,9 @@ var PERIOD_UNITS = /* @__PURE__ */ new Map([
284
297
  var I32_MIN = -(2 ** 31);
285
298
  var I32_MAX = 2 ** 31 - 1;
286
299
  function readPeriod(text) {
287
- const trimmed = trimHoconWs(text);
288
- let i = 0;
289
- while (i < trimmed.length && "+-0123456789".includes(trimmed[i])) i++;
290
- const digits = trimmed.slice(0, i);
291
- const unit = PERIOD_UNITS.get(trimHoconWs(trimmed.slice(i)));
300
+ const split = splitPeriodText(text);
301
+ const digits = split.digits;
302
+ const unit = PERIOD_UNITS.get(split.unit);
292
303
  if (!/^[+-]?\d+$/.test(digits) || unit === void 0) return { ok: false, problem: "invalid" };
293
304
  const n = Number(digits) * unit.factor;
294
305
  if (n < I32_MIN || n > I32_MAX) return { ok: false, problem: "invalid" };
@@ -3798,4 +3809,6 @@ function completeJsonNumber(raw) {
3798
3809
 
3799
3810
 
3800
3811
 
3801
- exports.coerceBoolean = coerceBoolean; exports.coerceNumber = coerceNumber; exports.readDuration = readDuration; exports.readBytes = readBytes; exports.readPeriod = readPeriod; exports.ParseError = ParseError; exports.ResolveError = ResolveError; exports.PackageLookupError = PackageLookupError; exports.ConfigError = ConfigError; exports.NotResolvedError = NotResolvedError; exports.tokenize = tokenize; exports.parseTokens = parseTokens; exports.stripBom = stripBom; exports.MAX_PATH_SEGMENTS = MAX_PATH_SEGMENTS; exports.tooDeep = tooDeep; exports.guardStackDepth = guardStackDepth; exports.depthError = depthError; exports.guardStackDepthAsync = guardStackDepthAsync; exports.parseProperties = parseProperties; exports.nestPairs = nestPairs; exports.pathKey = pathKey; exports.buildTree = buildTree; exports.buildTreeAsync = buildTreeAsync; exports.containsPlaceholders = containsPlaceholders; exports.resolve = resolve2; exports.resolveAsync = resolveAsync; exports.Config = Config;
3812
+
3813
+
3814
+ exports.coerceBoolean = coerceBoolean; exports.coerceNumber = coerceNumber; exports.readDuration = readDuration; exports.readBytes = readBytes; exports.namesMagnitudeUnit = namesMagnitudeUnit; exports.namesPeriodUnit = namesPeriodUnit; exports.readPeriod = readPeriod; exports.ParseError = ParseError; exports.ResolveError = ResolveError; exports.PackageLookupError = PackageLookupError; exports.ConfigError = ConfigError; exports.NotResolvedError = NotResolvedError; exports.tokenize = tokenize; exports.parseTokens = parseTokens; exports.stripBom = stripBom; exports.MAX_PATH_SEGMENTS = MAX_PATH_SEGMENTS; exports.tooDeep = tooDeep; exports.guardStackDepth = guardStackDepth; exports.depthError = depthError; exports.guardStackDepthAsync = guardStackDepthAsync; exports.parseProperties = parseProperties; exports.nestPairs = nestPairs; exports.pathKey = pathKey; exports.buildTree = buildTree; exports.buildTreeAsync = buildTreeAsync; exports.containsPlaceholders = containsPlaceholders; exports.resolve = resolve2; exports.resolveAsync = resolveAsync; exports.Config = Config;
@@ -3,20 +3,20 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkL3D2RE2Ucjs = require('./chunk-L3D2RE2U.cjs');
6
+ var _chunkNHJJUTADcjs = require('./chunk-NHJJUTAD.cjs');
7
7
 
8
8
  // src/value-factory.ts
9
9
  function fromMap(values, originDescription) {
10
- const fields = _chunkL3D2RE2Ucjs.guardStackDepth.call(void 0,
10
+ const fields = _chunkNHJJUTADcjs.guardStackDepth.call(void 0,
11
11
  () => coerceObject(values, ""),
12
- (msg) => _chunkL3D2RE2Ucjs.depthError.call(void 0, `fromMap: ${msg}`)
12
+ (msg) => _chunkNHJJUTADcjs.depthError.call(void 0, `fromMap: ${msg}`)
13
13
  );
14
14
  const root = { kind: "object", fields };
15
- return _chunkL3D2RE2Ucjs.Config._fromResolvedValue(root, { originDescription });
15
+ return _chunkNHJJUTADcjs.Config._fromResolvedValue(root, { originDescription });
16
16
  }
17
17
  function empty(originDescription) {
18
18
  const root = { kind: "object", fields: /* @__PURE__ */ new Map() };
19
- return _chunkL3D2RE2Ucjs.Config._fromResolvedValue(root, { originDescription });
19
+ return _chunkNHJJUTADcjs.Config._fromResolvedValue(root, { originDescription });
20
20
  }
21
21
  var INT64_MAX = 9223372036854775807n;
22
22
  var INT64_MIN = -9223372036854775808n;
@@ -33,7 +33,7 @@ function coerceValue(v, atPath) {
33
33
  return { kind: "scalar", raw: "null", valueType: "null" };
34
34
  }
35
35
  if (v === void 0) {
36
- throw new (0, _chunkL3D2RE2Ucjs.ConfigError)(
36
+ throw new (0, _chunkNHJJUTADcjs.ConfigError)(
37
37
  `fromMap: undefined is not a valid HOCON value at path "${atPath}"`,
38
38
  atPath
39
39
  );
@@ -43,7 +43,7 @@ function coerceValue(v, atPath) {
43
43
  return { kind: "scalar", raw: v, valueType: "string" };
44
44
  case "number": {
45
45
  if (Number.isNaN(v) || !Number.isFinite(v)) {
46
- throw new (0, _chunkL3D2RE2Ucjs.ConfigError)(
46
+ throw new (0, _chunkNHJJUTADcjs.ConfigError)(
47
47
  `fromMap: ${v} is not representable in HOCON (NaN/Infinity not allowed) at path "${atPath}"`,
48
48
  atPath
49
49
  );
@@ -54,7 +54,7 @@ function coerceValue(v, atPath) {
54
54
  return { kind: "scalar", raw: v ? "true" : "false", valueType: "boolean" };
55
55
  case "bigint": {
56
56
  if (v > INT64_MAX || v < INT64_MIN) {
57
- throw new (0, _chunkL3D2RE2Ucjs.ConfigError)(
57
+ throw new (0, _chunkNHJJUTADcjs.ConfigError)(
58
58
  `fromMap: integer ${v} is out of int64 range (HOCON integers are int64; spec F0.5) at path "${atPath}"`,
59
59
  atPath
60
60
  );
@@ -70,7 +70,7 @@ function coerceValue(v, atPath) {
70
70
  return { kind: "object", fields };
71
71
  }
72
72
  default:
73
- throw new (0, _chunkL3D2RE2Ucjs.ConfigError)(
73
+ throw new (0, _chunkNHJJUTADcjs.ConfigError)(
74
74
  `fromMap: unsupported value type "${typeof v}" at path "${atPath}"`,
75
75
  atPath
76
76
  );
@@ -3,7 +3,7 @@ import {
3
3
  ConfigError,
4
4
  depthError,
5
5
  guardStackDepth
6
- } from "./chunk-GOXMKYWS.js";
6
+ } from "./chunk-5PV3HO2V.js";
7
7
 
8
8
  // src/value-factory.ts
9
9
  function fromMap(values, originDescription) {
package/dist/index.cjs CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
 
10
10
 
11
- var _chunkOUPKYWL3cjs = require('./chunk-OUPKYWL3.cjs');
11
+ var _chunkCPM55MMQcjs = require('./chunk-CPM55MMQ.cjs');
12
12
 
13
13
 
14
14
 
15
- var _chunkPCAMDXJ4cjs = require('./chunk-PCAMDXJ4.cjs');
15
+ var _chunkSDGXLF4Gcjs = require('./chunk-SDGXLF4G.cjs');
16
16
 
17
17
 
18
18
 
@@ -22,17 +22,17 @@ var _chunkPCAMDXJ4cjs = require('./chunk-PCAMDXJ4.cjs');
22
22
 
23
23
 
24
24
 
25
- var _chunkL3D2RE2Ucjs = require('./chunk-L3D2RE2U.cjs');
25
+ var _chunkNHJJUTADcjs = require('./chunk-NHJJUTAD.cjs');
26
26
 
27
27
  // src/value.ts
28
28
  function asString(v) {
29
29
  return v.kind === "scalar" && v.valueType === "string" ? v.raw : void 0;
30
30
  }
31
31
  function asNumber(v) {
32
- return v.kind === "scalar" ? _chunkL3D2RE2Ucjs.coerceNumber.call(void 0, v.raw) : void 0;
32
+ return v.kind === "scalar" ? _chunkNHJJUTADcjs.coerceNumber.call(void 0, v.raw) : void 0;
33
33
  }
34
34
  function asBoolean(v) {
35
- return v.kind === "scalar" ? _chunkL3D2RE2Ucjs.coerceBoolean.call(void 0, v.raw) : void 0;
35
+ return v.kind === "scalar" ? _chunkNHJJUTADcjs.coerceBoolean.call(void 0, v.raw) : void 0;
36
36
  }
37
37
  function asObject(v) {
38
38
  return v.kind === "object" ? v.fields : void 0;
@@ -79,4 +79,4 @@ function isNull(v) {
79
79
 
80
80
 
81
81
 
82
- exports.Config = _chunkL3D2RE2Ucjs.Config; exports.ConfigError = _chunkL3D2RE2Ucjs.ConfigError; exports.NotResolvedError = _chunkL3D2RE2Ucjs.NotResolvedError; exports.PackageLookupError = _chunkL3D2RE2Ucjs.PackageLookupError; exports.ParseError = _chunkL3D2RE2Ucjs.ParseError; exports.ResolveError = _chunkL3D2RE2Ucjs.ResolveError; exports.asArray = asArray; exports.asBoolean = asBoolean; exports.asNumber = asNumber; exports.asObject = asObject; exports.asString = asString; exports.defaultParseOptions = _chunkOUPKYWL3cjs.defaultParseOptions; exports.defaultResolveOptions = _chunkOUPKYWL3cjs.defaultResolveOptions; exports.empty = _chunkPCAMDXJ4cjs.empty; exports.fromMap = _chunkPCAMDXJ4cjs.fromMap; exports.isArray = isArray; exports.isNull = isNull; exports.isObject = isObject; exports.isScalar = isScalar; exports.parse = _chunkOUPKYWL3cjs.parse; exports.parseAsync = _chunkOUPKYWL3cjs.parseAsync; exports.parseFile = _chunkOUPKYWL3cjs.parseFile; exports.parseFileAsync = _chunkOUPKYWL3cjs.parseFileAsync; exports.parseFileWithOptions = _chunkOUPKYWL3cjs.parseFileWithOptions; exports.parseString = _chunkOUPKYWL3cjs.parseString; exports.parseStringWithOptions = _chunkOUPKYWL3cjs.parseStringWithOptions;
82
+ exports.Config = _chunkNHJJUTADcjs.Config; exports.ConfigError = _chunkNHJJUTADcjs.ConfigError; exports.NotResolvedError = _chunkNHJJUTADcjs.NotResolvedError; exports.PackageLookupError = _chunkNHJJUTADcjs.PackageLookupError; exports.ParseError = _chunkNHJJUTADcjs.ParseError; exports.ResolveError = _chunkNHJJUTADcjs.ResolveError; exports.asArray = asArray; exports.asBoolean = asBoolean; exports.asNumber = asNumber; exports.asObject = asObject; exports.asString = asString; exports.defaultParseOptions = _chunkCPM55MMQcjs.defaultParseOptions; exports.defaultResolveOptions = _chunkCPM55MMQcjs.defaultResolveOptions; exports.empty = _chunkSDGXLF4Gcjs.empty; exports.fromMap = _chunkSDGXLF4Gcjs.fromMap; exports.isArray = isArray; exports.isNull = isNull; exports.isObject = isObject; exports.isScalar = isScalar; exports.parse = _chunkCPM55MMQcjs.parse; exports.parseAsync = _chunkCPM55MMQcjs.parseAsync; exports.parseFile = _chunkCPM55MMQcjs.parseFile; exports.parseFileAsync = _chunkCPM55MMQcjs.parseFileAsync; exports.parseFileWithOptions = _chunkCPM55MMQcjs.parseFileWithOptions; exports.parseString = _chunkCPM55MMQcjs.parseString; exports.parseStringWithOptions = _chunkCPM55MMQcjs.parseStringWithOptions;
package/dist/index.js CHANGED
@@ -8,11 +8,11 @@ import {
8
8
  parseFileWithOptions,
9
9
  parseString,
10
10
  parseStringWithOptions
11
- } from "./chunk-JVABBNF5.js";
11
+ } from "./chunk-ITRXT66R.js";
12
12
  import {
13
13
  empty,
14
14
  fromMap
15
- } from "./chunk-YRNDXYGQ.js";
15
+ } from "./chunk-SZ7MDLYZ.js";
16
16
  import {
17
17
  Config,
18
18
  ConfigError,
@@ -22,7 +22,7 @@ import {
22
22
  ResolveError,
23
23
  coerceBoolean,
24
24
  coerceNumber
25
- } from "./chunk-GOXMKYWS.js";
25
+ } from "./chunk-5PV3HO2V.js";
26
26
 
27
27
  // src/value.ts
28
28
  function asString(v) {
package/dist/zod.cjs CHANGED
@@ -1,14 +1,16 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
- var _chunkOUPKYWL3cjs = require('./chunk-OUPKYWL3.cjs');
4
+ var _chunkCPM55MMQcjs = require('./chunk-CPM55MMQ.cjs');
5
5
 
6
6
 
7
7
 
8
8
 
9
9
 
10
10
 
11
- var _chunkL3D2RE2Ucjs = require('./chunk-L3D2RE2U.cjs');
11
+
12
+
13
+ var _chunkNHJJUTADcjs = require('./chunk-NHJJUTAD.cjs');
12
14
 
13
15
  // src/zod.ts
14
16
  var _zod2 = require('zod');
@@ -63,7 +65,7 @@ function dropPrototypeKeys(value, path, issues) {
63
65
  }
64
66
  return kept;
65
67
  }
66
- function unitMarker(what, read) {
68
+ function unitMarker(what, read, namesUnit) {
67
69
  return _zod2.z.transform((input, ctx) => {
68
70
  if (typeof input !== "string" && typeof input !== "number") {
69
71
  ctx.issues.push({ code: "custom", message: `expected ${what}, got ${describeInput(input)}`, input });
@@ -71,16 +73,18 @@ function unitMarker(what, read) {
71
73
  }
72
74
  const text = typeof input === "string" ? input : String(input);
73
75
  const reading = read(text);
76
+ if (reading.ok && namesUnit !== void 0 && (typeof input === "number" || !namesUnit(text))) {
77
+ pushProblem(ctx, what, "missing-unit", input);
78
+ return _zod2.z.NEVER;
79
+ }
74
80
  if (reading.ok) return reading.value;
75
- ctx.issues.push({
76
- code: "custom",
77
- message: unitProblemMessage(what, reading.problem),
78
- input,
79
- params: { problem: reading.problem }
80
- });
81
+ pushProblem(ctx, what, reading.problem, input);
81
82
  return _zod2.z.NEVER;
82
83
  });
83
84
  }
85
+ function pushProblem(ctx, what, problem, input) {
86
+ ctx.issues.push({ code: "custom", message: unitProblemMessage(what, problem), input, params: { problem } });
87
+ }
84
88
  function unitProblemMessage(what, problem) {
85
89
  switch (problem) {
86
90
  case "invalid":
@@ -89,6 +93,8 @@ function unitProblemMessage(what, problem) {
89
93
  return `${what} must be non-negative`;
90
94
  case "overflow":
91
95
  return `${what} overflows the representable range`;
96
+ case "missing-unit":
97
+ return `${what} must name its unit`;
92
98
  }
93
99
  }
94
100
  function describeInput(input) {
@@ -103,9 +109,10 @@ var hocon = {
103
109
  * significant digits than a double holds can read differently: the getter
104
110
  * reads its text, the marker its JS value (`1.0000000000000001` in `us`:
105
111
  * 1000.0000000000001 through the getter, 1000 here).
112
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
106
113
  */
107
- duration(unit) {
108
- return unitMarker("duration", (text) => _chunkL3D2RE2Ucjs.readDuration.call(void 0, text, unit));
114
+ duration(unit, options) {
115
+ return unitMarker("duration", (text) => _chunkNHJJUTADcjs.readDuration.call(void 0, text, unit), requireUnit(options, _chunkNHJJUTADcjs.namesMagnitudeUnit));
109
116
  },
110
117
  /**
111
118
  * A byte size, read as {@link Config.getBytes} reads it (default unit `B`),
@@ -113,47 +120,52 @@ var hocon = {
113
120
  * significant digits than a double holds can read differently: the getter
114
121
  * reads its text, the marker its JS value (`1.99999999999999999`: 1 through
115
122
  * the getter, 2 here).
123
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
116
124
  */
117
- bytes(unit) {
118
- return unitMarker("byte size", (text) => _chunkL3D2RE2Ucjs.readBytes.call(void 0, text, unit));
125
+ bytes(unit, options) {
126
+ return unitMarker("byte size", (text) => _chunkNHJJUTADcjs.readBytes.call(void 0, text, unit), requireUnit(options, _chunkNHJJUTADcjs.namesMagnitudeUnit));
119
127
  },
120
128
  /**
121
129
  * A calendar period, read as {@link Config.getPeriod} reads it (a bare
122
130
  * integer is days), except that a number literal with a decimal point or in
123
131
  * exponent form (`7.0`, `1e2`) can read differently: the getter refuses it,
124
132
  * the marker reads the JS number.
133
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
125
134
  */
126
- period() {
127
- return unitMarker("period", _chunkL3D2RE2Ucjs.readPeriod);
135
+ period(options) {
136
+ return unitMarker("period", _chunkNHJJUTADcjs.readPeriod, requireUnit(options, _chunkNHJJUTADcjs.namesPeriodUnit));
128
137
  }
129
138
  };
139
+ function requireUnit(options, namesUnit) {
140
+ return _optionalChain([options, 'optionalAccess', _3 => _3.requireUnit]) === true ? namesUnit : void 0;
141
+ }
130
142
  function getDefType(schema) {
131
143
  const zod = schema._zod;
132
- return _optionalChain([zod, 'optionalAccess', _3 => _3.def, 'optionalAccess', _4 => _4.type]);
144
+ return _optionalChain([zod, 'optionalAccess', _4 => _4.def, 'optionalAccess', _5 => _5.type]);
133
145
  }
134
146
  function getDef(schema) {
135
- return _optionalChain([schema, 'access', _5 => _5._zod, 'optionalAccess', _6 => _6.def]);
147
+ return _optionalChain([schema, 'access', _6 => _6._zod, 'optionalAccess', _7 => _7.def]);
136
148
  }
137
149
  function getInnerSchema(schema) {
138
- const def = _optionalChain([schema, 'access', _7 => _7._zod, 'optionalAccess', _8 => _8.def]);
139
- return _nullishCoalesce(_optionalChain([def, 'optionalAccess', _9 => _9.innerType]), () => ( _optionalChain([def, 'optionalAccess', _10 => _10.schema])));
150
+ const def = _optionalChain([schema, 'access', _8 => _8._zod, 'optionalAccess', _9 => _9.def]);
151
+ return _nullishCoalesce(_optionalChain([def, 'optionalAccess', _10 => _10.innerType]), () => ( _optionalChain([def, 'optionalAccess', _11 => _11.schema])));
140
152
  }
141
153
  function getObjectShape(schema) {
142
- const shape = _optionalChain([schema, 'access', _11 => _11._zod, 'optionalAccess', _12 => _12.def, 'optionalAccess', _13 => _13.shape]);
154
+ const shape = _optionalChain([schema, 'access', _12 => _12._zod, 'optionalAccess', _13 => _13.def, 'optionalAccess', _14 => _14.shape]);
143
155
  return typeof shape === "object" && shape !== null ? shape : void 0;
144
156
  }
145
157
  function getPropValues(schema) {
146
- return _optionalChain([schema, 'access', _14 => _14._zod, 'optionalAccess', _15 => _15.propValues]);
158
+ return _optionalChain([schema, 'access', _15 => _15._zod, 'optionalAccess', _16 => _16.propValues]);
147
159
  }
148
160
  function getArrayElement(schema) {
149
- return _optionalChain([schema, 'access', _16 => _16._zod, 'optionalAccess', _17 => _17.def, 'optionalAccess', _18 => _18.element]);
161
+ return _optionalChain([schema, 'access', _17 => _17._zod, 'optionalAccess', _18 => _18.def, 'optionalAccess', _19 => _19.element]);
150
162
  }
151
163
  function parseWithSchema(input, schema, opts) {
152
- const config = _chunkOUPKYWL3cjs.parse.call(void 0, input, opts);
164
+ const config = _chunkCPM55MMQcjs.parse.call(void 0, input, opts);
153
165
  return validate(config, schema);
154
166
  }
155
167
  function parseFileWithSchema(filePath, schema, opts) {
156
- const config = _chunkOUPKYWL3cjs.parseFile.call(void 0, filePath, opts);
168
+ const config = _chunkCPM55MMQcjs.parseFile.call(void 0, filePath, opts);
157
169
  return validate(config, schema);
158
170
  }
159
171
  function coerceValue(value, schema) {
@@ -163,13 +175,13 @@ function coerceValue(value, schema) {
163
175
  switch (defType) {
164
176
  case "boolean":
165
177
  if (typeof value === "string") {
166
- const coerced = _chunkL3D2RE2Ucjs.coerceBoolean.call(void 0, value);
178
+ const coerced = _chunkNHJJUTADcjs.coerceBoolean.call(void 0, value);
167
179
  return coerced !== void 0 ? coerced : value;
168
180
  }
169
181
  return value;
170
182
  case "number":
171
183
  if (typeof value === "string") {
172
- const coerced = _chunkL3D2RE2Ucjs.coerceNumber.call(void 0, value);
184
+ const coerced = _chunkNHJJUTADcjs.coerceNumber.call(void 0, value);
173
185
  return coerced !== void 0 ? coerced : value;
174
186
  }
175
187
  return value;
@@ -178,7 +190,7 @@ function coerceValue(value, schema) {
178
190
  return coerceToLiteral(value, values);
179
191
  }
180
192
  case "literal": {
181
- const values = _optionalChain([getDef, 'call', _19 => _19(schema), 'optionalAccess', _20 => _20.values]);
193
+ const values = _optionalChain([getDef, 'call', _20 => _20(schema), 'optionalAccess', _21 => _21.values]);
182
194
  return values ? coerceToLiteral(value, new Set(values)) : value;
183
195
  }
184
196
  case "object": {
@@ -192,7 +204,7 @@ function coerceValue(value, schema) {
192
204
  result[key] = coerceValue(obj[key], shape[key]);
193
205
  }
194
206
  }
195
- const catchall = _optionalChain([getDef, 'call', _21 => _21(schema), 'optionalAccess', _22 => _22.catchall]);
207
+ const catchall = _optionalChain([getDef, 'call', _22 => _22(schema), 'optionalAccess', _23 => _23.catchall]);
196
208
  if (catchall) {
197
209
  for (const key of Object.keys(obj)) {
198
210
  if (!Object.prototype.hasOwnProperty.call(shape, key)) result[key] = coerceValue(obj[key], catchall);
@@ -217,7 +229,7 @@ function coerceValue(value, schema) {
217
229
  }
218
230
  case "record": {
219
231
  if (typeof value !== "object" || Array.isArray(value)) return value;
220
- const valueSchema = _optionalChain([getDef, 'call', _23 => _23(schema), 'optionalAccess', _24 => _24.valueType]);
232
+ const valueSchema = _optionalChain([getDef, 'call', _24 => _24(schema), 'optionalAccess', _25 => _25.valueType]);
221
233
  if (!valueSchema) return value;
222
234
  const result = {};
223
235
  for (const [key, item] of Object.entries(value)) result[key] = coerceValue(item, valueSchema);
@@ -226,8 +238,8 @@ function coerceValue(value, schema) {
226
238
  case "tuple": {
227
239
  if (!Array.isArray(value)) return value;
228
240
  const def = getDef(schema);
229
- const items = _nullishCoalesce(_optionalChain([def, 'optionalAccess', _25 => _25.items]), () => ( []));
230
- const rest = _optionalChain([def, 'optionalAccess', _26 => _26.rest]);
241
+ const items = _nullishCoalesce(_optionalChain([def, 'optionalAccess', _26 => _26.items]), () => ( []));
242
+ const rest = _optionalChain([def, 'optionalAccess', _27 => _27.rest]);
231
243
  return value.map((item, i) => {
232
244
  const itemSchema = i < items.length ? items[i] : rest;
233
245
  return itemSchema ? coerceValue(item, itemSchema) : item;
@@ -236,11 +248,11 @@ function coerceValue(value, schema) {
236
248
  case "union":
237
249
  return coerceUnion(value, schema);
238
250
  case "pipe": {
239
- const input = _optionalChain([getDef, 'call', _27 => _27(schema), 'optionalAccess', _28 => _28.in]);
251
+ const input = _optionalChain([getDef, 'call', _28 => _28(schema), 'optionalAccess', _29 => _29.in]);
240
252
  return input ? coerceValue(value, input) : value;
241
253
  }
242
254
  case "lazy": {
243
- const getter = _optionalChain([getDef, 'call', _29 => _29(schema), 'optionalAccess', _30 => _30.getter]);
255
+ const getter = _optionalChain([getDef, 'call', _30 => _30(schema), 'optionalAccess', _31 => _31.getter]);
244
256
  return getter ? coerceValue(value, getter()) : value;
245
257
  }
246
258
  case "optional":
@@ -260,13 +272,13 @@ function coerceValue(value, schema) {
260
272
  }
261
273
  function coerceUnion(value, schema) {
262
274
  const def = getDef(schema);
263
- const options = _nullishCoalesce(_optionalChain([def, 'optionalAccess', _31 => _31.options]), () => ( []));
264
- const discriminator = _optionalChain([def, 'optionalAccess', _32 => _32.discriminator]);
275
+ const options = _nullishCoalesce(_optionalChain([def, 'optionalAccess', _32 => _32.options]), () => ( []));
276
+ const discriminator = _optionalChain([def, 'optionalAccess', _33 => _33.discriminator]);
265
277
  if (discriminator !== void 0) {
266
278
  if (typeof value !== "object" || value === null || Array.isArray(value)) return value;
267
279
  const tag = Object.prototype.hasOwnProperty.call(value, discriminator) ? value[discriminator] : void 0;
268
- const tagsOf = (o) => _optionalChain([getPropValues, 'call', _33 => _33(o), 'optionalAccess', _34 => _34[discriminator]]);
269
- const option = _nullishCoalesce(options.find((o) => _optionalChain([tagsOf, 'call', _35 => _35(o), 'optionalAccess', _36 => _36.has, 'call', _37 => _37(tag)])), () => ( options.find((o) => {
280
+ const tagsOf = (o) => _optionalChain([getPropValues, 'call', _34 => _34(o), 'optionalAccess', _35 => _35[discriminator]]);
281
+ const option = _nullishCoalesce(options.find((o) => _optionalChain([tagsOf, 'call', _36 => _36(o), 'optionalAccess', _37 => _37.has, 'call', _38 => _38(tag)])), () => ( options.find((o) => {
270
282
  const tags = tagsOf(o);
271
283
  return tags !== void 0 && tags.has(coerceToLiteral(tag, tags));
272
284
  })));
@@ -281,9 +293,9 @@ function coerceUnion(value, schema) {
281
293
  }
282
294
  function coerceToLiteral(value, literals) {
283
295
  if (typeof value !== "string" || literals.has(value)) return value;
284
- const n = _chunkL3D2RE2Ucjs.coerceNumber.call(void 0, value);
296
+ const n = _chunkNHJJUTADcjs.coerceNumber.call(void 0, value);
285
297
  if (n !== void 0 && literals.has(n)) return n;
286
- const b = _chunkL3D2RE2Ucjs.coerceBoolean.call(void 0, value);
298
+ const b = _chunkNHJJUTADcjs.coerceBoolean.call(void 0, value);
287
299
  if (b !== void 0 && literals.has(b)) return b;
288
300
  return value;
289
301
  }
package/dist/zod.d.cts CHANGED
@@ -36,6 +36,18 @@ declare function validate<T>(config: Config, schema: ZodType<T>): T;
36
36
  * @throws `ZodError` when the value does not match the schema.
37
37
  */
38
38
  declare function getValidated<T>(config: Config, path: string, schema: ZodType<T>): T;
39
+ /**
40
+ * Options for the {@link hocon} unit markers.
41
+ */
42
+ interface UnitMarkerOptions {
43
+ /**
44
+ * Refuse a value that does not name its unit: a number (`ttl = 30`) or a
45
+ * string of the number alone (`"30"`, what an environment variable gives),
46
+ * which would otherwise read in the default unit (milliseconds, bytes, days).
47
+ * `30s`, `"30 s"`, `64KiB`, `2w` read as before. Default `false` (#233).
48
+ */
49
+ readonly requireUnit?: boolean;
50
+ }
39
51
  /**
40
52
  * Zod schema markers for HOCON unit values. Each reads the forms the matching
41
53
  * Config getter reads and gives what the getter gives (a number in the
@@ -56,23 +68,26 @@ declare const hocon: {
56
68
  * significant digits than a double holds can read differently: the getter
57
69
  * reads its text, the marker its JS value (`1.0000000000000001` in `us`:
58
70
  * 1000.0000000000001 through the getter, 1000 here).
71
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
59
72
  */
60
- duration(unit?: DurationUnit): ZodTransform<number, unknown>;
73
+ duration(unit?: DurationUnit, options?: UnitMarkerOptions): ZodTransform<number, unknown>;
61
74
  /**
62
75
  * A byte size, read as {@link Config.getBytes} reads it (default unit `B`),
63
76
  * exponent forms included, except that a number literal with more
64
77
  * significant digits than a double holds can read differently: the getter
65
78
  * reads its text, the marker its JS value (`1.99999999999999999`: 1 through
66
79
  * the getter, 2 here).
80
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
67
81
  */
68
- bytes(unit?: ByteUnit): ZodTransform<number, unknown>;
82
+ bytes(unit?: ByteUnit, options?: UnitMarkerOptions): ZodTransform<number, unknown>;
69
83
  /**
70
84
  * A calendar period, read as {@link Config.getPeriod} reads it (a bare
71
85
  * integer is days), except that a number literal with a decimal point or in
72
86
  * exponent form (`7.0`, `1e2`) can read differently: the getter refuses it,
73
87
  * the marker reads the JS number.
88
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
74
89
  */
75
- period(): ZodTransform<Period, unknown>;
90
+ period(options?: UnitMarkerOptions): ZodTransform<Period, unknown>;
76
91
  };
77
92
  /**
78
93
  * Parse a HOCON string and {@link validate} it.
@@ -91,4 +106,4 @@ declare function parseWithSchema<T>(input: string, schema: ZodType<T>, opts?: Pa
91
106
  */
92
107
  declare function parseFileWithSchema<T>(filePath: string, schema: ZodType<T>, opts?: ParseOptions): T;
93
108
 
94
- export { getValidated, hocon, parseFileWithSchema, parseWithSchema, validate };
109
+ export { type UnitMarkerOptions, getValidated, hocon, parseFileWithSchema, parseWithSchema, validate };
package/dist/zod.d.ts CHANGED
@@ -36,6 +36,18 @@ declare function validate<T>(config: Config, schema: ZodType<T>): T;
36
36
  * @throws `ZodError` when the value does not match the schema.
37
37
  */
38
38
  declare function getValidated<T>(config: Config, path: string, schema: ZodType<T>): T;
39
+ /**
40
+ * Options for the {@link hocon} unit markers.
41
+ */
42
+ interface UnitMarkerOptions {
43
+ /**
44
+ * Refuse a value that does not name its unit: a number (`ttl = 30`) or a
45
+ * string of the number alone (`"30"`, what an environment variable gives),
46
+ * which would otherwise read in the default unit (milliseconds, bytes, days).
47
+ * `30s`, `"30 s"`, `64KiB`, `2w` read as before. Default `false` (#233).
48
+ */
49
+ readonly requireUnit?: boolean;
50
+ }
39
51
  /**
40
52
  * Zod schema markers for HOCON unit values. Each reads the forms the matching
41
53
  * Config getter reads and gives what the getter gives (a number in the
@@ -56,23 +68,26 @@ declare const hocon: {
56
68
  * significant digits than a double holds can read differently: the getter
57
69
  * reads its text, the marker its JS value (`1.0000000000000001` in `us`:
58
70
  * 1000.0000000000001 through the getter, 1000 here).
71
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
59
72
  */
60
- duration(unit?: DurationUnit): ZodTransform<number, unknown>;
73
+ duration(unit?: DurationUnit, options?: UnitMarkerOptions): ZodTransform<number, unknown>;
61
74
  /**
62
75
  * A byte size, read as {@link Config.getBytes} reads it (default unit `B`),
63
76
  * exponent forms included, except that a number literal with more
64
77
  * significant digits than a double holds can read differently: the getter
65
78
  * reads its text, the marker its JS value (`1.99999999999999999`: 1 through
66
79
  * the getter, 2 here).
80
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
67
81
  */
68
- bytes(unit?: ByteUnit): ZodTransform<number, unknown>;
82
+ bytes(unit?: ByteUnit, options?: UnitMarkerOptions): ZodTransform<number, unknown>;
69
83
  /**
70
84
  * A calendar period, read as {@link Config.getPeriod} reads it (a bare
71
85
  * integer is days), except that a number literal with a decimal point or in
72
86
  * exponent form (`7.0`, `1e2`) can read differently: the getter refuses it,
73
87
  * the marker reads the JS number.
88
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
74
89
  */
75
- period(): ZodTransform<Period, unknown>;
90
+ period(options?: UnitMarkerOptions): ZodTransform<Period, unknown>;
76
91
  };
77
92
  /**
78
93
  * Parse a HOCON string and {@link validate} it.
@@ -91,4 +106,4 @@ declare function parseWithSchema<T>(input: string, schema: ZodType<T>, opts?: Pa
91
106
  */
92
107
  declare function parseFileWithSchema<T>(filePath: string, schema: ZodType<T>, opts?: ParseOptions): T;
93
108
 
94
- export { getValidated, hocon, parseFileWithSchema, parseWithSchema, validate };
109
+ export { type UnitMarkerOptions, getValidated, hocon, parseFileWithSchema, parseWithSchema, validate };
package/dist/zod.js CHANGED
@@ -1,14 +1,16 @@
1
1
  import {
2
2
  parse,
3
3
  parseFile
4
- } from "./chunk-JVABBNF5.js";
4
+ } from "./chunk-ITRXT66R.js";
5
5
  import {
6
6
  coerceBoolean,
7
7
  coerceNumber,
8
+ namesMagnitudeUnit,
9
+ namesPeriodUnit,
8
10
  readBytes,
9
11
  readDuration,
10
12
  readPeriod
11
- } from "./chunk-GOXMKYWS.js";
13
+ } from "./chunk-5PV3HO2V.js";
12
14
 
13
15
  // src/zod.ts
14
16
  import { z } from "zod";
@@ -63,7 +65,7 @@ function dropPrototypeKeys(value, path, issues) {
63
65
  }
64
66
  return kept;
65
67
  }
66
- function unitMarker(what, read) {
68
+ function unitMarker(what, read, namesUnit) {
67
69
  return z.transform((input, ctx) => {
68
70
  if (typeof input !== "string" && typeof input !== "number") {
69
71
  ctx.issues.push({ code: "custom", message: `expected ${what}, got ${describeInput(input)}`, input });
@@ -71,16 +73,18 @@ function unitMarker(what, read) {
71
73
  }
72
74
  const text = typeof input === "string" ? input : String(input);
73
75
  const reading = read(text);
76
+ if (reading.ok && namesUnit !== void 0 && (typeof input === "number" || !namesUnit(text))) {
77
+ pushProblem(ctx, what, "missing-unit", input);
78
+ return z.NEVER;
79
+ }
74
80
  if (reading.ok) return reading.value;
75
- ctx.issues.push({
76
- code: "custom",
77
- message: unitProblemMessage(what, reading.problem),
78
- input,
79
- params: { problem: reading.problem }
80
- });
81
+ pushProblem(ctx, what, reading.problem, input);
81
82
  return z.NEVER;
82
83
  });
83
84
  }
85
+ function pushProblem(ctx, what, problem, input) {
86
+ ctx.issues.push({ code: "custom", message: unitProblemMessage(what, problem), input, params: { problem } });
87
+ }
84
88
  function unitProblemMessage(what, problem) {
85
89
  switch (problem) {
86
90
  case "invalid":
@@ -89,6 +93,8 @@ function unitProblemMessage(what, problem) {
89
93
  return `${what} must be non-negative`;
90
94
  case "overflow":
91
95
  return `${what} overflows the representable range`;
96
+ case "missing-unit":
97
+ return `${what} must name its unit`;
92
98
  }
93
99
  }
94
100
  function describeInput(input) {
@@ -103,9 +109,10 @@ var hocon = {
103
109
  * significant digits than a double holds can read differently: the getter
104
110
  * reads its text, the marker its JS value (`1.0000000000000001` in `us`:
105
111
  * 1000.0000000000001 through the getter, 1000 here).
112
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
106
113
  */
107
- duration(unit) {
108
- return unitMarker("duration", (text) => readDuration(text, unit));
114
+ duration(unit, options) {
115
+ return unitMarker("duration", (text) => readDuration(text, unit), requireUnit(options, namesMagnitudeUnit));
109
116
  },
110
117
  /**
111
118
  * A byte size, read as {@link Config.getBytes} reads it (default unit `B`),
@@ -113,20 +120,25 @@ var hocon = {
113
120
  * significant digits than a double holds can read differently: the getter
114
121
  * reads its text, the marker its JS value (`1.99999999999999999`: 1 through
115
122
  * the getter, 2 here).
123
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
116
124
  */
117
- bytes(unit) {
118
- return unitMarker("byte size", (text) => readBytes(text, unit));
125
+ bytes(unit, options) {
126
+ return unitMarker("byte size", (text) => readBytes(text, unit), requireUnit(options, namesMagnitudeUnit));
119
127
  },
120
128
  /**
121
129
  * A calendar period, read as {@link Config.getPeriod} reads it (a bare
122
130
  * integer is days), except that a number literal with a decimal point or in
123
131
  * exponent form (`7.0`, `1e2`) can read differently: the getter refuses it,
124
132
  * the marker reads the JS number.
133
+ * `options.requireUnit` refuses a value that does not name its unit (#233).
125
134
  */
126
- period() {
127
- return unitMarker("period", readPeriod);
135
+ period(options) {
136
+ return unitMarker("period", readPeriod, requireUnit(options, namesPeriodUnit));
128
137
  }
129
138
  };
139
+ function requireUnit(options, namesUnit) {
140
+ return options?.requireUnit === true ? namesUnit : void 0;
141
+ }
130
142
  function getDefType(schema) {
131
143
  const zod = schema._zod;
132
144
  return zod?.def?.type;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3co/ts.hocon",
3
- "version": "1.14.2",
3
+ "version": "1.14.3",
4
4
  "description": "Full Lightbend HOCON spec-compliant parser and config library for TypeScript",
5
5
  "keywords": [
6
6
  "hocon",