@o3co/ts.hocon 1.9.0 → 1.11.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.
@@ -1,6 +1,3 @@
1
- type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
2
- type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
3
-
4
1
  type ScalarValueType = 'string' | 'number' | 'boolean' | 'null';
5
2
  type HoconValue = {
6
3
  kind: 'object';
@@ -226,6 +223,9 @@ declare function parseAsync(input: string, opts?: ParseOptions): Promise<Config>
226
223
  declare function parseFile(filePath: string, opts?: ParseOptions): Config;
227
224
  declare function parseFileAsync(filePath: string, opts?: ParseOptions): Promise<Config>;
228
225
 
226
+ type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
227
+ type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
228
+
229
229
  declare class Config {
230
230
  private readonly root;
231
231
  /** @internal resolved flag: true when no substitution placeholders remain. */
@@ -316,7 +316,53 @@ declare class Config {
316
316
  * E12 decisions 9, 10.
317
317
  */
318
318
  resolveWith(source: Config, opts?: ResolveOptions): Config;
319
- toObject(): unknown;
319
+ /**
320
+ * The whole config as plain JS data: objects, arrays, strings, numbers,
321
+ * booleans and `null`.
322
+ *
323
+ * Keys are reproduced exactly as the config carries them, `__proto__`,
324
+ * `constructor` and `prototype` included: each is defined as an **own data
325
+ * property**, so the returned object's prototype is always
326
+ * `Object.prototype`, and this call writes nothing to the global one.
327
+ *
328
+ * ### Passing the result to other code
329
+ *
330
+ * A config file — especially a `.properties` file or an env namespace you
331
+ * merged in — can therefore hand you an own `__proto__` key, and what happens
332
+ * next depends entirely on how the consumer copies it:
333
+ *
334
+ * ```ts
335
+ * const data = cfg.toObject()
336
+ * { ...data } // safe — own properties are copied as data
337
+ * structuredClone(data) // safe
338
+ * Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
339
+ * // Object.prototype's __proto__ setter: the key
340
+ * // vanishes and config data becomes the result's
341
+ * // prototype
342
+ * deepMerge({}, data) // NOT safe — a naive recursive merge reads
343
+ * // target['__proto__'], gets Object.prototype,
344
+ * // and writes to it: global pollution
345
+ * for (const k in data) … // prefer Object.entries / Object.keys
346
+ * ```
347
+ *
348
+ * Those two hazards come from the **destination** object's prototype, so no
349
+ * option here can disarm them — copy with spread or `structuredClone` instead.
350
+ *
351
+ * What `{ nullPrototype: true }` does give you is a result that inherits
352
+ * nothing: every object comes back with a `null` prototype, so reading
353
+ * `x.__proto__`, `x.constructor` or `x.toString` yields config data or
354
+ * `undefined` rather than something from `Object.prototype`, and code that
355
+ * merges *into* this object cannot climb out of it. Keys are all still
356
+ * present. The trade-off is the usual one for prototype-less objects: not
357
+ * `instanceof Object`, and no `hasOwnProperty` of their own.
358
+ *
359
+ * Numbers follow the JS number model, so an integer wider than 2^53 rounds
360
+ * here even when the config holds it exactly — read those with
361
+ * {@link Config.getString} instead.
362
+ */
363
+ toObject(opts?: {
364
+ nullPrototype?: boolean;
365
+ }): unknown;
320
366
  /**
321
367
  * @internal Test-only: renders this resolved Config's value tree as canonical
322
368
  * JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
@@ -1,6 +1,3 @@
1
- type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
2
- type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
3
-
4
1
  type ScalarValueType = 'string' | 'number' | 'boolean' | 'null';
5
2
  type HoconValue = {
6
3
  kind: 'object';
@@ -226,6 +223,9 @@ declare function parseAsync(input: string, opts?: ParseOptions): Promise<Config>
226
223
  declare function parseFile(filePath: string, opts?: ParseOptions): Config;
227
224
  declare function parseFileAsync(filePath: string, opts?: ParseOptions): Promise<Config>;
228
225
 
226
+ type DurationUnit = 'ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd';
227
+ type ByteUnit = 'B' | 'KB' | 'KiB' | 'MB' | 'MiB' | 'GB' | 'GiB' | 'TB' | 'TiB';
228
+
229
229
  declare class Config {
230
230
  private readonly root;
231
231
  /** @internal resolved flag: true when no substitution placeholders remain. */
@@ -316,7 +316,53 @@ declare class Config {
316
316
  * E12 decisions 9, 10.
317
317
  */
318
318
  resolveWith(source: Config, opts?: ResolveOptions): Config;
319
- toObject(): unknown;
319
+ /**
320
+ * The whole config as plain JS data: objects, arrays, strings, numbers,
321
+ * booleans and `null`.
322
+ *
323
+ * Keys are reproduced exactly as the config carries them, `__proto__`,
324
+ * `constructor` and `prototype` included: each is defined as an **own data
325
+ * property**, so the returned object's prototype is always
326
+ * `Object.prototype`, and this call writes nothing to the global one.
327
+ *
328
+ * ### Passing the result to other code
329
+ *
330
+ * A config file — especially a `.properties` file or an env namespace you
331
+ * merged in — can therefore hand you an own `__proto__` key, and what happens
332
+ * next depends entirely on how the consumer copies it:
333
+ *
334
+ * ```ts
335
+ * const data = cfg.toObject()
336
+ * { ...data } // safe — own properties are copied as data
337
+ * structuredClone(data) // safe
338
+ * Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
339
+ * // Object.prototype's __proto__ setter: the key
340
+ * // vanishes and config data becomes the result's
341
+ * // prototype
342
+ * deepMerge({}, data) // NOT safe — a naive recursive merge reads
343
+ * // target['__proto__'], gets Object.prototype,
344
+ * // and writes to it: global pollution
345
+ * for (const k in data) … // prefer Object.entries / Object.keys
346
+ * ```
347
+ *
348
+ * Those two hazards come from the **destination** object's prototype, so no
349
+ * option here can disarm them — copy with spread or `structuredClone` instead.
350
+ *
351
+ * What `{ nullPrototype: true }` does give you is a result that inherits
352
+ * nothing: every object comes back with a `null` prototype, so reading
353
+ * `x.__proto__`, `x.constructor` or `x.toString` yields config data or
354
+ * `undefined` rather than something from `Object.prototype`, and code that
355
+ * merges *into* this object cannot climb out of it. Keys are all still
356
+ * present. The trade-off is the usual one for prototype-less objects: not
357
+ * `instanceof Object`, and no `hasOwnProperty` of their own.
358
+ *
359
+ * Numbers follow the JS number model, so an integer wider than 2^53 rounds
360
+ * here even when the config holds it exactly — read those with
361
+ * {@link Config.getString} instead.
362
+ */
363
+ toObject(opts?: {
364
+ nullPrototype?: boolean;
365
+ }): unknown;
320
366
  /**
321
367
  * @internal Test-only: renders this resolved Config's value tree as canonical
322
368
  * JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
package/dist/index.cjs CHANGED
@@ -700,6 +700,7 @@ function isFileNotFoundError(e) {
700
700
  // src/internal/resolver/include-loader.ts
701
701
  var import_node_module = require("module");
702
702
  var nodePath = __toESM(require("path"), 1);
703
+ var import_node_url = require("url");
703
704
 
704
705
  // src/internal/lexer/lexer.ts
705
706
  function isHoconWhitespace(ch) {
@@ -1101,12 +1102,12 @@ function isDecimalDigit(ch) {
1101
1102
  }
1102
1103
  function isUnquotedStart(ch) {
1103
1104
  if (ch === "" || isHoconWhitespace(ch)) return false;
1104
- if ('{}[],:=+#"$?!@*&^\\'.includes(ch)) return false;
1105
+ if ('{}[],:=+#"$?!@*&^`\\'.includes(ch)) return false;
1105
1106
  return true;
1106
1107
  }
1107
1108
  function isUnquotedContinue(ch, nextFn) {
1108
1109
  if (ch === "" || isHoconWhitespace(ch)) return false;
1109
- if ('{}[],:=#"$?!@*&^\\'.includes(ch)) return false;
1110
+ if ('{}[],:=#"$?!@*&^`\\'.includes(ch)) return false;
1110
1111
  if (ch === "+" && nextFn() === "=") return false;
1111
1112
  if (ch === "/" && nextFn() === "/") return false;
1112
1113
  return true;
@@ -1255,6 +1256,17 @@ var Parser = class {
1255
1256
  this.advance();
1256
1257
  const raw = t.value.startsWith(".") && segments.length > 0 && !t.precedingSpace ? t.value.slice(1) : t.value;
1257
1258
  const parts = raw.split(".");
1259
+ const leadingDotIsSeparator = spaceConcat || postDotPrefix !== "";
1260
+ for (let i = 0; i < parts.length; i++) {
1261
+ if (parts[i] !== "") continue;
1262
+ if (i === parts.length - 1) continue;
1263
+ if (i === 0 && leadingDotIsSeparator) continue;
1264
+ throw new ParseError(
1265
+ `path has ${i === 0 ? "a leading period '.'" : "two adjacent periods '.'"} \u2014 empty key segment not allowed, use quoted "" (HOCON.md path rules)`,
1266
+ t.line,
1267
+ t.col
1268
+ );
1269
+ }
1258
1270
  const filtered = parts.filter((s) => s.length > 0);
1259
1271
  if (spaceConcat) {
1260
1272
  segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}`;
@@ -1531,45 +1543,135 @@ function parseTokens(tokens) {
1531
1543
  return new Parser(tokens).parse();
1532
1544
  }
1533
1545
 
1546
+ // src/internal/strip-bom.ts
1547
+ function stripBom(input) {
1548
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
1549
+ }
1550
+
1534
1551
  // src/internal/properties/properties.ts
1535
1552
  function parseProperties(input) {
1536
- const root = /* @__PURE__ */ Object.create(null);
1537
1553
  const pairs = [];
1538
- for (const line of input.split("\n")) {
1539
- const trimmed = line.trim();
1540
- if (trimmed === "" || trimmed.startsWith("#") || trimmed.startsWith("!")) continue;
1541
- const sepIdx = findSeparator(trimmed);
1542
- if (sepIdx === -1) continue;
1543
- const key = trimmed.slice(0, sepIdx).trim();
1544
- const value = trimmed.slice(sepIdx + 1).trim();
1554
+ for (const { text, line } of logicalLines(stripBom(input))) {
1555
+ const [rawKey, rawValue] = splitKeyValue(text);
1556
+ const key = unescapeProps(rawKey, line);
1545
1557
  if (key === "") continue;
1546
- pairs.push([key, value]);
1558
+ pairs.push([key.split("."), unescapeProps(rawValue, line)]);
1547
1559
  }
1548
- pairs.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
1549
- for (const [key, value] of pairs) {
1550
- setNested(root, key.split("."), value);
1560
+ return nestPairs(pairs);
1561
+ }
1562
+ function nestPairs(pairs) {
1563
+ const root = /* @__PURE__ */ Object.create(null);
1564
+ const sorted = [...pairs].sort(([a], [b]) => compareSegments(a, b));
1565
+ for (const [segments, value] of sorted) {
1566
+ setNested(root, segments, value);
1551
1567
  }
1552
1568
  return root;
1553
1569
  }
1554
- function findSeparator(line) {
1555
- for (let i = 0; i < line.length; i++) {
1556
- if (line[i] === "=" || line[i] === ":") return i;
1570
+ function compareSegments(a, b) {
1571
+ const n = Math.min(a.length, b.length);
1572
+ for (let i = 0; i < n; i++) {
1573
+ const x = a[i];
1574
+ const y = b[i];
1575
+ if (x !== y) return x < y ? -1 : 1;
1576
+ }
1577
+ return a.length - b.length;
1578
+ }
1579
+ function logicalLines(input) {
1580
+ const natural = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
1581
+ const out = [];
1582
+ for (let i = 0; i < natural.length; i++) {
1583
+ let text = trimLeadingSpace(natural[i] ?? "");
1584
+ if (text === "" || text.startsWith("#") || text.startsWith("!")) continue;
1585
+ const start = i + 1;
1586
+ while (endsWithContinuation(text)) {
1587
+ text = text.slice(0, -1);
1588
+ if (i + 1 >= natural.length) break;
1589
+ i++;
1590
+ text += trimLeadingSpace(natural[i] ?? "");
1591
+ }
1592
+ out.push({ text, line: start });
1593
+ }
1594
+ return out;
1595
+ }
1596
+ function trimLeadingSpace(s) {
1597
+ return s.replace(/^[ \t\f]+/, "");
1598
+ }
1599
+ function endsWithContinuation(line) {
1600
+ let n = 0;
1601
+ for (let i = line.length - 1; i >= 0 && line[i] === "\\"; i--) n++;
1602
+ return n % 2 === 1;
1603
+ }
1604
+ function splitKeyValue(line) {
1605
+ let key = "";
1606
+ let i = 0;
1607
+ for (; i < line.length; i++) {
1608
+ const c = line[i];
1609
+ if (c === "\\" && i + 1 < line.length) {
1610
+ key += c + line[i + 1];
1611
+ i++;
1612
+ continue;
1613
+ }
1614
+ if (c === "=" || c === ":" || isPropsSpace(c)) break;
1615
+ key += c;
1616
+ }
1617
+ while (i < line.length && isPropsSpace(line[i])) i++;
1618
+ if (i < line.length && (line[i] === "=" || line[i] === ":")) {
1619
+ i++;
1620
+ while (i < line.length && isPropsSpace(line[i])) i++;
1621
+ }
1622
+ return [key, line.slice(i)];
1623
+ }
1624
+ function isPropsSpace(c) {
1625
+ return c === " " || c === " " || c === "\f";
1626
+ }
1627
+ function unescapeProps(s, line) {
1628
+ let out = "";
1629
+ for (let i = 0; i < s.length; i++) {
1630
+ if (s[i] !== "\\") {
1631
+ out += s[i];
1632
+ continue;
1633
+ }
1634
+ i++;
1635
+ if (i >= s.length) break;
1636
+ const e = s[i];
1637
+ switch (e) {
1638
+ case "t":
1639
+ out += " ";
1640
+ break;
1641
+ case "n":
1642
+ out += "\n";
1643
+ break;
1644
+ case "r":
1645
+ out += "\r";
1646
+ break;
1647
+ case "f":
1648
+ out += "\f";
1649
+ break;
1650
+ case "u": {
1651
+ const hex = s.slice(i + 1, i + 5);
1652
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
1653
+ throw new ParseError(`malformed \\u escape in .properties: \\u${hex}`, line, i + 1);
1654
+ }
1655
+ out += String.fromCharCode(parseInt(hex, 16));
1656
+ i += 4;
1657
+ break;
1658
+ }
1659
+ default:
1660
+ out += e;
1661
+ }
1557
1662
  }
1558
- return -1;
1663
+ return out;
1559
1664
  }
1560
- var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1561
1665
  function setNested(obj, segments, value) {
1562
1666
  let current = obj;
1563
1667
  for (let i = 0; i < segments.length - 1; i++) {
1564
1668
  const seg = segments[i];
1565
- if (seg === void 0 || DANGEROUS_KEYS.has(seg)) return;
1566
1669
  if (!(seg in current) || typeof current[seg] !== "object" || current[seg] === null) {
1567
1670
  current[seg] = /* @__PURE__ */ Object.create(null);
1568
1671
  }
1569
1672
  current = current[seg];
1570
1673
  }
1571
1674
  const last = segments[segments.length - 1];
1572
- if (last === void 0 || DANGEROUS_KEYS.has(last)) return;
1573
1675
  if (typeof current[last] === "object" && current[last] !== null) return;
1574
1676
  current[last] = value;
1575
1677
  }
@@ -1591,7 +1693,22 @@ function recordToHoconValue(obj) {
1591
1693
 
1592
1694
  // src/internal/resolver/include-loader.ts
1593
1695
  var import_meta = {};
1594
- var _require = (0, import_node_module.createRequire)(import_meta.url);
1696
+ var _require;
1697
+ function getRequire() {
1698
+ if (_require === void 0) {
1699
+ _require = pickRequire(
1700
+ typeof require === "function" ? require : void 0,
1701
+ import_meta.url
1702
+ );
1703
+ }
1704
+ return _require;
1705
+ }
1706
+ function pickRequire(candidate, metaUrl) {
1707
+ if (typeof candidate?.resolve === "function") {
1708
+ return candidate;
1709
+ }
1710
+ return (0, import_node_module.createRequire)(metaUrl ?? (0, import_node_url.pathToFileURL)(nodePath.join(process.cwd(), "noop.js")));
1711
+ }
1595
1712
  function isPnpPath(p) {
1596
1713
  return p.includes(".yarn/cache") || p.includes(".pnp.cjs") || p.includes(".pnp.loader");
1597
1714
  }
@@ -1647,7 +1764,7 @@ function defaultPackageResolver(identifier, file, includingFile, baseDir, resolv
1647
1764
  const from = resolveFrom ? Array.isArray(resolveFrom) ? resolveFrom : [resolveFrom] : baseDir ? [baseDir] : includingFile ? [nodePath.dirname(includingFile)] : [process.cwd()];
1648
1765
  let resolved;
1649
1766
  try {
1650
- resolved = _require.resolve(`${identifier}/${file}`, { paths: from });
1767
+ resolved = getRequire().resolve(`${identifier}/${file}`, { paths: from });
1651
1768
  } catch {
1652
1769
  throw new PackageLookupError(
1653
1770
  `include package("${identifier}", "${file}"): module not found (starting from: ${from.join(", ")})`,
@@ -2701,10 +2818,10 @@ var Config = class _Config {
2701
2818
  }
2702
2819
  if (v.kind === "object") {
2703
2820
  const converted = numericObjectToArray(v);
2704
- if (converted !== null) return converted.map(hoconToJs);
2821
+ if (converted !== null) return converted.map((item) => hoconToJs(item));
2705
2822
  }
2706
2823
  if (v.kind !== "array") throw new ConfigError(`expected array at ${path2}`, path2);
2707
- return v.items.map(hoconToJs);
2824
+ return v.items.map((item) => hoconToJs(item));
2708
2825
  }
2709
2826
  has(path2) {
2710
2827
  return this.lookupNode(path2) !== void 0;
@@ -2832,8 +2949,52 @@ var Config = class _Config {
2832
2949
  originDescription: this._originDescription
2833
2950
  });
2834
2951
  }
2835
- toObject() {
2836
- return hoconToJs(this.root);
2952
+ /**
2953
+ * The whole config as plain JS data: objects, arrays, strings, numbers,
2954
+ * booleans and `null`.
2955
+ *
2956
+ * Keys are reproduced exactly as the config carries them, `__proto__`,
2957
+ * `constructor` and `prototype` included: each is defined as an **own data
2958
+ * property**, so the returned object's prototype is always
2959
+ * `Object.prototype`, and this call writes nothing to the global one.
2960
+ *
2961
+ * ### Passing the result to other code
2962
+ *
2963
+ * A config file — especially a `.properties` file or an env namespace you
2964
+ * merged in — can therefore hand you an own `__proto__` key, and what happens
2965
+ * next depends entirely on how the consumer copies it:
2966
+ *
2967
+ * ```ts
2968
+ * const data = cfg.toObject()
2969
+ * { ...data } // safe — own properties are copied as data
2970
+ * structuredClone(data) // safe
2971
+ * Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
2972
+ * // Object.prototype's __proto__ setter: the key
2973
+ * // vanishes and config data becomes the result's
2974
+ * // prototype
2975
+ * deepMerge({}, data) // NOT safe — a naive recursive merge reads
2976
+ * // target['__proto__'], gets Object.prototype,
2977
+ * // and writes to it: global pollution
2978
+ * for (const k in data) … // prefer Object.entries / Object.keys
2979
+ * ```
2980
+ *
2981
+ * Those two hazards come from the **destination** object's prototype, so no
2982
+ * option here can disarm them — copy with spread or `structuredClone` instead.
2983
+ *
2984
+ * What `{ nullPrototype: true }` does give you is a result that inherits
2985
+ * nothing: every object comes back with a `null` prototype, so reading
2986
+ * `x.__proto__`, `x.constructor` or `x.toString` yields config data or
2987
+ * `undefined` rather than something from `Object.prototype`, and code that
2988
+ * merges *into* this object cannot climb out of it. Keys are all still
2989
+ * present. The trade-off is the usual one for prototype-less objects: not
2990
+ * `instanceof Object`, and no `hasOwnProperty` of their own.
2991
+ *
2992
+ * Numbers follow the JS number model, so an integer wider than 2^53 rounds
2993
+ * here even when the config holds it exactly — read those with
2994
+ * {@link Config.getString} instead.
2995
+ */
2996
+ toObject(opts) {
2997
+ return hoconToJs(this.root, opts?.nullPrototype === true);
2837
2998
  }
2838
2999
  /**
2839
3000
  * @internal Test-only: renders this resolved Config's value tree as canonical
@@ -2945,16 +3106,25 @@ function scalarToJs(raw, valueType) {
2945
3106
  return raw;
2946
3107
  }
2947
3108
  }
2948
- function hoconToJs(v) {
3109
+ function hoconToJs(v, nullPrototype = false) {
2949
3110
  switch (v.kind) {
2950
3111
  case "scalar":
2951
3112
  return scalarToJs(v.raw, v.valueType);
2952
3113
  case "array":
2953
- return v.items.map(hoconToJs);
3114
+ return v.items.map((item) => hoconToJs(item, nullPrototype));
2954
3115
  case "object": {
2955
- const obj = /* @__PURE__ */ Object.create(null);
2956
- for (const [k, val] of v.fields) obj[k] = hoconToJs(val);
2957
- return Object.assign({}, obj);
3116
+ const entries = Array.from(v.fields, ([k, val]) => [k, hoconToJs(val, nullPrototype)]);
3117
+ if (nullPrototype) {
3118
+ const obj = /* @__PURE__ */ Object.create(null);
3119
+ for (const [k, val] of entries) Object.defineProperty(obj, k, {
3120
+ value: val,
3121
+ writable: true,
3122
+ enumerable: true,
3123
+ configurable: true
3124
+ });
3125
+ return obj;
3126
+ }
3127
+ return Object.fromEntries(entries);
2958
3128
  }
2959
3129
  }
2960
3130
  }
@@ -3188,6 +3358,8 @@ function empty(originDescription) {
3188
3358
  const root = { kind: "object", fields: /* @__PURE__ */ new Map() };
3189
3359
  return Config._fromResolvedValue(root, { originDescription });
3190
3360
  }
3361
+ var INT64_MAX = 9223372036854775807n;
3362
+ var INT64_MIN = -9223372036854775808n;
3191
3363
  function coerceObject(obj, atPath) {
3192
3364
  const fields = /* @__PURE__ */ new Map();
3193
3365
  for (const [k, v] of Object.entries(obj)) {
@@ -3216,14 +3388,14 @@ function coerceValue(v, atPath) {
3216
3388
  atPath
3217
3389
  );
3218
3390
  }
3219
- return { kind: "scalar", raw: String(v), valueType: "number" };
3391
+ return { kind: "scalar", raw: Object.is(v, -0) ? "-0" : String(v), valueType: "number" };
3220
3392
  }
3221
3393
  case "boolean":
3222
3394
  return { kind: "scalar", raw: v ? "true" : "false", valueType: "boolean" };
3223
3395
  case "bigint": {
3224
- if (v > BigInt(Number.MAX_SAFE_INTEGER) || v < BigInt(Number.MIN_SAFE_INTEGER)) {
3396
+ if (v > INT64_MAX || v < INT64_MIN) {
3225
3397
  throw new ConfigError(
3226
- `fromMap: bigint ${v} exceeds Number.MAX_SAFE_INTEGER (not representable as HOCON number) at path "${atPath}"`,
3398
+ `fromMap: integer ${v} is out of int64 range (HOCON integers are int64; spec F0.5) at path "${atPath}"`,
3227
3399
  atPath
3228
3400
  );
3229
3401
  }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Config } from './config-D27s3_aG.cjs';
2
- export { B as ByteUnit, D as DurationUnit, H as HoconValue, P as PackageResolver, a as ParseOptions, R as ReadonlyHoconValue, b as ResolveOptions, S as ScalarValueType, c as asArray, d as asBoolean, e as asNumber, f as asObject, g as asString, h as defaultParseOptions, i as defaultResolveOptions, j as isArray, k as isNull, l as isObject, m as isScalar, p as parse, n as parseAsync, o as parseFile, q as parseFileAsync, r as parseFileWithOptions, s as parseString, t as parseStringWithOptions } from './config-D27s3_aG.cjs';
1
+ import { C as Config } from './config-Dlq6rF3w.cjs';
2
+ export { B as ByteUnit, D as DurationUnit, H as HoconValue, P as PackageResolver, a as ParseOptions, R as ReadonlyHoconValue, b as ResolveOptions, S as ScalarValueType, c as asArray, d as asBoolean, e as asNumber, f as asObject, g as asString, h as defaultParseOptions, i as defaultResolveOptions, j as isArray, k as isNull, l as isObject, m as isScalar, p as parse, n as parseAsync, o as parseFile, q as parseFileAsync, r as parseFileWithOptions, s as parseString, t as parseStringWithOptions } from './config-Dlq6rF3w.cjs';
3
3
 
4
4
  declare class ParseError extends Error {
5
5
  readonly line: number;
@@ -48,7 +48,14 @@ declare class NotResolvedError extends ConfigError {
48
48
  * null → scalar/null
49
49
  * Array<unknown> → array (elements recursively coerced)
50
50
  * Record<string,unknown> → object (values recursively coerced)
51
- * undefined / function / symbol / bigint (> MAX_SAFE_INTEGER) → ConfigError
51
+ * bigint → scalar/number, digits kept verbatim (out of int64 = error)
52
+ * undefined / function / symbol → ConfigError
53
+ *
54
+ * A `bigint` is how a caller (or a format adapter) hands over an integer that a
55
+ * JS `number` cannot hold exactly: its digits are kept verbatim in the value's
56
+ * raw text, so `getString` returns them intact, while `getNumber` / `toObject`
57
+ * apply the JS number model as they do for any other value. Integers outside
58
+ * the int64 range are rejected (spec F0.5).
52
59
  *
53
60
  * originDescription (optional) provides a source name for error messages.
54
61
  * E12 decision 13.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Config } from './config-D27s3_aG.js';
2
- export { B as ByteUnit, D as DurationUnit, H as HoconValue, P as PackageResolver, a as ParseOptions, R as ReadonlyHoconValue, b as ResolveOptions, S as ScalarValueType, c as asArray, d as asBoolean, e as asNumber, f as asObject, g as asString, h as defaultParseOptions, i as defaultResolveOptions, j as isArray, k as isNull, l as isObject, m as isScalar, p as parse, n as parseAsync, o as parseFile, q as parseFileAsync, r as parseFileWithOptions, s as parseString, t as parseStringWithOptions } from './config-D27s3_aG.js';
1
+ import { C as Config } from './config-Dlq6rF3w.js';
2
+ export { B as ByteUnit, D as DurationUnit, H as HoconValue, P as PackageResolver, a as ParseOptions, R as ReadonlyHoconValue, b as ResolveOptions, S as ScalarValueType, c as asArray, d as asBoolean, e as asNumber, f as asObject, g as asString, h as defaultParseOptions, i as defaultResolveOptions, j as isArray, k as isNull, l as isObject, m as isScalar, p as parse, n as parseAsync, o as parseFile, q as parseFileAsync, r as parseFileWithOptions, s as parseString, t as parseStringWithOptions } from './config-Dlq6rF3w.js';
3
3
 
4
4
  declare class ParseError extends Error {
5
5
  readonly line: number;
@@ -48,7 +48,14 @@ declare class NotResolvedError extends ConfigError {
48
48
  * null → scalar/null
49
49
  * Array<unknown> → array (elements recursively coerced)
50
50
  * Record<string,unknown> → object (values recursively coerced)
51
- * undefined / function / symbol / bigint (> MAX_SAFE_INTEGER) → ConfigError
51
+ * bigint → scalar/number, digits kept verbatim (out of int64 = error)
52
+ * undefined / function / symbol → ConfigError
53
+ *
54
+ * A `bigint` is how a caller (or a format adapter) hands over an integer that a
55
+ * JS `number` cannot hold exactly: its digits are kept verbatim in the value's
56
+ * raw text, so `getString` returns them intact, while `getNumber` / `toObject`
57
+ * apply the JS number model as they do for any other value. Integers outside
58
+ * the int64 range are rejected (spec F0.5).
52
59
  *
53
60
  * originDescription (optional) provides a source name for error messages.
54
61
  * E12 decision 13.