@o3co/ts.hocon 1.10.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.
package/dist/zod.js CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/coerce.ts
2
9
  var DECIMAL_NUMBER_RE = /^-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
3
10
  function isHoconWs(cp) {
@@ -643,6 +650,7 @@ function isFileNotFoundError(e) {
643
650
  // src/internal/resolver/include-loader.ts
644
651
  import { createRequire } from "module";
645
652
  import * as nodePath from "path";
653
+ import { pathToFileURL } from "url";
646
654
 
647
655
  // src/internal/lexer/lexer.ts
648
656
  function isHoconWhitespace(ch) {
@@ -1485,25 +1493,39 @@ function parseTokens(tokens) {
1485
1493
  return new Parser(tokens).parse();
1486
1494
  }
1487
1495
 
1496
+ // src/internal/strip-bom.ts
1497
+ function stripBom(input) {
1498
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
1499
+ }
1500
+
1488
1501
  // src/internal/properties/properties.ts
1489
1502
  function parseProperties(input) {
1490
1503
  const pairs = [];
1491
- for (const { text, line } of logicalLines(input)) {
1504
+ for (const { text, line } of logicalLines(stripBom(input))) {
1492
1505
  const [rawKey, rawValue] = splitKeyValue(text);
1493
1506
  const key = unescapeProps(rawKey, line);
1494
1507
  if (key === "") continue;
1495
- pairs.push([key, unescapeProps(rawValue, line)]);
1508
+ pairs.push([key.split("."), unescapeProps(rawValue, line)]);
1496
1509
  }
1497
1510
  return nestPairs(pairs);
1498
1511
  }
1499
1512
  function nestPairs(pairs) {
1500
1513
  const root = /* @__PURE__ */ Object.create(null);
1501
- const sorted = [...pairs].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
1502
- for (const [key, value] of sorted) {
1503
- setNested(root, key.split("."), value);
1514
+ const sorted = [...pairs].sort(([a], [b]) => compareSegments(a, b));
1515
+ for (const [segments, value] of sorted) {
1516
+ setNested(root, segments, value);
1504
1517
  }
1505
1518
  return root;
1506
1519
  }
1520
+ function compareSegments(a, b) {
1521
+ const n = Math.min(a.length, b.length);
1522
+ for (let i = 0; i < n; i++) {
1523
+ const x = a[i];
1524
+ const y = b[i];
1525
+ if (x !== y) return x < y ? -1 : 1;
1526
+ }
1527
+ return a.length - b.length;
1528
+ }
1507
1529
  function logicalLines(input) {
1508
1530
  const natural = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
1509
1531
  const out = [];
@@ -1590,19 +1612,16 @@ function unescapeProps(s, line) {
1590
1612
  }
1591
1613
  return out;
1592
1614
  }
1593
- var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
1594
1615
  function setNested(obj, segments, value) {
1595
1616
  let current = obj;
1596
1617
  for (let i = 0; i < segments.length - 1; i++) {
1597
1618
  const seg = segments[i];
1598
- if (seg === void 0 || DANGEROUS_KEYS.has(seg)) return;
1599
1619
  if (!(seg in current) || typeof current[seg] !== "object" || current[seg] === null) {
1600
1620
  current[seg] = /* @__PURE__ */ Object.create(null);
1601
1621
  }
1602
1622
  current = current[seg];
1603
1623
  }
1604
1624
  const last = segments[segments.length - 1];
1605
- if (last === void 0 || DANGEROUS_KEYS.has(last)) return;
1606
1625
  if (typeof current[last] === "object" && current[last] !== null) return;
1607
1626
  current[last] = value;
1608
1627
  }
@@ -1623,7 +1642,22 @@ function recordToHoconValue(obj) {
1623
1642
  }
1624
1643
 
1625
1644
  // src/internal/resolver/include-loader.ts
1626
- var _require = createRequire(import.meta.url);
1645
+ var _require;
1646
+ function getRequire() {
1647
+ if (_require === void 0) {
1648
+ _require = pickRequire(
1649
+ typeof __require === "function" ? __require : void 0,
1650
+ import.meta.url
1651
+ );
1652
+ }
1653
+ return _require;
1654
+ }
1655
+ function pickRequire(candidate, metaUrl) {
1656
+ if (typeof candidate?.resolve === "function") {
1657
+ return candidate;
1658
+ }
1659
+ return createRequire(metaUrl ?? pathToFileURL(nodePath.join(process.cwd(), "noop.js")));
1660
+ }
1627
1661
  function isPnpPath(p) {
1628
1662
  return p.includes(".yarn/cache") || p.includes(".pnp.cjs") || p.includes(".pnp.loader");
1629
1663
  }
@@ -1679,7 +1713,7 @@ function defaultPackageResolver(identifier, file, includingFile, baseDir, resolv
1679
1713
  const from = resolveFrom ? Array.isArray(resolveFrom) ? resolveFrom : [resolveFrom] : baseDir ? [baseDir] : includingFile ? [nodePath.dirname(includingFile)] : [process.cwd()];
1680
1714
  let resolved;
1681
1715
  try {
1682
- resolved = _require.resolve(`${identifier}/${file}`, { paths: from });
1716
+ resolved = getRequire().resolve(`${identifier}/${file}`, { paths: from });
1683
1717
  } catch {
1684
1718
  throw new PackageLookupError(
1685
1719
  `include package("${identifier}", "${file}"): module not found (starting from: ${from.join(", ")})`,
@@ -2729,10 +2763,10 @@ var Config = class _Config {
2729
2763
  }
2730
2764
  if (v.kind === "object") {
2731
2765
  const converted = numericObjectToArray(v);
2732
- if (converted !== null) return converted.map(hoconToJs);
2766
+ if (converted !== null) return converted.map((item) => hoconToJs(item));
2733
2767
  }
2734
2768
  if (v.kind !== "array") throw new ConfigError(`expected array at ${path2}`, path2);
2735
- return v.items.map(hoconToJs);
2769
+ return v.items.map((item) => hoconToJs(item));
2736
2770
  }
2737
2771
  has(path2) {
2738
2772
  return this.lookupNode(path2) !== void 0;
@@ -2860,8 +2894,52 @@ var Config = class _Config {
2860
2894
  originDescription: this._originDescription
2861
2895
  });
2862
2896
  }
2863
- toObject() {
2864
- return hoconToJs(this.root);
2897
+ /**
2898
+ * The whole config as plain JS data: objects, arrays, strings, numbers,
2899
+ * booleans and `null`.
2900
+ *
2901
+ * Keys are reproduced exactly as the config carries them, `__proto__`,
2902
+ * `constructor` and `prototype` included: each is defined as an **own data
2903
+ * property**, so the returned object's prototype is always
2904
+ * `Object.prototype`, and this call writes nothing to the global one.
2905
+ *
2906
+ * ### Passing the result to other code
2907
+ *
2908
+ * A config file — especially a `.properties` file or an env namespace you
2909
+ * merged in — can therefore hand you an own `__proto__` key, and what happens
2910
+ * next depends entirely on how the consumer copies it:
2911
+ *
2912
+ * ```ts
2913
+ * const data = cfg.toObject()
2914
+ * { ...data } // safe — own properties are copied as data
2915
+ * structuredClone(data) // safe
2916
+ * Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
2917
+ * // Object.prototype's __proto__ setter: the key
2918
+ * // vanishes and config data becomes the result's
2919
+ * // prototype
2920
+ * deepMerge({}, data) // NOT safe — a naive recursive merge reads
2921
+ * // target['__proto__'], gets Object.prototype,
2922
+ * // and writes to it: global pollution
2923
+ * for (const k in data) … // prefer Object.entries / Object.keys
2924
+ * ```
2925
+ *
2926
+ * Those two hazards come from the **destination** object's prototype, so no
2927
+ * option here can disarm them — copy with spread or `structuredClone` instead.
2928
+ *
2929
+ * What `{ nullPrototype: true }` does give you is a result that inherits
2930
+ * nothing: every object comes back with a `null` prototype, so reading
2931
+ * `x.__proto__`, `x.constructor` or `x.toString` yields config data or
2932
+ * `undefined` rather than something from `Object.prototype`, and code that
2933
+ * merges *into* this object cannot climb out of it. Keys are all still
2934
+ * present. The trade-off is the usual one for prototype-less objects: not
2935
+ * `instanceof Object`, and no `hasOwnProperty` of their own.
2936
+ *
2937
+ * Numbers follow the JS number model, so an integer wider than 2^53 rounds
2938
+ * here even when the config holds it exactly — read those with
2939
+ * {@link Config.getString} instead.
2940
+ */
2941
+ toObject(opts) {
2942
+ return hoconToJs(this.root, opts?.nullPrototype === true);
2865
2943
  }
2866
2944
  /**
2867
2945
  * @internal Test-only: renders this resolved Config's value tree as canonical
@@ -2973,16 +3051,25 @@ function scalarToJs(raw, valueType) {
2973
3051
  return raw;
2974
3052
  }
2975
3053
  }
2976
- function hoconToJs(v) {
3054
+ function hoconToJs(v, nullPrototype = false) {
2977
3055
  switch (v.kind) {
2978
3056
  case "scalar":
2979
3057
  return scalarToJs(v.raw, v.valueType);
2980
3058
  case "array":
2981
- return v.items.map(hoconToJs);
3059
+ return v.items.map((item) => hoconToJs(item, nullPrototype));
2982
3060
  case "object": {
2983
- const obj = /* @__PURE__ */ Object.create(null);
2984
- for (const [k, val] of v.fields) obj[k] = hoconToJs(val);
2985
- return Object.assign({}, obj);
3061
+ const entries = Array.from(v.fields, ([k, val]) => [k, hoconToJs(val, nullPrototype)]);
3062
+ if (nullPrototype) {
3063
+ const obj = /* @__PURE__ */ Object.create(null);
3064
+ for (const [k, val] of entries) Object.defineProperty(obj, k, {
3065
+ value: val,
3066
+ writable: true,
3067
+ enumerable: true,
3068
+ configurable: true
3069
+ });
3070
+ return obj;
3071
+ }
3072
+ return Object.fromEntries(entries);
2986
3073
  }
2987
3074
  }
2988
3075
  }
@@ -3173,7 +3260,7 @@ function coerceValue(value, schema) {
3173
3260
  const obj = value;
3174
3261
  const result = { ...obj };
3175
3262
  for (const key of Object.keys(shape)) {
3176
- if (key in obj) {
3263
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
3177
3264
  result[key] = coerceValue(obj[key], shape[key]);
3178
3265
  }
3179
3266
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3co/ts.hocon",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "Full Lightbend HOCON spec-compliant parser and config library for TypeScript",
5
5
  "keywords": [
6
6
  "hocon",
@@ -13,39 +13,74 @@
13
13
  "type": "module",
14
14
  "exports": {
15
15
  ".": {
16
- "types": "./dist/index.d.ts",
17
- "import": "./dist/index.js",
18
- "require": "./dist/index.cjs"
16
+ "import": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "require": {
21
+ "types": "./dist/index.d.cts",
22
+ "default": "./dist/index.cjs"
23
+ }
19
24
  },
20
25
  "./zod": {
21
- "types": "./dist/zod.d.ts",
22
- "import": "./dist/zod.js",
23
- "require": "./dist/zod.cjs"
26
+ "import": {
27
+ "types": "./dist/zod.d.ts",
28
+ "default": "./dist/zod.js"
29
+ },
30
+ "require": {
31
+ "types": "./dist/zod.d.cts",
32
+ "default": "./dist/zod.cjs"
33
+ }
24
34
  },
25
35
  "./adapters/properties": {
26
- "types": "./dist/adapters/properties.d.ts",
27
- "import": "./dist/adapters/properties.js",
28
- "require": "./dist/adapters/properties.cjs"
36
+ "import": {
37
+ "types": "./dist/adapters/properties.d.ts",
38
+ "default": "./dist/adapters/properties.js"
39
+ },
40
+ "require": {
41
+ "types": "./dist/adapters/properties.d.cts",
42
+ "default": "./dist/adapters/properties.cjs"
43
+ }
29
44
  },
30
45
  "./adapters/env": {
31
- "types": "./dist/adapters/env.d.ts",
32
- "import": "./dist/adapters/env.js",
33
- "require": "./dist/adapters/env.cjs"
46
+ "import": {
47
+ "types": "./dist/adapters/env.d.ts",
48
+ "default": "./dist/adapters/env.js"
49
+ },
50
+ "require": {
51
+ "types": "./dist/adapters/env.d.cts",
52
+ "default": "./dist/adapters/env.cjs"
53
+ }
34
54
  },
35
55
  "./adapters/jsonc": {
36
- "types": "./dist/adapters/jsonc.d.ts",
37
- "import": "./dist/adapters/jsonc.js",
38
- "require": "./dist/adapters/jsonc.cjs"
56
+ "import": {
57
+ "types": "./dist/adapters/jsonc.d.ts",
58
+ "default": "./dist/adapters/jsonc.js"
59
+ },
60
+ "require": {
61
+ "types": "./dist/adapters/jsonc.d.cts",
62
+ "default": "./dist/adapters/jsonc.cjs"
63
+ }
39
64
  },
40
65
  "./adapters/toml": {
41
- "types": "./dist/adapters/toml.d.ts",
42
- "import": "./dist/adapters/toml.js",
43
- "require": "./dist/adapters/toml.cjs"
66
+ "import": {
67
+ "types": "./dist/adapters/toml.d.ts",
68
+ "default": "./dist/adapters/toml.js"
69
+ },
70
+ "require": {
71
+ "types": "./dist/adapters/toml.d.cts",
72
+ "default": "./dist/adapters/toml.cjs"
73
+ }
44
74
  },
45
75
  "./adapters/yaml": {
46
- "types": "./dist/adapters/yaml.d.ts",
47
- "import": "./dist/adapters/yaml.js",
48
- "require": "./dist/adapters/yaml.cjs"
76
+ "import": {
77
+ "types": "./dist/adapters/yaml.d.ts",
78
+ "default": "./dist/adapters/yaml.js"
79
+ },
80
+ "require": {
81
+ "types": "./dist/adapters/yaml.d.cts",
82
+ "default": "./dist/adapters/yaml.cjs"
83
+ }
49
84
  }
50
85
  },
51
86
  "main": "./dist/index.cjs",
@@ -95,6 +130,7 @@
95
130
  "bugs": "https://github.com/o3co/ts.hocon/issues",
96
131
  "scripts": {
97
132
  "build": "tsup",
133
+ "smoke": "tsup && node tools/smoke-entrypoints.mjs",
98
134
  "test": "vitest run",
99
135
  "test:watch": "vitest",
100
136
  "typecheck": "tsc --noEmit",