@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.
- package/README.ja.md +129 -1
- package/README.md +122 -2
- package/dist/adapters/env.cjs +1738 -0
- package/dist/adapters/env.d.cts +56 -0
- package/dist/adapters/env.d.ts +56 -0
- package/dist/adapters/env.js +1700 -0
- package/dist/adapters/jsonc.cjs +1716 -0
- package/dist/adapters/jsonc.d.cts +45 -0
- package/dist/adapters/jsonc.d.ts +45 -0
- package/dist/adapters/jsonc.js +1678 -0
- package/dist/adapters/properties.cjs +1744 -0
- package/dist/adapters/properties.d.cts +32 -0
- package/dist/adapters/properties.d.ts +32 -0
- package/dist/adapters/properties.js +1707 -0
- package/dist/adapters/toml.cjs +1629 -0
- package/dist/adapters/toml.d.cts +18 -0
- package/dist/adapters/toml.d.ts +18 -0
- package/dist/adapters/toml.js +1594 -0
- package/dist/adapters/yaml.cjs +1686 -0
- package/dist/adapters/yaml.d.cts +51 -0
- package/dist/adapters/yaml.d.ts +51 -0
- package/dist/adapters/yaml.js +1650 -0
- package/dist/{config-D27s3_aG.d.cts → config-Dlq6rF3w.d.cts} +50 -4
- package/dist/{config-D27s3_aG.d.ts → config-Dlq6rF3w.d.ts} +50 -4
- package/dist/index.cjs +207 -35
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +214 -35
- package/dist/zod.cjs +203 -33
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +210 -33
- package/package.json +89 -19
package/dist/zod.cjs
CHANGED
|
@@ -682,6 +682,7 @@ function isFileNotFoundError(e) {
|
|
|
682
682
|
// src/internal/resolver/include-loader.ts
|
|
683
683
|
var import_node_module = require("module");
|
|
684
684
|
var nodePath = __toESM(require("path"), 1);
|
|
685
|
+
var import_node_url = require("url");
|
|
685
686
|
|
|
686
687
|
// src/internal/lexer/lexer.ts
|
|
687
688
|
function isHoconWhitespace(ch) {
|
|
@@ -1083,12 +1084,12 @@ function isDecimalDigit(ch) {
|
|
|
1083
1084
|
}
|
|
1084
1085
|
function isUnquotedStart(ch) {
|
|
1085
1086
|
if (ch === "" || isHoconWhitespace(ch)) return false;
|
|
1086
|
-
if ('{}[],:=+#"
|
|
1087
|
+
if ('{}[],:=+#"$?!@*&^`\\'.includes(ch)) return false;
|
|
1087
1088
|
return true;
|
|
1088
1089
|
}
|
|
1089
1090
|
function isUnquotedContinue(ch, nextFn) {
|
|
1090
1091
|
if (ch === "" || isHoconWhitespace(ch)) return false;
|
|
1091
|
-
if ('{}[],:=#"
|
|
1092
|
+
if ('{}[],:=#"$?!@*&^`\\'.includes(ch)) return false;
|
|
1092
1093
|
if (ch === "+" && nextFn() === "=") return false;
|
|
1093
1094
|
if (ch === "/" && nextFn() === "/") return false;
|
|
1094
1095
|
return true;
|
|
@@ -1237,6 +1238,17 @@ var Parser = class {
|
|
|
1237
1238
|
this.advance();
|
|
1238
1239
|
const raw = t.value.startsWith(".") && segments.length > 0 && !t.precedingSpace ? t.value.slice(1) : t.value;
|
|
1239
1240
|
const parts = raw.split(".");
|
|
1241
|
+
const leadingDotIsSeparator = spaceConcat || postDotPrefix !== "";
|
|
1242
|
+
for (let i = 0; i < parts.length; i++) {
|
|
1243
|
+
if (parts[i] !== "") continue;
|
|
1244
|
+
if (i === parts.length - 1) continue;
|
|
1245
|
+
if (i === 0 && leadingDotIsSeparator) continue;
|
|
1246
|
+
throw new ParseError(
|
|
1247
|
+
`path has ${i === 0 ? "a leading period '.'" : "two adjacent periods '.'"} \u2014 empty key segment not allowed, use quoted "" (HOCON.md path rules)`,
|
|
1248
|
+
t.line,
|
|
1249
|
+
t.col
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1240
1252
|
const filtered = parts.filter((s) => s.length > 0);
|
|
1241
1253
|
if (spaceConcat) {
|
|
1242
1254
|
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}`;
|
|
@@ -1513,45 +1525,135 @@ function parseTokens(tokens) {
|
|
|
1513
1525
|
return new Parser(tokens).parse();
|
|
1514
1526
|
}
|
|
1515
1527
|
|
|
1528
|
+
// src/internal/strip-bom.ts
|
|
1529
|
+
function stripBom(input) {
|
|
1530
|
+
return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1516
1533
|
// src/internal/properties/properties.ts
|
|
1517
1534
|
function parseProperties(input) {
|
|
1518
|
-
const root = /* @__PURE__ */ Object.create(null);
|
|
1519
1535
|
const pairs = [];
|
|
1520
|
-
for (const line of input
|
|
1521
|
-
const
|
|
1522
|
-
|
|
1523
|
-
const sepIdx = findSeparator(trimmed);
|
|
1524
|
-
if (sepIdx === -1) continue;
|
|
1525
|
-
const key = trimmed.slice(0, sepIdx).trim();
|
|
1526
|
-
const value = trimmed.slice(sepIdx + 1).trim();
|
|
1536
|
+
for (const { text, line } of logicalLines(stripBom(input))) {
|
|
1537
|
+
const [rawKey, rawValue] = splitKeyValue(text);
|
|
1538
|
+
const key = unescapeProps(rawKey, line);
|
|
1527
1539
|
if (key === "") continue;
|
|
1528
|
-
pairs.push([key,
|
|
1540
|
+
pairs.push([key.split("."), unescapeProps(rawValue, line)]);
|
|
1529
1541
|
}
|
|
1530
|
-
pairs
|
|
1531
|
-
|
|
1532
|
-
|
|
1542
|
+
return nestPairs(pairs);
|
|
1543
|
+
}
|
|
1544
|
+
function nestPairs(pairs) {
|
|
1545
|
+
const root = /* @__PURE__ */ Object.create(null);
|
|
1546
|
+
const sorted = [...pairs].sort(([a], [b]) => compareSegments(a, b));
|
|
1547
|
+
for (const [segments, value] of sorted) {
|
|
1548
|
+
setNested(root, segments, value);
|
|
1533
1549
|
}
|
|
1534
1550
|
return root;
|
|
1535
1551
|
}
|
|
1536
|
-
function
|
|
1537
|
-
|
|
1538
|
-
|
|
1552
|
+
function compareSegments(a, b) {
|
|
1553
|
+
const n = Math.min(a.length, b.length);
|
|
1554
|
+
for (let i = 0; i < n; i++) {
|
|
1555
|
+
const x = a[i];
|
|
1556
|
+
const y = b[i];
|
|
1557
|
+
if (x !== y) return x < y ? -1 : 1;
|
|
1558
|
+
}
|
|
1559
|
+
return a.length - b.length;
|
|
1560
|
+
}
|
|
1561
|
+
function logicalLines(input) {
|
|
1562
|
+
const natural = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
|
|
1563
|
+
const out = [];
|
|
1564
|
+
for (let i = 0; i < natural.length; i++) {
|
|
1565
|
+
let text = trimLeadingSpace(natural[i] ?? "");
|
|
1566
|
+
if (text === "" || text.startsWith("#") || text.startsWith("!")) continue;
|
|
1567
|
+
const start = i + 1;
|
|
1568
|
+
while (endsWithContinuation(text)) {
|
|
1569
|
+
text = text.slice(0, -1);
|
|
1570
|
+
if (i + 1 >= natural.length) break;
|
|
1571
|
+
i++;
|
|
1572
|
+
text += trimLeadingSpace(natural[i] ?? "");
|
|
1573
|
+
}
|
|
1574
|
+
out.push({ text, line: start });
|
|
1575
|
+
}
|
|
1576
|
+
return out;
|
|
1577
|
+
}
|
|
1578
|
+
function trimLeadingSpace(s) {
|
|
1579
|
+
return s.replace(/^[ \t\f]+/, "");
|
|
1580
|
+
}
|
|
1581
|
+
function endsWithContinuation(line) {
|
|
1582
|
+
let n = 0;
|
|
1583
|
+
for (let i = line.length - 1; i >= 0 && line[i] === "\\"; i--) n++;
|
|
1584
|
+
return n % 2 === 1;
|
|
1585
|
+
}
|
|
1586
|
+
function splitKeyValue(line) {
|
|
1587
|
+
let key = "";
|
|
1588
|
+
let i = 0;
|
|
1589
|
+
for (; i < line.length; i++) {
|
|
1590
|
+
const c = line[i];
|
|
1591
|
+
if (c === "\\" && i + 1 < line.length) {
|
|
1592
|
+
key += c + line[i + 1];
|
|
1593
|
+
i++;
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
if (c === "=" || c === ":" || isPropsSpace(c)) break;
|
|
1597
|
+
key += c;
|
|
1539
1598
|
}
|
|
1540
|
-
|
|
1599
|
+
while (i < line.length && isPropsSpace(line[i])) i++;
|
|
1600
|
+
if (i < line.length && (line[i] === "=" || line[i] === ":")) {
|
|
1601
|
+
i++;
|
|
1602
|
+
while (i < line.length && isPropsSpace(line[i])) i++;
|
|
1603
|
+
}
|
|
1604
|
+
return [key, line.slice(i)];
|
|
1605
|
+
}
|
|
1606
|
+
function isPropsSpace(c) {
|
|
1607
|
+
return c === " " || c === " " || c === "\f";
|
|
1608
|
+
}
|
|
1609
|
+
function unescapeProps(s, line) {
|
|
1610
|
+
let out = "";
|
|
1611
|
+
for (let i = 0; i < s.length; i++) {
|
|
1612
|
+
if (s[i] !== "\\") {
|
|
1613
|
+
out += s[i];
|
|
1614
|
+
continue;
|
|
1615
|
+
}
|
|
1616
|
+
i++;
|
|
1617
|
+
if (i >= s.length) break;
|
|
1618
|
+
const e = s[i];
|
|
1619
|
+
switch (e) {
|
|
1620
|
+
case "t":
|
|
1621
|
+
out += " ";
|
|
1622
|
+
break;
|
|
1623
|
+
case "n":
|
|
1624
|
+
out += "\n";
|
|
1625
|
+
break;
|
|
1626
|
+
case "r":
|
|
1627
|
+
out += "\r";
|
|
1628
|
+
break;
|
|
1629
|
+
case "f":
|
|
1630
|
+
out += "\f";
|
|
1631
|
+
break;
|
|
1632
|
+
case "u": {
|
|
1633
|
+
const hex = s.slice(i + 1, i + 5);
|
|
1634
|
+
if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
|
|
1635
|
+
throw new ParseError(`malformed \\u escape in .properties: \\u${hex}`, line, i + 1);
|
|
1636
|
+
}
|
|
1637
|
+
out += String.fromCharCode(parseInt(hex, 16));
|
|
1638
|
+
i += 4;
|
|
1639
|
+
break;
|
|
1640
|
+
}
|
|
1641
|
+
default:
|
|
1642
|
+
out += e;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
return out;
|
|
1541
1646
|
}
|
|
1542
|
-
var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1543
1647
|
function setNested(obj, segments, value) {
|
|
1544
1648
|
let current = obj;
|
|
1545
1649
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
1546
1650
|
const seg = segments[i];
|
|
1547
|
-
if (seg === void 0 || DANGEROUS_KEYS.has(seg)) return;
|
|
1548
1651
|
if (!(seg in current) || typeof current[seg] !== "object" || current[seg] === null) {
|
|
1549
1652
|
current[seg] = /* @__PURE__ */ Object.create(null);
|
|
1550
1653
|
}
|
|
1551
1654
|
current = current[seg];
|
|
1552
1655
|
}
|
|
1553
1656
|
const last = segments[segments.length - 1];
|
|
1554
|
-
if (last === void 0 || DANGEROUS_KEYS.has(last)) return;
|
|
1555
1657
|
if (typeof current[last] === "object" && current[last] !== null) return;
|
|
1556
1658
|
current[last] = value;
|
|
1557
1659
|
}
|
|
@@ -1573,7 +1675,22 @@ function recordToHoconValue(obj) {
|
|
|
1573
1675
|
|
|
1574
1676
|
// src/internal/resolver/include-loader.ts
|
|
1575
1677
|
var import_meta = {};
|
|
1576
|
-
var _require
|
|
1678
|
+
var _require;
|
|
1679
|
+
function getRequire() {
|
|
1680
|
+
if (_require === void 0) {
|
|
1681
|
+
_require = pickRequire(
|
|
1682
|
+
typeof require === "function" ? require : void 0,
|
|
1683
|
+
import_meta.url
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
return _require;
|
|
1687
|
+
}
|
|
1688
|
+
function pickRequire(candidate, metaUrl) {
|
|
1689
|
+
if (typeof candidate?.resolve === "function") {
|
|
1690
|
+
return candidate;
|
|
1691
|
+
}
|
|
1692
|
+
return (0, import_node_module.createRequire)(metaUrl ?? (0, import_node_url.pathToFileURL)(nodePath.join(process.cwd(), "noop.js")));
|
|
1693
|
+
}
|
|
1577
1694
|
function isPnpPath(p) {
|
|
1578
1695
|
return p.includes(".yarn/cache") || p.includes(".pnp.cjs") || p.includes(".pnp.loader");
|
|
1579
1696
|
}
|
|
@@ -1629,7 +1746,7 @@ function defaultPackageResolver(identifier, file, includingFile, baseDir, resolv
|
|
|
1629
1746
|
const from = resolveFrom ? Array.isArray(resolveFrom) ? resolveFrom : [resolveFrom] : baseDir ? [baseDir] : includingFile ? [nodePath.dirname(includingFile)] : [process.cwd()];
|
|
1630
1747
|
let resolved;
|
|
1631
1748
|
try {
|
|
1632
|
-
resolved =
|
|
1749
|
+
resolved = getRequire().resolve(`${identifier}/${file}`, { paths: from });
|
|
1633
1750
|
} catch {
|
|
1634
1751
|
throw new PackageLookupError(
|
|
1635
1752
|
`include package("${identifier}", "${file}"): module not found (starting from: ${from.join(", ")})`,
|
|
@@ -2679,10 +2796,10 @@ var Config = class _Config {
|
|
|
2679
2796
|
}
|
|
2680
2797
|
if (v.kind === "object") {
|
|
2681
2798
|
const converted = numericObjectToArray(v);
|
|
2682
|
-
if (converted !== null) return converted.map(hoconToJs);
|
|
2799
|
+
if (converted !== null) return converted.map((item) => hoconToJs(item));
|
|
2683
2800
|
}
|
|
2684
2801
|
if (v.kind !== "array") throw new ConfigError(`expected array at ${path2}`, path2);
|
|
2685
|
-
return v.items.map(hoconToJs);
|
|
2802
|
+
return v.items.map((item) => hoconToJs(item));
|
|
2686
2803
|
}
|
|
2687
2804
|
has(path2) {
|
|
2688
2805
|
return this.lookupNode(path2) !== void 0;
|
|
@@ -2810,8 +2927,52 @@ var Config = class _Config {
|
|
|
2810
2927
|
originDescription: this._originDescription
|
|
2811
2928
|
});
|
|
2812
2929
|
}
|
|
2813
|
-
|
|
2814
|
-
|
|
2930
|
+
/**
|
|
2931
|
+
* The whole config as plain JS data: objects, arrays, strings, numbers,
|
|
2932
|
+
* booleans and `null`.
|
|
2933
|
+
*
|
|
2934
|
+
* Keys are reproduced exactly as the config carries them, `__proto__`,
|
|
2935
|
+
* `constructor` and `prototype` included: each is defined as an **own data
|
|
2936
|
+
* property**, so the returned object's prototype is always
|
|
2937
|
+
* `Object.prototype`, and this call writes nothing to the global one.
|
|
2938
|
+
*
|
|
2939
|
+
* ### Passing the result to other code
|
|
2940
|
+
*
|
|
2941
|
+
* A config file — especially a `.properties` file or an env namespace you
|
|
2942
|
+
* merged in — can therefore hand you an own `__proto__` key, and what happens
|
|
2943
|
+
* next depends entirely on how the consumer copies it:
|
|
2944
|
+
*
|
|
2945
|
+
* ```ts
|
|
2946
|
+
* const data = cfg.toObject()
|
|
2947
|
+
* { ...data } // safe — own properties are copied as data
|
|
2948
|
+
* structuredClone(data) // safe
|
|
2949
|
+
* Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
|
|
2950
|
+
* // Object.prototype's __proto__ setter: the key
|
|
2951
|
+
* // vanishes and config data becomes the result's
|
|
2952
|
+
* // prototype
|
|
2953
|
+
* deepMerge({}, data) // NOT safe — a naive recursive merge reads
|
|
2954
|
+
* // target['__proto__'], gets Object.prototype,
|
|
2955
|
+
* // and writes to it: global pollution
|
|
2956
|
+
* for (const k in data) … // prefer Object.entries / Object.keys
|
|
2957
|
+
* ```
|
|
2958
|
+
*
|
|
2959
|
+
* Those two hazards come from the **destination** object's prototype, so no
|
|
2960
|
+
* option here can disarm them — copy with spread or `structuredClone` instead.
|
|
2961
|
+
*
|
|
2962
|
+
* What `{ nullPrototype: true }` does give you is a result that inherits
|
|
2963
|
+
* nothing: every object comes back with a `null` prototype, so reading
|
|
2964
|
+
* `x.__proto__`, `x.constructor` or `x.toString` yields config data or
|
|
2965
|
+
* `undefined` rather than something from `Object.prototype`, and code that
|
|
2966
|
+
* merges *into* this object cannot climb out of it. Keys are all still
|
|
2967
|
+
* present. The trade-off is the usual one for prototype-less objects: not
|
|
2968
|
+
* `instanceof Object`, and no `hasOwnProperty` of their own.
|
|
2969
|
+
*
|
|
2970
|
+
* Numbers follow the JS number model, so an integer wider than 2^53 rounds
|
|
2971
|
+
* here even when the config holds it exactly — read those with
|
|
2972
|
+
* {@link Config.getString} instead.
|
|
2973
|
+
*/
|
|
2974
|
+
toObject(opts) {
|
|
2975
|
+
return hoconToJs(this.root, opts?.nullPrototype === true);
|
|
2815
2976
|
}
|
|
2816
2977
|
/**
|
|
2817
2978
|
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
@@ -2923,16 +3084,25 @@ function scalarToJs(raw, valueType) {
|
|
|
2923
3084
|
return raw;
|
|
2924
3085
|
}
|
|
2925
3086
|
}
|
|
2926
|
-
function hoconToJs(v) {
|
|
3087
|
+
function hoconToJs(v, nullPrototype = false) {
|
|
2927
3088
|
switch (v.kind) {
|
|
2928
3089
|
case "scalar":
|
|
2929
3090
|
return scalarToJs(v.raw, v.valueType);
|
|
2930
3091
|
case "array":
|
|
2931
|
-
return v.items.map(hoconToJs);
|
|
3092
|
+
return v.items.map((item) => hoconToJs(item, nullPrototype));
|
|
2932
3093
|
case "object": {
|
|
2933
|
-
const
|
|
2934
|
-
|
|
2935
|
-
|
|
3094
|
+
const entries = Array.from(v.fields, ([k, val]) => [k, hoconToJs(val, nullPrototype)]);
|
|
3095
|
+
if (nullPrototype) {
|
|
3096
|
+
const obj = /* @__PURE__ */ Object.create(null);
|
|
3097
|
+
for (const [k, val] of entries) Object.defineProperty(obj, k, {
|
|
3098
|
+
value: val,
|
|
3099
|
+
writable: true,
|
|
3100
|
+
enumerable: true,
|
|
3101
|
+
configurable: true
|
|
3102
|
+
});
|
|
3103
|
+
return obj;
|
|
3104
|
+
}
|
|
3105
|
+
return Object.fromEntries(entries);
|
|
2936
3106
|
}
|
|
2937
3107
|
}
|
|
2938
3108
|
}
|
|
@@ -3123,7 +3293,7 @@ function coerceValue(value, schema) {
|
|
|
3123
3293
|
const obj = value;
|
|
3124
3294
|
const result = { ...obj };
|
|
3125
3295
|
for (const key of Object.keys(shape)) {
|
|
3126
|
-
if (key
|
|
3296
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
3127
3297
|
result[key] = coerceValue(obj[key], shape[key]);
|
|
3128
3298
|
}
|
|
3129
3299
|
}
|
package/dist/zod.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZodType } from 'zod';
|
|
2
|
-
import { C as Config, a as ParseOptions } from './config-
|
|
2
|
+
import { C as Config, a as ParseOptions } from './config-Dlq6rF3w.cjs';
|
|
3
3
|
|
|
4
4
|
declare function validate<T>(config: Config, schema: ZodType<T>): T;
|
|
5
5
|
declare function getValidated<T>(config: Config, path: string, schema: ZodType<T>): T;
|
package/dist/zod.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZodType } from 'zod';
|
|
2
|
-
import { C as Config, a as ParseOptions } from './config-
|
|
2
|
+
import { C as Config, a as ParseOptions } from './config-Dlq6rF3w.js';
|
|
3
3
|
|
|
4
4
|
declare function validate<T>(config: Config, schema: ZodType<T>): T;
|
|
5
5
|
declare function getValidated<T>(config: Config, path: string, schema: ZodType<T>): T;
|