effect 4.0.0-beta.84 → 4.0.0-beta.85

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.
Files changed (56) hide show
  1. package/dist/Context.d.ts.map +1 -1
  2. package/dist/Context.js +4 -3
  3. package/dist/Context.js.map +1 -1
  4. package/dist/Layer.js +4 -3
  5. package/dist/Layer.js.map +1 -1
  6. package/dist/LayerMap.d.ts.map +1 -1
  7. package/dist/LayerMap.js +4 -3
  8. package/dist/LayerMap.js.map +1 -1
  9. package/dist/Random.d.ts +31 -0
  10. package/dist/Random.d.ts.map +1 -1
  11. package/dist/Random.js +32 -0
  12. package/dist/Random.js.map +1 -1
  13. package/dist/Schema.d.ts +48 -6
  14. package/dist/Schema.d.ts.map +1 -1
  15. package/dist/Schema.js +31 -11
  16. package/dist/Schema.js.map +1 -1
  17. package/dist/SchemaAST.d.ts +8 -7
  18. package/dist/SchemaAST.d.ts.map +1 -1
  19. package/dist/SchemaAST.js +190 -131
  20. package/dist/SchemaAST.js.map +1 -1
  21. package/dist/internal/effect.js +10 -10
  22. package/dist/internal/effect.js.map +1 -1
  23. package/dist/internal/schema/arbitrary.js +17 -1
  24. package/dist/internal/schema/arbitrary.js.map +1 -1
  25. package/dist/internal/stackTraceLimit.d.ts +2 -0
  26. package/dist/internal/stackTraceLimit.d.ts.map +1 -0
  27. package/dist/internal/stackTraceLimit.js +40 -0
  28. package/dist/internal/stackTraceLimit.js.map +1 -0
  29. package/dist/internal/tracer.d.ts.map +1 -1
  30. package/dist/internal/tracer.js +4 -3
  31. package/dist/internal/tracer.js.map +1 -1
  32. package/dist/unstable/ai/Tool.d.ts.map +1 -1
  33. package/dist/unstable/ai/Tool.js +4 -5
  34. package/dist/unstable/ai/Tool.js.map +1 -1
  35. package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
  36. package/dist/unstable/httpapi/HttpApiMiddleware.js +4 -3
  37. package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
  38. package/dist/unstable/persistence/PersistedQueue.js +1 -1
  39. package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
  40. package/dist/unstable/rpc/RpcMiddleware.js +4 -3
  41. package/dist/unstable/rpc/RpcMiddleware.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/Context.ts +4 -5
  44. package/src/Layer.ts +4 -4
  45. package/src/LayerMap.ts +4 -3
  46. package/src/Random.ts +42 -0
  47. package/src/Schema.ts +75 -22
  48. package/src/SchemaAST.ts +217 -137
  49. package/src/internal/effect.ts +11 -11
  50. package/src/internal/schema/arbitrary.ts +23 -2
  51. package/src/internal/stackTraceLimit.ts +63 -0
  52. package/src/internal/tracer.ts +4 -3
  53. package/src/unstable/ai/Tool.ts +4 -3
  54. package/src/unstable/httpapi/HttpApiMiddleware.ts +4 -3
  55. package/src/unstable/persistence/PersistedQueue.ts +1 -1
  56. package/src/unstable/rpc/RpcMiddleware.ts +4 -3
package/src/SchemaAST.ts CHANGED
@@ -25,7 +25,6 @@ import * as InternalSchemaCause from "./internal/schema/cause.ts"
25
25
  import * as Option from "./Option.ts"
26
26
  import * as Pipeable from "./Pipeable.ts"
27
27
  import * as Predicate from "./Predicate.ts"
28
- import * as RegEx from "./RegExp.ts"
29
28
  import * as Result from "./Result.ts"
30
29
  import type * as Schema from "./Schema.ts"
31
30
  import * as SchemaGetter from "./SchemaGetter.ts"
@@ -679,7 +678,7 @@ export class Declaration extends Base {
679
678
  return Effect.mapEager(run(oinput.value, this, options), Option.some)
680
679
  }
681
680
  }
682
- private rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
681
+ private _rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
683
682
  const tps = mapOrSame(this.typeParameters, recur)
684
683
  return tps === this.typeParameters ?
685
684
  this :
@@ -687,11 +686,11 @@ export class Declaration extends Base {
687
686
  }
688
687
  /** @internal */
689
688
  recur(recur: (ast: AST) => AST) {
690
- return this.rebuild(recur, this.checks, this.encodingChecks)
689
+ return this._rebuild(recur, this.checks, this.encodingChecks)
691
690
  }
692
691
  /** @internal */
693
692
  flip(recur: (ast: AST) => AST) {
694
- return this.rebuild(recur, this.encodingChecks, this.checks)
693
+ return this._rebuild(recur, this.encodingChecks, this.checks)
695
694
  }
696
695
  /** @internal */
697
696
  getExpected(): string {
@@ -1066,11 +1065,12 @@ function isTemplateLiteralPart(ast: AST): ast is TemplateLiteralPart {
1066
1065
  case "String":
1067
1066
  case "Number":
1068
1067
  case "BigInt":
1068
+ return true
1069
1069
  case "Literal":
1070
1070
  case "TemplateLiteral":
1071
- return true
1071
+ return ast.checks === undefined
1072
1072
  case "Union":
1073
- return ast.types.every(isTemplateLiteralPart)
1073
+ return ast.checks === undefined && ast.types.every(isTemplateLiteralPart)
1074
1074
  default:
1075
1075
  return false
1076
1076
  }
@@ -1082,8 +1082,7 @@ function isTemplateLiteralPart(ast: AST): ast is TemplateLiteralPart {
1082
1082
  *
1083
1083
  * **Details**
1084
1084
  *
1085
- * `parts` is an array of AST nodes; each part contributes to the
1086
- * template literal pattern. A regex is derived from the parts to validate
1085
+ * `parts` is an array of AST nodes; each part contributes to matching
1087
1086
  * strings at runtime.
1088
1087
  *
1089
1088
  * @see {@link isTemplateLiteral}
@@ -1130,19 +1129,22 @@ export class TemplateLiteral extends Base {
1130
1129
  return "string"
1131
1130
  }
1132
1131
  /** @internal */
1132
+ matchPart(s: string, options: ParseOptions): string | undefined {
1133
+ return segmentTemplateLiteralParts(this.encodedParts, s, options) === undefined ? undefined : s
1134
+ }
1135
+ /** @internal */
1133
1136
  asTemplateLiteralParser(): Arrays {
1134
- const tuple = new Arrays(false, this.parts.map(templateLiteralPartFromString), [])
1135
- const regExp = getTemplateLiteralRegExp(this)
1137
+ const tuple = new Arrays(false, this.parts.map(partFromString), [])
1136
1138
  return decodeTo(
1137
1139
  string,
1138
1140
  tuple,
1139
1141
  new SchemaTransformation.Transformation(
1140
- SchemaGetter.transformOrFail((s: string) => {
1141
- const match = regExp.exec(s)
1142
- if (match) return Effect.succeed(match.slice(1, this.parts.length + 1))
1142
+ SchemaGetter.transformOrFail((s: string, options) => {
1143
+ const segments = segmentTemplateLiteralParts(this.encodedParts, s, options)
1144
+ if (segments !== undefined) return Effect.succeed(segments)
1143
1145
  return Effect.fail(
1144
1146
  new SchemaIssue.InvalidValue(Option.some(s), {
1145
- message: `Expected a value matching ${regExp.source}, got ${format(s)}`
1147
+ message: `Expected a string matching template literal parts, got ${format(s)}`
1146
1148
  })
1147
1149
  )
1148
1150
  }),
@@ -1248,6 +1250,10 @@ export class Literal extends Base {
1248
1250
  return fromConst(this, this.literal)
1249
1251
  }
1250
1252
  /** @internal */
1253
+ matchPart(s: string, _options: ParseOptions): LiteralValue | undefined {
1254
+ return s === globalThis.String(this.literal) ? this.literal : undefined
1255
+ }
1256
+ /** @internal */
1251
1257
  toCodecJson(): AST {
1252
1258
  return typeof this.literal === "bigint" ? literalToString(this) : this
1253
1259
  }
@@ -1290,6 +1296,10 @@ export class String extends Base {
1290
1296
  return fromRefinement(this, Predicate.isString)
1291
1297
  }
1292
1298
  /** @internal */
1299
+ matchPart(s: string, options: ParseOptions): string | undefined {
1300
+ return applyTemplateLiteralPartChecks(this, s, options)
1301
+ }
1302
+ /** @internal */
1293
1303
  getExpected(): string {
1294
1304
  return "string"
1295
1305
  }
@@ -1336,6 +1346,19 @@ export class Number extends Base {
1336
1346
  return fromRefinement(this, Predicate.isNumber)
1337
1347
  }
1338
1348
  /** @internal */
1349
+ matchKey(s: string, options: ParseOptions): number | undefined {
1350
+ return this._match(isStringNumberRegExp, s, options)
1351
+ }
1352
+ /** @internal */
1353
+ matchPart(s: string, options: ParseOptions): number | undefined {
1354
+ return this._match(isStringFiniteRegExp, s, options)
1355
+ }
1356
+ private _match(regexp: RegExp, s: string, options: ParseOptions): number | undefined {
1357
+ return regexp.test(s)
1358
+ ? applyTemplateLiteralPartChecks(this, globalThis.Number(s), options)
1359
+ : undefined
1360
+ }
1361
+ /** @internal */
1339
1362
  toCodecJson(): AST {
1340
1363
  if (this.checks && (hasCheck(this.checks, "isFinite") || hasCheck(this.checks, "isInt"))) {
1341
1364
  return this
@@ -1445,6 +1468,10 @@ export class Symbol extends Base {
1445
1468
  return fromRefinement(this, Predicate.isSymbol)
1446
1469
  }
1447
1470
  /** @internal */
1471
+ matchKey(s: symbol, options: ParseOptions): symbol | undefined {
1472
+ return applyTemplateLiteralPartChecks(this, s, options)
1473
+ }
1474
+ /** @internal */
1448
1475
  toCodecStringTree(): AST {
1449
1476
  return replaceEncoding(this, [symbolToString])
1450
1477
  }
@@ -1494,6 +1521,12 @@ export class BigInt extends Base {
1494
1521
  return fromRefinement(this, Predicate.isBigInt)
1495
1522
  }
1496
1523
  /** @internal */
1524
+ matchPart(s: string, options: ParseOptions): bigint | undefined {
1525
+ return isStringBigIntRegExp.test(s)
1526
+ ? applyTemplateLiteralPartChecks(this, globalThis.BigInt(s), options)
1527
+ : undefined
1528
+ }
1529
+ /** @internal */
1497
1530
  toCodecStringTree(): AST {
1498
1531
  return replaceEncoding(this, [bigIntToString])
1499
1532
  }
@@ -1668,7 +1701,7 @@ export class Arrays extends Base {
1668
1701
  return Option.some(state.output)
1669
1702
  })
1670
1703
  }
1671
- private rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
1704
+ private _rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
1672
1705
  const elements = mapOrSame(this.elements, recur)
1673
1706
  const rest = mapOrSame(this.rest, recur)
1674
1707
  return elements === this.elements && rest === this.rest ?
@@ -1686,11 +1719,11 @@ export class Arrays extends Base {
1686
1719
  }
1687
1720
  /** @internal */
1688
1721
  recur(recur: (ast: AST) => AST) {
1689
- return this.rebuild(recur, this.checks, this.encodingChecks)
1722
+ return this._rebuild(recur, this.checks, this.encodingChecks)
1690
1723
  }
1691
1724
  /** @internal */
1692
1725
  flip(recur: (ast: AST) => AST) {
1693
- return this.rebuild(recur, this.encodingChecks, this.checks)
1726
+ return this._rebuild(recur, this.encodingChecks, this.checks)
1694
1727
  }
1695
1728
  /** @internal */
1696
1729
  getExpected(): string {
@@ -1783,33 +1816,36 @@ const wrapPropertyKeyIssue = (
1783
1816
  */
1784
1817
  export const FINITE_PATTERN = "[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?"
1785
1818
 
1786
- const isNumberStringRegExp = new globalThis.RegExp(`(?:${FINITE_PATTERN}|Infinity|-Infinity|NaN)`)
1787
-
1788
1819
  /**
1789
1820
  * Returns the object keys that match the index signature parameter schema.
1790
1821
  * @internal
1791
1822
  */
1792
1823
  export function getIndexSignatureKeys(
1793
1824
  input: { readonly [x: PropertyKey]: unknown },
1794
- parameter: AST
1825
+ parameter: IndexSignatureParameter,
1826
+ options: ParseOptions = defaultParseOptions
1795
1827
  ): ReadonlyArray<PropertyKey> {
1796
- const encoded = toEncoded(parameter)
1797
- switch (encoded._tag) {
1798
- case "String":
1799
- return Object.keys(input)
1800
- case "TemplateLiteral": {
1801
- const regExp = getTemplateLiteralRegExp(encoded)
1802
- return Object.keys(input).filter((k) => regExp.test(k))
1828
+ let stringKeys: ReadonlyArray<string> | undefined
1829
+ let symbolKeys: ReadonlyArray<symbol> | undefined
1830
+
1831
+ function go(parameter: AST): ReadonlyArray<PropertyKey> {
1832
+ switch (parameter._tag) {
1833
+ case "String":
1834
+ case "TemplateLiteral":
1835
+ return (stringKeys ??= Object.keys(input)).filter((k) => parameter.matchPart(k, options) !== undefined)
1836
+ case "Number":
1837
+ return (stringKeys ??= Object.keys(input)).filter((k) => parameter.matchKey(k, options) !== undefined)
1838
+ case "Symbol":
1839
+ return (symbolKeys ??= Object.getOwnPropertySymbols(input)).filter((k) =>
1840
+ parameter.matchKey(k, options) !== undefined
1841
+ )
1842
+ case "Union":
1843
+ return [...new Set(parameter.types.flatMap(go))]
1844
+ default:
1845
+ return []
1803
1846
  }
1804
- case "Symbol":
1805
- return Object.getOwnPropertySymbols(input)
1806
- case "Number":
1807
- return Object.keys(input).filter((k) => isNumberStringRegExp.test(k))
1808
- case "Union":
1809
- return [...new Set(encoded.types.flatMap((t) => getIndexSignatureKeys(input, t)))]
1810
- default:
1811
- return []
1812
1847
  }
1848
+ return go(parameterFromPropertyKey(toEncoded(parameter)))
1813
1849
  }
1814
1850
 
1815
1851
  /**
@@ -1869,6 +1905,31 @@ export class KeyValueCombiner {
1869
1905
  }
1870
1906
  }
1871
1907
 
1908
+ type IndexSignatureParameter =
1909
+ | String
1910
+ | Number
1911
+ | Symbol
1912
+ | TemplateLiteral
1913
+ | Union<IndexSignatureParameter>
1914
+
1915
+ function isIndexSignatureParameterSide(ast: AST): ast is IndexSignatureParameter {
1916
+ switch (ast._tag) {
1917
+ case "String":
1918
+ case "Number":
1919
+ case "Symbol":
1920
+ case "TemplateLiteral":
1921
+ return true
1922
+ case "Union":
1923
+ return ast.types.every(isIndexSignatureParameterSide)
1924
+ default:
1925
+ return false
1926
+ }
1927
+ }
1928
+
1929
+ function isIndexSignatureParameter(ast: AST): ast is IndexSignatureParameter {
1930
+ return isIndexSignatureParameterSide(ast) && isIndexSignatureParameterSide(toEncoded(ast))
1931
+ }
1932
+
1872
1933
  /**
1873
1934
  * Represents an index signature entry within an {@link Objects} node.
1874
1935
  *
@@ -1895,7 +1956,7 @@ export class KeyValueCombiner {
1895
1956
  * @since 3.10.0
1896
1957
  */
1897
1958
  export class IndexSignature {
1898
- readonly parameter: AST
1959
+ readonly parameter: IndexSignatureParameter
1899
1960
  readonly type: AST
1900
1961
  readonly merge: KeyValueCombiner | undefined
1901
1962
 
@@ -1904,6 +1965,9 @@ export class IndexSignature {
1904
1965
  type: AST,
1905
1966
  merge: KeyValueCombiner | undefined
1906
1967
  ) {
1968
+ if (!isIndexSignatureParameter(parameter)) {
1969
+ throw new Error(`Invalid index signature parameter ${parameter._tag}`)
1970
+ }
1907
1971
  this.parameter = parameter
1908
1972
  this.type = type
1909
1973
  this.merge = merge
@@ -2026,7 +2090,7 @@ export class Objects extends Base {
2026
2090
  s,
2027
2091
  [key, is]
2028
2092
  ) {
2029
- const parserKey = recur(indexSignatureParameterFromString(is.parameter))
2093
+ const parserKey = recur(parameterFromPropertyKey(is.parameter))
2030
2094
  const effKey = parserKey(Option.some(key), s.options)
2031
2095
  const exitKey = (effectIsExit(effKey) ? effKey : yield* Effect.exit(effKey)) as Exit.Exit<
2032
2096
  Option.Option<PropertyKey>,
@@ -2133,7 +2197,7 @@ export class Objects extends Base {
2133
2197
  const keyPairs = Arr.empty<[PropertyKey, IndexSignature]>()
2134
2198
  for (let i = 0; i < indexCount; i++) {
2135
2199
  const is = ast.indexSignatures[i]
2136
- const keys = getIndexSignatureKeys(input, is.parameter)
2200
+ const keys = getIndexSignatureKeys(input, is.parameter, options)
2137
2201
  for (let j = 0; j < keys.length; j++) {
2138
2202
  const key = keys[j]
2139
2203
  keyPairs.push([key, is])
@@ -2160,8 +2224,9 @@ export class Objects extends Base {
2160
2224
  return Option.some(out)
2161
2225
  })
2162
2226
  }
2163
- private rebuild(
2227
+ private _rebuild(
2164
2228
  recur: (ast: AST) => AST,
2229
+ recurParameter: (ast: AST) => AST,
2165
2230
  flipMerge: boolean,
2166
2231
  checks: Checks | undefined,
2167
2232
  encodingChecks: Checks | undefined
@@ -2172,7 +2237,7 @@ export class Objects extends Base {
2172
2237
  })
2173
2238
 
2174
2239
  const indexes = mapOrSame(this.indexSignatures, (is) => {
2175
- const p = recur(is.parameter)
2240
+ const p = recurParameter(is.parameter)
2176
2241
  const t = recur(is.type)
2177
2242
  const merge = flipMerge ? is.merge?.flip() : is.merge
2178
2243
  return p === is.parameter && t === is.type && merge === is.merge
@@ -2194,11 +2259,11 @@ export class Objects extends Base {
2194
2259
  }
2195
2260
  /** @internal */
2196
2261
  flip(recur: (ast: AST) => AST): AST {
2197
- return this.rebuild(recur, true, this.encodingChecks, this.checks)
2262
+ return this._rebuild(recur, recur, true, this.encodingChecks, this.checks)
2198
2263
  }
2199
2264
  /** @internal */
2200
- recur(recur: (ast: AST) => AST): AST {
2201
- return this.rebuild(recur, false, this.checks, this.encodingChecks)
2265
+ recur(recur: (ast: AST) => AST, recurParameter: (ast: AST) => AST = recur): AST {
2266
+ return this._rebuild(recur, recurParameter, false, this.checks, this.encodingChecks)
2202
2267
  }
2203
2268
  /** @internal */
2204
2269
  getExpected(): string {
@@ -2257,14 +2322,10 @@ const parseProperties = iterateEager<{
2257
2322
  }
2258
2323
  })
2259
2324
 
2260
- function mergeChecks(checks: Checks | undefined, b: AST): Checks | undefined {
2261
- if (!checks) {
2262
- return b.checks
2263
- }
2264
- if (!b.checks) {
2265
- return checks
2266
- }
2267
- return [...checks, ...b.checks]
2325
+ function combineChecks(a: Checks | undefined, b: Checks | undefined): Checks | undefined {
2326
+ if (!a) return b
2327
+ if (!b) return a
2328
+ return [...a, ...b]
2268
2329
  }
2269
2330
 
2270
2331
  /** @internal */
@@ -2313,10 +2374,10 @@ export function structWithRest(ast: Objects, records: ReadonlyArray<Objects>): O
2313
2374
  let propertySignatures = ast.propertySignatures
2314
2375
  let indexSignatures = ast.indexSignatures
2315
2376
  let checks = ast.checks
2316
- for (const r of records) {
2317
- propertySignatures = propertySignatures.concat(r.propertySignatures)
2318
- indexSignatures = indexSignatures.concat(r.indexSignatures)
2319
- checks = mergeChecks(checks, r)
2377
+ for (const record of records) {
2378
+ propertySignatures = propertySignatures.concat(record.propertySignatures)
2379
+ indexSignatures = indexSignatures.concat(record.indexSignatures)
2380
+ checks = combineChecks(checks, record.checks)
2320
2381
  }
2321
2382
  return new Objects(propertySignatures, indexSignatures, undefined, checks)
2322
2383
  }
@@ -2598,7 +2659,7 @@ export class Union<A extends AST = AST> extends Base {
2598
2659
  })
2599
2660
  }
2600
2661
  }
2601
- private rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
2662
+ private _rebuild(recur: (ast: AST) => AST, checks: Checks | undefined, encodingChecks: Checks | undefined) {
2602
2663
  const types = mapOrSame(this.types, recur)
2603
2664
  return types === this.types ?
2604
2665
  this :
@@ -2606,11 +2667,19 @@ export class Union<A extends AST = AST> extends Base {
2606
2667
  }
2607
2668
  /** @internal */
2608
2669
  recur(recur: (ast: AST) => AST) {
2609
- return this.rebuild(recur, this.checks, this.encodingChecks)
2670
+ return this._rebuild(recur, this.checks, this.encodingChecks)
2610
2671
  }
2611
2672
  /** @internal */
2612
2673
  flip(recur: (ast: AST) => AST) {
2613
- return this.rebuild(recur, this.encodingChecks, this.checks)
2674
+ return this._rebuild(recur, this.encodingChecks, this.checks)
2675
+ }
2676
+ /** @internal */
2677
+ matchPart(s: string, options: ParseOptions): LiteralValue | undefined {
2678
+ for (const type of this.types) {
2679
+ const out = (type as TemplateLiteralPart).matchPart(s, options)
2680
+ if (out !== undefined) return out
2681
+ }
2682
+ return undefined
2614
2683
  }
2615
2684
  /** @internal */
2616
2685
  getExpected(getExpected: (ast: AST) => string): string {
@@ -3052,8 +3121,8 @@ export function replaceChecks<A extends AST>(ast: A, checks: Checks | undefined)
3052
3121
  }
3053
3122
 
3054
3123
  /** @internal */
3055
- export function appendChecks<A extends AST>(ast: A, checks: Checks): A {
3056
- return replaceChecks(ast, ast.checks ? [...ast.checks, ...checks] : checks)
3124
+ export function appendChecks<A extends AST>(ast: A, checks: Checks | undefined): A {
3125
+ return replaceChecks(ast, combineChecks(ast.checks, checks))
3057
3126
  }
3058
3127
 
3059
3128
  function updateLastLink(encoding: Encoding, f: (ast: AST) => AST): Encoding {
@@ -3222,39 +3291,31 @@ function parseParameter(ast: AST): {
3222
3291
  literals: ReadonlyArray<PropertyKey>
3223
3292
  parameters: ReadonlyArray<AST>
3224
3293
  } {
3225
- switch (ast._tag) {
3226
- case "Literal":
3227
- return {
3228
- literals: Predicate.isPropertyKey(ast.literal) ? [ast.literal] : [],
3229
- parameters: []
3230
- }
3231
- case "UniqueSymbol":
3232
- return {
3233
- literals: [ast.symbol],
3234
- parameters: []
3235
- }
3236
- case "String":
3237
- case "Number":
3238
- case "Symbol":
3239
- case "TemplateLiteral":
3240
- return {
3241
- literals: [],
3242
- parameters: [ast]
3243
- }
3244
- case "Union": {
3245
- const out: {
3246
- literals: ReadonlyArray<PropertyKey>
3247
- parameters: ReadonlyArray<AST>
3248
- } = { literals: [], parameters: [] }
3249
- for (let i = 0; i < ast.types.length; i++) {
3250
- const parsed = parseParameter(ast.types[i])
3251
- out.literals = out.literals.concat(parsed.literals)
3252
- out.parameters = out.parameters.concat(parsed.parameters)
3253
- }
3254
- return out
3294
+ const literals: Array<PropertyKey> = []
3295
+ const parameters: Array<AST> = []
3296
+ function go(ast: AST) {
3297
+ switch (ast._tag) {
3298
+ case "Literal":
3299
+ if (Predicate.isPropertyKey(ast.literal)) {
3300
+ literals.push(ast.literal)
3301
+ }
3302
+ return
3303
+ case "UniqueSymbol":
3304
+ literals.push(ast.symbol)
3305
+ return
3306
+ case "Never":
3307
+ return
3308
+ case "Union":
3309
+ for (let i = 0; i < ast.types.length; i++) {
3310
+ go(ast.types[i])
3311
+ }
3312
+ return
3313
+ default:
3314
+ parameters.push(ast)
3255
3315
  }
3256
3316
  }
3257
- return { literals: [], parameters: [] }
3317
+ go(ast)
3318
+ return { literals, parameters }
3258
3319
  }
3259
3320
 
3260
3321
  /** @internal */
@@ -3416,45 +3477,6 @@ export function containsUndefined(ast: AST): boolean {
3416
3477
  }
3417
3478
  }
3418
3479
 
3419
- function getTemplateLiteralSource(ast: TemplateLiteral, top: boolean): string {
3420
- return ast.encodedParts.map((part) =>
3421
- handleTemplateLiteralASTPartParens(part, getTemplateLiteralASTPartPattern(part), top)
3422
- ).join("")
3423
- }
3424
-
3425
- /** @internal */
3426
- export const getTemplateLiteralRegExp = memoize((ast: TemplateLiteral): RegExp => {
3427
- return new globalThis.RegExp(`^${getTemplateLiteralSource(ast, true)}$`)
3428
- })
3429
-
3430
- function getTemplateLiteralASTPartPattern(part: TemplateLiteralPart): string {
3431
- switch (part._tag) {
3432
- case "Literal":
3433
- return RegEx.escape(globalThis.String(part.literal))
3434
- case "String":
3435
- return STRING_PATTERN
3436
- case "Number":
3437
- return FINITE_PATTERN
3438
- case "BigInt":
3439
- return BIGINT_PATTERN
3440
- case "TemplateLiteral":
3441
- return getTemplateLiteralSource(part, false)
3442
- case "Union":
3443
- return part.types.map(getTemplateLiteralASTPartPattern).join("|")
3444
- }
3445
- }
3446
-
3447
- function handleTemplateLiteralASTPartParens(part: TemplateLiteralPart, s: string, top: boolean): string {
3448
- if (isUnion(part)) {
3449
- if (!top) {
3450
- return `(?:${s})`
3451
- }
3452
- } else if (!top) {
3453
- return s
3454
- }
3455
- return `(${s})`
3456
- }
3457
-
3458
3480
  function fromConst<const T>(
3459
3481
  ast: AST,
3460
3482
  value: T
@@ -3484,6 +3506,52 @@ function fromRefinement<T>(
3484
3506
  }
3485
3507
  }
3486
3508
 
3509
+ function applyTemplateLiteralPartChecks<A>(ast: AST, value: A, options: ParseOptions): A | undefined {
3510
+ if (options?.disableChecks || ast.checks === undefined) return value
3511
+ const issues: Array<SchemaIssue.Issue> = []
3512
+ collectIssues(ast.checks, value, issues, ast, options)
3513
+ return issues.length === 0 ? value : undefined
3514
+ }
3515
+
3516
+ function segmentTemplateLiteralParts(
3517
+ parts: ReadonlyArray<TemplateLiteralPart>,
3518
+ input: string,
3519
+ options: ParseOptions
3520
+ ): Array<string> | undefined {
3521
+ const out = new Array<string>(parts.length)
3522
+ const failures = new Set<string>()
3523
+ function go(i: number, pos: number): boolean {
3524
+ if (i === parts.length) return pos === input.length
3525
+ const key = `${i}/${pos}`
3526
+ if (failures.has(key)) return false
3527
+ const part = parts[i]
3528
+ if (i === parts.length - 1) {
3529
+ const s = input.slice(pos)
3530
+ if (part.matchPart(s, options) !== undefined) {
3531
+ out[i] = s
3532
+ return true
3533
+ }
3534
+ } else if (part._tag === "Literal") {
3535
+ const s = globalThis.String(part.literal)
3536
+ if (input.startsWith(s, pos) && go(i + 1, pos + s.length)) {
3537
+ out[i] = s
3538
+ return true
3539
+ }
3540
+ } else {
3541
+ for (let end = input.length; end >= pos; end--) {
3542
+ const s = input.slice(pos, end)
3543
+ if (part.matchPart(s, options) !== undefined && go(i + 1, end)) {
3544
+ out[i] = s
3545
+ return true
3546
+ }
3547
+ }
3548
+ }
3549
+ failures.add(key)
3550
+ return false
3551
+ }
3552
+ return go(0, 0) ? out : undefined
3553
+ }
3554
+
3487
3555
  /** @internal */
3488
3556
  export const enumsToLiterals = memoize((ast: Enum): Union<Literal> => {
3489
3557
  return new Union(
@@ -3500,30 +3568,40 @@ export function toCodec(f: (ast: AST) => AST) {
3500
3568
  return memoize(out)
3501
3569
  }
3502
3570
 
3503
- const indexSignatureParameterFromString = toCodec((ast) => {
3571
+ const parameterFromPropertyKey = toCodec((ast) => {
3504
3572
  switch (ast._tag) {
3505
3573
  default:
3506
3574
  return ast
3507
3575
  case "Number":
3508
3576
  return ast.toCodecStringTree()
3509
3577
  case "Union":
3510
- return ast.recur(indexSignatureParameterFromString)
3578
+ return ast.recur(parameterFromPropertyKey)
3511
3579
  }
3512
3580
  })
3513
3581
 
3514
- const templateLiteralPartFromString = toCodec((ast) => {
3582
+ /** @internal */
3583
+ export const parameterFromString = toCodec((ast) => {
3515
3584
  switch (ast._tag) {
3516
3585
  default:
3517
3586
  return ast
3518
- case "String":
3519
- case "TemplateLiteral":
3587
+ case "Symbol":
3588
+ case "UniqueSymbol":
3589
+ return ast.toCodecStringTree()
3590
+ case "Union":
3591
+ return ast.recur(parameterFromString)
3592
+ }
3593
+ })
3594
+
3595
+ const partFromString = toCodec((ast) => {
3596
+ switch (ast._tag) {
3597
+ default:
3520
3598
  return ast
3521
- case "BigInt":
3522
3599
  case "Number":
3523
3600
  case "Literal":
3601
+ case "BigInt":
3524
3602
  return ast.toCodecStringTree()
3525
3603
  case "Union":
3526
- return ast.recur(templateLiteralPartFromString)
3604
+ return ast.recur(partFromString)
3527
3605
  }
3528
3606
  })
3529
3607
 
@@ -3535,6 +3613,8 @@ export const STRING_PATTERN = "[\\s\\S]*?"
3535
3613
 
3536
3614
  const isStringFiniteRegExp = new globalThis.RegExp(`^${FINITE_PATTERN}$`)
3537
3615
 
3616
+ const isStringNumberRegExp = new globalThis.RegExp(`(?:${FINITE_PATTERN}|Infinity|-Infinity|NaN)`)
3617
+
3538
3618
  /** @internal */
3539
3619
  export function isStringFinite(annotations?: Schema.Annotations.Filter) {
3540
3620
  return isPattern(
@@ -96,7 +96,8 @@ import {
96
96
  TracerSpanLinks,
97
97
  TracerTimingEnabled
98
98
  } from "./references.ts"
99
- import { addSpanStackTrace, type ErrorWithStackTraceLimit, makeStackCleaner } from "./tracer.ts"
99
+ import { getStackTraceLimit, setStackTraceLimit } from "./stackTraceLimit.ts"
100
+ import { addSpanStackTrace, makeStackCleaner } from "./tracer.ts"
100
101
  import { version } from "./version.ts"
101
102
 
102
103
  // ----------------------------------------------------------------------------
@@ -314,9 +315,8 @@ export const causePrettyErrors = <E>(self: Cause.Cause<E>): Array<Error> => {
314
315
  const interrupts: Array<Cause.Interrupt> = []
315
316
  if (self.reasons.length === 0) return errors
316
317
 
317
- const prevStackLimit = (Error as ErrorWithStackTraceLimit).stackTraceLimit
318
- ;(Error as ErrorWithStackTraceLimit)
319
- .stackTraceLimit = 1
318
+ const prevStackLimit = getStackTraceLimit()
319
+ setStackTraceLimit(1)
320
320
 
321
321
  for (const failure of self.reasons) {
322
322
  if (failure._tag === "Interrupt") {
@@ -340,7 +340,7 @@ export const causePrettyErrors = <E>(self: Cause.Cause<E>): Array<Error> => {
340
340
  errors.push(causePrettyError(error, interrupts[0].annotations))
341
341
  }
342
342
 
343
- ;(Error as ErrorWithStackTraceLimit).stackTraceLimit = prevStackLimit
343
+ setStackTraceLimit(prevStackLimit)
344
344
  return errors
345
345
  }
346
346
 
@@ -1157,10 +1157,10 @@ export const fn: typeof Effect.fn = function() {
1157
1157
  const name = nameFirst ? arguments[0] : "Effect.fn"
1158
1158
  const spanOptions = nameFirst ? arguments[1] : undefined
1159
1159
 
1160
- const prevLimit = globalThis.Error.stackTraceLimit
1161
- globalThis.Error.stackTraceLimit = 2
1160
+ const prevLimit = getStackTraceLimit()
1161
+ setStackTraceLimit(2)
1162
1162
  const defError = new globalThis.Error()
1163
- globalThis.Error.stackTraceLimit = prevLimit
1163
+ setStackTraceLimit(prevLimit)
1164
1164
 
1165
1165
  if (nameFirst) {
1166
1166
  return (body: Function | { readonly self: any }, ...pipeables: Array<Function>) =>
@@ -1200,10 +1200,10 @@ const makeFn = (
1200
1200
  if (!isEffect(result)) {
1201
1201
  return result
1202
1202
  }
1203
- const prevLimit = globalThis.Error.stackTraceLimit
1204
- globalThis.Error.stackTraceLimit = 2
1203
+ const prevLimit = getStackTraceLimit()
1204
+ setStackTraceLimit(2)
1205
1205
  const callError = new globalThis.Error()
1206
- globalThis.Error.stackTraceLimit = prevLimit
1206
+ setStackTraceLimit(prevLimit)
1207
1207
  return updateService(
1208
1208
  addSpan ?
1209
1209
  useSpan(name, spanOptions!, (span) => provideParentSpan(result, span)) :