@o3co/ts.hocon 1.4.0 → 1.5.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/index.cjs CHANGED
@@ -949,12 +949,17 @@ var Parser = class {
949
949
  const segments = [];
950
950
  let trailingDot = false;
951
951
  let firstWasQuoted = false;
952
+ let spaceConcat = false;
952
953
  while (true) {
953
954
  const t = this.peek();
954
955
  if (t.kind === "string") {
955
956
  this.advance();
956
957
  if (segments.length === 0) firstWasQuoted = true;
957
- segments.push(t.value);
958
+ if (spaceConcat) {
959
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${t.value}`;
960
+ } else {
961
+ segments.push(t.value);
962
+ }
958
963
  trailingDot = false;
959
964
  } else if (t.kind === "unquoted") {
960
965
  this.advance();
@@ -971,12 +976,23 @@ var Parser = class {
971
976
  );
972
977
  }
973
978
  }
974
- segments.push(...filtered);
979
+ if (spaceConcat && filtered.length > 0) {
980
+ if (raw.startsWith(".")) {
981
+ segments.push(...filtered);
982
+ } else {
983
+ const [head, ...tail] = filtered;
984
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${head}`;
985
+ segments.push(...tail);
986
+ }
987
+ } else {
988
+ segments.push(...filtered);
989
+ }
975
990
  trailingDot = raw.endsWith(".");
976
991
  } else {
977
992
  if (segments.length === 0) throw new ParseError(`expected key, got ${t.kind}`, t.line, t.col);
978
993
  break;
979
994
  }
995
+ spaceConcat = false;
980
996
  if (trailingDot) continue;
981
997
  const next = this.peek();
982
998
  if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
@@ -988,6 +1004,10 @@ var Parser = class {
988
1004
  trailingDot = true;
989
1005
  continue;
990
1006
  }
1007
+ if ((next.kind === "unquoted" || next.kind === "string") && next.precedingSpace) {
1008
+ spaceConcat = true;
1009
+ continue;
1010
+ }
991
1011
  break;
992
1012
  }
993
1013
  return { segments, firstWasQuoted };
@@ -1503,7 +1523,9 @@ var IncludeLoader = class {
1503
1523
  return hoconValueToResObj(propertiesToHoconValue(content));
1504
1524
  }
1505
1525
  const tokens = tokenize(content);
1506
- assertNonEmptyDocument(tokens, candidate);
1526
+ if (!hasContentTokens(tokens)) {
1527
+ return makeResObj();
1528
+ }
1507
1529
  const ast = parseTokens(tokens);
1508
1530
  return this.onBuildResObj(ast, {
1509
1531
  ...this.opts,
@@ -1528,7 +1550,9 @@ var IncludeLoader = class {
1528
1550
  return hoconValueToResObj(propertiesToHoconValue(content));
1529
1551
  }
1530
1552
  const tokens = tokenize(content);
1531
- assertNonEmptyDocument(tokens, candidate);
1553
+ if (!hasContentTokens(tokens)) {
1554
+ return makeResObj();
1555
+ }
1532
1556
  const ast = parseTokens(tokens);
1533
1557
  return this.onBuildResObjAsync(ast, {
1534
1558
  ...this.opts,
@@ -2100,8 +2124,33 @@ var SubstitutionResolver = class {
2100
2124
  }
2101
2125
  resolveAppend(a, scope) {
2102
2126
  const existing = this.resolveVal(a.existing, scope) ?? { kind: "array", items: [] };
2127
+ if (this.opts.allowUnresolved && (isSubst(existing) || isConcat(existing) || isAppend(existing))) {
2128
+ return a;
2129
+ }
2103
2130
  const elem = this.resolveVal(a.elem, scope);
2104
- const items = existing.kind === "array" ? [...existing.items] : [existing];
2131
+ let priorItems;
2132
+ if (existing.kind === "array") {
2133
+ priorItems = existing.items;
2134
+ } else if (existing.kind === "object") {
2135
+ const converted = numericObjectToArray(existing);
2136
+ if (converted === null) {
2137
+ throw new ResolveError(
2138
+ `'+=' on non-array value: prior value is object with non-numeric keys (spec L732)`,
2139
+ "",
2140
+ 0,
2141
+ 0
2142
+ );
2143
+ }
2144
+ priorItems = converted;
2145
+ } else {
2146
+ throw new ResolveError(
2147
+ `'+=' on non-array value: prior value is ${existing.kind} (spec L732)`,
2148
+ "",
2149
+ 0,
2150
+ 0
2151
+ );
2152
+ }
2153
+ const items = [...priorItems];
2105
2154
  if (elem !== void 0) items.push(elem);
2106
2155
  return { kind: "array", items };
2107
2156
  }
@@ -2203,6 +2252,9 @@ var Config = class _Config {
2203
2252
  }
2204
2253
  getString(path2) {
2205
2254
  const v = this.requireScalar(path2);
2255
+ if (v.valueType === "null") {
2256
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2257
+ }
2206
2258
  return v.raw;
2207
2259
  }
2208
2260
  getNumber(path2) {
package/dist/index.js CHANGED
@@ -897,12 +897,17 @@ var Parser = class {
897
897
  const segments = [];
898
898
  let trailingDot = false;
899
899
  let firstWasQuoted = false;
900
+ let spaceConcat = false;
900
901
  while (true) {
901
902
  const t = this.peek();
902
903
  if (t.kind === "string") {
903
904
  this.advance();
904
905
  if (segments.length === 0) firstWasQuoted = true;
905
- segments.push(t.value);
906
+ if (spaceConcat) {
907
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${t.value}`;
908
+ } else {
909
+ segments.push(t.value);
910
+ }
906
911
  trailingDot = false;
907
912
  } else if (t.kind === "unquoted") {
908
913
  this.advance();
@@ -919,12 +924,23 @@ var Parser = class {
919
924
  );
920
925
  }
921
926
  }
922
- segments.push(...filtered);
927
+ if (spaceConcat && filtered.length > 0) {
928
+ if (raw.startsWith(".")) {
929
+ segments.push(...filtered);
930
+ } else {
931
+ const [head, ...tail] = filtered;
932
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${head}`;
933
+ segments.push(...tail);
934
+ }
935
+ } else {
936
+ segments.push(...filtered);
937
+ }
923
938
  trailingDot = raw.endsWith(".");
924
939
  } else {
925
940
  if (segments.length === 0) throw new ParseError(`expected key, got ${t.kind}`, t.line, t.col);
926
941
  break;
927
942
  }
943
+ spaceConcat = false;
928
944
  if (trailingDot) continue;
929
945
  const next = this.peek();
930
946
  if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
@@ -936,6 +952,10 @@ var Parser = class {
936
952
  trailingDot = true;
937
953
  continue;
938
954
  }
955
+ if ((next.kind === "unquoted" || next.kind === "string") && next.precedingSpace) {
956
+ spaceConcat = true;
957
+ continue;
958
+ }
939
959
  break;
940
960
  }
941
961
  return { segments, firstWasQuoted };
@@ -1450,7 +1470,9 @@ var IncludeLoader = class {
1450
1470
  return hoconValueToResObj(propertiesToHoconValue(content));
1451
1471
  }
1452
1472
  const tokens = tokenize(content);
1453
- assertNonEmptyDocument(tokens, candidate);
1473
+ if (!hasContentTokens(tokens)) {
1474
+ return makeResObj();
1475
+ }
1454
1476
  const ast = parseTokens(tokens);
1455
1477
  return this.onBuildResObj(ast, {
1456
1478
  ...this.opts,
@@ -1475,7 +1497,9 @@ var IncludeLoader = class {
1475
1497
  return hoconValueToResObj(propertiesToHoconValue(content));
1476
1498
  }
1477
1499
  const tokens = tokenize(content);
1478
- assertNonEmptyDocument(tokens, candidate);
1500
+ if (!hasContentTokens(tokens)) {
1501
+ return makeResObj();
1502
+ }
1479
1503
  const ast = parseTokens(tokens);
1480
1504
  return this.onBuildResObjAsync(ast, {
1481
1505
  ...this.opts,
@@ -2047,8 +2071,33 @@ var SubstitutionResolver = class {
2047
2071
  }
2048
2072
  resolveAppend(a, scope) {
2049
2073
  const existing = this.resolveVal(a.existing, scope) ?? { kind: "array", items: [] };
2074
+ if (this.opts.allowUnresolved && (isSubst(existing) || isConcat(existing) || isAppend(existing))) {
2075
+ return a;
2076
+ }
2050
2077
  const elem = this.resolveVal(a.elem, scope);
2051
- const items = existing.kind === "array" ? [...existing.items] : [existing];
2078
+ let priorItems;
2079
+ if (existing.kind === "array") {
2080
+ priorItems = existing.items;
2081
+ } else if (existing.kind === "object") {
2082
+ const converted = numericObjectToArray(existing);
2083
+ if (converted === null) {
2084
+ throw new ResolveError(
2085
+ `'+=' on non-array value: prior value is object with non-numeric keys (spec L732)`,
2086
+ "",
2087
+ 0,
2088
+ 0
2089
+ );
2090
+ }
2091
+ priorItems = converted;
2092
+ } else {
2093
+ throw new ResolveError(
2094
+ `'+=' on non-array value: prior value is ${existing.kind} (spec L732)`,
2095
+ "",
2096
+ 0,
2097
+ 0
2098
+ );
2099
+ }
2100
+ const items = [...priorItems];
2052
2101
  if (elem !== void 0) items.push(elem);
2053
2102
  return { kind: "array", items };
2054
2103
  }
@@ -2150,6 +2199,9 @@ var Config = class _Config {
2150
2199
  }
2151
2200
  getString(path2) {
2152
2201
  const v = this.requireScalar(path2);
2202
+ if (v.valueType === "null") {
2203
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2204
+ }
2153
2205
  return v.raw;
2154
2206
  }
2155
2207
  getNumber(path2) {
package/dist/zod.cjs CHANGED
@@ -940,12 +940,17 @@ var Parser = class {
940
940
  const segments = [];
941
941
  let trailingDot = false;
942
942
  let firstWasQuoted = false;
943
+ let spaceConcat = false;
943
944
  while (true) {
944
945
  const t = this.peek();
945
946
  if (t.kind === "string") {
946
947
  this.advance();
947
948
  if (segments.length === 0) firstWasQuoted = true;
948
- segments.push(t.value);
949
+ if (spaceConcat) {
950
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${t.value}`;
951
+ } else {
952
+ segments.push(t.value);
953
+ }
949
954
  trailingDot = false;
950
955
  } else if (t.kind === "unquoted") {
951
956
  this.advance();
@@ -962,12 +967,23 @@ var Parser = class {
962
967
  );
963
968
  }
964
969
  }
965
- segments.push(...filtered);
970
+ if (spaceConcat && filtered.length > 0) {
971
+ if (raw.startsWith(".")) {
972
+ segments.push(...filtered);
973
+ } else {
974
+ const [head, ...tail] = filtered;
975
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${head}`;
976
+ segments.push(...tail);
977
+ }
978
+ } else {
979
+ segments.push(...filtered);
980
+ }
966
981
  trailingDot = raw.endsWith(".");
967
982
  } else {
968
983
  if (segments.length === 0) throw new ParseError(`expected key, got ${t.kind}`, t.line, t.col);
969
984
  break;
970
985
  }
986
+ spaceConcat = false;
971
987
  if (trailingDot) continue;
972
988
  const next = this.peek();
973
989
  if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
@@ -979,6 +995,10 @@ var Parser = class {
979
995
  trailingDot = true;
980
996
  continue;
981
997
  }
998
+ if ((next.kind === "unquoted" || next.kind === "string") && next.precedingSpace) {
999
+ spaceConcat = true;
1000
+ continue;
1001
+ }
982
1002
  break;
983
1003
  }
984
1004
  return { segments, firstWasQuoted };
@@ -1494,7 +1514,9 @@ var IncludeLoader = class {
1494
1514
  return hoconValueToResObj(propertiesToHoconValue(content));
1495
1515
  }
1496
1516
  const tokens = tokenize(content);
1497
- assertNonEmptyDocument(tokens, candidate);
1517
+ if (!hasContentTokens(tokens)) {
1518
+ return makeResObj();
1519
+ }
1498
1520
  const ast = parseTokens(tokens);
1499
1521
  return this.onBuildResObj(ast, {
1500
1522
  ...this.opts,
@@ -1519,7 +1541,9 @@ var IncludeLoader = class {
1519
1541
  return hoconValueToResObj(propertiesToHoconValue(content));
1520
1542
  }
1521
1543
  const tokens = tokenize(content);
1522
- assertNonEmptyDocument(tokens, candidate);
1544
+ if (!hasContentTokens(tokens)) {
1545
+ return makeResObj();
1546
+ }
1523
1547
  const ast = parseTokens(tokens);
1524
1548
  return this.onBuildResObjAsync(ast, {
1525
1549
  ...this.opts,
@@ -2091,8 +2115,33 @@ var SubstitutionResolver = class {
2091
2115
  }
2092
2116
  resolveAppend(a, scope) {
2093
2117
  const existing = this.resolveVal(a.existing, scope) ?? { kind: "array", items: [] };
2118
+ if (this.opts.allowUnresolved && (isSubst(existing) || isConcat(existing) || isAppend(existing))) {
2119
+ return a;
2120
+ }
2094
2121
  const elem = this.resolveVal(a.elem, scope);
2095
- const items = existing.kind === "array" ? [...existing.items] : [existing];
2122
+ let priorItems;
2123
+ if (existing.kind === "array") {
2124
+ priorItems = existing.items;
2125
+ } else if (existing.kind === "object") {
2126
+ const converted = numericObjectToArray(existing);
2127
+ if (converted === null) {
2128
+ throw new ResolveError(
2129
+ `'+=' on non-array value: prior value is object with non-numeric keys (spec L732)`,
2130
+ "",
2131
+ 0,
2132
+ 0
2133
+ );
2134
+ }
2135
+ priorItems = converted;
2136
+ } else {
2137
+ throw new ResolveError(
2138
+ `'+=' on non-array value: prior value is ${existing.kind} (spec L732)`,
2139
+ "",
2140
+ 0,
2141
+ 0
2142
+ );
2143
+ }
2144
+ const items = [...priorItems];
2096
2145
  if (elem !== void 0) items.push(elem);
2097
2146
  return { kind: "array", items };
2098
2147
  }
@@ -2190,6 +2239,9 @@ var Config = class _Config {
2190
2239
  }
2191
2240
  getString(path2) {
2192
2241
  const v = this.requireScalar(path2);
2242
+ if (v.valueType === "null") {
2243
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2244
+ }
2193
2245
  return v.raw;
2194
2246
  }
2195
2247
  getNumber(path2) {
package/dist/zod.js CHANGED
@@ -901,12 +901,17 @@ var Parser = class {
901
901
  const segments = [];
902
902
  let trailingDot = false;
903
903
  let firstWasQuoted = false;
904
+ let spaceConcat = false;
904
905
  while (true) {
905
906
  const t = this.peek();
906
907
  if (t.kind === "string") {
907
908
  this.advance();
908
909
  if (segments.length === 0) firstWasQuoted = true;
909
- segments.push(t.value);
910
+ if (spaceConcat) {
911
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${t.value}`;
912
+ } else {
913
+ segments.push(t.value);
914
+ }
910
915
  trailingDot = false;
911
916
  } else if (t.kind === "unquoted") {
912
917
  this.advance();
@@ -923,12 +928,23 @@ var Parser = class {
923
928
  );
924
929
  }
925
930
  }
926
- segments.push(...filtered);
931
+ if (spaceConcat && filtered.length > 0) {
932
+ if (raw.startsWith(".")) {
933
+ segments.push(...filtered);
934
+ } else {
935
+ const [head, ...tail] = filtered;
936
+ segments[segments.length - 1] = `${segments[segments.length - 1]} ${head}`;
937
+ segments.push(...tail);
938
+ }
939
+ } else {
940
+ segments.push(...filtered);
941
+ }
927
942
  trailingDot = raw.endsWith(".");
928
943
  } else {
929
944
  if (segments.length === 0) throw new ParseError(`expected key, got ${t.kind}`, t.line, t.col);
930
945
  break;
931
946
  }
947
+ spaceConcat = false;
932
948
  if (trailingDot) continue;
933
949
  const next = this.peek();
934
950
  if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
@@ -940,6 +956,10 @@ var Parser = class {
940
956
  trailingDot = true;
941
957
  continue;
942
958
  }
959
+ if ((next.kind === "unquoted" || next.kind === "string") && next.precedingSpace) {
960
+ spaceConcat = true;
961
+ continue;
962
+ }
943
963
  break;
944
964
  }
945
965
  return { segments, firstWasQuoted };
@@ -1454,7 +1474,9 @@ var IncludeLoader = class {
1454
1474
  return hoconValueToResObj(propertiesToHoconValue(content));
1455
1475
  }
1456
1476
  const tokens = tokenize(content);
1457
- assertNonEmptyDocument(tokens, candidate);
1477
+ if (!hasContentTokens(tokens)) {
1478
+ return makeResObj();
1479
+ }
1458
1480
  const ast = parseTokens(tokens);
1459
1481
  return this.onBuildResObj(ast, {
1460
1482
  ...this.opts,
@@ -1479,7 +1501,9 @@ var IncludeLoader = class {
1479
1501
  return hoconValueToResObj(propertiesToHoconValue(content));
1480
1502
  }
1481
1503
  const tokens = tokenize(content);
1482
- assertNonEmptyDocument(tokens, candidate);
1504
+ if (!hasContentTokens(tokens)) {
1505
+ return makeResObj();
1506
+ }
1483
1507
  const ast = parseTokens(tokens);
1484
1508
  return this.onBuildResObjAsync(ast, {
1485
1509
  ...this.opts,
@@ -2051,8 +2075,33 @@ var SubstitutionResolver = class {
2051
2075
  }
2052
2076
  resolveAppend(a, scope) {
2053
2077
  const existing = this.resolveVal(a.existing, scope) ?? { kind: "array", items: [] };
2078
+ if (this.opts.allowUnresolved && (isSubst(existing) || isConcat(existing) || isAppend(existing))) {
2079
+ return a;
2080
+ }
2054
2081
  const elem = this.resolveVal(a.elem, scope);
2055
- const items = existing.kind === "array" ? [...existing.items] : [existing];
2082
+ let priorItems;
2083
+ if (existing.kind === "array") {
2084
+ priorItems = existing.items;
2085
+ } else if (existing.kind === "object") {
2086
+ const converted = numericObjectToArray(existing);
2087
+ if (converted === null) {
2088
+ throw new ResolveError(
2089
+ `'+=' on non-array value: prior value is object with non-numeric keys (spec L732)`,
2090
+ "",
2091
+ 0,
2092
+ 0
2093
+ );
2094
+ }
2095
+ priorItems = converted;
2096
+ } else {
2097
+ throw new ResolveError(
2098
+ `'+=' on non-array value: prior value is ${existing.kind} (spec L732)`,
2099
+ "",
2100
+ 0,
2101
+ 0
2102
+ );
2103
+ }
2104
+ const items = [...priorItems];
2056
2105
  if (elem !== void 0) items.push(elem);
2057
2106
  return { kind: "array", items };
2058
2107
  }
@@ -2150,6 +2199,9 @@ var Config = class _Config {
2150
2199
  }
2151
2200
  getString(path2) {
2152
2201
  const v = this.requireScalar(path2);
2202
+ if (v.valueType === "null") {
2203
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2204
+ }
2153
2205
  return v.raw;
2154
2206
  }
2155
2207
  getNumber(path2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3co/ts.hocon",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Full Lightbend HOCON spec-compliant parser and config library for TypeScript",
5
5
  "keywords": [
6
6
  "hocon",