effect 4.0.0-beta.44 → 4.0.0-beta.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Equal.d.ts.map +1 -1
- package/dist/Equal.js +16 -0
- package/dist/Equal.js.map +1 -1
- package/dist/Hash.js +1 -1
- package/dist/Hash.js.map +1 -1
- package/dist/Semaphore.d.ts +1 -1
- package/dist/Semaphore.d.ts.map +1 -1
- package/dist/Semaphore.js +1 -3
- package/dist/Semaphore.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +24 -21
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/eventlog/Event.d.ts +0 -6
- package/dist/unstable/eventlog/Event.d.ts.map +1 -1
- package/dist/unstable/eventlog/Event.js +0 -5
- package/dist/unstable/eventlog/Event.js.map +1 -1
- package/dist/unstable/eventlog/EventGroup.d.ts +0 -2
- package/dist/unstable/eventlog/EventGroup.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventGroup.js +0 -2
- package/dist/unstable/eventlog/EventGroup.js.map +1 -1
- package/dist/unstable/eventlog/EventJournal.d.ts +22 -5
- package/dist/unstable/eventlog/EventJournal.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventJournal.js +126 -67
- package/dist/unstable/eventlog/EventJournal.js.map +1 -1
- package/dist/unstable/eventlog/EventLog.d.ts +88 -34
- package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLog.js +215 -141
- package/dist/unstable/eventlog/EventLog.js.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.d.ts +9 -7
- package/dist/unstable/eventlog/EventLogEncryption.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogEncryption.js +13 -15
- package/dist/unstable/eventlog/EventLogEncryption.js.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.d.ts +228 -0
- package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -0
- package/dist/unstable/eventlog/EventLogMessage.js +214 -0
- package/dist/unstable/eventlog/EventLogMessage.js.map +1 -0
- package/dist/unstable/eventlog/EventLogRemote.d.ts +109 -194
- package/dist/unstable/eventlog/EventLogRemote.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.js +165 -320
- package/dist/unstable/eventlog/EventLogRemote.js.map +1 -1
- package/dist/unstable/eventlog/EventLogServer.d.ts +25 -47
- package/dist/unstable/eventlog/EventLogServer.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogServer.js +127 -198
- package/dist/unstable/eventlog/EventLogServer.js.map +1 -1
- package/dist/unstable/eventlog/EventLogServerEncrypted.d.ts +60 -0
- package/dist/unstable/eventlog/EventLogServerEncrypted.d.ts.map +1 -0
- package/dist/unstable/eventlog/EventLogServerEncrypted.js +166 -0
- package/dist/unstable/eventlog/EventLogServerEncrypted.js.map +1 -0
- package/dist/unstable/eventlog/EventLogServerUnencrypted.d.ts +183 -0
- package/dist/unstable/eventlog/EventLogServerUnencrypted.d.ts.map +1 -0
- package/dist/unstable/eventlog/EventLogServerUnencrypted.js +461 -0
- package/dist/unstable/eventlog/EventLogServerUnencrypted.js.map +1 -0
- package/dist/unstable/eventlog/EventLogSessionAuth.d.ts +117 -0
- package/dist/unstable/eventlog/EventLogSessionAuth.d.ts.map +1 -0
- package/dist/unstable/eventlog/EventLogSessionAuth.js +284 -0
- package/dist/unstable/eventlog/EventLogSessionAuth.js.map +1 -0
- package/dist/unstable/eventlog/{SqlEventLogJournal.d.ts → SqlEventJournal.d.ts} +2 -2
- package/dist/unstable/eventlog/SqlEventJournal.d.ts.map +1 -0
- package/dist/unstable/eventlog/{SqlEventLogJournal.js → SqlEventJournal.js} +20 -14
- package/dist/unstable/eventlog/SqlEventJournal.js.map +1 -0
- package/dist/unstable/eventlog/{SqlEventLogServer.d.ts → SqlEventLogServerEncrypted.d.ts} +5 -5
- package/dist/unstable/eventlog/SqlEventLogServerEncrypted.d.ts.map +1 -0
- package/dist/unstable/eventlog/{SqlEventLogServer.js → SqlEventLogServerEncrypted.js} +65 -24
- package/dist/unstable/eventlog/SqlEventLogServerEncrypted.js.map +1 -0
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.d.ts +25 -0
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.d.ts.map +1 -0
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js +354 -0
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js.map +1 -0
- package/dist/unstable/eventlog/index.d.ts +22 -2
- package/dist/unstable/eventlog/index.d.ts.map +1 -1
- package/dist/unstable/eventlog/index.js +22 -2
- package/dist/unstable/eventlog/index.js.map +1 -1
- package/dist/unstable/eventlog/internal/identityRootSecretDerivation.d.ts +2 -0
- package/dist/unstable/eventlog/internal/identityRootSecretDerivation.d.ts.map +1 -0
- package/dist/unstable/eventlog/internal/identityRootSecretDerivation.js +89 -0
- package/dist/unstable/eventlog/internal/identityRootSecretDerivation.js.map +1 -0
- package/dist/unstable/reactivity/AtomHttpApi.d.ts +1 -2
- package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.js +2 -2
- package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.d.ts +1 -2
- package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.js +3 -3
- package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
- package/dist/unstable/rpc/Rpc.d.ts +25 -4
- package/dist/unstable/rpc/Rpc.d.ts.map +1 -1
- package/dist/unstable/rpc/Rpc.js +26 -0
- package/dist/unstable/rpc/Rpc.js.map +1 -1
- package/dist/unstable/rpc/RpcClient.d.ts +3 -13
- package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcClient.js +47 -23
- package/dist/unstable/rpc/RpcClient.js.map +1 -1
- package/dist/unstable/rpc/RpcGroup.d.ts +1 -1
- package/dist/unstable/rpc/RpcGroup.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcMiddleware.d.ts +2 -2
- package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +3 -2
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/rpc/Utils.d.ts +6 -0
- package/dist/unstable/rpc/Utils.d.ts.map +1 -1
- package/dist/unstable/rpc/Utils.js +44 -0
- package/dist/unstable/rpc/Utils.js.map +1 -1
- package/dist/unstable/schema/Model.d.ts +2 -2
- package/dist/unstable/schema/Model.d.ts.map +1 -1
- package/dist/unstable/schema/Model.js +2 -4
- package/dist/unstable/schema/Model.js.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.js +1 -12
- package/dist/unstable/schema/VariantSchema.js.map +1 -1
- package/dist/unstable/workers/Transferable.d.ts +1 -1
- package/dist/unstable/workers/Transferable.d.ts.map +1 -1
- package/dist/unstable/workers/Transferable.js +1 -1
- package/dist/unstable/workers/Transferable.js.map +1 -1
- package/package.json +1 -1
- package/src/Equal.ts +17 -0
- package/src/Hash.ts +2 -2
- package/src/Semaphore.ts +2 -4
- package/src/unstable/ai/McpServer.ts +24 -22
- package/src/unstable/eventlog/Event.ts +0 -8
- package/src/unstable/eventlog/EventGroup.ts +0 -4
- package/src/unstable/eventlog/EventJournal.ts +144 -76
- package/src/unstable/eventlog/EventLog.ts +342 -221
- package/src/unstable/eventlog/EventLogEncryption.ts +16 -30
- package/src/unstable/eventlog/EventLogMessage.ts +277 -0
- package/src/unstable/eventlog/EventLogRemote.ts +261 -408
- package/src/unstable/eventlog/EventLogServer.ts +182 -274
- package/src/unstable/eventlog/EventLogServerEncrypted.ts +206 -0
- package/src/unstable/eventlog/EventLogServerUnencrypted.ts +749 -0
- package/src/unstable/eventlog/EventLogSessionAuth.ts +437 -0
- package/src/unstable/eventlog/{SqlEventLogJournal.ts → SqlEventJournal.ts} +26 -18
- package/src/unstable/eventlog/{SqlEventLogServer.ts → SqlEventLogServerEncrypted.ts} +102 -40
- package/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +500 -0
- package/src/unstable/eventlog/index.ts +27 -2
- package/src/unstable/eventlog/internal/identityRootSecretDerivation.ts +153 -0
- package/src/unstable/reactivity/AtomHttpApi.ts +23 -8
- package/src/unstable/reactivity/AtomRpc.ts +16 -5
- package/src/unstable/rpc/Rpc.ts +42 -4
- package/src/unstable/rpc/RpcClient.ts +59 -24
- package/src/unstable/rpc/RpcGroup.ts +1 -1
- package/src/unstable/rpc/RpcMiddleware.ts +2 -2
- package/src/unstable/rpc/RpcServer.ts +5 -3
- package/src/unstable/rpc/Utils.ts +59 -0
- package/src/unstable/schema/Model.ts +4 -6
- package/src/unstable/schema/VariantSchema.ts +4 -17
- package/src/unstable/workers/Transferable.ts +9 -11
- package/dist/unstable/eventlog/SqlEventLogJournal.d.ts.map +0 -1
- package/dist/unstable/eventlog/SqlEventLogJournal.js.map +0 -1
- package/dist/unstable/eventlog/SqlEventLogServer.d.ts.map +0 -1
- package/dist/unstable/eventlog/SqlEventLogServer.js.map +0 -1
|
@@ -30,7 +30,6 @@ export interface AtomHttpApiClient<Self, Id extends string, Groups extends HttpA
|
|
|
30
30
|
{
|
|
31
31
|
new(_: never): Context.ServiceClass.Shape<Id, HttpApiClient.Client<Groups, never, never>>
|
|
32
32
|
|
|
33
|
-
readonly layer: Layer.Layer<Self>
|
|
34
33
|
readonly runtime: Atom.AtomRuntime<Self>
|
|
35
34
|
|
|
36
35
|
readonly mutation: <
|
|
@@ -147,10 +146,15 @@ export const Service = <Self>() =>
|
|
|
147
146
|
id: Id,
|
|
148
147
|
options: {
|
|
149
148
|
readonly api: HttpApi.HttpApi<ApiId, Groups>
|
|
150
|
-
readonly httpClient:
|
|
151
|
-
|
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
readonly httpClient:
|
|
150
|
+
| Layer.Layer<
|
|
151
|
+
| HttpApiGroup.ClientServices<Groups>
|
|
152
|
+
| HttpClient.HttpClient
|
|
153
|
+
>
|
|
154
|
+
| ((get: Atom.AtomContext) => Layer.Layer<
|
|
155
|
+
| HttpApiGroup.ClientServices<Groups>
|
|
156
|
+
| HttpClient.HttpClient
|
|
157
|
+
>)
|
|
154
158
|
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
|
|
155
159
|
readonly transformResponse?:
|
|
156
160
|
| ((effect: Effect.Effect<unknown, unknown, unknown>) => Effect.Effect<unknown, unknown, unknown>)
|
|
@@ -164,12 +168,23 @@ export const Service = <Self>() =>
|
|
|
164
168
|
HttpApiClient.Client<Groups, never, never>
|
|
165
169
|
>()(id) as any
|
|
166
170
|
|
|
167
|
-
|
|
171
|
+
const layer = Layer.effect(
|
|
168
172
|
self,
|
|
169
173
|
HttpApiClient.make(options.api, options)
|
|
170
|
-
)
|
|
174
|
+
)
|
|
171
175
|
const runtimeFactory = options.runtime ?? Atom.runtime
|
|
172
|
-
self.runtime = runtimeFactory(
|
|
176
|
+
self.runtime = runtimeFactory(
|
|
177
|
+
typeof options.httpClient === "function" ?
|
|
178
|
+
(get) =>
|
|
179
|
+
Layer.provide(
|
|
180
|
+
layer,
|
|
181
|
+
(options.httpClient as (get: Atom.AtomContext) => Layer.Layer<
|
|
182
|
+
| HttpApiGroup.ClientServices<Groups>
|
|
183
|
+
| HttpClient.HttpClient
|
|
184
|
+
>)(get)
|
|
185
|
+
) as Layer.Layer<Self> :
|
|
186
|
+
Layer.provide(layer, options.httpClient) as Layer.Layer<Self>
|
|
187
|
+
)
|
|
173
188
|
|
|
174
189
|
const catchErrors = Effect.catch((e: unknown) =>
|
|
175
190
|
Schema.isSchemaError(e) || HttpClientError.isHttpClientError(e) ? Effect.die(e) : Effect.fail(e)
|
|
@@ -37,7 +37,6 @@ export interface AtomRpcClient<Self, Id extends string, Rpcs extends Rpc.Any> ex
|
|
|
37
37
|
RpcClient.RpcClient.Flat<Rpcs, RpcClientError>
|
|
38
38
|
>
|
|
39
39
|
|
|
40
|
-
readonly layer: Layer.Layer<Self>
|
|
41
40
|
readonly runtime: Atom.AtomRuntime<Self>
|
|
42
41
|
|
|
43
42
|
readonly mutation: <Tag extends Rpc.Tag<Rpcs>>(
|
|
@@ -120,7 +119,9 @@ export const Service = <Self>() =>
|
|
|
120
119
|
id: Id,
|
|
121
120
|
options: {
|
|
122
121
|
readonly group: RpcGroup.RpcGroup<Rpcs>
|
|
123
|
-
readonly protocol:
|
|
122
|
+
readonly protocol:
|
|
123
|
+
| Layer.Layer<Exclude<NoInfer<RM>, Scope>, ER>
|
|
124
|
+
| ((get: Atom.AtomContext) => Layer.Layer<Exclude<NoInfer<RM>, Scope>, ER>)
|
|
124
125
|
readonly spanPrefix?: string | undefined
|
|
125
126
|
readonly spanAttributes?: Record<string, unknown> | undefined
|
|
126
127
|
readonly generateRequestId?: (() => RequestId) | undefined
|
|
@@ -140,7 +141,7 @@ export const Service = <Self>() =>
|
|
|
140
141
|
RpcClient.RpcClient.Flat<Rpcs, RpcClientError>
|
|
141
142
|
>()(id) as any
|
|
142
143
|
|
|
143
|
-
|
|
144
|
+
const layer = Layer.effect(
|
|
144
145
|
self,
|
|
145
146
|
options.makeEffect ??
|
|
146
147
|
(RpcClient.make(options.group, {
|
|
@@ -151,9 +152,19 @@ export const Service = <Self>() =>
|
|
|
151
152
|
never,
|
|
152
153
|
RM
|
|
153
154
|
>)
|
|
154
|
-
)
|
|
155
|
+
)
|
|
155
156
|
const runtimeFactory = options.runtime ?? Atom.runtime
|
|
156
|
-
self.runtime = runtimeFactory(
|
|
157
|
+
self.runtime = runtimeFactory(
|
|
158
|
+
typeof options.protocol === "function" ?
|
|
159
|
+
(get) =>
|
|
160
|
+
Layer.provide(
|
|
161
|
+
layer,
|
|
162
|
+
Layer.orDie(
|
|
163
|
+
(options.protocol as ((get: Atom.AtomContext) => Layer.Layer<Exclude<NoInfer<RM>, Scope>, ER>))(get)
|
|
164
|
+
)
|
|
165
|
+
) :
|
|
166
|
+
Layer.provide(layer, Layer.orDie(options.protocol))
|
|
167
|
+
)
|
|
157
168
|
|
|
158
169
|
self.mutation = Atom.family(<Tag extends Rpc.Tag<Rpcs>>(tag: Tag) => {
|
|
159
170
|
const rpc = options.group.requests.get(tag)! as any as Rpc.AnyWithProps
|
package/src/unstable/rpc/Rpc.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type * as Queue from "../../Queue.ts"
|
|
|
13
13
|
import * as Schema from "../../Schema.ts"
|
|
14
14
|
import type { Stream } from "../../Stream.ts"
|
|
15
15
|
import type * as Struct from "../../Struct.ts"
|
|
16
|
+
import type { NoInfer } from "../../Types.ts"
|
|
16
17
|
import type { Headers } from "../http/Headers.ts"
|
|
17
18
|
import type { RequestId } from "./RpcMessage.ts"
|
|
18
19
|
import type * as RpcMiddleware from "./RpcMiddleware.ts"
|
|
@@ -134,7 +135,7 @@ export interface Rpc<
|
|
|
134
135
|
*/
|
|
135
136
|
annotate<I, S>(
|
|
136
137
|
tag: Context.Key<I, S>,
|
|
137
|
-
value: S
|
|
138
|
+
value: NoInfer<S>
|
|
138
139
|
): Rpc<Tag, Payload, Success, Error, Middleware, Requires>
|
|
139
140
|
|
|
140
141
|
/**
|
|
@@ -145,6 +146,26 @@ export interface Rpc<
|
|
|
145
146
|
): Rpc<Tag, Payload, Success, Error, Middleware, Requires>
|
|
146
147
|
}
|
|
147
148
|
|
|
149
|
+
/**
|
|
150
|
+
* @since 4.0.0
|
|
151
|
+
* @category models
|
|
152
|
+
*/
|
|
153
|
+
export class ServerClient {
|
|
154
|
+
readonly id: number
|
|
155
|
+
annotations: Context.Context<never>
|
|
156
|
+
constructor(id: number) {
|
|
157
|
+
this.id = id
|
|
158
|
+
this.annotations = Context.empty()
|
|
159
|
+
}
|
|
160
|
+
annotate<I, S>(
|
|
161
|
+
tag: Context.Key<I, S>,
|
|
162
|
+
value: NoInfer<S>
|
|
163
|
+
): ServerClient {
|
|
164
|
+
this.annotations = Context.add(this.annotations, tag, value)
|
|
165
|
+
return this
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
148
169
|
/**
|
|
149
170
|
* Represents an implemented rpc.
|
|
150
171
|
*
|
|
@@ -155,7 +176,7 @@ export interface Handler<Tag extends string> {
|
|
|
155
176
|
readonly _: unique symbol
|
|
156
177
|
readonly tag: Tag
|
|
157
178
|
readonly handler: (request: any, options: {
|
|
158
|
-
readonly
|
|
179
|
+
readonly client: ServerClient
|
|
159
180
|
readonly requestId: RequestId
|
|
160
181
|
readonly headers: Headers
|
|
161
182
|
readonly rpc: Any
|
|
@@ -475,12 +496,12 @@ export type ToHandler<R extends Any> = R extends Rpc<
|
|
|
475
496
|
export type ToHandlerFn<Current extends Any, R = any> = (
|
|
476
497
|
payload: Payload<Current>,
|
|
477
498
|
options: {
|
|
478
|
-
readonly
|
|
499
|
+
readonly client: ServerClient
|
|
479
500
|
readonly requestId: RequestId
|
|
480
501
|
readonly headers: Headers
|
|
481
502
|
readonly rpc: Current
|
|
482
503
|
}
|
|
483
|
-
) =>
|
|
504
|
+
) => WrapperOr<ResultFrom<Current, R>>
|
|
484
505
|
|
|
485
506
|
/**
|
|
486
507
|
* @since 4.0.0
|
|
@@ -810,6 +831,12 @@ export interface Wrapper<A> {
|
|
|
810
831
|
readonly uninterruptible: boolean
|
|
811
832
|
}
|
|
812
833
|
|
|
834
|
+
/**
|
|
835
|
+
* @since 4.0.0
|
|
836
|
+
* @category Wrapper
|
|
837
|
+
*/
|
|
838
|
+
export type WrapperOr<A> = A | Wrapper<A>
|
|
839
|
+
|
|
813
840
|
/**
|
|
814
841
|
* @since 4.0.0
|
|
815
842
|
* @category Wrapper
|
|
@@ -839,6 +866,17 @@ export const wrap = (options: {
|
|
|
839
866
|
uninterruptible: options.uninterruptible ?? false
|
|
840
867
|
}
|
|
841
868
|
|
|
869
|
+
/**
|
|
870
|
+
* @since 4.0.0
|
|
871
|
+
* @category Wrapper
|
|
872
|
+
*/
|
|
873
|
+
export const wrapMap = <A extends object, B extends object>(self: WrapperOr<A>, f: (value: A) => B): WrapperOr<B> => {
|
|
874
|
+
if (isWrapper(self)) {
|
|
875
|
+
return wrap(self)(f(self.value))
|
|
876
|
+
}
|
|
877
|
+
return f(self)
|
|
878
|
+
}
|
|
879
|
+
|
|
842
880
|
/**
|
|
843
881
|
* You can use `fork` to wrap a response Effect or Stream, to ensure that the
|
|
844
882
|
* response is executed concurrently regardless of the RpcServer concurrency
|
|
@@ -39,7 +39,7 @@ import type * as RpcMiddleware from "./RpcMiddleware.ts"
|
|
|
39
39
|
import * as RpcSchema from "./RpcSchema.ts"
|
|
40
40
|
import * as RpcSerialization from "./RpcSerialization.ts"
|
|
41
41
|
import * as RpcWorker from "./RpcWorker.ts"
|
|
42
|
-
import {
|
|
42
|
+
import { withRunClient } from "./Utils.ts"
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @since 4.0.0
|
|
@@ -587,6 +587,8 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any, E, const Flatten extend
|
|
|
587
587
|
return { client, write } as const
|
|
588
588
|
})
|
|
589
589
|
|
|
590
|
+
let clientIdCounter = 0
|
|
591
|
+
|
|
590
592
|
/**
|
|
591
593
|
* @since 4.0.0
|
|
592
594
|
* @category client
|
|
@@ -614,6 +616,7 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
614
616
|
readonly flatten?: Flatten | undefined
|
|
615
617
|
} | undefined
|
|
616
618
|
) {
|
|
619
|
+
const clientId = clientIdCounter++
|
|
617
620
|
const { run, send, supportsAck, supportsTransferables } = yield* Protocol
|
|
618
621
|
|
|
619
622
|
type ClientEntry = {
|
|
@@ -645,7 +648,7 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
645
648
|
Effect.provideContext(entry.context),
|
|
646
649
|
Effect.orDie,
|
|
647
650
|
Effect.flatMap((payload) =>
|
|
648
|
-
send({
|
|
651
|
+
send(clientId, {
|
|
649
652
|
...message,
|
|
650
653
|
id: String(message.id),
|
|
651
654
|
payload,
|
|
@@ -657,7 +660,7 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
657
660
|
case "Ack": {
|
|
658
661
|
const entry = entries.get(message.requestId)
|
|
659
662
|
if (!entry) return Effect.void
|
|
660
|
-
return send({
|
|
663
|
+
return send(clientId, {
|
|
661
664
|
_tag: "Ack",
|
|
662
665
|
requestId: String(message.requestId)
|
|
663
666
|
}) as Effect.Effect<void, RpcClientError>
|
|
@@ -666,7 +669,7 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
666
669
|
const entry = entries.get(message.requestId)
|
|
667
670
|
if (!entry) return Effect.void
|
|
668
671
|
entries.delete(message.requestId)
|
|
669
|
-
return send({
|
|
672
|
+
return send(clientId, {
|
|
670
673
|
_tag: "Interrupt",
|
|
671
674
|
requestId: String(message.requestId)
|
|
672
675
|
}) as Effect.Effect<void, RpcClientError>
|
|
@@ -678,7 +681,7 @@ export const make: <Rpcs extends Rpc.Any, const Flatten extends boolean = false>
|
|
|
678
681
|
}
|
|
679
682
|
})
|
|
680
683
|
|
|
681
|
-
yield* run((message) => {
|
|
684
|
+
yield* run(clientId, (message) => {
|
|
682
685
|
switch (message._tag) {
|
|
683
686
|
case "Chunk": {
|
|
684
687
|
const requestId = RequestId(message.requestId)
|
|
@@ -798,9 +801,11 @@ export const withHeaders: {
|
|
|
798
801
|
*/
|
|
799
802
|
export class Protocol extends Context.Service<Protocol, {
|
|
800
803
|
readonly run: (
|
|
804
|
+
clientId: number,
|
|
801
805
|
f: (data: FromServerEncoded) => Effect.Effect<void>
|
|
802
806
|
) => Effect.Effect<never>
|
|
803
807
|
readonly send: (
|
|
808
|
+
clientId: number,
|
|
804
809
|
request: FromClientEncoded,
|
|
805
810
|
transferables?: ReadonlyArray<globalThis.Transferable>
|
|
806
811
|
) => Effect.Effect<void, RpcClientError>
|
|
@@ -810,7 +815,7 @@ export class Protocol extends Context.Service<Protocol, {
|
|
|
810
815
|
/**
|
|
811
816
|
* @since 4.0.0
|
|
812
817
|
*/
|
|
813
|
-
static make =
|
|
818
|
+
static make = withRunClient
|
|
814
819
|
}
|
|
815
820
|
|
|
816
821
|
/**
|
|
@@ -836,7 +841,7 @@ export const makeProtocolHttp = (client: HttpClient.HttpClient): Effect.Effect<
|
|
|
836
841
|
const emptyResponseError = (request: FromClientEncoded) =>
|
|
837
842
|
protocolDefect("Received empty HTTP response from RPC server", request)
|
|
838
843
|
|
|
839
|
-
const send = Effect.fnUntraced(function*(request: FromClientEncoded) {
|
|
844
|
+
const send = Effect.fnUntraced(function*(clientId: number, request: FromClientEncoded) {
|
|
840
845
|
if (request._tag !== "Request") {
|
|
841
846
|
return
|
|
842
847
|
}
|
|
@@ -857,15 +862,15 @@ export const makeProtocolHttp = (client: HttpClient.HttpClient): Effect.Effect<
|
|
|
857
862
|
catch: (cause) => protocolDefect("Error decoding HTTP response", cause)
|
|
858
863
|
})
|
|
859
864
|
if (!Array.isArray(responses)) {
|
|
860
|
-
return yield*
|
|
865
|
+
return yield* protocolDefect("Expected an array of responses", responses)
|
|
861
866
|
}
|
|
862
867
|
if (responses.length === 0) {
|
|
863
|
-
return yield*
|
|
868
|
+
return yield* emptyResponseError(request)
|
|
864
869
|
}
|
|
865
870
|
let i = 0
|
|
866
871
|
return yield* Effect.whileLoop({
|
|
867
872
|
while: () => i < responses.length,
|
|
868
|
-
body: () => writeResponse(responses[i++]),
|
|
873
|
+
body: () => writeResponse(clientId, responses[i++]),
|
|
869
874
|
step: constVoid
|
|
870
875
|
})
|
|
871
876
|
}
|
|
@@ -882,7 +887,7 @@ export const makeProtocolHttp = (client: HttpClient.HttpClient): Effect.Effect<
|
|
|
882
887
|
let i = 0
|
|
883
888
|
return Effect.whileLoop({
|
|
884
889
|
while: () => i < responses.length,
|
|
885
|
-
body: () => writeResponse(responses[i++]),
|
|
890
|
+
body: () => writeResponse(clientId, responses[i++]),
|
|
886
891
|
step: constVoid
|
|
887
892
|
})
|
|
888
893
|
})
|
|
@@ -890,7 +895,7 @@ export const makeProtocolHttp = (client: HttpClient.HttpClient): Effect.Effect<
|
|
|
890
895
|
Effect.mapError((cause) => cause instanceof RpcClientError ? cause : httpClientError(cause))
|
|
891
896
|
)
|
|
892
897
|
if (!hasResponse) {
|
|
893
|
-
return yield*
|
|
898
|
+
return yield* emptyResponseError(request)
|
|
894
899
|
}
|
|
895
900
|
})
|
|
896
901
|
|
|
@@ -931,10 +936,11 @@ export const makeProtocolSocket = (options?: {
|
|
|
931
936
|
never,
|
|
932
937
|
Scope.Scope | RpcSerialization.RpcSerialization | Socket.Socket
|
|
933
938
|
> =>
|
|
934
|
-
Protocol.make(Effect.fnUntraced(function*(writeResponse) {
|
|
939
|
+
Protocol.make(Effect.fnUntraced(function*(writeResponse, clientIds) {
|
|
935
940
|
const socket = yield* Socket.Socket
|
|
936
941
|
const serialization = yield* RpcSerialization.RpcSerialization
|
|
937
942
|
const hooks = yield* Effect.serviceOption(ConnectionHooks)
|
|
943
|
+
const requestClientMap = new Map<string, number>()
|
|
938
944
|
|
|
939
945
|
const write = yield* socket.writer
|
|
940
946
|
|
|
@@ -947,6 +953,9 @@ export const makeProtocolSocket = (options?: {
|
|
|
947
953
|
return Option.isSome(hooks) ? hooks.value.onConnect : Effect.void
|
|
948
954
|
})
|
|
949
955
|
|
|
956
|
+
const broadcast = (response: FromServerEncoded) =>
|
|
957
|
+
Effect.forEach(clientIds, (clientId) => writeResponse(clientId, response))
|
|
958
|
+
|
|
950
959
|
yield* Effect.suspend(() => {
|
|
951
960
|
parser = serialization.makeUnsafe()
|
|
952
961
|
pinger.reset()
|
|
@@ -961,13 +970,23 @@ export const makeProtocolSocket = (options?: {
|
|
|
961
970
|
const response = responses[i++]
|
|
962
971
|
if (response._tag === "Pong") {
|
|
963
972
|
pinger.onPong()
|
|
973
|
+
return Effect.void
|
|
964
974
|
}
|
|
965
|
-
|
|
975
|
+
if ("requestId" in response) {
|
|
976
|
+
const clientId = requestClientMap.get(response.requestId)
|
|
977
|
+
if (clientId !== undefined) {
|
|
978
|
+
if (response._tag === "Exit") {
|
|
979
|
+
requestClientMap.delete(response.requestId)
|
|
980
|
+
}
|
|
981
|
+
return writeResponse(clientId, response)
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
return broadcast(response)
|
|
966
985
|
},
|
|
967
986
|
step: constVoid
|
|
968
987
|
})
|
|
969
988
|
} catch (defect) {
|
|
970
|
-
return
|
|
989
|
+
return broadcast({
|
|
971
990
|
_tag: "ClientProtocolError",
|
|
972
991
|
error: new RpcClientError({
|
|
973
992
|
reason: new RpcClientDefect({
|
|
@@ -1011,7 +1030,7 @@ export const makeProtocolSocket = (options?: {
|
|
|
1011
1030
|
cause: Cause.squash(cause)
|
|
1012
1031
|
})
|
|
1013
1032
|
})
|
|
1014
|
-
return
|
|
1033
|
+
return broadcast({
|
|
1015
1034
|
_tag: "ClientProtocolError",
|
|
1016
1035
|
error: currentError
|
|
1017
1036
|
})
|
|
@@ -1025,10 +1044,13 @@ export const makeProtocolSocket = (options?: {
|
|
|
1025
1044
|
)
|
|
1026
1045
|
|
|
1027
1046
|
return {
|
|
1028
|
-
send(request) {
|
|
1047
|
+
send(clientId, request) {
|
|
1029
1048
|
if (currentError) {
|
|
1030
1049
|
return Effect.fail(currentError)
|
|
1031
1050
|
}
|
|
1051
|
+
if (request._tag === "Request") {
|
|
1052
|
+
requestClientMap.set(request.id, clientId)
|
|
1053
|
+
}
|
|
1032
1054
|
const encoded = parser.encode(request)
|
|
1033
1055
|
if (encoded === undefined) return Effect.void
|
|
1034
1056
|
return Effect.orDie(write(encoded))
|
|
@@ -1099,7 +1121,7 @@ export const makeProtocolWorker = (
|
|
|
1099
1121
|
WorkerError,
|
|
1100
1122
|
Scope.Scope | Worker.WorkerPlatform | Worker.Spawner
|
|
1101
1123
|
> =>
|
|
1102
|
-
Protocol.make(Effect.fnUntraced(function*(writeResponse) {
|
|
1124
|
+
Protocol.make(Effect.fnUntraced(function*(writeResponse, clientIds) {
|
|
1103
1125
|
const worker = yield* Worker.WorkerPlatform
|
|
1104
1126
|
const scope = yield* Effect.scope
|
|
1105
1127
|
let workerId = 0
|
|
@@ -1107,10 +1129,14 @@ export const makeProtocolWorker = (
|
|
|
1107
1129
|
const hooks = yield* Effect.serviceOption(ConnectionHooks)
|
|
1108
1130
|
|
|
1109
1131
|
const entries = new Map<string, {
|
|
1132
|
+
readonly clientId: number
|
|
1110
1133
|
readonly worker: Worker.Worker<FromServerEncoded, FromClientEncoded | RpcWorker.InitialMessage.Encoded>
|
|
1111
1134
|
readonly latch: Latch.Latch
|
|
1112
1135
|
}>()
|
|
1113
1136
|
|
|
1137
|
+
const broadcast = (response: FromServerEncoded) =>
|
|
1138
|
+
Effect.forEach(clientIds, (clientId) => writeResponse(clientId, response))
|
|
1139
|
+
|
|
1114
1140
|
const acquire = Effect.gen(function*() {
|
|
1115
1141
|
const id = workerId++
|
|
1116
1142
|
const backing = yield* worker.spawn<FromServerEncoded, FromClientEncoded | RpcWorker.InitialMessage.Encoded>(id)
|
|
@@ -1121,16 +1147,21 @@ export const makeProtocolWorker = (
|
|
|
1121
1147
|
if (entry) {
|
|
1122
1148
|
entries.delete(response.requestId)
|
|
1123
1149
|
entry.latch.openUnsafe()
|
|
1124
|
-
return writeResponse(response)
|
|
1150
|
+
return writeResponse(entry.clientId, response)
|
|
1125
1151
|
}
|
|
1126
1152
|
} else if (response._tag === "Defect") {
|
|
1127
1153
|
for (const [requestId, entry] of entries) {
|
|
1128
1154
|
entries.delete(requestId)
|
|
1129
1155
|
entry.latch.openUnsafe()
|
|
1130
1156
|
}
|
|
1131
|
-
return
|
|
1157
|
+
return broadcast(response)
|
|
1158
|
+
} else if ("requestId" in response) {
|
|
1159
|
+
const entry = entries.get(response.requestId)
|
|
1160
|
+
if (entry) {
|
|
1161
|
+
return writeResponse(entry.clientId, response)
|
|
1162
|
+
}
|
|
1132
1163
|
}
|
|
1133
|
-
return
|
|
1164
|
+
return broadcast(response)
|
|
1134
1165
|
}, {
|
|
1135
1166
|
onSpawn: Option.isSome(initialMessage) ?
|
|
1136
1167
|
Effect.flatMap(
|
|
@@ -1141,7 +1172,7 @@ export const makeProtocolWorker = (
|
|
|
1141
1172
|
}).pipe(
|
|
1142
1173
|
Effect.tapCause((cause) => {
|
|
1143
1174
|
const error = Cause.findError(cause)
|
|
1144
|
-
return
|
|
1175
|
+
return broadcast({
|
|
1145
1176
|
_tag: "ClientProtocolError",
|
|
1146
1177
|
error: new RpcClientError({
|
|
1147
1178
|
reason: Result.isSuccess(error) ? error.success.reason : new RpcClientDefect({
|
|
@@ -1189,13 +1220,17 @@ export const makeProtocolWorker = (
|
|
|
1189
1220
|
})
|
|
1190
1221
|
)
|
|
1191
1222
|
|
|
1192
|
-
const send = (
|
|
1223
|
+
const send = (
|
|
1224
|
+
clientId: number,
|
|
1225
|
+
request: FromClientEncoded,
|
|
1226
|
+
transferables?: ReadonlyArray<globalThis.Transferable>
|
|
1227
|
+
) => {
|
|
1193
1228
|
switch (request._tag) {
|
|
1194
1229
|
case "Request": {
|
|
1195
1230
|
return Pool.get(pool).pipe(
|
|
1196
1231
|
Effect.flatMap((worker) => {
|
|
1197
1232
|
const latch = Latch.makeUnsafe(false)
|
|
1198
|
-
entries.set(request.id, { worker, latch })
|
|
1233
|
+
entries.set(request.id, { clientId, worker, latch })
|
|
1199
1234
|
return Effect.flatMap(worker.send(request, transferables), () => latch.await)
|
|
1200
1235
|
}),
|
|
1201
1236
|
Effect.scoped,
|
|
@@ -119,7 +119,7 @@ export interface RpcGroup<in out R extends Rpc.Any> extends Pipeable {
|
|
|
119
119
|
(
|
|
120
120
|
payload: Rpc.Payload<Extract<R, { readonly _tag: Tag }>>,
|
|
121
121
|
options: {
|
|
122
|
-
readonly
|
|
122
|
+
readonly client: Rpc.ServerClient
|
|
123
123
|
readonly requestId: RequestId
|
|
124
124
|
readonly headers: Headers
|
|
125
125
|
}
|
|
@@ -31,7 +31,7 @@ export interface RpcMiddleware<Provides, E, Requires> {
|
|
|
31
31
|
(
|
|
32
32
|
effect: Effect.Effect<SuccessValue, E | unhandled, Provides>,
|
|
33
33
|
options: {
|
|
34
|
-
readonly
|
|
34
|
+
readonly client: Rpc.ServerClient
|
|
35
35
|
readonly requestId: RequestId
|
|
36
36
|
readonly rpc: Rpc.AnyWithProps
|
|
37
37
|
readonly payload: unknown
|
|
@@ -77,7 +77,7 @@ export interface Any {
|
|
|
77
77
|
(
|
|
78
78
|
effect: Effect.Effect<SuccessValue, any, any>,
|
|
79
79
|
options: {
|
|
80
|
-
readonly
|
|
80
|
+
readonly client: Rpc.ServerClient
|
|
81
81
|
readonly requestId: RequestId
|
|
82
82
|
readonly rpc: Rpc.AnyWithProps
|
|
83
83
|
readonly payload: unknown
|
|
@@ -109,6 +109,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
109
109
|
readonly id: number
|
|
110
110
|
readonly latches: Map<RequestId, Latch.Latch>
|
|
111
111
|
readonly fibers: Map<RequestId, Fiber.Fiber<unknown, any>>
|
|
112
|
+
readonly serverClient: Rpc.ServerClient
|
|
112
113
|
ended: boolean
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -157,7 +158,8 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
157
158
|
id: clientId,
|
|
158
159
|
latches: new Map(),
|
|
159
160
|
fibers: new Map(),
|
|
160
|
-
ended: false
|
|
161
|
+
ended: false,
|
|
162
|
+
serverClient: new Rpc.ServerClient(clientId)
|
|
161
163
|
}
|
|
162
164
|
clients.set(clientId, client)
|
|
163
165
|
} else if (client.ended) {
|
|
@@ -236,7 +238,7 @@ export const makeNoSerialization: <Rpcs extends Rpc.Any>(
|
|
|
236
238
|
const isStream = RpcSchema.isStreamSchema(rpc.successSchema)
|
|
237
239
|
const metadata = {
|
|
238
240
|
rpc,
|
|
239
|
-
|
|
241
|
+
client: client.serverClient,
|
|
240
242
|
requestId: request.id,
|
|
241
243
|
headers: request.headers,
|
|
242
244
|
payload: request.payload
|
|
@@ -410,7 +412,7 @@ const applyMiddleware = <A, E, R>(
|
|
|
410
412
|
handler: Effect.Effect<A, E, R>,
|
|
411
413
|
options: {
|
|
412
414
|
readonly rpc: Rpc.AnyWithProps
|
|
413
|
-
readonly
|
|
415
|
+
readonly client: Rpc.ServerClient
|
|
414
416
|
readonly requestId: RequestId
|
|
415
417
|
readonly headers: Headers.Headers
|
|
416
418
|
readonly payload: A
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import type * as Context from "../../Context.ts"
|
|
5
5
|
import * as Effect from "../../Effect.ts"
|
|
6
6
|
import * as Semaphore from "../../Semaphore.ts"
|
|
7
|
+
import type { Protocol } from "./RpcClient.ts"
|
|
8
|
+
import type { FromServerEncoded } from "./RpcMessage.ts"
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* @since 4.0.0
|
|
@@ -42,3 +44,60 @@ export const withRun = <
|
|
|
42
44
|
}
|
|
43
45
|
} as A))
|
|
44
46
|
})
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @since 4.0.0
|
|
50
|
+
*/
|
|
51
|
+
export const withRunClient = <EX, RX>(
|
|
52
|
+
f: (
|
|
53
|
+
write: (clientId: number, response: FromServerEncoded) => Effect.Effect<void>,
|
|
54
|
+
clientIds: ReadonlySet<number>
|
|
55
|
+
) => Effect.Effect<Omit<Protocol["Service"], "run">, EX, RX>
|
|
56
|
+
): Effect.Effect<Protocol["Service"], EX, RX> =>
|
|
57
|
+
Effect.suspend(() => {
|
|
58
|
+
const clientIds = new Set<number>()
|
|
59
|
+
const clientBuffers = new Map<number, Array<[FromServerEncoded, Context.Context<never>]>>()
|
|
60
|
+
const clientWrites = new Map<number, (data: FromServerEncoded) => Effect.Effect<void>>()
|
|
61
|
+
let write = (clientId: number, data: FromServerEncoded): Effect.Effect<void> =>
|
|
62
|
+
Effect.contextWith((context) => {
|
|
63
|
+
let buffer = clientBuffers.get(clientId)
|
|
64
|
+
if (!buffer) {
|
|
65
|
+
buffer = []
|
|
66
|
+
clientBuffers.set(clientId, buffer)
|
|
67
|
+
}
|
|
68
|
+
buffer.push([data, context])
|
|
69
|
+
return Effect.void
|
|
70
|
+
})
|
|
71
|
+
return Effect.map(
|
|
72
|
+
f((clientId, data) => {
|
|
73
|
+
const clientWrite = clientWrites.get(clientId)
|
|
74
|
+
if (clientWrite) {
|
|
75
|
+
return clientWrite(data)
|
|
76
|
+
}
|
|
77
|
+
return write(clientId, data)
|
|
78
|
+
}, clientIds),
|
|
79
|
+
(a) => ({
|
|
80
|
+
...a,
|
|
81
|
+
run(clientId, f) {
|
|
82
|
+
return Effect.gen(function*() {
|
|
83
|
+
clientIds.add(clientId)
|
|
84
|
+
clientWrites.set(clientId, f)
|
|
85
|
+
|
|
86
|
+
const buffer = clientBuffers.get(clientId)
|
|
87
|
+
if (buffer) {
|
|
88
|
+
clientBuffers.delete(clientId)
|
|
89
|
+
for (const [args, context] of buffer) {
|
|
90
|
+
yield* Effect.provideContext(Effect.suspend(() => f(args)), context)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return yield* Effect.onExit(Effect.never, () => {
|
|
95
|
+
clientIds.delete(clientId)
|
|
96
|
+
clientWrites.delete(clientId)
|
|
97
|
+
return Effect.void
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
} satisfies Protocol["Service"])
|
|
102
|
+
)
|
|
103
|
+
})
|
|
@@ -581,7 +581,7 @@ export interface JsonFromString<S extends Schema.Top> extends
|
|
|
581
581
|
export const JsonFromString = <S extends Schema.Top>(
|
|
582
582
|
schema: S
|
|
583
583
|
): JsonFromString<S> => {
|
|
584
|
-
const parsed = Schema.fromJsonString(schema)
|
|
584
|
+
const parsed = Schema.fromJsonString(Schema.toCodecJson(schema)) as any
|
|
585
585
|
return Field({
|
|
586
586
|
select: parsed,
|
|
587
587
|
insert: parsed,
|
|
@@ -599,7 +599,7 @@ export const JsonFromString = <S extends Schema.Top>(
|
|
|
599
599
|
export interface UuidV4Insert<B extends string> extends
|
|
600
600
|
VariantSchema.Field<{
|
|
601
601
|
readonly select: Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>
|
|
602
|
-
readonly insert:
|
|
602
|
+
readonly insert: Schema.withConstructorDefault<Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>>
|
|
603
603
|
readonly update: Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>
|
|
604
604
|
readonly json: Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>
|
|
605
605
|
}>
|
|
@@ -619,10 +619,8 @@ export const Uint8Array: Schema.instanceOf<Uint8Array<ArrayBuffer>> = Schema.Uin
|
|
|
619
619
|
*/
|
|
620
620
|
export const UuidV4WithGenerate = <B extends string>(
|
|
621
621
|
schema: Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>
|
|
622
|
-
):
|
|
623
|
-
|
|
624
|
-
defaultValue: Effect.sync(() => Uuid.v4({}, new globalThis.Uint8Array(16)))
|
|
625
|
-
})
|
|
622
|
+
): Schema.withConstructorDefault<Schema.brand<Schema.instanceOf<Uint8Array<ArrayBuffer>>, B>> =>
|
|
623
|
+
schema.pipe(Schema.withConstructorDefault(Effect.sync(() => Uuid.v4({}, new globalThis.Uint8Array(16)))))
|
|
626
624
|
|
|
627
625
|
/**
|
|
628
626
|
* A field that represents a binary UUID v4 that is generated on inserts.
|