effect 3.20.0 → 3.21.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.
Files changed (66) hide show
  1. package/dist/cjs/Cron.js +144 -48
  2. package/dist/cjs/Cron.js.map +1 -1
  3. package/dist/cjs/Effect.js +9 -4
  4. package/dist/cjs/Effect.js.map +1 -1
  5. package/dist/cjs/Equal.js +3 -0
  6. package/dist/cjs/Equal.js.map +1 -1
  7. package/dist/cjs/Layer.js +50 -2
  8. package/dist/cjs/Layer.js.map +1 -1
  9. package/dist/cjs/RcMap.js +1 -0
  10. package/dist/cjs/RcMap.js.map +1 -1
  11. package/dist/cjs/internal/cause.js +28 -29
  12. package/dist/cjs/internal/cause.js.map +1 -1
  13. package/dist/cjs/internal/core-effect.js +8 -4
  14. package/dist/cjs/internal/core-effect.js.map +1 -1
  15. package/dist/cjs/internal/fiberRuntime.js +1 -1
  16. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  17. package/dist/cjs/internal/logger.js +1 -3
  18. package/dist/cjs/internal/logger.js.map +1 -1
  19. package/dist/cjs/internal/rcMap.js +11 -6
  20. package/dist/cjs/internal/rcMap.js.map +1 -1
  21. package/dist/cjs/internal/version.js +1 -1
  22. package/dist/dts/Cron.d.ts +29 -1
  23. package/dist/dts/Cron.d.ts.map +1 -1
  24. package/dist/dts/Effect.d.ts +5 -0
  25. package/dist/dts/Effect.d.ts.map +1 -1
  26. package/dist/dts/Equal.d.ts.map +1 -1
  27. package/dist/dts/Layer.d.ts +43 -1
  28. package/dist/dts/Layer.d.ts.map +1 -1
  29. package/dist/dts/RcMap.d.ts +5 -2
  30. package/dist/dts/RcMap.d.ts.map +1 -1
  31. package/dist/dts/internal/core-effect.d.ts +5 -0
  32. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  33. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  34. package/dist/esm/Cron.js +139 -45
  35. package/dist/esm/Cron.js.map +1 -1
  36. package/dist/esm/Effect.js +5 -0
  37. package/dist/esm/Effect.js.map +1 -1
  38. package/dist/esm/Equal.js +3 -0
  39. package/dist/esm/Equal.js.map +1 -1
  40. package/dist/esm/Layer.js +46 -1
  41. package/dist/esm/Layer.js.map +1 -1
  42. package/dist/esm/RcMap.js +1 -0
  43. package/dist/esm/RcMap.js.map +1 -1
  44. package/dist/esm/internal/cause.js +26 -27
  45. package/dist/esm/internal/cause.js.map +1 -1
  46. package/dist/esm/internal/core-effect.js +6 -2
  47. package/dist/esm/internal/core-effect.js.map +1 -1
  48. package/dist/esm/internal/fiberRuntime.js +1 -1
  49. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  50. package/dist/esm/internal/logger.js +1 -3
  51. package/dist/esm/internal/logger.js.map +1 -1
  52. package/dist/esm/internal/rcMap.js +12 -7
  53. package/dist/esm/internal/rcMap.js.map +1 -1
  54. package/dist/esm/internal/version.js +1 -1
  55. package/package.json +1 -1
  56. package/src/Cron.ts +175 -45
  57. package/src/Effect.ts +6 -0
  58. package/src/Equal.ts +3 -0
  59. package/src/Layer.ts +53 -1
  60. package/src/RcMap.ts +5 -2
  61. package/src/internal/cause.ts +40 -41
  62. package/src/internal/core-effect.ts +18 -7
  63. package/src/internal/fiberRuntime.ts +4 -2
  64. package/src/internal/logger.ts +1 -1
  65. package/src/internal/rcMap.ts +21 -11
  66. package/src/internal/version.ts +1 -1
package/src/RcMap.ts CHANGED
@@ -56,6 +56,7 @@ export declare namespace RcMap {
56
56
  *
57
57
  * - `capacity`: The maximum number of resources that can be held in the map.
58
58
  * - `idleTimeToLive`: When the reference count reaches zero, the resource will be released after this duration.
59
+ * Can be a static duration or a function that returns a duration based on the key.
59
60
  *
60
61
  * @since 3.5.0
61
62
  * @category models
@@ -93,6 +94,7 @@ export const make: {
93
94
  *
94
95
  * - `capacity`: The maximum number of resources that can be held in the map.
95
96
  * - `idleTimeToLive`: When the reference count reaches zero, the resource will be released after this duration.
97
+ * Can be a static duration or a function that returns a duration based on the key.
96
98
  *
97
99
  * @since 3.5.0
98
100
  * @category models
@@ -121,7 +123,7 @@ export const make: {
121
123
  <K, A, E, R>(
122
124
  options: {
123
125
  readonly lookup: (key: K) => Effect.Effect<A, E, R>
124
- readonly idleTimeToLive?: Duration.DurationInput | undefined
126
+ readonly idleTimeToLive?: Duration.DurationInput | ((key: K) => Duration.DurationInput) | undefined
125
127
  readonly capacity?: undefined
126
128
  }
127
129
  ): Effect.Effect<RcMap<K, A, E>, never, Scope.Scope | R>
@@ -136,6 +138,7 @@ export const make: {
136
138
  *
137
139
  * - `capacity`: The maximum number of resources that can be held in the map.
138
140
  * - `idleTimeToLive`: When the reference count reaches zero, the resource will be released after this duration.
141
+ * Can be a static duration or a function that returns a duration based on the key.
139
142
  *
140
143
  * @since 3.5.0
141
144
  * @category models
@@ -164,7 +167,7 @@ export const make: {
164
167
  <K, A, E, R>(
165
168
  options: {
166
169
  readonly lookup: (key: K) => Effect.Effect<A, E, R>
167
- readonly idleTimeToLive?: Duration.DurationInput | undefined
170
+ readonly idleTimeToLive?: Duration.DurationInput | ((key: K) => Duration.DurationInput) | undefined
168
171
  readonly capacity: number
169
172
  }
170
173
  ): Effect.Effect<RcMap<K, A, E | Cause.ExceededCapacityException>, never, Scope.Scope | R>
@@ -14,7 +14,7 @@ import { pipeArguments } from "../Pipeable.js"
14
14
  import type { Predicate, Refinement } from "../Predicate.js"
15
15
  import { hasProperty, isFunction } from "../Predicate.js"
16
16
  import type { AnySpan, Span } from "../Tracer.js"
17
- import type { NoInfer } from "../Types.js"
17
+ import type * as Types from "../Types.js"
18
18
  import { getBugErrorMessage } from "./errors.js"
19
19
  import * as OpCodes from "./opCodes/cause.js"
20
20
 
@@ -879,59 +879,58 @@ export const pretty = <E>(cause: Cause.Cause<E>, options?: {
879
879
  if (options?.renderErrorCause !== true || e.cause === undefined) {
880
880
  return e.stack
881
881
  }
882
- return `${e.stack} {\n${renderErrorCause(e.cause as PrettyError, " ")}\n}`
882
+ return `${e.stack} {\n${renderErrorCause(e.cause as Cause.PrettyError, " ")}\n}`
883
883
  }).join("\n")
884
884
  }
885
885
 
886
- const renderErrorCause = (cause: PrettyError, prefix: string) => {
886
+ const renderErrorCause = (cause: Cause.PrettyError, prefix: string) => {
887
887
  const lines = cause.stack!.split("\n")
888
888
  let stack = `${prefix}[cause]: ${lines[0]}`
889
889
  for (let i = 1, len = lines.length; i < len; i++) {
890
890
  stack += `\n${prefix}${lines[i]}`
891
891
  }
892
892
  if (cause.cause) {
893
- stack += ` {\n${renderErrorCause(cause.cause as PrettyError, `${prefix} `)}\n${prefix}}`
893
+ stack += ` {\n${renderErrorCause(cause.cause as Cause.PrettyError, `${prefix} `)}\n${prefix}}`
894
894
  }
895
895
  return stack
896
896
  }
897
897
 
898
898
  /** @internal */
899
- export class PrettyError extends globalThis.Error implements Cause.PrettyError {
900
- span: undefined | Span = undefined
901
- constructor(originalError: unknown) {
902
- const originalErrorIsObject = typeof originalError === "object" && originalError !== null
903
- const prevLimit = Error.stackTraceLimit
904
- Error.stackTraceLimit = 1
905
- super(
906
- prettyErrorMessage(originalError),
907
- originalErrorIsObject && "cause" in originalError && typeof originalError.cause !== "undefined"
908
- ? { cause: new PrettyError(originalError.cause) }
909
- : undefined
910
- )
911
- if (this.message === "") {
912
- this.message = "An error has occurred"
899
+ export const makePrettyError = (originalError: unknown): Cause.PrettyError => {
900
+ const originalErrorIsObject = typeof originalError === "object" && originalError !== null
901
+ const prevLimit = Error.stackTraceLimit
902
+ Error.stackTraceLimit = 1
903
+ const error = new Error(
904
+ prettyErrorMessage(originalError),
905
+ originalErrorIsObject && "cause" in originalError && typeof originalError.cause !== "undefined"
906
+ ? { cause: makePrettyError(originalError.cause) }
907
+ : undefined
908
+ ) as Types.Mutable<Cause.PrettyError>
909
+ Error.stackTraceLimit = prevLimit
910
+ if (error.message === "") {
911
+ error.message = "An error has occurred"
912
+ }
913
+ Error.stackTraceLimit = prevLimit
914
+ error.name = originalError instanceof Error ? originalError.name : "Error"
915
+ if (originalErrorIsObject) {
916
+ if (spanSymbol in originalError) {
917
+ error.span = originalError[spanSymbol] as Span
913
918
  }
914
- Error.stackTraceLimit = prevLimit
915
- this.name = originalError instanceof Error ? originalError.name : "Error"
916
- if (originalErrorIsObject) {
917
- if (spanSymbol in originalError) {
918
- this.span = originalError[spanSymbol] as Span
919
+ Object.keys(originalError).forEach((key) => {
920
+ if (!(key in error)) {
921
+ // @ts-expect-error
922
+ error[key] = originalError[key]
919
923
  }
920
- Object.keys(originalError).forEach((key) => {
921
- if (!(key in this)) {
922
- // @ts-expect-error
923
- this[key] = originalError[key]
924
- }
925
- })
926
- }
927
- this.stack = prettyErrorStack(
928
- `${this.name}: ${this.message}`,
929
- originalError instanceof Error && originalError.stack
930
- ? originalError.stack
931
- : "",
932
- this.span
933
- )
924
+ })
934
925
  }
926
+ error.stack = prettyErrorStack(
927
+ `${error.name}: ${error.message}`,
928
+ originalError instanceof Error && originalError.stack
929
+ ? originalError.stack
930
+ : "",
931
+ error.span
932
+ )
933
+ return error
935
934
  }
936
935
 
937
936
  /**
@@ -1035,14 +1034,14 @@ const prettyErrorStack = (message: string, stack: string, span?: Span | undefine
1035
1034
  export const spanSymbol = Symbol.for("effect/SpanAnnotation")
1036
1035
 
1037
1036
  /** @internal */
1038
- export const prettyErrors = <E>(cause: Cause.Cause<E>): Array<PrettyError> =>
1037
+ export const prettyErrors = <E>(cause: Cause.Cause<E>): Array<Cause.PrettyError> =>
1039
1038
  reduceWithContext(cause, void 0, {
1040
- emptyCase: (): Array<PrettyError> => [],
1039
+ emptyCase: (): Array<Cause.PrettyError> => [],
1041
1040
  dieCase: (_, unknownError) => {
1042
- return [new PrettyError(unknownError)]
1041
+ return [makePrettyError(unknownError)]
1043
1042
  },
1044
1043
  failCase: (_, error) => {
1045
- return [new PrettyError(error)]
1044
+ return [makePrettyError(error)]
1046
1045
  },
1047
1046
  interruptCase: () => [],
1048
1047
  parallelCase: (_, l, r) => [...l, ...r],
@@ -1966,7 +1966,7 @@ export const annotateCurrentSpan: {
1966
1966
  } = function(): Effect.Effect<void> {
1967
1967
  const args = arguments
1968
1968
  return ignore(core.flatMap(
1969
- currentSpan,
1969
+ currentPropagatedSpan,
1970
1970
  (span) =>
1971
1971
  core.sync(() => {
1972
1972
  if (typeof args[0] === "string") {
@@ -2041,6 +2041,16 @@ export const currentSpan: Effect.Effect<Tracer.Span, Cause.NoSuchElementExceptio
2041
2041
  }
2042
2042
  )
2043
2043
 
2044
+ export const currentPropagatedSpan: Effect.Effect<Tracer.Span, Cause.NoSuchElementException> = core.flatMap(
2045
+ core.context<never>(),
2046
+ (context) => {
2047
+ const span = filterDisablePropagation(Context.getOption(context, internalTracer.spanTag))
2048
+ return span._tag === "Some" && span.value._tag === "Span"
2049
+ ? core.succeed(span.value)
2050
+ : core.fail(new core.NoSuchElementException())
2051
+ }
2052
+ )
2053
+
2044
2054
  /* @internal */
2045
2055
  export const linkSpans = dual<
2046
2056
  (
@@ -2070,12 +2080,13 @@ export const linkSpans = dual<
2070
2080
 
2071
2081
  const bigint0 = BigInt(0)
2072
2082
 
2073
- const filterDisablePropagation: (self: Option.Option<Tracer.AnySpan>) => Option.Option<Tracer.AnySpan> = Option.flatMap(
2074
- (span) =>
2075
- Context.get(span.context, internalTracer.DisablePropagation)
2076
- ? span._tag === "Span" ? filterDisablePropagation(span.parent) : Option.none()
2077
- : Option.some(span)
2078
- )
2083
+ export const filterDisablePropagation: (self: Option.Option<Tracer.AnySpan>) => Option.Option<Tracer.AnySpan> = Option
2084
+ .flatMap(
2085
+ (span) =>
2086
+ Context.get(span.context, internalTracer.DisablePropagation)
2087
+ ? span._tag === "Span" ? filterDisablePropagation(span.parent) : Option.none()
2088
+ : Option.some(span)
2089
+ )
2079
2090
 
2080
2091
  /** @internal */
2081
2092
  export const unsafeMakeSpan = <XA, XE>(
@@ -1522,13 +1522,15 @@ export const tracerLogger = globalValue(
1522
1522
  logLevel,
1523
1523
  message
1524
1524
  }) => {
1525
- const span = Context.getOption(
1525
+ const span = internalEffect.filterDisablePropagation(Context.getOption(
1526
1526
  fiberRefs.getOrDefault(context, core.currentContext),
1527
1527
  tracer.spanTag
1528
- )
1528
+ ))
1529
+
1529
1530
  if (span._tag === "None" || span.value._tag === "ExternalSpan") {
1530
1531
  return
1531
1532
  }
1533
+
1532
1534
  const clockService = Context.unsafeGet(
1533
1535
  fiberRefs.getOrDefault(context, defaultServices.currentServices),
1534
1536
  clock.clockTag
@@ -456,7 +456,7 @@ const prettyLoggerBrowser = (options: {
456
456
  console.groupCollapsed(firstLine, ...firstParams)
457
457
 
458
458
  if (!Cause.isEmpty(cause)) {
459
- console.error(Cause.pretty(cause, { renderErrorCause: true }))
459
+ console.error(...Cause.prettyErrors(cause))
460
460
  }
461
461
 
462
462
  if (messageIndex < message.length) {
@@ -4,7 +4,7 @@ import type * as Deferred from "../Deferred.js"
4
4
  import * as Duration from "../Duration.js"
5
5
  import type { Effect } from "../Effect.js"
6
6
  import type { RuntimeFiber } from "../Fiber.js"
7
- import { dual, identity } from "../Function.js"
7
+ import { constant, dual, flow, identity } from "../Function.js"
8
8
  import * as MutableHashMap from "../MutableHashMap.js"
9
9
  import { pipeArguments } from "../Pipeable.js"
10
10
  import type * as RcMap from "../RcMap.js"
@@ -33,6 +33,7 @@ declare namespace State {
33
33
  readonly deferred: Deferred.Deferred<A, E>
34
34
  readonly scope: Scope.CloseableScope
35
35
  readonly finalizer: Effect<void>
36
+ readonly idleTimeToLive: Duration.Duration
36
37
  fiber: RuntimeFiber<void, never> | undefined
37
38
  expiresAt: number
38
39
  refCount: number
@@ -58,7 +59,7 @@ class RcMapImpl<K, A, E> implements RcMap.RcMap<K, A, E> {
58
59
  readonly lookup: (key: K) => Effect<A, E, Scope.Scope>,
59
60
  readonly context: Context.Context<never>,
60
61
  readonly scope: Scope.Scope,
61
- readonly idleTimeToLive: Duration.Duration | undefined,
62
+ readonly idleTimeToLive: ((key: K) => Duration.Duration) | undefined,
62
63
  readonly capacity: number
63
64
  ) {
64
65
  this[TypeId] = variance
@@ -73,27 +74,32 @@ class RcMapImpl<K, A, E> implements RcMap.RcMap<K, A, E> {
73
74
  export const make: {
74
75
  <K, A, E, R>(options: {
75
76
  readonly lookup: (key: K) => Effect<A, E, R>
76
- readonly idleTimeToLive?: Duration.DurationInput | undefined
77
+ readonly idleTimeToLive?: Duration.DurationInput | ((key: K) => Duration.DurationInput) | undefined
77
78
  readonly capacity?: undefined
78
79
  }): Effect<RcMap.RcMap<K, A, E>, never, Scope.Scope | R>
79
80
  <K, A, E, R>(options: {
80
81
  readonly lookup: (key: K) => Effect<A, E, R>
81
- readonly idleTimeToLive?: Duration.DurationInput | undefined
82
+ readonly idleTimeToLive?: Duration.DurationInput | ((key: K) => Duration.DurationInput) | undefined
82
83
  readonly capacity: number
83
84
  }): Effect<RcMap.RcMap<K, A, E | Cause.ExceededCapacityException>, never, Scope.Scope | R>
84
85
  } = <K, A, E, R>(options: {
85
86
  readonly lookup: (key: K) => Effect<A, E, R>
86
- readonly idleTimeToLive?: Duration.DurationInput | undefined
87
+ readonly idleTimeToLive?: Duration.DurationInput | ((key: K) => Duration.DurationInput) | undefined
87
88
  readonly capacity?: number | undefined
88
89
  }) =>
89
90
  core.withFiberRuntime<RcMap.RcMap<K, A, E>, never, R | Scope.Scope>((fiber) => {
90
91
  const context = fiber.getFiberRef(core.currentContext) as Context.Context<R | Scope.Scope>
91
92
  const scope = Context.get(context, fiberRuntime.scopeTag)
93
+ const idleTimeToLive = options.idleTimeToLive === undefined
94
+ ? undefined
95
+ : typeof options.idleTimeToLive === "function"
96
+ ? flow(options.idleTimeToLive, Duration.decode)
97
+ : constant(Duration.decode(options.idleTimeToLive))
92
98
  const self = new RcMapImpl<K, A, E>(
93
99
  options.lookup as any,
94
100
  context,
95
101
  scope,
96
- options.idleTimeToLive ? Duration.decode(options.idleTimeToLive) : undefined,
102
+ idleTimeToLive,
97
103
  Math.max(options.capacity ?? Number.POSITIVE_INFINITY, 0)
98
104
  )
99
105
  return core.as(
@@ -169,10 +175,12 @@ const acquire = core.fnUntraced(function*<K, A, E>(self: RcMapImpl<K, A, E>, key
169
175
  core.flatMap((exit) => core.deferredDone(deferred, exit)),
170
176
  circular.forkIn(scope)
171
177
  )
178
+ const idleTimeToLive = self.idleTimeToLive ? self.idleTimeToLive(key) : Duration.zero
172
179
  const entry: State.Entry<A, E> = {
173
180
  deferred,
174
181
  scope,
175
182
  finalizer: undefined as any,
183
+ idleTimeToLive,
176
184
  fiber: undefined,
177
185
  expiresAt: 0,
178
186
  refCount: 1
@@ -192,7 +200,7 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
192
200
  } else if (
193
201
  self.state._tag === "Closed"
194
202
  || !MutableHashMap.has(self.state.map, key)
195
- || self.idleTimeToLive === undefined
203
+ || Duration.isZero(entry.idleTimeToLive)
196
204
  ) {
197
205
  if (self.state._tag === "Open") {
198
206
  MutableHashMap.remove(self.state.map, key)
@@ -200,11 +208,11 @@ const release = <K, A, E>(self: RcMapImpl<K, A, E>, key: K, entry: State.Entry<A
200
208
  return core.scopeClose(entry.scope, core.exitVoid)
201
209
  }
202
210
 
203
- if (!Duration.isFinite(self.idleTimeToLive)) {
211
+ if (!Duration.isFinite(entry.idleTimeToLive)) {
204
212
  return core.void
205
213
  }
206
214
 
207
- entry.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(self.idleTimeToLive)
215
+ entry.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(entry.idleTimeToLive)
208
216
  if (entry.fiber) return core.void
209
217
 
210
218
  return core.interruptibleMask(function loop(restore): Effect<void> {
@@ -276,10 +284,12 @@ export const touch: {
276
284
  <K, A, E>(self_: RcMap.RcMap<K, A, E>, key: K) =>
277
285
  coreEffect.clockWith((clock) => {
278
286
  const self = self_ as RcMapImpl<K, A, E>
279
- if (!self.idleTimeToLive || self.state._tag === "Closed") return core.void
287
+ if (self.state._tag === "Closed") return core.void
280
288
  const o = MutableHashMap.get(self.state.map, key)
281
289
  if (o._tag === "None") return core.void
282
- o.value.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(self.idleTimeToLive)
290
+ const entry = o.value
291
+ if (Duration.isZero(entry.idleTimeToLive)) return core.void
292
+ entry.expiresAt = clock.unsafeCurrentTimeMillis() + Duration.toMillis(entry.idleTimeToLive)
283
293
  return core.void
284
294
  })
285
295
  )
@@ -1,4 +1,4 @@
1
- let moduleVersion = "3.20.0"
1
+ let moduleVersion = "3.21.0"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4