liminal 0.17.6 → 0.17.8
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/Actor.ts +19 -20
- package/ActorTransport.ts +17 -0
- package/CHANGELOG.md +12 -0
- package/Client.ts +32 -23
- package/ClientDirectory.ts +104 -0
- package/Protocol.ts +15 -39
- package/_util/schema.ts +7 -0
- package/dist/Actor.d.ts +10 -12
- package/dist/Actor.js +1 -3
- package/dist/Actor.js.map +1 -1
- package/dist/ActorTransport.d.ts +7 -0
- package/dist/ActorTransport.js +2 -0
- package/dist/ActorTransport.js.map +1 -0
- package/dist/Client.d.ts +2 -2
- package/dist/Client.js +45 -31
- package/dist/Client.js.map +1 -1
- package/dist/ClientDirectory.d.ts +21 -0
- package/dist/ClientDirectory.js +41 -0
- package/dist/ClientDirectory.js.map +1 -0
- package/dist/Protocol.d.ts +8 -6
- package/dist/Protocol.js +9 -20
- package/dist/Protocol.js.map +1 -1
- package/dist/_util/schema.d.ts +4 -0
- package/dist/_util/schema.js +5 -0
- package/dist/_util/schema.js.map +1 -0
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/errors.ts +2 -2
- package/index.ts +2 -0
- package/package.json +1 -1
package/Actor.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { Context, Schema as S, Effect } from "effect"
|
|
2
2
|
|
|
3
|
+
import type { TopFromString } from "./_util/schema.ts"
|
|
3
4
|
import type * as ActorClient from "./Client.ts"
|
|
4
5
|
import type * as ClientHandle from "./ClientHandle.ts"
|
|
5
|
-
import type { ProtocolDefinition } from "./Protocol.ts"
|
|
6
6
|
import type { Send } from "./Send.ts"
|
|
7
7
|
|
|
8
8
|
import * as Diagnostic from "./_util/Diagnostic.ts"
|
|
9
9
|
import * as Method from "./Method.ts"
|
|
10
|
+
import { type ProtocolDefinition } from "./Protocol.ts"
|
|
10
11
|
|
|
11
12
|
const { span } = Diagnostic.module("Actor")
|
|
12
13
|
|
|
13
14
|
export const TypeId = "~liminal/Actor" as const
|
|
14
15
|
|
|
15
|
-
export interface Service<
|
|
16
|
-
|
|
16
|
+
export interface Service<
|
|
17
|
+
ActorSelf,
|
|
18
|
+
Name extends TopFromString,
|
|
19
|
+
AttachmentFields extends S.Struct.Fields,
|
|
20
|
+
D extends ProtocolDefinition,
|
|
21
|
+
> {
|
|
22
|
+
readonly name: Name["Type"]
|
|
17
23
|
|
|
18
24
|
readonly currentClient: ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>
|
|
19
25
|
|
|
@@ -21,13 +27,13 @@ export interface Service<ActorSelf, NameA, AttachmentFields extends S.Struct.Fie
|
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
export interface ActorDefinition<
|
|
24
|
-
|
|
30
|
+
Name extends TopFromString,
|
|
25
31
|
AttachmentFields extends S.Struct.Fields,
|
|
26
32
|
ClientSelf,
|
|
27
33
|
ClientId extends string,
|
|
28
34
|
D extends ProtocolDefinition,
|
|
29
35
|
> {
|
|
30
|
-
readonly name:
|
|
36
|
+
readonly name: Name
|
|
31
37
|
|
|
32
38
|
readonly attachments: AttachmentFields
|
|
33
39
|
|
|
@@ -37,21 +43,17 @@ export interface ActorDefinition<
|
|
|
37
43
|
export interface Actor<
|
|
38
44
|
ActorSelf,
|
|
39
45
|
ActorId extends string,
|
|
40
|
-
|
|
46
|
+
Name extends TopFromString,
|
|
41
47
|
AttachmentFields extends S.Struct.Fields,
|
|
42
48
|
ActorClientSelf,
|
|
43
49
|
ActorClientId extends string,
|
|
44
50
|
D extends ProtocolDefinition,
|
|
45
|
-
> extends Context.Service<ActorSelf, Service<ActorSelf,
|
|
46
|
-
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf,
|
|
51
|
+
> extends Context.Service<ActorSelf, Service<ActorSelf, Name, AttachmentFields, D>> {
|
|
52
|
+
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf, Name, AttachmentFields, D>>
|
|
47
53
|
|
|
48
54
|
readonly [TypeId]: typeof TypeId
|
|
49
55
|
|
|
50
|
-
readonly definition: ActorDefinition<
|
|
51
|
-
|
|
52
|
-
readonly protocol: {
|
|
53
|
-
readonly Attachments: S.Struct<AttachmentFields>
|
|
54
|
-
}
|
|
56
|
+
readonly definition: ActorDefinition<Name, AttachmentFields, ActorClientSelf, ActorClientId, D>
|
|
55
57
|
|
|
56
58
|
readonly sendAll: Send<ActorSelf, D>
|
|
57
59
|
|
|
@@ -67,16 +69,16 @@ export const Service =
|
|
|
67
69
|
<ActorSelf>() =>
|
|
68
70
|
<
|
|
69
71
|
ActorId extends string,
|
|
70
|
-
|
|
72
|
+
Name extends TopFromString,
|
|
71
73
|
D extends ProtocolDefinition,
|
|
72
74
|
AttachmentFields extends S.Struct.Fields,
|
|
73
75
|
ClientSelf,
|
|
74
76
|
ClientId extends string,
|
|
75
77
|
>(
|
|
76
78
|
id: ActorId,
|
|
77
|
-
definition: ActorDefinition<
|
|
78
|
-
): Actor<ActorSelf, ActorId,
|
|
79
|
-
const tag = Context.Service<ActorSelf, Service<ActorSelf,
|
|
79
|
+
definition: ActorDefinition<Name, AttachmentFields, ClientSelf, ClientId, D>,
|
|
80
|
+
): Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D> => {
|
|
81
|
+
const tag = Context.Service<ActorSelf, Service<ActorSelf, Name, AttachmentFields, D>>()(id)
|
|
80
82
|
|
|
81
83
|
const sendAll: Send<ActorSelf, D> = (key, payload) =>
|
|
82
84
|
tag.asEffect().pipe(
|
|
@@ -99,9 +101,6 @@ export const Service =
|
|
|
99
101
|
return Object.assign(tag, {
|
|
100
102
|
[TypeId]: TypeId,
|
|
101
103
|
definition,
|
|
102
|
-
protocol: {
|
|
103
|
-
Attachments: S.Struct(definition.attachments),
|
|
104
|
-
},
|
|
105
104
|
sendAll,
|
|
106
105
|
disconnectAll,
|
|
107
106
|
handler,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Effect, Schema as S } from "effect"
|
|
2
|
+
|
|
3
|
+
import type { Protocol, ProtocolDefinition } from "./Protocol.ts"
|
|
4
|
+
|
|
5
|
+
export interface ActorTransport<Raw, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
|
|
6
|
+
readonly send: (
|
|
7
|
+
transport: Raw,
|
|
8
|
+
event: Protocol<D>["Event"]["Type"],
|
|
9
|
+
) => Effect.Effect<void, S.SchemaError, Protocol<D>["Event"]["EncodingServices"]>
|
|
10
|
+
|
|
11
|
+
readonly close: (transport: Raw) => Effect.Effect<void>
|
|
12
|
+
|
|
13
|
+
readonly snapshot: (
|
|
14
|
+
transport: Raw,
|
|
15
|
+
attachments: S.Struct<AttachmentFields>["Type"],
|
|
16
|
+
) => Effect.Effect<void, S.SchemaError, S.Struct<AttachmentFields>["EncodingServices"]>
|
|
17
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# liminal
|
|
2
2
|
|
|
3
|
+
## 0.17.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5c2a730: Move cloudflare bindings into subdir in preparation for extraction into different package."
|
|
8
|
+
|
|
9
|
+
## 0.17.7
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- e5c54be: Decouple actor transport. Implement proper multi-actor instance browser registry.
|
|
14
|
+
|
|
3
15
|
## 0.17.6
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/Client.ts
CHANGED
|
@@ -26,6 +26,7 @@ import { Socket } from "effect/unstable/socket"
|
|
|
26
26
|
import { Worker } from "effect/unstable/workers"
|
|
27
27
|
|
|
28
28
|
import * as Diagnostic from "./_util/Diagnostic.ts"
|
|
29
|
+
import { decodeJsonString, encodeJsonString } from "./_util/schema.ts"
|
|
29
30
|
import { type ClientError, AuditionError, ConnectionError, type FError, UnresolvedError } from "./errors.ts"
|
|
30
31
|
import { type F } from "./F.ts"
|
|
31
32
|
import { Protocol, type ProtocolDefinition } from "./Protocol.ts"
|
|
@@ -190,9 +191,9 @@ const make = <Self, Id extends string, D extends ProtocolDefinition, R>(
|
|
|
190
191
|
return
|
|
191
192
|
}
|
|
192
193
|
case "Audition.Failure": {
|
|
193
|
-
const {
|
|
194
|
-
yield* debug("Audition.Failed", {
|
|
195
|
-
return yield* new AuditionError({ value: {
|
|
194
|
+
const { expected, actual } = message
|
|
195
|
+
yield* debug("Audition.Failed", { expected, actual })
|
|
196
|
+
return yield* new AuditionError({ value: { expected, actual } })
|
|
196
197
|
}
|
|
197
198
|
case "Event": {
|
|
198
199
|
const { event } = message
|
|
@@ -377,11 +378,14 @@ export const layerSocket = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
377
378
|
| Socket.WebSocketConstructor
|
|
378
379
|
| Protocol<D>["Actor"]["DecodingServices"]
|
|
379
380
|
| Protocol<D>["F"]["Payload"]["EncodingServices"]
|
|
380
|
-
> =>
|
|
381
|
-
|
|
381
|
+
> => {
|
|
382
|
+
const { F, Actor } = client.protocol
|
|
383
|
+
const encodeFPayload = encodeJsonString(F.Payload)
|
|
384
|
+
const decodeActor = decodeJsonString(Actor)
|
|
385
|
+
|
|
386
|
+
return make<Self, Id, D, Socket.WebSocketConstructor>(
|
|
382
387
|
client,
|
|
383
388
|
Effect.gen(function* () {
|
|
384
|
-
const { protocol } = client
|
|
385
389
|
const socket = yield* Socket.makeWebSocket(url ?? "/", {
|
|
386
390
|
protocols: ["liminal", Encoding.encodeBase64Url(client.key), ...(protocols ? Array.ensure(protocols) : [])],
|
|
387
391
|
})
|
|
@@ -391,7 +395,7 @@ export const layerSocket = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
391
395
|
.runRaw((raw) =>
|
|
392
396
|
pipe(
|
|
393
397
|
raw instanceof Uint8Array ? new TextDecoder().decode(raw) : raw,
|
|
394
|
-
|
|
398
|
+
decodeActor,
|
|
395
399
|
Effect.andThen(publish),
|
|
396
400
|
),
|
|
397
401
|
)
|
|
@@ -413,7 +417,7 @@ export const layerSocket = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
413
417
|
send: Effect.fnUntraced(
|
|
414
418
|
function* (v) {
|
|
415
419
|
const write = yield* socket.writer
|
|
416
|
-
const message = yield*
|
|
420
|
+
const message = yield* encodeFPayload(v)
|
|
417
421
|
yield* write(message).pipe(
|
|
418
422
|
Effect.catchTag("SocketError", (cause) => new ConnectionError({ cause }).asEffect()),
|
|
419
423
|
)
|
|
@@ -425,8 +429,9 @@ export const layerSocket = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
425
429
|
}),
|
|
426
430
|
replay,
|
|
427
431
|
)
|
|
432
|
+
}
|
|
428
433
|
|
|
429
|
-
export const layerWorker = <Self, Id extends string, D extends ProtocolDefinition
|
|
434
|
+
export const layerWorker = <Self, Id extends string, D extends ProtocolDefinition, T extends Protocol<D>>({
|
|
430
435
|
client,
|
|
431
436
|
replay,
|
|
432
437
|
}: {
|
|
@@ -435,22 +440,17 @@ export const layerWorker = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
435
440
|
}): Layer.Layer<
|
|
436
441
|
Self,
|
|
437
442
|
never,
|
|
438
|
-
| Worker.
|
|
439
|
-
| Worker.Spawner
|
|
440
|
-
| Protocol<D>["Actor"]["DecodingServices"]
|
|
441
|
-
| Protocol<D>["F"]["Payload"]["EncodingServices"]
|
|
443
|
+
Worker.WorkerPlatform | Worker.Spawner | T["Actor"]["DecodingServices"] | T["F"]["Payload"]["EncodingServices"]
|
|
442
444
|
> =>
|
|
443
445
|
make<Self, Id, D, Worker.WorkerPlatform | Worker.Spawner>(
|
|
444
446
|
client,
|
|
445
447
|
Effect.gen(function* () {
|
|
446
|
-
type T = Protocol<D>
|
|
447
|
-
|
|
448
448
|
const platform = yield* Worker.WorkerPlatform
|
|
449
449
|
const backing = yield* platform
|
|
450
|
-
.spawn<T["Actor"]["Type"], T["
|
|
450
|
+
.spawn<T["Actor"]["Type"], T["Client"]["Type"]>(0)
|
|
451
451
|
.pipe(Effect.catchTag("WorkerError", (cause) => new ConnectionError({ cause }).asEffect()))
|
|
452
452
|
|
|
453
|
-
const send = (message: T["
|
|
453
|
+
const send = (message: T["Client"]["Type"]) =>
|
|
454
454
|
backing.send(message).pipe(
|
|
455
455
|
Effect.catchTag("WorkerError", (cause) => new ConnectionError({ cause }).asEffect()),
|
|
456
456
|
span("send"),
|
|
@@ -459,18 +459,27 @@ export const layerWorker = <Self, Id extends string, D extends ProtocolDefinitio
|
|
|
459
459
|
return {
|
|
460
460
|
listen: Effect.fnUntraced(function* (publish) {
|
|
461
461
|
const stop = yield* Deferred.make<void>()
|
|
462
|
-
yield*
|
|
463
|
-
|
|
462
|
+
yield* backing
|
|
463
|
+
.run(
|
|
464
464
|
Effect.fnUntraced(function* (message) {
|
|
465
465
|
yield* publish(message)
|
|
466
466
|
if (message._tag === "Disconnect" || message._tag === "Audition.Failure") {
|
|
467
467
|
yield* Deferred.succeed(stop, void 0)
|
|
468
468
|
}
|
|
469
469
|
}),
|
|
470
|
-
{
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
470
|
+
{
|
|
471
|
+
onSpawn: backing
|
|
472
|
+
.send({
|
|
473
|
+
_tag: "Audition.Payload",
|
|
474
|
+
client: client.key,
|
|
475
|
+
})
|
|
476
|
+
.pipe(Effect.orDie),
|
|
477
|
+
},
|
|
478
|
+
)
|
|
479
|
+
.pipe(
|
|
480
|
+
Effect.raceFirst(Deferred.await(stop)),
|
|
481
|
+
Effect.catchTag("WorkerError", (cause) => new ConnectionError({ cause }).asEffect()),
|
|
482
|
+
)
|
|
474
483
|
}, span("listen")),
|
|
475
484
|
send,
|
|
476
485
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Schema as S, Effect, Cause, Ref } from "effect"
|
|
2
|
+
|
|
3
|
+
import type { TopFromString } from "./_util/schema.ts"
|
|
4
|
+
import type { Actor } from "./Actor.ts"
|
|
5
|
+
import type { ActorTransport } from "./ActorTransport.ts"
|
|
6
|
+
import type { ProtocolDefinition, Disconnect, Protocol } from "./Protocol.ts"
|
|
7
|
+
|
|
8
|
+
import * as Diagnostic from "./_util/Diagnostic.ts"
|
|
9
|
+
import { phantom } from "./_util/phantom.ts"
|
|
10
|
+
import * as ClientHandle from "./ClientHandle.ts"
|
|
11
|
+
|
|
12
|
+
const { span } = Diagnostic.module("ClientDirectory")
|
|
13
|
+
|
|
14
|
+
export interface ClientDirectory<
|
|
15
|
+
Raw,
|
|
16
|
+
ActorSelf,
|
|
17
|
+
AttachmentFields extends S.Struct.Fields,
|
|
18
|
+
D extends ProtocolDefinition,
|
|
19
|
+
> {
|
|
20
|
+
readonly "": {
|
|
21
|
+
readonly Handle: ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
readonly handles: ReadonlySet<this[""]["Handle"]>
|
|
25
|
+
|
|
26
|
+
readonly register: (
|
|
27
|
+
raw: Raw,
|
|
28
|
+
attachments: S.Struct<AttachmentFields>["Type"],
|
|
29
|
+
) => Effect.Effect<this[""]["Handle"], S.SchemaError, S.Struct<AttachmentFields>["EncodingServices"]>
|
|
30
|
+
|
|
31
|
+
readonly get: (raw: Raw) => Effect.Effect<this[""]["Handle"], Cause.NoSuchElementError>
|
|
32
|
+
|
|
33
|
+
readonly unregister: (raw: Raw) => Effect.Effect<void>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface HandleEncoders<T, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
|
|
37
|
+
attachments: (
|
|
38
|
+
value: S.Struct<AttachmentFields>["Type"],
|
|
39
|
+
) => Effect.Effect<T, S.SchemaError, S.Struct<AttachmentFields>["EncodingServices"]>
|
|
40
|
+
event: (
|
|
41
|
+
value: Protocol<D>["Event"]["Type"],
|
|
42
|
+
) => Effect.Effect<T, S.SchemaError, Protocol<D>["Event"]["EncodingServices"]>
|
|
43
|
+
disconnect: Effect.Effect<T, S.SchemaError, (typeof Disconnect)["EncodingServices"]>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const make = <
|
|
47
|
+
Raw,
|
|
48
|
+
ActorSelf,
|
|
49
|
+
ActorId extends string,
|
|
50
|
+
Name extends TopFromString,
|
|
51
|
+
AttachmentFields extends S.Struct.Fields,
|
|
52
|
+
ClientSelf,
|
|
53
|
+
ClientId extends string,
|
|
54
|
+
D extends ProtocolDefinition,
|
|
55
|
+
>(
|
|
56
|
+
_actor: Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>,
|
|
57
|
+
{ send, close, snapshot }: ActorTransport<Raw, AttachmentFields, D>,
|
|
58
|
+
): ClientDirectory<Raw, ActorSelf, AttachmentFields, D> => {
|
|
59
|
+
type Handle = ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>
|
|
60
|
+
|
|
61
|
+
const raws = new Map<Raw, Handle>()
|
|
62
|
+
const handles = new Set<Handle>()
|
|
63
|
+
|
|
64
|
+
const get = (raw: Raw) => Effect.fromNullishOr(raws.get(raw))
|
|
65
|
+
|
|
66
|
+
const register = Effect.fnUntraced(function* (raw: Raw, attachments: S.Struct<AttachmentFields>["Type"]) {
|
|
67
|
+
yield* snapshot(raw, attachments)
|
|
68
|
+
const attachmentsRef = yield* Ref.make(attachments)
|
|
69
|
+
const handle: Handle = ClientHandle.make({
|
|
70
|
+
attachments: Ref.get(attachmentsRef),
|
|
71
|
+
save: Effect.fnUntraced(function* (attachments) {
|
|
72
|
+
yield* Ref.set(attachmentsRef, attachments)
|
|
73
|
+
yield* snapshot(raw, attachments)
|
|
74
|
+
}),
|
|
75
|
+
send: (_tag, payload) =>
|
|
76
|
+
send(raw, {
|
|
77
|
+
_tag: "Event",
|
|
78
|
+
event: { _tag, ...payload } as never,
|
|
79
|
+
}),
|
|
80
|
+
disconnect: close(raw).pipe(
|
|
81
|
+
Effect.andThen(() =>
|
|
82
|
+
Effect.sync(() => {
|
|
83
|
+
raws.delete(raw)
|
|
84
|
+
handles.delete(handle)
|
|
85
|
+
}),
|
|
86
|
+
),
|
|
87
|
+
),
|
|
88
|
+
})
|
|
89
|
+
raws.set(raw, handle)
|
|
90
|
+
handles.add(handle)
|
|
91
|
+
return handle
|
|
92
|
+
}, span("register"))
|
|
93
|
+
|
|
94
|
+
const unregister = (raw: Raw) =>
|
|
95
|
+
Effect.sync(() => {
|
|
96
|
+
const handle = raws.get(raw)
|
|
97
|
+
if (handle) {
|
|
98
|
+
raws.delete(raw)
|
|
99
|
+
handles.delete(handle)
|
|
100
|
+
}
|
|
101
|
+
}).pipe(span("unregister"))
|
|
102
|
+
|
|
103
|
+
return { ...phantom, handles, register, get, unregister }
|
|
104
|
+
}
|
package/Protocol.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema as S, Record, Types } from "effect"
|
|
2
2
|
|
|
3
3
|
import type * as Method from "./Method.ts"
|
|
4
4
|
|
|
@@ -24,18 +24,15 @@ export declare namespace ProtocolDefinition {
|
|
|
24
24
|
>
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const parseJson = flow(S.toCodecJson, S.fromJsonString)
|
|
28
|
-
const decode = flow(parseJson, S.decodeUnknownEffect)
|
|
29
|
-
const encode = flow(parseJson, S.encodeEffect)
|
|
30
|
-
|
|
31
27
|
export interface Protocol<D extends ProtocolDefinition> {
|
|
32
28
|
readonly Audition: {
|
|
29
|
+
readonly Payload: S.TaggedStruct<"Audition.Payload", { client: S.String }>
|
|
33
30
|
readonly Success: S.TaggedStruct<"Audition.Success", {}>
|
|
34
31
|
readonly Failure: S.TaggedStruct<
|
|
35
32
|
"Audition.Failure",
|
|
36
33
|
{
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
expected: S.String
|
|
35
|
+
actual: S.String
|
|
39
36
|
}
|
|
40
37
|
>
|
|
41
38
|
}
|
|
@@ -83,6 +80,8 @@ export interface Protocol<D extends ProtocolDefinition> {
|
|
|
83
80
|
|
|
84
81
|
readonly Disconnect: S.TaggedStruct<"Disconnect", {}>
|
|
85
82
|
|
|
83
|
+
readonly Client: S.Union<[this["Audition"]["Payload"], this["F"]["Payload"], this["Disconnect"]]>
|
|
84
|
+
|
|
86
85
|
readonly Actor: S.Union<
|
|
87
86
|
[
|
|
88
87
|
this["Audition"]["Success"],
|
|
@@ -93,30 +92,18 @@ export interface Protocol<D extends ProtocolDefinition> {
|
|
|
93
92
|
this["Disconnect"],
|
|
94
93
|
]
|
|
95
94
|
>
|
|
96
|
-
|
|
97
|
-
readonly encodeFPayload: (
|
|
98
|
-
input: this["F"]["Payload"]["Type"],
|
|
99
|
-
options?: SchemaAST.ParseOptions,
|
|
100
|
-
) => Effect.Effect<string, S.SchemaError, this["F"]["Payload"]["EncodingServices"]>
|
|
101
|
-
|
|
102
|
-
readonly decodeEvent: (
|
|
103
|
-
input: unknown,
|
|
104
|
-
options?: SchemaAST.ParseOptions,
|
|
105
|
-
) => Effect.Effect<this["Event"]["Type"], S.SchemaError, this["Event"]["DecodingServices"]>
|
|
106
|
-
|
|
107
|
-
readonly decodeActor: (
|
|
108
|
-
input: unknown,
|
|
109
|
-
options?: SchemaAST.ParseOptions,
|
|
110
|
-
) => Effect.Effect<this["Actor"]["Type"], S.SchemaError, this["Actor"]["DecodingServices"]>
|
|
111
95
|
}
|
|
112
96
|
|
|
113
|
-
const Disconnect = S.TaggedStruct("Disconnect", {})
|
|
97
|
+
export const Disconnect = S.TaggedStruct("Disconnect", {})
|
|
114
98
|
|
|
115
99
|
const Audition = {
|
|
100
|
+
Payload: S.TaggedStruct("Audition.Payload", {
|
|
101
|
+
client: S.String,
|
|
102
|
+
}),
|
|
116
103
|
Success: S.TaggedStruct("Audition.Success", {}),
|
|
117
104
|
Failure: S.TaggedStruct("Audition.Failure", {
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
expected: S.String,
|
|
106
|
+
actual: S.String,
|
|
120
107
|
}),
|
|
121
108
|
}
|
|
122
109
|
|
|
@@ -142,20 +129,9 @@ export const Protocol = <D extends ProtocolDefinition>({ events, methods }: D):
|
|
|
142
129
|
event: S.TaggedUnion(events),
|
|
143
130
|
}) as never
|
|
144
131
|
|
|
132
|
+
const Client: T["Client"] = S.Union([Audition.Payload, F.Payload, Disconnect])
|
|
133
|
+
|
|
145
134
|
const Actor: T["Actor"] = S.Union([Audition.Success, Audition.Failure, F.Success, F.Failure, Event, Disconnect])
|
|
146
135
|
|
|
147
|
-
|
|
148
|
-
const decodeEvent = decode(Event)
|
|
149
|
-
const decodeActor = decode(Actor)
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
Audition,
|
|
153
|
-
Event,
|
|
154
|
-
F,
|
|
155
|
-
Actor,
|
|
156
|
-
Disconnect,
|
|
157
|
-
encodeFPayload,
|
|
158
|
-
decodeEvent,
|
|
159
|
-
decodeActor,
|
|
160
|
-
}
|
|
136
|
+
return { Audition, Event, F, Client, Actor, Disconnect }
|
|
161
137
|
}
|
package/_util/schema.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Schema as S, flow } from "effect"
|
|
2
|
+
|
|
3
|
+
export type TopFromString = S.Codec<any, string, any, any>
|
|
4
|
+
|
|
5
|
+
const toJsonStringCodec = flow(S.toCodecJson, S.fromJsonString)
|
|
6
|
+
export const encodeJsonString = flow(toJsonStringCodec, S.encodeEffect)
|
|
7
|
+
export const decodeJsonString = flow(toJsonStringCodec, S.decodeUnknownEffect)
|
package/dist/Actor.d.ts
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
1
|
import { Context, Schema as S, Effect } from "effect";
|
|
2
|
+
import type { TopFromString } from "./_util/schema.ts";
|
|
2
3
|
import type * as ActorClient from "./Client.ts";
|
|
3
4
|
import type * as ClientHandle from "./ClientHandle.ts";
|
|
4
|
-
import type { ProtocolDefinition } from "./Protocol.ts";
|
|
5
5
|
import type { Send } from "./Send.ts";
|
|
6
6
|
import * as Method from "./Method.ts";
|
|
7
|
+
import { type ProtocolDefinition } from "./Protocol.ts";
|
|
7
8
|
export declare const TypeId: "~liminal/Actor";
|
|
8
|
-
export interface Service<ActorSelf,
|
|
9
|
-
readonly name:
|
|
9
|
+
export interface Service<ActorSelf, Name extends TopFromString, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
|
|
10
|
+
readonly name: Name["Type"];
|
|
10
11
|
readonly currentClient: ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>;
|
|
11
12
|
readonly clients: ReadonlySet<ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>>;
|
|
12
13
|
}
|
|
13
|
-
export interface ActorDefinition<
|
|
14
|
-
readonly name:
|
|
14
|
+
export interface ActorDefinition<Name extends TopFromString, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string, D extends ProtocolDefinition> {
|
|
15
|
+
readonly name: Name;
|
|
15
16
|
readonly attachments: AttachmentFields;
|
|
16
17
|
readonly client: ActorClient.Client<ClientSelf, ClientId, D>;
|
|
17
18
|
}
|
|
18
|
-
export interface Actor<ActorSelf, ActorId extends string,
|
|
19
|
-
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf,
|
|
19
|
+
export interface Actor<ActorSelf, ActorId extends string, Name extends TopFromString, AttachmentFields extends S.Struct.Fields, ActorClientSelf, ActorClientId extends string, D extends ProtocolDefinition> extends Context.Service<ActorSelf, Service<ActorSelf, Name, AttachmentFields, D>> {
|
|
20
|
+
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf, Name, AttachmentFields, D>>;
|
|
20
21
|
readonly [TypeId]: typeof TypeId;
|
|
21
|
-
readonly definition: ActorDefinition<
|
|
22
|
-
readonly protocol: {
|
|
23
|
-
readonly Attachments: S.Struct<AttachmentFields>;
|
|
24
|
-
};
|
|
22
|
+
readonly definition: ActorDefinition<Name, AttachmentFields, ActorClientSelf, ActorClientId, D>;
|
|
25
23
|
readonly sendAll: Send<ActorSelf, D>;
|
|
26
24
|
readonly disconnectAll: Effect.Effect<void, never, ActorSelf>;
|
|
27
25
|
readonly handler: <K extends keyof D["methods"], R>(tag: K, f: Method.Handler<D["methods"][K], R>) => Method.Handler<D["methods"][K], R>;
|
|
28
26
|
}
|
|
29
|
-
export declare const Service: <ActorSelf>() => <ActorId extends string,
|
|
27
|
+
export declare const Service: <ActorSelf>() => <ActorId extends string, Name extends TopFromString, D extends ProtocolDefinition, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string>(id: ActorId, definition: ActorDefinition<Name, AttachmentFields, ClientSelf, ClientId, D>) => Actor<ActorSelf, ActorId, Name, AttachmentFields, ClientSelf, ClientId, D>;
|
package/dist/Actor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Context, Schema as S, Effect } from "effect";
|
|
2
2
|
import * as Diagnostic from "./_util/Diagnostic.js";
|
|
3
3
|
import * as Method from "./Method.js";
|
|
4
|
+
import {} from "./Protocol.js";
|
|
4
5
|
const { span } = Diagnostic.module("Actor");
|
|
5
6
|
export const TypeId = "~liminal/Actor";
|
|
6
7
|
export const Service = () => (id, definition) => {
|
|
@@ -11,9 +12,6 @@ export const Service = () => (id, definition) => {
|
|
|
11
12
|
return Object.assign(tag, {
|
|
12
13
|
[TypeId]: TypeId,
|
|
13
14
|
definition,
|
|
14
|
-
protocol: {
|
|
15
|
-
Attachments: S.Struct(definition.attachments),
|
|
16
|
-
},
|
|
17
15
|
sendAll,
|
|
18
16
|
disconnectAll,
|
|
19
17
|
handler,
|
package/dist/Actor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Actor.js","sourceRoot":"","sources":["../Actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAOrD,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"Actor.js","sourceRoot":"","sources":["../Actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAOrD,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAA2B,MAAM,eAAe,CAAA;AAEvD,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAE3C,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAA;AAsD/C,MAAM,CAAC,MAAM,OAAO,GAClB,GAAc,EAAE,CAChB,CAQE,EAAW,EACX,UAA4E,EACA,EAAE;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAA4D,CAAC,EAAE,CAAC,CAAA;IAE3F,MAAM,OAAO,GAAuB,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACnD,GAAG,CAAC,QAAQ,EAAE,CAAC,IAAI,CACjB,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAC7B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAC7F,EACD,IAAI,CAAC,SAAS,CAAC,CAChB,CAAA;IAEH,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,IAAI,CACvC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EACxF,IAAI,CAAC,eAAe,CAAC,CACtB,CAAA;IAED,MAAM,OAAO,GAAG,CACd,IAAO,EACP,CAAqC,EACD,EAAE,CAAC,CAAC,CAAA;IAE1C,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;QACxB,CAAC,MAAM,CAAC,EAAE,MAAM;QAChB,UAAU;QACV,OAAO;QACP,aAAa;QACb,OAAO;KACR,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Effect, Schema as S } from "effect";
|
|
2
|
+
import type { Protocol, ProtocolDefinition } from "./Protocol.ts";
|
|
3
|
+
export interface ActorTransport<Raw, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
|
|
4
|
+
readonly send: (transport: Raw, event: Protocol<D>["Event"]["Type"]) => Effect.Effect<void, S.SchemaError, Protocol<D>["Event"]["EncodingServices"]>;
|
|
5
|
+
readonly close: (transport: Raw) => Effect.Effect<void>;
|
|
6
|
+
readonly snapshot: (transport: Raw, attachments: S.Struct<AttachmentFields>["Type"]) => Effect.Effect<void, S.SchemaError, S.Struct<AttachmentFields>["EncodingServices"]>;
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActorTransport.js","sourceRoot":"","sources":["../ActorTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA"}
|
package/dist/Client.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare const layerSocket: <Self, Id extends string, D extends ProtocolDe
|
|
|
35
35
|
readonly protocols?: string | Array<string> | undefined;
|
|
36
36
|
readonly replay?: ReplayConfig | undefined;
|
|
37
37
|
}) => Layer.Layer<Self, never, Socket.WebSocketConstructor | Protocol<D>["Actor"]["DecodingServices"] | Protocol<D>["F"]["Payload"]["EncodingServices"]>;
|
|
38
|
-
export declare const layerWorker: <Self, Id extends string, D extends ProtocolDefinition
|
|
38
|
+
export declare const layerWorker: <Self, Id extends string, D extends ProtocolDefinition, T extends Protocol<D>>({ client, replay, }: {
|
|
39
39
|
readonly client: Client<Self, Id, D>;
|
|
40
40
|
readonly replay?: ReplayConfig | undefined;
|
|
41
|
-
}) => Layer.Layer<Self, never, Worker.WorkerPlatform | Worker.Spawner |
|
|
41
|
+
}) => Layer.Layer<Self, never, Worker.WorkerPlatform | Worker.Spawner | T["Actor"]["DecodingServices"] | T["F"]["Payload"]["EncodingServices"]>;
|