effect 4.0.0-beta.10 → 4.0.0-beta.11

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 (122) hide show
  1. package/dist/Channel.d.ts +7 -7
  2. package/dist/Effect.d.ts +217 -8
  3. package/dist/Effect.d.ts.map +1 -1
  4. package/dist/Effect.js +46 -0
  5. package/dist/Effect.js.map +1 -1
  6. package/dist/ErrorReporter.d.ts +376 -0
  7. package/dist/ErrorReporter.d.ts.map +1 -0
  8. package/dist/ErrorReporter.js +246 -0
  9. package/dist/ErrorReporter.js.map +1 -0
  10. package/dist/LogLevel.d.ts +5 -0
  11. package/dist/LogLevel.d.ts.map +1 -1
  12. package/dist/LogLevel.js.map +1 -1
  13. package/dist/Logger.d.ts +25 -91
  14. package/dist/Logger.d.ts.map +1 -1
  15. package/dist/Logger.js +2 -3
  16. package/dist/Logger.js.map +1 -1
  17. package/dist/Queue.d.ts.map +1 -1
  18. package/dist/Queue.js +0 -1
  19. package/dist/Queue.js.map +1 -1
  20. package/dist/References.d.ts +3 -3
  21. package/dist/References.d.ts.map +1 -1
  22. package/dist/SchemaAST.d.ts.map +1 -1
  23. package/dist/SchemaAST.js +2 -1
  24. package/dist/SchemaAST.js.map +1 -1
  25. package/dist/Stream.d.ts +5 -5
  26. package/dist/index.d.ts +4 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +4 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/internal/effect.js +54 -4
  31. package/dist/internal/effect.js.map +1 -1
  32. package/dist/internal/hashMap.js +2 -2
  33. package/dist/internal/hashMap.js.map +1 -1
  34. package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
  35. package/dist/unstable/ai/LanguageModel.js +41 -0
  36. package/dist/unstable/ai/LanguageModel.js.map +1 -1
  37. package/dist/unstable/cli/CliOutput.js +37 -6
  38. package/dist/unstable/cli/CliOutput.js.map +1 -1
  39. package/dist/unstable/cli/Command.d.ts +199 -7
  40. package/dist/unstable/cli/Command.d.ts.map +1 -1
  41. package/dist/unstable/cli/Command.js +116 -6
  42. package/dist/unstable/cli/Command.js.map +1 -1
  43. package/dist/unstable/cli/HelpDoc.d.ts +60 -2
  44. package/dist/unstable/cli/HelpDoc.d.ts.map +1 -1
  45. package/dist/unstable/cli/internal/command.d.ts +11 -1
  46. package/dist/unstable/cli/internal/command.d.ts.map +1 -1
  47. package/dist/unstable/cli/internal/command.js +33 -8
  48. package/dist/unstable/cli/internal/command.js.map +1 -1
  49. package/dist/unstable/cli/internal/completions/CommandDescriptor.js +7 -2
  50. package/dist/unstable/cli/internal/completions/CommandDescriptor.js.map +1 -1
  51. package/dist/unstable/cli/internal/parser.js +10 -2
  52. package/dist/unstable/cli/internal/parser.js.map +1 -1
  53. package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
  54. package/dist/unstable/http/Headers.d.ts.map +1 -1
  55. package/dist/unstable/http/Headers.js +27 -10
  56. package/dist/unstable/http/Headers.js.map +1 -1
  57. package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
  58. package/dist/unstable/http/HttpEffect.js +12 -7
  59. package/dist/unstable/http/HttpEffect.js.map +1 -1
  60. package/dist/unstable/http/HttpServerError.d.ts +8 -26
  61. package/dist/unstable/http/HttpServerError.d.ts.map +1 -1
  62. package/dist/unstable/http/HttpServerError.js +11 -27
  63. package/dist/unstable/http/HttpServerError.js.map +1 -1
  64. package/dist/unstable/http/HttpServerRespondable.d.ts +2 -2
  65. package/dist/unstable/http/HttpServerRespondable.d.ts.map +1 -1
  66. package/dist/unstable/http/HttpServerRespondable.js +5 -5
  67. package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
  68. package/dist/unstable/http/HttpServerResponse.d.ts +2 -1
  69. package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
  70. package/dist/unstable/http/HttpServerResponse.js +2 -0
  71. package/dist/unstable/http/HttpServerResponse.js.map +1 -1
  72. package/dist/unstable/httpapi/HttpApiBuilder.js +1 -1
  73. package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
  74. package/dist/unstable/httpapi/HttpApiError.d.ts +11 -0
  75. package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
  76. package/dist/unstable/httpapi/HttpApiError.js +29 -9
  77. package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
  78. package/dist/unstable/observability/OtlpLogger.d.ts.map +1 -1
  79. package/dist/unstable/observability/OtlpLogger.js +7 -4
  80. package/dist/unstable/observability/OtlpLogger.js.map +1 -1
  81. package/dist/unstable/reactivity/AtomRegistry.d.ts +6 -0
  82. package/dist/unstable/reactivity/AtomRegistry.d.ts.map +1 -1
  83. package/dist/unstable/reactivity/AtomRegistry.js +22 -1
  84. package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
  85. package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
  86. package/dist/unstable/rpc/RpcServer.js +4 -0
  87. package/dist/unstable/rpc/RpcServer.js.map +1 -1
  88. package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
  89. package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
  90. package/dist/unstable/workflow/WorkflowEngine.js +131 -0
  91. package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
  92. package/package.json +1 -1
  93. package/src/Channel.ts +9 -9
  94. package/src/Effect.ts +235 -8
  95. package/src/ErrorReporter.ts +459 -0
  96. package/src/LogLevel.ts +6 -0
  97. package/src/Logger.ts +28 -95
  98. package/src/Queue.ts +0 -1
  99. package/src/References.ts +4 -4
  100. package/src/SchemaAST.ts +2 -1
  101. package/src/Stream.ts +7 -7
  102. package/src/index.ts +5 -0
  103. package/src/internal/effect.ts +137 -14
  104. package/src/internal/hashMap.ts +2 -2
  105. package/src/unstable/ai/LanguageModel.ts +71 -0
  106. package/src/unstable/cli/CliOutput.ts +45 -6
  107. package/src/unstable/cli/Command.ts +298 -11
  108. package/src/unstable/cli/HelpDoc.ts +68 -2
  109. package/src/unstable/cli/internal/command.ts +47 -11
  110. package/src/unstable/cli/internal/completions/CommandDescriptor.ts +7 -2
  111. package/src/unstable/cli/internal/parser.ts +11 -3
  112. package/src/unstable/http/Headers.ts +28 -13
  113. package/src/unstable/http/HttpEffect.ts +10 -5
  114. package/src/unstable/http/HttpServerError.ts +13 -27
  115. package/src/unstable/http/HttpServerRespondable.ts +6 -6
  116. package/src/unstable/http/HttpServerResponse.ts +3 -1
  117. package/src/unstable/httpapi/HttpApiBuilder.ts +1 -0
  118. package/src/unstable/httpapi/HttpApiError.ts +30 -9
  119. package/src/unstable/observability/OtlpLogger.ts +9 -5
  120. package/src/unstable/reactivity/AtomRegistry.ts +29 -1
  121. package/src/unstable/rpc/RpcServer.ts +4 -0
  122. package/src/unstable/workflow/WorkflowEngine.ts +178 -0
@@ -157,11 +157,16 @@ export const fromCommand = (cmd: Command.Any): CommandDescriptor => {
157
157
  }
158
158
  }
159
159
 
160
- const subcommands: Array<CommandDescriptor> = cmd.subcommands.map(fromCommand)
160
+ const subcommands: Array<CommandDescriptor> = []
161
+ for (const group of cmd.subcommands) {
162
+ for (const subcommand of group.commands) {
163
+ subcommands.push(fromCommand(subcommand))
164
+ }
165
+ }
161
166
 
162
167
  return {
163
168
  name: cmd.name,
164
- description: cmd.description,
169
+ description: cmd.shortDescription ?? cmd.description,
165
170
  flags,
166
171
  arguments: args,
167
172
  subcommands
@@ -273,8 +273,16 @@ const createFlagRegistry = (params: ReadonlyArray<FlagParam>): FlagRegistry => {
273
273
  }
274
274
 
275
275
  const buildSubcommandIndex = (
276
- subcommands: ReadonlyArray<Command<string, unknown, unknown, unknown>>
277
- ): Map<string, Command<string, unknown, unknown, unknown>> => new Map(subcommands.map((sub) => [sub.name, sub]))
276
+ subcommands: Command.Any["subcommands"]
277
+ ): Map<string, Command<string, unknown, unknown, unknown>> => {
278
+ const index = new Map<string, Command<string, unknown, unknown, unknown>>()
279
+ for (const group of subcommands) {
280
+ for (const subcommand of group.commands) {
281
+ index.set(subcommand.name, subcommand)
282
+ }
283
+ }
284
+ return index
285
+ }
278
286
 
279
287
  /* ========================================================================== */
280
288
  /* Flag Accumulator */
@@ -506,7 +514,7 @@ const resolveFirstValue = (
506
514
  // Not a subcommand. Check if this looks like a typo.
507
515
  const expectsArgs = toImpl(command).config.arguments.length > 0
508
516
  if (!expectsArgs && subIndex.size > 0) {
509
- const suggestions = suggest(value, command.subcommands.map((s) => s.name))
517
+ const suggestions = suggest(value, Array.from(subIndex.keys()))
510
518
  state.errors.push(
511
519
  new CliError.UnknownSubcommand({
512
520
  subcommand: value,
@@ -44,22 +44,37 @@ export interface Headers extends Redactable.Redactable {
44
44
  readonly [key: string]: string
45
45
  }
46
46
 
47
- const Proto = Object.assign(Object.create(null), Inspectable.BaseProto, {
48
- [TypeId]: TypeId,
49
- [Redactable.symbolRedactable](
50
- this: Headers,
51
- context: ServiceMap.ServiceMap<never>
52
- ): Record<string, string | Redacted.Redacted<string>> {
53
- return redact(this, ServiceMap.get(context, CurrentRedactedNames))
47
+ const Proto = Object.create(null)
48
+
49
+ Object.defineProperties(Proto, {
50
+ [TypeId]: {
51
+ value: TypeId
52
+ },
53
+ [Redactable.symbolRedactable]: {
54
+ value(this: Headers, context: ServiceMap.ServiceMap<never>): Record<string, string | Redacted.Redacted<string>> {
55
+ return redact(this, ServiceMap.get(context, CurrentRedactedNames))
56
+ }
57
+ },
58
+ toJSON: {
59
+ value(this: Headers) {
60
+ return Redactable.redact(this)
61
+ }
62
+ },
63
+ [Equal.symbol]: {
64
+ value(this: Headers, that: Headers): boolean {
65
+ return Equivalence(this, that)
66
+ }
54
67
  },
55
- toJSON() {
56
- return Redactable.redact(this)
68
+ [Hash.symbol]: {
69
+ value(this: Headers): number {
70
+ return Hash.structure(this)
71
+ }
57
72
  },
58
- [Equal.symbol](this: Headers, that: Headers): boolean {
59
- return Equivalence(this, that)
73
+ toString: {
74
+ value: Inspectable.BaseProto.toString
60
75
  },
61
- [Hash.symbol](this: Headers): number {
62
- return Hash.structure(this)
76
+ [Inspectable.NodeInspectSymbol]: {
77
+ value: Inspectable.BaseProto[Inspectable.NodeInspectSymbol]
63
78
  }
64
79
  })
65
80
 
@@ -6,6 +6,7 @@ import * as Effect from "../../Effect.ts"
6
6
  import * as Exit from "../../Exit.ts"
7
7
  import * as Fiber from "../../Fiber.ts"
8
8
  import { dual } from "../../Function.ts"
9
+ import { reportCauseUnsafe } from "../../internal/effect.ts"
9
10
  import * as Layer from "../../Layer.ts"
10
11
  import * as Scope from "../../Scope.ts"
11
12
  import * as ServiceMap from "../../ServiceMap.ts"
@@ -34,6 +35,7 @@ export const toHandled = <E, R, EH, RH>(
34
35
  const handleCause = (cause: Cause<E | EH | HttpServerError>) =>
35
36
  Effect.flatMapEager(causeResponse(cause), ([response, cause]) => {
36
37
  const fiber = Fiber.getCurrent()!
38
+ reportCauseUnsafe(fiber, cause)
37
39
  const request = ServiceMap.getUnsafe(fiber.services, HttpServerRequest)
38
40
  const handler = fiber.getRef(PreResponseHandlers)
39
41
  const cont = cause.reasons.length === 0 ? Effect.succeed(response) : Effect.failCause(cause)
@@ -80,13 +82,16 @@ export const toHandled = <E, R, EH, RH>(
80
82
  Effect.matchCauseEffect(tracer(middleware(responded)), {
81
83
  onFailure(cause): Effect.Effect<void, EH, RH> {
82
84
  const fiber = Fiber.getCurrent()!
85
+ reportCauseUnsafe(fiber, cause)
83
86
  const request = ServiceMap.getUnsafe(fiber.services, HttpServerRequest)
84
- if (handledSymbol in request) {
85
- return Effect.void
86
- }
87
+ if (handledSymbol in request) return Effect.void
87
88
  return Effect.matchCauseEffectEager(causeResponse(cause), {
88
- onFailure: (_cause) => handleResponse(request, Response.empty({ status: 500 })),
89
- onSuccess: ([response]) => handleResponse(request, response)
89
+ onFailure(_) {
90
+ return handleResponse(request, Response.empty({ status: 500 }))
91
+ },
92
+ onSuccess([response]) {
93
+ return handleResponse(request, response)
94
+ }
90
95
  })
91
96
  },
92
97
  onSuccess(response): Effect.Effect<void, EH, RH> {
@@ -4,6 +4,7 @@
4
4
  import * as Cause from "../../Cause.ts"
5
5
  import * as Data from "../../Data.ts"
6
6
  import * as Effect from "../../Effect.ts"
7
+ import * as ErrorReporter from "../../ErrorReporter.ts"
7
8
  import type * as Exit from "../../Exit.ts"
8
9
  import { hasProperty } from "../../Predicate.ts"
9
10
  import type * as Request from "./HttpServerRequest.ts"
@@ -32,35 +33,24 @@ export class HttpServerError extends Data.TaggedError("HttpServerError")<{
32
33
  }
33
34
  }
34
35
 
35
- /**
36
- * @since 4.0.0
37
- */
38
36
  readonly [TypeId] = TypeId
39
37
 
40
- /**
41
- * @since 4.0.0
42
- */
43
38
  override stack = `${this.name}: ${this.message}`
44
39
 
45
- /**
46
- * @since 4.0.0
47
- */
48
40
  get request(): Request.HttpServerRequest {
49
41
  return this.reason.request
50
42
  }
51
43
 
52
- /**
53
- * @since 4.0.0
54
- */
55
44
  get response(): Response.HttpServerResponse | undefined {
56
45
  return "response" in this.reason ? this.reason.response : undefined
57
46
  }
58
47
 
59
- /**
60
- * @since 4.0.0
61
- */
62
- [Respondable.TypeId]() {
63
- return this.reason[Respondable.TypeId]()
48
+ [Respondable.symbol]() {
49
+ return this.reason[Respondable.symbol]()
50
+ }
51
+
52
+ override get [ErrorReporter.ignore](): boolean {
53
+ return this.reason[ErrorReporter.ignore] ?? false
64
54
  }
65
55
 
66
56
  override get message(): string {
@@ -80,7 +70,7 @@ export class RequestParseError extends Data.TaggedError("RequestParseError")<{
80
70
  /**
81
71
  * @since 4.0.0
82
72
  */
83
- [Respondable.TypeId]() {
73
+ [Respondable.symbol]() {
84
74
  return Effect.succeed(Response.empty({ status: 400 }))
85
75
  }
86
76
 
@@ -102,13 +92,12 @@ export class RouteNotFound extends Data.TaggedError("RouteNotFound")<{
102
92
  readonly description?: string
103
93
  readonly cause?: unknown
104
94
  }> implements Respondable.Respondable {
105
- /**
106
- * @since 4.0.0
107
- */
108
- [Respondable.TypeId]() {
95
+ [Respondable.symbol]() {
109
96
  return Effect.succeed(Response.empty({ status: 404 }))
110
97
  }
111
98
 
99
+ override readonly [ErrorReporter.ignore] = true
100
+
112
101
  get methodAndUrl() {
113
102
  return `${this.request.method} ${this.request.url}`
114
103
  }
@@ -130,7 +119,7 @@ export class InternalError extends Data.TaggedError("InternalError")<{
130
119
  /**
131
120
  * @since 4.0.0
132
121
  */
133
- [Respondable.TypeId]() {
122
+ [Respondable.symbol]() {
134
123
  return Effect.succeed(Response.empty({ status: 500 }))
135
124
  }
136
125
 
@@ -159,10 +148,7 @@ export class ResponseError extends Data.TaggedError("ResponseError")<{
159
148
  readonly description?: string
160
149
  readonly cause?: unknown
161
150
  }> implements Respondable.Respondable {
162
- /**
163
- * @since 4.0.0
164
- */
165
- [Respondable.TypeId]() {
151
+ [Respondable.symbol]() {
166
152
  return Effect.succeed(Response.empty({ status: 500 }))
167
153
  }
168
154
 
@@ -12,21 +12,21 @@ import * as Response from "./HttpServerResponse.ts"
12
12
  * @since 4.0.0
13
13
  * @category Type IDs
14
14
  */
15
- export const TypeId = "~effect/http/HttpServerRespondable"
15
+ export const symbol = "~effect/http/HttpServerRespondable"
16
16
 
17
17
  /**
18
18
  * @since 4.0.0
19
19
  * @category models
20
20
  */
21
21
  export interface Respondable {
22
- readonly [TypeId]: () => Effect.Effect<HttpServerResponse, unknown>
22
+ [symbol](): Effect.Effect<HttpServerResponse, unknown>
23
23
  }
24
24
 
25
25
  /**
26
26
  * @since 4.0.0
27
27
  * @category guards
28
28
  */
29
- export const isRespondable = (u: unknown): u is Respondable => hasProperty(u, TypeId)
29
+ export const isRespondable = (u: unknown): u is Respondable => hasProperty(u, symbol)
30
30
 
31
31
  const badRequest = Response.empty({ status: 400 })
32
32
  const notFound = Response.empty({ status: 404 })
@@ -39,7 +39,7 @@ export const toResponse = (self: Respondable): Effect.Effect<HttpServerResponse>
39
39
  if (Response.isHttpServerResponse(self)) {
40
40
  return Effect.succeed(self)
41
41
  }
42
- return Effect.orDie(self[TypeId]())
42
+ return Effect.orDie(self[symbol]())
43
43
  }
44
44
 
45
45
  /**
@@ -50,7 +50,7 @@ export const toResponseOrElse = (u: unknown, orElse: HttpServerResponse): Effect
50
50
  if (Response.isHttpServerResponse(u)) {
51
51
  return Effect.succeed(u)
52
52
  } else if (isRespondable(u)) {
53
- return Effect.catchCause(u[TypeId](), () => Effect.succeed(orElse))
53
+ return Effect.catchCause(u[symbol](), () => Effect.succeed(orElse))
54
54
  // add support for some commmon types
55
55
  } else if (Schema.isSchemaError(u)) {
56
56
  return Effect.succeed(badRequest)
@@ -68,7 +68,7 @@ export const toResponseOrElseDefect = (u: unknown, orElse: HttpServerResponse):
68
68
  if (Response.isHttpServerResponse(u)) {
69
69
  return Effect.succeed(u)
70
70
  } else if (isRespondable(u)) {
71
- return Effect.catchCause(u[TypeId](), () => Effect.succeed(orElse))
71
+ return Effect.catchCause(u[symbol](), () => Effect.succeed(orElse))
72
72
  }
73
73
  return Effect.succeed(orElse)
74
74
  }
@@ -2,6 +2,7 @@
2
2
  * @since 4.0.0
3
3
  */
4
4
  import * as Effect from "../../Effect.ts"
5
+ import * as ErrorReporter from "../../ErrorReporter.ts"
5
6
  import type * as FileSystem from "../../FileSystem.ts"
6
7
  import { dual } from "../../Function.ts"
7
8
  import type * as Inspectable from "../../Inspectable.ts"
@@ -28,7 +29,7 @@ const TypeId = "~effect/http/HttpServerResponse"
28
29
  * @since 4.0.0
29
30
  * @category models
30
31
  */
31
- export interface HttpServerResponse extends Inspectable.Inspectable, Pipeable {
32
+ export interface HttpServerResponse extends Inspectable.Inspectable, Pipeable, ErrorReporter.Reportable {
32
33
  readonly [TypeId]: typeof TypeId
33
34
  readonly status: number
34
35
  readonly statusText?: string | undefined
@@ -834,6 +835,7 @@ const Proto: Omit<
834
835
  > = {
835
836
  ...PipeInspectableProto,
836
837
  [TypeId]: TypeId,
838
+ [ErrorReporter.ignore]: true,
837
839
  toJSON(this: HttpServerResponse) {
838
840
  return {
839
841
  _id: "HttpServerResponse",
@@ -549,6 +549,7 @@ function handlerToRoute(
549
549
  return Response.isHttpServerResponse(response) ? response : yield* encodeSuccess(response)
550
550
  })
551
551
  ).pipe(
552
+ Effect.withErrorReporting,
552
553
  Effect.catch((error) => {
553
554
  if (Schema.isSchemaError(error)) {
554
555
  error = HttpApiSchemaError.fromSchemaError(error)
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @since 4.0.0
3
3
  */
4
+ import * as ErrorReporter from "../../ErrorReporter.ts"
4
5
  import * as Schema from "../../Schema.ts"
5
6
  import * as HttpApiSchema from "./HttpApiSchema.ts"
6
7
 
@@ -21,6 +22,8 @@ export class HttpApiSchemaError extends Schema.ErrorClass<HttpApiSchemaError>("e
21
22
  static fromSchemaError(error: Schema.SchemaError): HttpApiSchemaError {
22
23
  return new HttpApiSchemaError({ message: error.message })
23
24
  }
25
+
26
+ override readonly [ErrorReporter.ignore] = true
24
27
  }
25
28
 
26
29
  /**
@@ -32,7 +35,9 @@ export class BadRequest extends Schema.ErrorClass<BadRequest>("effect/HttpApiErr
32
35
  }, {
33
36
  description: "BadRequest",
34
37
  httpApiStatus: 400
35
- }) {}
38
+ }) {
39
+ override readonly [ErrorReporter.ignore] = true
40
+ }
36
41
 
37
42
  /**
38
43
  * @category NoContent errors
@@ -51,7 +56,9 @@ export class Unauthorized extends Schema.ErrorClass<Unauthorized>("effect/HttpAp
51
56
  }, {
52
57
  description: "Unauthorized",
53
58
  httpApiStatus: 401
54
- }) {}
59
+ }) {
60
+ override readonly [ErrorReporter.ignore] = true
61
+ }
55
62
 
56
63
  /**
57
64
  * @category NoContent errors
@@ -70,7 +77,9 @@ export class Forbidden extends Schema.ErrorClass<Forbidden>("effect/HttpApiError
70
77
  }, {
71
78
  description: "Forbidden",
72
79
  httpApiStatus: 403
73
- }) {}
80
+ }) {
81
+ override readonly [ErrorReporter.ignore] = true
82
+ }
74
83
 
75
84
  /**
76
85
  * @category NoContent errors
@@ -89,7 +98,9 @@ export class NotFound extends Schema.ErrorClass<NotFound>("effect/HttpApiError/N
89
98
  }, {
90
99
  description: "NotFound",
91
100
  httpApiStatus: 404
92
- }) {}
101
+ }) {
102
+ override readonly [ErrorReporter.ignore] = true
103
+ }
93
104
 
94
105
  /**
95
106
  * @category NoContent errors
@@ -108,7 +119,9 @@ export class MethodNotAllowed extends Schema.ErrorClass<MethodNotAllowed>("effec
108
119
  }, {
109
120
  description: "MethodNotAllowed",
110
121
  httpApiStatus: 405
111
- }) {}
122
+ }) {
123
+ override readonly [ErrorReporter.ignore] = true
124
+ }
112
125
 
113
126
  /**
114
127
  * @category NoContent errors
@@ -127,7 +140,9 @@ export class NotAcceptable extends Schema.ErrorClass<NotAcceptable>("effect/Http
127
140
  }, {
128
141
  description: "NotAcceptable",
129
142
  httpApiStatus: 406
130
- }) {}
143
+ }) {
144
+ override readonly [ErrorReporter.ignore] = true
145
+ }
131
146
 
132
147
  /**
133
148
  * @category NoContent errors
@@ -146,7 +161,9 @@ export class RequestTimeout extends Schema.ErrorClass<RequestTimeout>("effect/Ht
146
161
  }, {
147
162
  description: "RequestTimeout",
148
163
  httpApiStatus: 408
149
- }) {}
164
+ }) {
165
+ override readonly [ErrorReporter.ignore] = true
166
+ }
150
167
 
151
168
  /**
152
169
  * @category NoContent errors
@@ -165,7 +182,9 @@ export class Conflict extends Schema.ErrorClass<Conflict>("effect/HttpApiError/C
165
182
  }, {
166
183
  description: "Conflict",
167
184
  httpApiStatus: 409
168
- }) {}
185
+ }) {
186
+ override readonly [ErrorReporter.ignore] = true
187
+ }
169
188
 
170
189
  /**
171
190
  * @since 4.0.0
@@ -184,7 +203,9 @@ export class Gone extends Schema.ErrorClass<Gone>("effect/HttpApiError/Gone")({
184
203
  }, {
185
204
  description: "Gone",
186
205
  httpApiStatus: 410
187
- }) {}
206
+ }) {
207
+ override readonly [ErrorReporter.ignore] = true
208
+ }
188
209
 
189
210
  /**
190
211
  * @category NoContent errors
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import * as Arr from "../../Array.ts"
5
5
  import * as Cause from "../../Cause.ts"
6
+ import { Clock } from "../../Clock.ts"
6
7
  import * as Duration from "../../Duration.ts"
7
8
  import * as Effect from "../../Effect.ts"
8
9
  import type * as Layer from "../../Layer.ts"
@@ -66,7 +67,8 @@ export const make: (
66
67
  })
67
68
 
68
69
  const opts = {
69
- excludeLogSpans: options.excludeLogSpans ?? false
70
+ excludeLogSpans: options.excludeLogSpans ?? false,
71
+ clock: yield* Clock
70
72
  }
71
73
  return Logger.make((options) => {
72
74
  exporter.push(makeLogRecord(options, opts))
@@ -104,11 +106,13 @@ export interface LogsData {
104
106
 
105
107
  // internal
106
108
 
107
- const makeLogRecord = (options: Logger.Logger.Options<unknown>, opts: {
109
+ const makeLogRecord = (options: Logger.Options<unknown>, opts: {
108
110
  readonly excludeLogSpans: boolean
111
+ readonly clock: Clock
109
112
  }): ILogRecord => {
110
- const now = options.date.getTime()
111
- const nanosString = `${now}000000`
113
+ const now = opts.clock.currentTimeNanosUnsafe()
114
+ const nanosString = now.toString()
115
+ const nowMillis = options.date.getTime()
112
116
 
113
117
  const attributes = OtlpResource.entriesToAttributes(Object.entries(options.fiber.getRef(CurrentLogAnnotations)))
114
118
  attributes.push({
@@ -119,7 +123,7 @@ const makeLogRecord = (options: Logger.Logger.Options<unknown>, opts: {
119
123
  for (const [label, startTime] of options.fiber.getRef(CurrentLogSpans)) {
120
124
  attributes.push({
121
125
  key: `logSpan.${label}`,
122
- value: { stringValue: `${now - startTime}ms` }
126
+ value: { stringValue: `${nowMillis - startTime}ms` }
123
127
  })
124
128
  }
125
129
  }
@@ -56,6 +56,8 @@ export interface AtomRegistry {
56
56
  }) => () => void
57
57
  readonly reset: () => void
58
58
  readonly dispose: () => void
59
+ onNodeAdded?: ((node: Node<any>) => void) | undefined
60
+ onNodeRemoved?: ((node: Node<any>) => void) | undefined
59
61
  }
60
62
 
61
63
  /**
@@ -65,6 +67,10 @@ export interface AtomRegistry {
65
67
  export interface Node<A> {
66
68
  readonly atom: Atom.Atom<A>
67
69
  readonly value: () => A
70
+ parents: Array<Node<any>>
71
+ children: Array<Node<any>>
72
+ listeners: Set<() => void>
73
+ currentState(): "uninitialized" | "stale" | "valid" | "removed"
68
74
  }
69
75
 
70
76
  /**
@@ -290,6 +296,8 @@ class RegistryImpl implements AtomRegistry {
290
296
  readonly defaultIdleTTL: number | undefined
291
297
  readonly scheduler: Scheduler
292
298
  readonly schedulerAsync: Scheduler
299
+ onNodeAdded?: ((node: Node<any>) => void) | undefined
300
+ onNodeRemoved?: ((node: Node<any>) => void) | undefined
293
301
 
294
302
  constructor(
295
303
  initialValues?: Iterable<readonly [Atom.Atom<any>, any]>,
@@ -386,6 +394,7 @@ class RegistryImpl implements AtomRegistry {
386
394
  if (node === undefined) {
387
395
  node = this.createNode(atom)
388
396
  this.nodes.set(key, node)
397
+ this.onNodeAdded?.(node)
389
398
  } else if (this.atomHasTtl(atom)) {
390
399
  this.removeNodeTimeout(node)
391
400
  }
@@ -436,6 +445,7 @@ class RegistryImpl implements AtomRegistry {
436
445
  } else {
437
446
  this.nodes.delete(atomKey(node.atom))
438
447
  node.remove()
448
+ this.onNodeRemoved?.(node)
439
449
  }
440
450
  }
441
451
 
@@ -450,6 +460,7 @@ class RegistryImpl implements AtomRegistry {
450
460
  if (idleTTL <= 0) {
451
461
  this.nodes.delete(atomKey(node.atom))
452
462
  node.remove()
463
+ this.onNodeRemoved?.(node)
453
464
  return
454
465
  }
455
466
  }
@@ -496,6 +507,7 @@ class RegistryImpl implements AtomRegistry {
496
507
  }
497
508
  this.nodeTimeoutBucket.delete(node)
498
509
  this.nodes.delete(atomKey(node.atom))
510
+ this.onNodeRemoved?.(node)
499
511
  this.#currentSweepTTL = node.atom.idleTTL ?? this.defaultIdleTTL!
500
512
  node.remove()
501
513
  this.#currentSweepTTL = null
@@ -507,7 +519,10 @@ class RegistryImpl implements AtomRegistry {
507
519
  this.timeoutBuckets.clear()
508
520
  this.nodeTimeoutBucket.clear()
509
521
 
510
- this.nodes.forEach((node) => node.remove())
522
+ this.nodes.forEach((node) => {
523
+ node.remove()
524
+ this.onNodeRemoved?.(node)
525
+ })
511
526
  this.nodes.clear()
512
527
  }
513
528
 
@@ -554,6 +569,19 @@ class NodeImpl<A> {
554
569
  listeners: Set<() => void> = new Set()
555
570
  skipInvalidation = false
556
571
 
572
+ currentState() {
573
+ switch (this.state) {
574
+ case NodeState.uninitialized:
575
+ return "uninitialized"
576
+ case NodeState.stale:
577
+ return "stale"
578
+ case NodeState.valid:
579
+ return "valid"
580
+ default:
581
+ return "removed"
582
+ }
583
+ }
584
+
557
585
  get canBeRemoved(): boolean {
558
586
  return !this.atom.keepAlive && this.listeners.size === 0 && this.children.length === 0 && this.state !== 0
559
587
  }
@@ -8,6 +8,7 @@ import * as Effect from "../../Effect.ts"
8
8
  import * as Exit from "../../Exit.ts"
9
9
  import * as Fiber from "../../Fiber.ts"
10
10
  import { constant, constTrue, constVoid, identity } from "../../Function.ts"
11
+ import { reportCauseUnsafe } from "../../internal/effect.ts"
11
12
  import * as Latch from "../../Latch.ts"
12
13
  import * as Layer from "../../Layer.ts"
13
14
  import type * as Option from "../../Option.ts"
@@ -273,6 +274,9 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
273
274
  requestId: request.id,
274
275
  exit
275
276
  })
277
+ if (exit._tag === "Failure") {
278
+ reportCauseUnsafe(Fiber.getCurrent()!, exit.cause)
279
+ }
276
280
  return close ? Effect.ensuring(write, close) : write
277
281
  })
278
282
  if (enableTracing) {