@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/README.ja.md +129 -1
- package/README.md +90 -2
- package/dist/adapters/env.cjs +98 -28
- package/dist/adapters/env.d.cts +16 -1
- package/dist/adapters/env.d.ts +16 -1
- package/dist/adapters/env.js +98 -27
- package/dist/adapters/jsonc.cjs +120 -17
- package/dist/adapters/jsonc.d.cts +24 -4
- package/dist/adapters/jsonc.d.ts +24 -4
- package/dist/adapters/jsonc.js +120 -16
- package/dist/adapters/properties.cjs +87 -24
- package/dist/adapters/properties.d.cts +6 -1
- package/dist/adapters/properties.d.ts +6 -1
- package/dist/adapters/properties.js +87 -23
- package/dist/adapters/toml.cjs +79 -20
- package/dist/adapters/toml.d.cts +1 -1
- package/dist/adapters/toml.d.ts +1 -1
- package/dist/adapters/toml.js +79 -19
- package/dist/adapters/yaml.cjs +100 -24
- package/dist/adapters/yaml.d.cts +10 -2
- package/dist/adapters/yaml.d.ts +10 -2
- package/dist/adapters/yaml.js +100 -23
- package/dist/{config-PdhVgeLS.d.cts → config-Dlq6rF3w.d.cts} +47 -1
- package/dist/{config-PdhVgeLS.d.ts → config-Dlq6rF3w.d.ts} +47 -1
- package/dist/index.cjs +104 -22
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +111 -22
- package/dist/zod.cjs +100 -20
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +107 -20
- package/package.json +58 -22
package/dist/adapters/yaml.js
CHANGED
|
@@ -516,7 +516,12 @@ function deepMergeHoconValues(base, overlay) {
|
|
|
516
516
|
// src/internal/resolver/include-loader.ts
|
|
517
517
|
import { createRequire } from "module";
|
|
518
518
|
import * as nodePath from "path";
|
|
519
|
-
|
|
519
|
+
import { pathToFileURL } from "url";
|
|
520
|
+
|
|
521
|
+
// src/internal/strip-bom.ts
|
|
522
|
+
function stripBom(input) {
|
|
523
|
+
return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
|
|
524
|
+
}
|
|
520
525
|
|
|
521
526
|
// src/value/numeric-array.ts
|
|
522
527
|
function numericObjectToArray(value) {
|
|
@@ -1105,10 +1110,10 @@ var Config = class _Config {
|
|
|
1105
1110
|
}
|
|
1106
1111
|
if (v.kind === "object") {
|
|
1107
1112
|
const converted = numericObjectToArray(v);
|
|
1108
|
-
if (converted !== null) return converted.map(hoconToJs);
|
|
1113
|
+
if (converted !== null) return converted.map((item) => hoconToJs(item));
|
|
1109
1114
|
}
|
|
1110
1115
|
if (v.kind !== "array") throw new ConfigError(`expected array at ${path}`, path);
|
|
1111
|
-
return v.items.map(hoconToJs);
|
|
1116
|
+
return v.items.map((item) => hoconToJs(item));
|
|
1112
1117
|
}
|
|
1113
1118
|
has(path) {
|
|
1114
1119
|
return this.lookupNode(path) !== void 0;
|
|
@@ -1236,8 +1241,52 @@ var Config = class _Config {
|
|
|
1236
1241
|
originDescription: this._originDescription
|
|
1237
1242
|
});
|
|
1238
1243
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1244
|
+
/**
|
|
1245
|
+
* The whole config as plain JS data: objects, arrays, strings, numbers,
|
|
1246
|
+
* booleans and `null`.
|
|
1247
|
+
*
|
|
1248
|
+
* Keys are reproduced exactly as the config carries them, `__proto__`,
|
|
1249
|
+
* `constructor` and `prototype` included: each is defined as an **own data
|
|
1250
|
+
* property**, so the returned object's prototype is always
|
|
1251
|
+
* `Object.prototype`, and this call writes nothing to the global one.
|
|
1252
|
+
*
|
|
1253
|
+
* ### Passing the result to other code
|
|
1254
|
+
*
|
|
1255
|
+
* A config file — especially a `.properties` file or an env namespace you
|
|
1256
|
+
* merged in — can therefore hand you an own `__proto__` key, and what happens
|
|
1257
|
+
* next depends entirely on how the consumer copies it:
|
|
1258
|
+
*
|
|
1259
|
+
* ```ts
|
|
1260
|
+
* const data = cfg.toObject()
|
|
1261
|
+
* { ...data } // safe — own properties are copied as data
|
|
1262
|
+
* structuredClone(data) // safe
|
|
1263
|
+
* Object.assign({}, data) // NOT safe — [[Set]] on the {} target hits
|
|
1264
|
+
* // Object.prototype's __proto__ setter: the key
|
|
1265
|
+
* // vanishes and config data becomes the result's
|
|
1266
|
+
* // prototype
|
|
1267
|
+
* deepMerge({}, data) // NOT safe — a naive recursive merge reads
|
|
1268
|
+
* // target['__proto__'], gets Object.prototype,
|
|
1269
|
+
* // and writes to it: global pollution
|
|
1270
|
+
* for (const k in data) … // prefer Object.entries / Object.keys
|
|
1271
|
+
* ```
|
|
1272
|
+
*
|
|
1273
|
+
* Those two hazards come from the **destination** object's prototype, so no
|
|
1274
|
+
* option here can disarm them — copy with spread or `structuredClone` instead.
|
|
1275
|
+
*
|
|
1276
|
+
* What `{ nullPrototype: true }` does give you is a result that inherits
|
|
1277
|
+
* nothing: every object comes back with a `null` prototype, so reading
|
|
1278
|
+
* `x.__proto__`, `x.constructor` or `x.toString` yields config data or
|
|
1279
|
+
* `undefined` rather than something from `Object.prototype`, and code that
|
|
1280
|
+
* merges *into* this object cannot climb out of it. Keys are all still
|
|
1281
|
+
* present. The trade-off is the usual one for prototype-less objects: not
|
|
1282
|
+
* `instanceof Object`, and no `hasOwnProperty` of their own.
|
|
1283
|
+
*
|
|
1284
|
+
* Numbers follow the JS number model, so an integer wider than 2^53 rounds
|
|
1285
|
+
* here even when the config holds it exactly — read those with
|
|
1286
|
+
* {@link Config.getString} instead.
|
|
1287
|
+
*/
|
|
1288
|
+
toObject(opts) {
|
|
1289
|
+
return hoconToJs(this.root, opts?.nullPrototype === true);
|
|
1241
1290
|
}
|
|
1242
1291
|
/**
|
|
1243
1292
|
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
@@ -1349,16 +1398,25 @@ function scalarToJs(raw, valueType) {
|
|
|
1349
1398
|
return raw;
|
|
1350
1399
|
}
|
|
1351
1400
|
}
|
|
1352
|
-
function hoconToJs(v) {
|
|
1401
|
+
function hoconToJs(v, nullPrototype = false) {
|
|
1353
1402
|
switch (v.kind) {
|
|
1354
1403
|
case "scalar":
|
|
1355
1404
|
return scalarToJs(v.raw, v.valueType);
|
|
1356
1405
|
case "array":
|
|
1357
|
-
return v.items.map(hoconToJs);
|
|
1406
|
+
return v.items.map((item) => hoconToJs(item, nullPrototype));
|
|
1358
1407
|
case "object": {
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
|
|
1408
|
+
const entries = Array.from(v.fields, ([k, val]) => [k, hoconToJs(val, nullPrototype)]);
|
|
1409
|
+
if (nullPrototype) {
|
|
1410
|
+
const obj = /* @__PURE__ */ Object.create(null);
|
|
1411
|
+
for (const [k, val] of entries) Object.defineProperty(obj, k, {
|
|
1412
|
+
value: val,
|
|
1413
|
+
writable: true,
|
|
1414
|
+
enumerable: true,
|
|
1415
|
+
configurable: true
|
|
1416
|
+
});
|
|
1417
|
+
return obj;
|
|
1418
|
+
}
|
|
1419
|
+
return Object.fromEntries(entries);
|
|
1362
1420
|
}
|
|
1363
1421
|
}
|
|
1364
1422
|
}
|
|
@@ -1447,6 +1505,8 @@ function fromMap(values, originDescription) {
|
|
|
1447
1505
|
const root = { kind: "object", fields };
|
|
1448
1506
|
return Config._fromResolvedValue(root, { originDescription });
|
|
1449
1507
|
}
|
|
1508
|
+
var INT64_MAX = 9223372036854775807n;
|
|
1509
|
+
var INT64_MIN = -9223372036854775808n;
|
|
1450
1510
|
function coerceObject(obj, atPath) {
|
|
1451
1511
|
const fields = /* @__PURE__ */ new Map();
|
|
1452
1512
|
for (const [k, v] of Object.entries(obj)) {
|
|
@@ -1475,14 +1535,14 @@ function coerceValue(v, atPath) {
|
|
|
1475
1535
|
atPath
|
|
1476
1536
|
);
|
|
1477
1537
|
}
|
|
1478
|
-
return { kind: "scalar", raw: String(v), valueType: "number" };
|
|
1538
|
+
return { kind: "scalar", raw: Object.is(v, -0) ? "-0" : String(v), valueType: "number" };
|
|
1479
1539
|
}
|
|
1480
1540
|
case "boolean":
|
|
1481
1541
|
return { kind: "scalar", raw: v ? "true" : "false", valueType: "boolean" };
|
|
1482
1542
|
case "bigint": {
|
|
1483
|
-
if (v >
|
|
1543
|
+
if (v > INT64_MAX || v < INT64_MIN) {
|
|
1484
1544
|
throw new ConfigError(
|
|
1485
|
-
`fromMap:
|
|
1545
|
+
`fromMap: integer ${v} is out of int64 range (HOCON integers are int64; spec F0.5) at path "${atPath}"`,
|
|
1486
1546
|
atPath
|
|
1487
1547
|
);
|
|
1488
1548
|
}
|
|
@@ -1506,7 +1566,7 @@ function coerceValue(v, atPath) {
|
|
|
1506
1566
|
|
|
1507
1567
|
// src/adapters/yaml.ts
|
|
1508
1568
|
function parseYaml(input, originDescription) {
|
|
1509
|
-
const docs = YAML.parseAllDocuments(input, { version: "1.2", merge: true });
|
|
1569
|
+
const docs = YAML.parseAllDocuments(stripBom(input), { version: "1.2", merge: true, intAsBigInt: true });
|
|
1510
1570
|
if (docs.length > 1) {
|
|
1511
1571
|
throw new ConfigError(
|
|
1512
1572
|
"yaml: multi-document streams are not supported (spec F5.7); a config is one document",
|
|
@@ -1537,7 +1597,7 @@ function convert(v, atPath) {
|
|
|
1537
1597
|
return v.toISOString();
|
|
1538
1598
|
}
|
|
1539
1599
|
if (v instanceof Map) {
|
|
1540
|
-
const
|
|
1600
|
+
const entries = [];
|
|
1541
1601
|
for (const [k, e] of v) {
|
|
1542
1602
|
if (k !== null && typeof k === "object") {
|
|
1543
1603
|
throw new ConfigError(
|
|
@@ -1545,19 +1605,20 @@ function convert(v, atPath) {
|
|
|
1545
1605
|
atPath
|
|
1546
1606
|
);
|
|
1547
1607
|
}
|
|
1548
|
-
|
|
1608
|
+
const key = String(k);
|
|
1609
|
+
entries.push([key, convert(e, atPath === "" ? key : `${atPath}.${key}`)]);
|
|
1549
1610
|
}
|
|
1550
|
-
return
|
|
1611
|
+
return Object.fromEntries(entries);
|
|
1551
1612
|
}
|
|
1552
1613
|
if (v instanceof Uint8Array) {
|
|
1553
|
-
return
|
|
1614
|
+
return bytesToBase64(v);
|
|
1554
1615
|
}
|
|
1555
1616
|
if (v !== null && typeof v === "object") {
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1617
|
+
return Object.fromEntries(
|
|
1618
|
+
Object.entries(v).map(
|
|
1619
|
+
([k, e]) => [k, convert(e, atPath === "" ? k : `${atPath}.${k}`)]
|
|
1620
|
+
)
|
|
1621
|
+
);
|
|
1561
1622
|
}
|
|
1562
1623
|
if (typeof v === "number" && !Number.isFinite(v)) {
|
|
1563
1624
|
throw new ConfigError(
|
|
@@ -1565,8 +1626,24 @@ function convert(v, atPath) {
|
|
|
1565
1626
|
atPath
|
|
1566
1627
|
);
|
|
1567
1628
|
}
|
|
1629
|
+
if (typeof v === "bigint") {
|
|
1630
|
+
return isSafeIntegerBigInt(v) ? Number(v) : v;
|
|
1631
|
+
}
|
|
1568
1632
|
return v;
|
|
1569
1633
|
}
|
|
1634
|
+
function bytesToBase64(bytes) {
|
|
1635
|
+
const CHUNK = 32768;
|
|
1636
|
+
let binary = "";
|
|
1637
|
+
for (let i = 0; i < bytes.length; i += CHUNK) {
|
|
1638
|
+
binary += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
|
|
1639
|
+
}
|
|
1640
|
+
return btoa(binary);
|
|
1641
|
+
}
|
|
1642
|
+
var MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1643
|
+
var MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);
|
|
1644
|
+
function isSafeIntegerBigInt(v) {
|
|
1645
|
+
return v <= MAX_SAFE && v >= MIN_SAFE;
|
|
1646
|
+
}
|
|
1570
1647
|
export {
|
|
1571
1648
|
fromYamlValue,
|
|
1572
1649
|
parseYaml
|
|
@@ -316,7 +316,53 @@ declare class Config {
|
|
|
316
316
|
* E12 decisions 9, 10.
|
|
317
317
|
*/
|
|
318
318
|
resolveWith(source: Config, opts?: ResolveOptions): Config;
|
|
319
|
-
|
|
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
|
|
@@ -316,7 +316,53 @@ declare class Config {
|
|
|
316
316
|
* E12 decisions 9, 10.
|
|
317
317
|
*/
|
|
318
318
|
resolveWith(source: Config, opts?: ResolveOptions): Config;
|
|
319
|
-
|
|
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) {
|
|
@@ -1542,25 +1543,39 @@ function parseTokens(tokens) {
|
|
|
1542
1543
|
return new Parser(tokens).parse();
|
|
1543
1544
|
}
|
|
1544
1545
|
|
|
1546
|
+
// src/internal/strip-bom.ts
|
|
1547
|
+
function stripBom(input) {
|
|
1548
|
+
return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1545
1551
|
// src/internal/properties/properties.ts
|
|
1546
1552
|
function parseProperties(input) {
|
|
1547
1553
|
const pairs = [];
|
|
1548
|
-
for (const { text, line } of logicalLines(input)) {
|
|
1554
|
+
for (const { text, line } of logicalLines(stripBom(input))) {
|
|
1549
1555
|
const [rawKey, rawValue] = splitKeyValue(text);
|
|
1550
1556
|
const key = unescapeProps(rawKey, line);
|
|
1551
1557
|
if (key === "") continue;
|
|
1552
|
-
pairs.push([key, unescapeProps(rawValue, line)]);
|
|
1558
|
+
pairs.push([key.split("."), unescapeProps(rawValue, line)]);
|
|
1553
1559
|
}
|
|
1554
1560
|
return nestPairs(pairs);
|
|
1555
1561
|
}
|
|
1556
1562
|
function nestPairs(pairs) {
|
|
1557
1563
|
const root = /* @__PURE__ */ Object.create(null);
|
|
1558
|
-
const sorted = [...pairs].sort(([a], [b]) => a
|
|
1559
|
-
for (const [
|
|
1560
|
-
setNested(root,
|
|
1564
|
+
const sorted = [...pairs].sort(([a], [b]) => compareSegments(a, b));
|
|
1565
|
+
for (const [segments, value] of sorted) {
|
|
1566
|
+
setNested(root, segments, value);
|
|
1561
1567
|
}
|
|
1562
1568
|
return root;
|
|
1563
1569
|
}
|
|
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
|
+
}
|
|
1564
1579
|
function logicalLines(input) {
|
|
1565
1580
|
const natural = input.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
|
|
1566
1581
|
const out = [];
|
|
@@ -1647,19 +1662,16 @@ function unescapeProps(s, line) {
|
|
|
1647
1662
|
}
|
|
1648
1663
|
return out;
|
|
1649
1664
|
}
|
|
1650
|
-
var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
1651
1665
|
function setNested(obj, segments, value) {
|
|
1652
1666
|
let current = obj;
|
|
1653
1667
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
1654
1668
|
const seg = segments[i];
|
|
1655
|
-
if (seg === void 0 || DANGEROUS_KEYS.has(seg)) return;
|
|
1656
1669
|
if (!(seg in current) || typeof current[seg] !== "object" || current[seg] === null) {
|
|
1657
1670
|
current[seg] = /* @__PURE__ */ Object.create(null);
|
|
1658
1671
|
}
|
|
1659
1672
|
current = current[seg];
|
|
1660
1673
|
}
|
|
1661
1674
|
const last = segments[segments.length - 1];
|
|
1662
|
-
if (last === void 0 || DANGEROUS_KEYS.has(last)) return;
|
|
1663
1675
|
if (typeof current[last] === "object" && current[last] !== null) return;
|
|
1664
1676
|
current[last] = value;
|
|
1665
1677
|
}
|
|
@@ -1681,7 +1693,22 @@ function recordToHoconValue(obj) {
|
|
|
1681
1693
|
|
|
1682
1694
|
// src/internal/resolver/include-loader.ts
|
|
1683
1695
|
var import_meta = {};
|
|
1684
|
-
var _require
|
|
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
|
+
}
|
|
1685
1712
|
function isPnpPath(p) {
|
|
1686
1713
|
return p.includes(".yarn/cache") || p.includes(".pnp.cjs") || p.includes(".pnp.loader");
|
|
1687
1714
|
}
|
|
@@ -1737,7 +1764,7 @@ function defaultPackageResolver(identifier, file, includingFile, baseDir, resolv
|
|
|
1737
1764
|
const from = resolveFrom ? Array.isArray(resolveFrom) ? resolveFrom : [resolveFrom] : baseDir ? [baseDir] : includingFile ? [nodePath.dirname(includingFile)] : [process.cwd()];
|
|
1738
1765
|
let resolved;
|
|
1739
1766
|
try {
|
|
1740
|
-
resolved =
|
|
1767
|
+
resolved = getRequire().resolve(`${identifier}/${file}`, { paths: from });
|
|
1741
1768
|
} catch {
|
|
1742
1769
|
throw new PackageLookupError(
|
|
1743
1770
|
`include package("${identifier}", "${file}"): module not found (starting from: ${from.join(", ")})`,
|
|
@@ -2791,10 +2818,10 @@ var Config = class _Config {
|
|
|
2791
2818
|
}
|
|
2792
2819
|
if (v.kind === "object") {
|
|
2793
2820
|
const converted = numericObjectToArray(v);
|
|
2794
|
-
if (converted !== null) return converted.map(hoconToJs);
|
|
2821
|
+
if (converted !== null) return converted.map((item) => hoconToJs(item));
|
|
2795
2822
|
}
|
|
2796
2823
|
if (v.kind !== "array") throw new ConfigError(`expected array at ${path2}`, path2);
|
|
2797
|
-
return v.items.map(hoconToJs);
|
|
2824
|
+
return v.items.map((item) => hoconToJs(item));
|
|
2798
2825
|
}
|
|
2799
2826
|
has(path2) {
|
|
2800
2827
|
return this.lookupNode(path2) !== void 0;
|
|
@@ -2922,8 +2949,52 @@ var Config = class _Config {
|
|
|
2922
2949
|
originDescription: this._originDescription
|
|
2923
2950
|
});
|
|
2924
2951
|
}
|
|
2925
|
-
|
|
2926
|
-
|
|
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);
|
|
2927
2998
|
}
|
|
2928
2999
|
/**
|
|
2929
3000
|
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
@@ -3035,16 +3106,25 @@ function scalarToJs(raw, valueType) {
|
|
|
3035
3106
|
return raw;
|
|
3036
3107
|
}
|
|
3037
3108
|
}
|
|
3038
|
-
function hoconToJs(v) {
|
|
3109
|
+
function hoconToJs(v, nullPrototype = false) {
|
|
3039
3110
|
switch (v.kind) {
|
|
3040
3111
|
case "scalar":
|
|
3041
3112
|
return scalarToJs(v.raw, v.valueType);
|
|
3042
3113
|
case "array":
|
|
3043
|
-
return v.items.map(hoconToJs);
|
|
3114
|
+
return v.items.map((item) => hoconToJs(item, nullPrototype));
|
|
3044
3115
|
case "object": {
|
|
3045
|
-
const
|
|
3046
|
-
|
|
3047
|
-
|
|
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);
|
|
3048
3128
|
}
|
|
3049
3129
|
}
|
|
3050
3130
|
}
|
|
@@ -3278,6 +3358,8 @@ function empty(originDescription) {
|
|
|
3278
3358
|
const root = { kind: "object", fields: /* @__PURE__ */ new Map() };
|
|
3279
3359
|
return Config._fromResolvedValue(root, { originDescription });
|
|
3280
3360
|
}
|
|
3361
|
+
var INT64_MAX = 9223372036854775807n;
|
|
3362
|
+
var INT64_MIN = -9223372036854775808n;
|
|
3281
3363
|
function coerceObject(obj, atPath) {
|
|
3282
3364
|
const fields = /* @__PURE__ */ new Map();
|
|
3283
3365
|
for (const [k, v] of Object.entries(obj)) {
|
|
@@ -3306,14 +3388,14 @@ function coerceValue(v, atPath) {
|
|
|
3306
3388
|
atPath
|
|
3307
3389
|
);
|
|
3308
3390
|
}
|
|
3309
|
-
return { kind: "scalar", raw: String(v), valueType: "number" };
|
|
3391
|
+
return { kind: "scalar", raw: Object.is(v, -0) ? "-0" : String(v), valueType: "number" };
|
|
3310
3392
|
}
|
|
3311
3393
|
case "boolean":
|
|
3312
3394
|
return { kind: "scalar", raw: v ? "true" : "false", valueType: "boolean" };
|
|
3313
3395
|
case "bigint": {
|
|
3314
|
-
if (v >
|
|
3396
|
+
if (v > INT64_MAX || v < INT64_MIN) {
|
|
3315
3397
|
throw new ConfigError(
|
|
3316
|
-
`fromMap:
|
|
3398
|
+
`fromMap: integer ${v} is out of int64 range (HOCON integers are int64; spec F0.5) at path "${atPath}"`,
|
|
3317
3399
|
atPath
|
|
3318
3400
|
);
|
|
3319
3401
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Config } from './config-
|
|
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-
|
|
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
|
-
*
|
|
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-
|
|
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-
|
|
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
|
-
*
|
|
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.
|