liminal 0.17.14 → 0.17.15

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 (94) hide show
  1. package/Actor.ts +12 -13
  2. package/ActorTransport.ts +6 -4
  3. package/Audition.ts +87 -40
  4. package/CHANGELOG.md +8 -0
  5. package/Client.ts +260 -134
  6. package/ClientDirectory.ts +50 -36
  7. package/ClientHandleEncoders.ts +15 -0
  8. package/Fn.ts +55 -0
  9. package/Method.ts +11 -21
  10. package/Protocol.ts +44 -36
  11. package/Reducer.ts +22 -0
  12. package/Tracing.ts +37 -0
  13. package/browser/BrowserActorNamespace.ts +65 -30
  14. package/dist/Actor.d.ts +1 -1
  15. package/dist/Actor.js +6 -6
  16. package/dist/Actor.js.map +1 -1
  17. package/dist/ActorTransport.d.ts +5 -4
  18. package/dist/Audition.d.ts +16 -9
  19. package/dist/Audition.js +25 -9
  20. package/dist/Audition.js.map +1 -1
  21. package/dist/Client.d.ts +21 -14
  22. package/dist/Client.js +147 -100
  23. package/dist/Client.js.map +1 -1
  24. package/dist/ClientDirectory.d.ts +14 -6
  25. package/dist/ClientDirectory.js +25 -22
  26. package/dist/ClientDirectory.js.map +1 -1
  27. package/dist/ClientHandleEncoders.d.ts +7 -0
  28. package/dist/ClientHandleEncoders.js +2 -0
  29. package/dist/ClientHandleEncoders.js.map +1 -0
  30. package/dist/Fn.d.ts +16 -0
  31. package/dist/Fn.js +2 -0
  32. package/dist/Fn.js.map +1 -0
  33. package/dist/Method.d.ts +9 -14
  34. package/dist/Method.js +0 -1
  35. package/dist/Method.js.map +1 -1
  36. package/dist/Protocol.d.ts +19 -22
  37. package/dist/Protocol.js +20 -15
  38. package/dist/Protocol.js.map +1 -1
  39. package/dist/Reducer.d.ts +11 -0
  40. package/dist/Reducer.js +2 -0
  41. package/dist/Reducer.js.map +1 -0
  42. package/dist/Tracing.d.ts +37 -0
  43. package/dist/Tracing.js +29 -0
  44. package/dist/Tracing.js.map +1 -0
  45. package/dist/browser/BrowserActorNamespace.d.ts +5 -5
  46. package/dist/browser/BrowserActorNamespace.js +41 -20
  47. package/dist/browser/BrowserActorNamespace.js.map +1 -1
  48. package/dist/errors.d.ts +0 -4
  49. package/dist/errors.js.map +1 -1
  50. package/dist/experimental/TaggedTemplateFunction.js +1 -1
  51. package/dist/experimental/TaggedTemplateFunction.js.map +1 -1
  52. package/dist/index.d.ts +3 -3
  53. package/dist/index.js +3 -3
  54. package/dist/index.js.map +1 -1
  55. package/dist/package.json +16 -21
  56. package/dist/tsconfig.tsbuildinfo +1 -1
  57. package/dist/workerd/ActorHandle.d.ts +9 -0
  58. package/dist/workerd/ActorHandle.js +4 -0
  59. package/dist/workerd/ActorHandle.js.map +1 -0
  60. package/dist/workerd/WorkerdActorNamespace.d.ts +18 -20
  61. package/dist/workerd/WorkerdActorNamespace.js +30 -122
  62. package/dist/workerd/WorkerdActorNamespace.js.map +1 -1
  63. package/dist/workerd/WorkerdActorRuntime.d.ts +19 -0
  64. package/dist/workerd/WorkerdActorRuntime.js +204 -0
  65. package/dist/workerd/WorkerdActorRuntime.js.map +1 -0
  66. package/dist/workerd/index.d.ts +2 -0
  67. package/dist/workerd/index.js +2 -0
  68. package/dist/workerd/index.js.map +1 -1
  69. package/errors.ts +0 -6
  70. package/experimental/TaggedTemplateFunction.ts +1 -1
  71. package/index.ts +3 -3
  72. package/package.json +7 -22
  73. package/tsconfig.json +1 -1
  74. package/vitest.config.ts +7 -0
  75. package/workerd/ActorHandle.ts +29 -0
  76. package/workerd/WorkerdActorNamespace.ts +72 -260
  77. package/workerd/WorkerdActorRuntime.ts +422 -0
  78. package/workerd/index.ts +2 -0
  79. package/Accumulator.ts +0 -103
  80. package/F.ts +0 -10
  81. package/_diagnostic.ts +0 -3
  82. package/_util/Mutex.ts +0 -13
  83. package/dist/Accumulator.d.ts +0 -22
  84. package/dist/Accumulator.js +0 -37
  85. package/dist/Accumulator.js.map +0 -1
  86. package/dist/F.d.ts +0 -4
  87. package/dist/F.js +0 -2
  88. package/dist/F.js.map +0 -1
  89. package/dist/_diagnostic.d.ts +0 -4
  90. package/dist/_diagnostic.js +0 -3
  91. package/dist/_diagnostic.js.map +0 -1
  92. package/dist/_util/Mutex.d.ts +0 -7
  93. package/dist/_util/Mutex.js +0 -9
  94. package/dist/_util/Mutex.js.map +0 -1
package/tsconfig.json CHANGED
@@ -6,6 +6,6 @@
6
6
  "types": ["@cloudflare/workers-types"]
7
7
  },
8
8
  "include": [".", "package.json"],
9
- "exclude": ["dist"],
9
+ "exclude": ["dist", "vitest.config.ts"],
10
10
  "references": [{ "path": "../effect-workerd" }, { "path": "../liminal-util" }]
11
11
  }
@@ -0,0 +1,7 @@
1
+ import { mergeConfig, type ViteUserConfig } from "vitest/config"
2
+
3
+ import config from "../konfik/vitest.ts"
4
+
5
+ export default mergeConfig(config, {
6
+ test: { name: "liminal" },
7
+ } satisfies ViteUserConfig)
@@ -0,0 +1,29 @@
1
+ import { Schema as S, Effect, Cause, Encoding } from "effect"
2
+ import { NativeRequest } from "effect-workerd"
3
+ import { HttpServerResponse } from "effect/unstable/http"
4
+
5
+ import type { TopFromString } from "../_util/schema.ts"
6
+ import type { Methods } from "../Method.ts"
7
+
8
+ export interface ActorHandle<
9
+ NamespaceSelf,
10
+ Internal extends Methods,
11
+ Name extends TopFromString,
12
+ AttachmentFields extends S.Struct.Fields,
13
+ > {
14
+ readonly upgrade: (
15
+ attachments: S.Struct<AttachmentFields>["Type"],
16
+ ) => Effect.Effect<
17
+ HttpServerResponse.HttpServerResponse,
18
+ S.SchemaError | Encoding.EncodingError | Cause.NoSuchElementError,
19
+ | NamespaceSelf
20
+ | NativeRequest.NativeRequest
21
+ | Name["EncodingServices"]
22
+ | S.Struct<AttachmentFields>["EncodingServices"]
23
+ >
24
+
25
+ readonly call: <K extends keyof Internal, M extends Internal[K]>(
26
+ method: K,
27
+ payload: M["payload"]["Type"],
28
+ ) => Effect.Effect<M["success"]["Type"], M["failure"]["Type"], NamespaceSelf>
29
+ }
@@ -1,39 +1,19 @@
1
- import { DurableObject } from "cloudflare:workers"
2
- import {
3
- Layer,
4
- Effect,
5
- Scope,
6
- Schema as S,
7
- Context,
8
- ManagedRuntime,
9
- ConfigProvider,
10
- Duration,
11
- flow,
12
- String,
13
- Array,
14
- Encoding,
15
- Option,
16
- Cause,
17
- } from "effect"
18
- import { Binding, DoState, NativeRequest } from "effect-workerd"
1
+ import { Layer, Effect, Schema as S, Context, flow, String, Array, Encoding, Exit } from "effect"
2
+ import { Binding, NativeRequest } from "effect-workerd"
19
3
  import { SecWebSocketProtocol, close } from "effect-workerd/socket_util"
20
- import { HttpServerResponse, HttpClient, FetchHttpClient } from "effect/unstable/http"
21
- import { boundLayer } from "liminal-util/boundLayer"
22
- import { logCause } from "liminal-util/logCause"
4
+ import { HttpServerResponse, HttpTraceContext } from "effect/unstable/http"
5
+ import * as Spanner from "liminal-util/Spanner"
23
6
 
7
+ import { type TopFromString, encodeJsonString } from "../_util/schema.ts"
24
8
  import type { Actor } from "../Actor.ts"
25
- import type { ActorTransport } from "../ActorTransport.ts"
9
+ import type { Methods } from "../Method.ts"
26
10
  import type { ProtocolDefinition } from "../Protocol.ts"
11
+ import type { ActorHandle } from "./ActorHandle.ts"
27
12
 
28
- import { diagnostic } from "../_diagnostic.ts"
29
- import * as Mutex from "../_util/Mutex.ts"
30
- import { type TopFromString, encodeJsonString, decodeJsonString } from "../_util/schema.ts"
31
- import * as ClientDirectory from "../ClientDirectory.ts"
32
- import * as Method from "../Method.ts"
33
-
34
- const { debug, span } = diagnostic("workerd.WorkerdActorNamespace")
13
+ const span = Spanner.make(import.meta.url)
35
14
 
36
15
  export interface ActorNamespaceDefinition<
16
+ Internal extends Methods,
37
17
  ActorSelf,
38
18
  ActorId extends string,
39
19
  Name extends TopFromString,
@@ -41,47 +21,18 @@ export interface ActorNamespaceDefinition<
41
21
  ClientSelf,
42
22
  ClientId extends string,
43
23
  D extends ProtocolDefinition,
44
- PreludeROut,
45
- PreludeE,
46
- RunROut,
47
- RunE,
48
24
  > {
49
- readonly ""?: this["actor"]["definition"]["client"]["protocol"]
50
-
51
- readonly actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>
52
-
53
- readonly prelude: Layer.Layer<
54
- | PreludeROut
55
- | NonNullable<this[""]>["F"]["Payload"]["DecodingServices"]
56
- | NonNullable<this[""]>["F"]["Success"]["EncodingServices"]
57
- | NonNullable<this[""]>["F"]["Failure"]["EncodingServices"]
58
- | NonNullable<this[""]>["Event"]["EncodingServices"]
59
- | S.Struct<AttachmentFields>["DecodingServices"]
60
- | S.Struct<AttachmentFields>["EncodingServices"]
61
- | Name["EncodingServices"]
62
- | Name["DecodingServices"],
63
- PreludeE
64
- >
65
-
66
- readonly layer: Layer.Layer<RunROut, RunE, ActorSelf | HttpClient.HttpClient | PreludeROut>
25
+ readonly binding: string
67
26
 
68
- readonly handlers: Method.Handlers<
69
- D["methods"],
70
- ActorSelf | HttpClient.HttpClient | PreludeROut | RunROut | Scope.Scope
71
- >
72
-
73
- readonly onConnect: Effect.Effect<
74
- void,
75
- never,
76
- ActorSelf | HttpClient.HttpClient | PreludeROut | RunROut | Scope.Scope
77
- >
27
+ readonly internal: Internal
78
28
 
79
- readonly hibernation?: Duration.Input | undefined
29
+ readonly actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>
80
30
  }
81
31
 
82
32
  export interface ActorNamespace<
83
33
  NamespaceSelf,
84
34
  NamespaceId extends string,
35
+ Internal extends Methods,
85
36
  ActorSelf,
86
37
  ActorId extends string,
87
38
  Name extends TopFromString,
@@ -89,48 +40,44 @@ export interface ActorNamespace<
89
40
  ClientSelf,
90
41
  ClientId extends string,
91
42
  D extends ProtocolDefinition,
92
- PreludeROut,
93
- PreludeE,
94
- RunROut,
95
- RunE,
96
43
  > {
97
- new (state: DurableObjectState<{}>, env: Cloudflare.Env): DurableObject
98
-
99
- readonly service: Context.ServiceClass<NamespaceSelf, NamespaceId, DurableObjectNamespace>
44
+ new (
45
+ _: never,
46
+ ): Context.ServiceClass.Shape<
47
+ NamespaceId,
48
+ DurableObjectNamespace<Rpc.DurableObjectBranded & WorkerdActorNamespace.MakeRpc<Internal>>
49
+ >
100
50
 
101
51
  readonly definition: ActorNamespaceDefinition<
52
+ Methods,
102
53
  ActorSelf,
103
54
  ActorId,
104
55
  Name,
105
56
  AttachmentFields,
106
57
  ClientSelf,
107
58
  ClientId,
108
- D,
109
- PreludeROut,
110
- PreludeE,
111
- RunROut,
112
- RunE
59
+ D
113
60
  >
114
61
 
115
- readonly upgrade: (
116
- name: Name["Type"],
117
- attachments: S.Struct<AttachmentFields>["Type"],
118
- ) => Effect.Effect<
119
- HttpServerResponse.HttpServerResponse,
120
- S.SchemaError | Encoding.EncodingError | Cause.NoSuchElementError,
121
- | NamespaceSelf
122
- | NativeRequest.NativeRequest
123
- | Name["EncodingServices"]
124
- | S.Struct<AttachmentFields>["EncodingServices"]
125
- >
62
+ readonly bind: (name: Name["Type"]) => ActorHandle<NamespaceSelf, Internal, Name, AttachmentFields>
63
+
64
+ readonly layer: Layer.Layer<NamespaceSelf, S.SchemaError, never>
65
+ }
126
66
 
127
- readonly layer: (binding: string) => Layer.Layer<NamespaceSelf, S.SchemaError, never>
67
+ export declare namespace WorkerdActorNamespace {
68
+ export type MakeRpc<External extends Methods> = {
69
+ rpc: <K extends keyof External>(
70
+ method: K,
71
+ payload: External[K]["payload"]["Type"],
72
+ ) => Promise<Exit.Exit<External[K]["success"]["Type"], External[K]["failure"]["Type"]>>
73
+ }
128
74
  }
129
75
 
130
76
  export const Service =
131
77
  <NamespaceSelf>() =>
132
78
  <
133
79
  NamespaceId extends string,
80
+ Internal extends Methods,
134
81
  ActorSelf,
135
82
  ActorId extends string,
136
83
  Name extends TopFromString,
@@ -138,41 +85,22 @@ export const Service =
138
85
  ClientSelf,
139
86
  ClientId extends string,
140
87
  D extends ProtocolDefinition,
141
- PreludeROut,
142
- PreludeE,
143
- RunROut,
144
- RunE,
145
88
  >(
146
89
  id: NamespaceId,
147
- definition: ActorNamespaceDefinition<
148
- ActorSelf,
149
- ActorId,
150
- Name,
151
- AttachmentFields,
152
- ClientSelf,
153
- ClientId,
154
- D,
155
- PreludeROut,
156
- PreludeE,
157
- RunROut,
158
- RunE
159
- >,
90
+ definition: ActorNamespaceDefinition<Internal, ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>,
160
91
  ): ActorNamespace<
161
92
  NamespaceSelf,
162
93
  NamespaceId,
94
+ Internal,
163
95
  ActorSelf,
164
96
  ActorId,
165
97
  Name,
166
98
  AttachmentFields,
167
99
  ClientSelf,
168
100
  ClientId,
169
- D,
170
- PreludeROut,
171
- PreludeE,
172
- RunROut,
173
- RunE
101
+ D
174
102
  > => {
175
- const { hibernation, actor, prelude, handlers, layer, onConnect } = definition
103
+ const { binding, actor } = definition
176
104
  const {
177
105
  definition: {
178
106
  name: Name,
@@ -181,160 +109,25 @@ export const Service =
181
109
  },
182
110
  } = actor
183
111
 
184
- const encodeName = S.encodeEffect(Name)
112
+ const tag = Context.Service<
113
+ NamespaceSelf,
114
+ DurableObjectNamespace<Rpc.DurableObjectBranded & WorkerdActorNamespace.MakeRpc<Internal>>
115
+ >()(id)
185
116
 
117
+ const encodeName = S.encodeEffect(Name)
186
118
  const Attachments = S.Struct(AttachmentFields)
187
- const encodeAttachments = S.encodeEffect(S.toCodecJson(Attachments))
188
- const decodeAttachments = S.decodeUnknownEffect(S.toCodecJson(Attachments))
189
119
  const encodeAttachmentsString = encodeJsonString(Attachments)
190
- const decodeAttachmentsString = decodeJsonString(Attachments)
191
-
192
- const encodeAuditionSuccess = encodeJsonString(P.Audition.Success)
193
120
  const encodeAuditionFailure = encodeJsonString(P.Audition.Failure)
194
- const decodeClientM = decodeJsonString(P.Client)
195
- const encodeFSuccess = encodeJsonString(P.F.Success)
196
- const encodeFFailure = encodeJsonString(P.F.Failure)
197
-
198
- const encodeEvent = encodeJsonString(P.Event)
199
-
200
- const transport: ActorTransport<WebSocket, AttachmentFields, D> = {
201
- send: (socket, event) => encodeEvent(event).pipe(Effect.andThen((v) => Effect.sync(() => socket.send(v)))),
202
- close: (socket) => Effect.sync(() => socket.close(1000)),
203
- snapshot: (socket, attachments) =>
204
- encodeAttachments(attachments).pipe(Effect.andThen((v) => Effect.sync(() => socket.serializeAttachment(v)))),
205
- }
206
121
 
207
- class NameDecoded extends Context.Service<NameDecoded, Name["Type"]>()(
208
- "liminal/WorkerdActorNamespace/NameDecoded",
209
- ) {}
122
+ const bind = (name: Name["Type"]): ActorHandle<NamespaceSelf, Internal, Name, AttachmentFields> => {
123
+ const getStub = Effect.gen(function* () {
124
+ const namespace = yield* tag
125
+ const nameEncoded = yield* encodeName(name)
126
+ return namespace.getByName(nameEncoded)
127
+ })
210
128
 
211
- return class extends DurableObject {
212
- static definition = definition
213
- static service = Context.Service<NamespaceSelf, DurableObjectNamespace>()(id)
214
- static layer = Binding.layer(this.service, ["idFromName", "idFromString", "newUniqueId", "get"])
215
-
216
- readonly runtime
217
- readonly directory = ClientDirectory.make(actor, transport)
218
-
219
- constructor(state: DurableObjectState<{}>, env: Cloudflare.Env) {
220
- super(state, env)
221
- if (hibernation) {
222
- Option.andThen(
223
- Duration.fromInput(hibernation),
224
- flow(Duration.toMillis, state.setHibernatableWebSocketEventTimeout),
225
- )
226
- }
227
-
228
- const Live = Layer.mergeAll(
229
- FetchHttpClient.layer,
230
- Layer.succeed(DoState.DoState, state),
231
- Mutex.layer,
232
- Layer.effect(NameDecoded, S.decodeUnknownEffect(Name)(state.id.name)).pipe(
233
- Layer.provideMerge(prelude.pipe(Layer.provideMerge(ConfigProvider.layer(ConfigProvider.fromUnknown(env))))),
234
- ),
235
- ).pipe(boundLayer("actor"))
236
-
237
- const hydrateAttachments = Effect.gen({ self: this }, function* () {
238
- for (const socket of state.getWebSockets()) {
239
- const attachments = yield* decodeAttachments(socket.deserializeAttachment())
240
- yield* this.directory.register(socket, attachments)
241
- }
242
- }).pipe(span("hydrateAttachments"), Effect.tapCause(logCause))
243
-
244
- this.runtime = hydrateAttachments.pipe(Layer.effectDiscard, Layer.provideMerge(Live), ManagedRuntime.make)
245
- }
246
-
247
- override fetch(request: Request): Promise<Response> {
248
- return Effect.gen({ self: this }, function* () {
249
- const url = new URL(request.url)
250
- const attachments = yield* decodeAttachmentsString(url.searchParams.get("__liminal_attachments"))
251
- const { 0: webSocket, 1: server } = new WebSocketPair()
252
- const state = yield* DoState.DoState
253
- state.acceptWebSocket(server)
254
- server.send(yield* encodeAuditionSuccess({ _tag: "Audition.Success" }))
255
- const currentClient = yield* this.directory.register(server, attachments)
256
- const name = yield* NameDecoded
257
- const ActorLive = Layer.succeed(actor, {
258
- name,
259
- clients: this.directory.handles,
260
- currentClient,
261
- })
262
- yield* onConnect.pipe(
263
- Effect.scoped,
264
- span("onConnect"),
265
- Effect.scoped,
266
- Effect.provide(Layer.provideMerge(layer, ActorLive)),
267
- )
268
- yield* debug("ClientRegistered")
269
- return new Response(null, {
270
- status: 101,
271
- webSocket,
272
- headers: { [SecWebSocketProtocol]: "liminal" },
273
- })
274
- }).pipe(Effect.tapCause(logCause), span("fetch"), this.runtime.runPromise)
275
- }
276
-
277
- override webSocketMessage(socket: WebSocket, raw: string | ArrayBuffer) {
129
+ const upgrade = (attachments: S.Struct<AttachmentFields>["Type"]) =>
278
130
  Effect.gen({ self: this }, function* () {
279
- const currentClient = yield* this.directory.get(socket)
280
- const name = yield* NameDecoded
281
- const ActorLive = Layer.succeed(actor, {
282
- name,
283
- clients: this.directory.handles,
284
- currentClient,
285
- })
286
- const message = yield* decodeClientM(raw instanceof ArrayBuffer ? new TextDecoder().decode(raw) : raw)
287
- yield* debug("MessageReceived", { message })
288
- if (message._tag === "Audition.Payload") {
289
- return yield* Effect.die(undefined)
290
- }
291
- if (message._tag === "Disconnect") {
292
- return yield* currentClient.disconnect
293
- }
294
- const { id, payload } = message
295
- const { _tag, value } = payload as never
296
- yield* handlers[_tag]!(value).pipe(
297
- Effect.matchEffect({
298
- onSuccess: (value) =>
299
- encodeFSuccess({
300
- _tag: "F.Success",
301
- id,
302
- success: { _tag, value } as never,
303
- }),
304
- onFailure: (value) =>
305
- encodeFFailure({
306
- _tag: "F.Failure",
307
- id,
308
- failure: { _tag, value } as never,
309
- }),
310
- }),
311
- span("handler", { attributes: { _tag } }),
312
- Effect.andThen((v) => Effect.sync(() => socket.send(v))),
313
- Effect.scoped,
314
- Effect.provide(Layer.provideMerge(layer, ActorLive)),
315
- )
316
- }).pipe(Effect.scoped, Mutex.task, Effect.tapCause(logCause), span("webSocketMessage"), this.runtime.runFork)
317
- }
318
-
319
- override webSocketClose(socket: WebSocket, _code: number, _reason: string, _wasClean: boolean) {
320
- this.directory
321
- .unregister(socket)
322
- .pipe(Effect.tap(debug("SocketClosed")), Effect.tapCause(logCause), this.runtime.runFork)
323
- }
324
-
325
- override webSocketError(socket: WebSocket, cause: unknown) {
326
- Effect.gen({ self: this }, function* () {
327
- yield* debug("SocketErrored", { cause })
328
- yield* this.directory.unregister(socket)
329
- }).pipe(Effect.tapCause(logCause), span("SocketErrored", { attributes: { cause } }), this.runtime.runFork)
330
- }
331
-
332
- static readonly upgrade = (name: Name["Type"], attachments: (typeof Attachments)["Type"]) =>
333
- Effect.gen({ self: this }, function* () {
334
- yield* debug("UpgradeInitiated", { attachments })
335
- const namespace = yield* this.service
336
- const nameEncoded = yield* encodeName(name)
337
- const stub = namespace.getByName(nameEncoded)
338
131
  const request = yield* NativeRequest.NativeRequest
339
132
  const protocols = yield* Effect.fromNullishOr(request.headers.get(SecWebSocketProtocol)).pipe(
340
133
  Effect.map(flow(String.split(","), Array.map(String.trim))),
@@ -354,9 +147,28 @@ export const Service =
354
147
  }
355
148
  const url = new URL(request.url)
356
149
  url.searchParams.set("__liminal_attachments", yield* encodeAttachmentsString(attachments))
357
- return yield* Effect.promise(() => stub.fetch(new Request(url, request))).pipe(
358
- Effect.map(HttpServerResponse.raw),
359
- )
360
- }).pipe(span("upgrade"))
150
+ const actorRequest = new Request(url, request)
151
+ const traceHeaders = yield* Effect.currentSpan.pipe(Effect.map(HttpTraceContext.toHeaders))
152
+ for (const [key, value] of Object.entries(traceHeaders)) {
153
+ actorRequest.headers.set(key, value)
154
+ }
155
+ const stub = yield* getStub
156
+ return yield* Effect.promise(() => stub.fetch(actorRequest)).pipe(Effect.map(HttpServerResponse.raw))
157
+ }).pipe(span("upgrade", { kind: "client" }))
158
+
159
+ const call = Effect.fnUntraced(function* <K extends keyof Internal, M extends Internal[K]>(
160
+ method: K,
161
+ payload: M["payload"]["Type"],
162
+ ): Effect.fn.Return<M["success"]["Type"], M["failure"]["Type"], NamespaceSelf> {
163
+ const stub = yield* getStub
164
+ const exit = yield* Effect.promise(() => stub.rpc(method as never, payload as never))
165
+ return yield* exit as any
166
+ })
167
+
168
+ return { upgrade, call }
361
169
  }
170
+
171
+ const layer = Binding.layer(tag, ["idFromName", "idFromString", "newUniqueId", "get", "getByName"])(binding)
172
+
173
+ return Object.assign(tag, { definition, bind, layer })
362
174
  }