@o3co/ts.hocon 1.4.1 → 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 };
@@ -2104,8 +2124,33 @@ var SubstitutionResolver = class {
2104
2124
  }
2105
2125
  resolveAppend(a, scope) {
2106
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
+ }
2107
2130
  const elem = this.resolveVal(a.elem, scope);
2108
- 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];
2109
2154
  if (elem !== void 0) items.push(elem);
2110
2155
  return { kind: "array", items };
2111
2156
  }
@@ -2207,6 +2252,9 @@ var Config = class _Config {
2207
2252
  }
2208
2253
  getString(path2) {
2209
2254
  const v = this.requireScalar(path2);
2255
+ if (v.valueType === "null") {
2256
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2257
+ }
2210
2258
  return v.raw;
2211
2259
  }
2212
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 };
@@ -2051,8 +2071,33 @@ var SubstitutionResolver = class {
2051
2071
  }
2052
2072
  resolveAppend(a, scope) {
2053
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
+ }
2054
2077
  const elem = this.resolveVal(a.elem, scope);
2055
- 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];
2056
2101
  if (elem !== void 0) items.push(elem);
2057
2102
  return { kind: "array", items };
2058
2103
  }
@@ -2154,6 +2199,9 @@ var Config = class _Config {
2154
2199
  }
2155
2200
  getString(path2) {
2156
2201
  const v = this.requireScalar(path2);
2202
+ if (v.valueType === "null") {
2203
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2204
+ }
2157
2205
  return v.raw;
2158
2206
  }
2159
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 };
@@ -2095,8 +2115,33 @@ var SubstitutionResolver = class {
2095
2115
  }
2096
2116
  resolveAppend(a, scope) {
2097
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
+ }
2098
2121
  const elem = this.resolveVal(a.elem, scope);
2099
- 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];
2100
2145
  if (elem !== void 0) items.push(elem);
2101
2146
  return { kind: "array", items };
2102
2147
  }
@@ -2194,6 +2239,9 @@ var Config = class _Config {
2194
2239
  }
2195
2240
  getString(path2) {
2196
2241
  const v = this.requireScalar(path2);
2242
+ if (v.valueType === "null") {
2243
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2244
+ }
2197
2245
  return v.raw;
2198
2246
  }
2199
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 };
@@ -2055,8 +2075,33 @@ var SubstitutionResolver = class {
2055
2075
  }
2056
2076
  resolveAppend(a, scope) {
2057
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
+ }
2058
2081
  const elem = this.resolveVal(a.elem, scope);
2059
- 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];
2060
2105
  if (elem !== void 0) items.push(elem);
2061
2106
  return { kind: "array", items };
2062
2107
  }
@@ -2154,6 +2199,9 @@ var Config = class _Config {
2154
2199
  }
2155
2200
  getString(path2) {
2156
2201
  const v = this.requireScalar(path2);
2202
+ if (v.valueType === "null") {
2203
+ throw new ConfigError(`expected string at ${path2}, got ${v.valueType}`, path2);
2204
+ }
2157
2205
  return v.raw;
2158
2206
  }
2159
2207
  getNumber(path2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@o3co/ts.hocon",
3
- "version": "1.4.1",
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",