liminal 0.17.5 → 0.17.6
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 +27 -42
- package/Audition.ts +27 -48
- package/CHANGELOG.md +6 -0
- package/Client.ts +86 -164
- package/ClientHandle.ts +6 -13
- package/F.ts +5 -7
- package/Method.ts +5 -13
- package/Protocol.ts +110 -69
- package/Send.ts +5 -9
- package/dist/Actor.d.ts +14 -14
- package/dist/Actor.js +2 -2
- package/dist/Actor.js.map +1 -1
- package/dist/Audition.d.ts +7 -7
- package/dist/Audition.js.map +1 -1
- package/dist/Client.d.ts +23 -28
- package/dist/Client.js +33 -51
- package/dist/Client.js.map +1 -1
- package/dist/ClientHandle.d.ts +6 -5
- package/dist/ClientHandle.js.map +1 -1
- package/dist/F.d.ts +2 -2
- package/dist/F.js +1 -1
- package/dist/F.js.map +1 -1
- package/dist/Method.d.ts +5 -10
- package/dist/Method.js +1 -1
- package/dist/Method.js.map +1 -1
- package/dist/Protocol.d.ts +50 -35
- package/dist/Protocol.js +31 -22
- package/dist/Protocol.js.map +1 -1
- package/dist/Send.d.ts +2 -1
- package/dist/errors.d.ts +3 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/errors.ts +3 -3
- package/package.json +1 -1
package/Protocol.ts
CHANGED
|
@@ -1,120 +1,161 @@
|
|
|
1
|
-
import { Schema as S, Record } from "effect"
|
|
1
|
+
import { flow, Schema as S, Record, Types, Effect, SchemaAST } from "effect"
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import type * as Method from "./Method.ts"
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export interface ProtocolDefinition<
|
|
6
|
+
Methods extends Record<string, Method.Any> = Record<string, Method.Any>,
|
|
7
|
+
Events extends Record<string, S.Struct.Fields> = Record<string, S.Struct.Fields>,
|
|
8
|
+
> {
|
|
9
|
+
readonly methods: Methods
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
routed: S.String,
|
|
10
|
-
})
|
|
11
|
+
readonly events: Events
|
|
12
|
+
}
|
|
11
13
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
export declare namespace ProtocolDefinition {
|
|
15
|
+
export type Merge<T extends ProtocolDefinition, U extends ProtocolDefinition> = ProtocolDefinition<
|
|
16
|
+
[T] extends [never]
|
|
17
|
+
? U["methods"]
|
|
18
|
+
: {
|
|
19
|
+
[K in keyof T["methods"] & keyof U["methods"] as Types.Equals<T["methods"][K], U["methods"][K]> extends true
|
|
20
|
+
? K
|
|
21
|
+
: never]: T["methods"][K]
|
|
22
|
+
},
|
|
23
|
+
[T] extends [never] ? U["events"] : T["events"] & U["events"]
|
|
24
|
+
>
|
|
25
|
+
}
|
|
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
|
+
export interface Protocol<D extends ProtocolDefinition> {
|
|
32
|
+
readonly Audition: {
|
|
33
|
+
readonly Success: S.TaggedStruct<"Audition.Success", {}>
|
|
34
|
+
readonly Failure: S.TaggedStruct<
|
|
35
|
+
"Audition.Failure",
|
|
36
|
+
{
|
|
37
|
+
client: S.String
|
|
38
|
+
routed: S.String
|
|
39
|
+
}
|
|
40
|
+
>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
readonly Event: S.TaggedStruct<
|
|
44
|
+
"Event",
|
|
45
|
+
{
|
|
46
|
+
readonly event: S.TaggedUnion<{
|
|
47
|
+
readonly [K in keyof D["events"] & string]: S.TaggedStruct<K, D["events"][K]>
|
|
48
|
+
}>
|
|
49
|
+
}
|
|
50
|
+
>
|
|
51
|
+
|
|
52
|
+
readonly F: {
|
|
53
|
+
readonly Payload: S.TaggedStruct<
|
|
54
|
+
"F.Payload",
|
|
19
55
|
{
|
|
20
56
|
readonly id: S.Int
|
|
21
57
|
readonly payload: S.TaggedUnion<{
|
|
22
|
-
readonly [K in keyof
|
|
23
|
-
K,
|
|
24
|
-
{ readonly value: MethodDefinitions[K]["payload"] }
|
|
25
|
-
>
|
|
58
|
+
readonly [K in keyof D["methods"] & string]: S.TaggedStruct<K, { readonly value: D["methods"][K]["payload"] }>
|
|
26
59
|
}>
|
|
27
60
|
}
|
|
28
61
|
>
|
|
29
62
|
|
|
30
|
-
readonly
|
|
31
|
-
"
|
|
63
|
+
readonly Success: S.TaggedStruct<
|
|
64
|
+
"F.Success",
|
|
32
65
|
{
|
|
33
66
|
readonly id: S.Int
|
|
34
67
|
readonly success: S.TaggedUnion<{
|
|
35
|
-
readonly [K in keyof
|
|
36
|
-
K,
|
|
37
|
-
{ readonly value: MethodDefinitions[K]["success"] }
|
|
38
|
-
>
|
|
68
|
+
readonly [K in keyof D["methods"] & string]: S.TaggedStruct<K, { readonly value: D["methods"][K]["success"] }>
|
|
39
69
|
}>
|
|
40
70
|
}
|
|
41
71
|
>
|
|
42
72
|
|
|
43
|
-
readonly
|
|
44
|
-
"
|
|
73
|
+
readonly Failure: S.TaggedStruct<
|
|
74
|
+
"F.Failure",
|
|
45
75
|
{
|
|
46
76
|
readonly id: S.Int
|
|
47
77
|
readonly failure: S.TaggedUnion<{
|
|
48
|
-
readonly [K in keyof
|
|
49
|
-
K,
|
|
50
|
-
{ readonly value: MethodDefinitions[K]["failure"] }
|
|
51
|
-
>
|
|
78
|
+
readonly [K in keyof D["methods"] & string]: S.TaggedStruct<K, { readonly value: D["methods"][K]["failure"] }>
|
|
52
79
|
}>
|
|
53
80
|
}
|
|
54
81
|
>
|
|
55
82
|
}
|
|
56
83
|
|
|
57
|
-
readonly
|
|
58
|
-
"Event",
|
|
59
|
-
{
|
|
60
|
-
readonly event: S.TaggedUnion<{
|
|
61
|
-
readonly [K in keyof EventDefinitions & string]: S.TaggedStruct<K, EventDefinitions[K]>
|
|
62
|
-
}>
|
|
63
|
-
}
|
|
64
|
-
>
|
|
84
|
+
readonly Disconnect: S.TaggedStruct<"Disconnect", {}>
|
|
65
85
|
|
|
66
|
-
readonly
|
|
86
|
+
readonly Actor: S.Union<
|
|
67
87
|
[
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this["
|
|
71
|
-
this["
|
|
72
|
-
this["
|
|
73
|
-
|
|
88
|
+
this["Audition"]["Success"],
|
|
89
|
+
this["Audition"]["Failure"],
|
|
90
|
+
this["F"]["Success"],
|
|
91
|
+
this["F"]["Failure"],
|
|
92
|
+
this["Event"],
|
|
93
|
+
this["Disconnect"],
|
|
74
94
|
]
|
|
75
95
|
>
|
|
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"]>
|
|
76
111
|
}
|
|
77
112
|
|
|
78
|
-
|
|
113
|
+
const Disconnect = S.TaggedStruct("Disconnect", {})
|
|
79
114
|
|
|
80
|
-
|
|
115
|
+
const Audition = {
|
|
116
|
+
Success: S.TaggedStruct("Audition.Success", {}),
|
|
117
|
+
Failure: S.TaggedStruct("Audition.Failure", {
|
|
118
|
+
client: S.String,
|
|
119
|
+
routed: S.String,
|
|
120
|
+
}),
|
|
121
|
+
}
|
|
81
122
|
|
|
82
|
-
export const
|
|
83
|
-
|
|
84
|
-
EventDefinitions extends Record<string, S.Struct.Fields>,
|
|
85
|
-
>(
|
|
86
|
-
methods: MethodDefinitions,
|
|
87
|
-
events: EventDefinitions,
|
|
88
|
-
): ProtocolSchemas<MethodDefinitions, EventDefinitions> => {
|
|
89
|
-
type T = ProtocolSchemas<MethodDefinitions, EventDefinitions>
|
|
123
|
+
export const Protocol = <D extends ProtocolDefinition>({ events, methods }: D): Protocol<D> => {
|
|
124
|
+
type T = Protocol<D>
|
|
90
125
|
|
|
91
|
-
const
|
|
92
|
-
|
|
126
|
+
const F: T["F"] = {
|
|
127
|
+
Payload: S.TaggedStruct("F.Payload", {
|
|
93
128
|
id: S.Int,
|
|
94
129
|
payload: S.TaggedUnion(Record.map(methods, ({ payload: value }) => ({ value }))),
|
|
95
130
|
}) as never,
|
|
96
|
-
|
|
131
|
+
Success: S.TaggedStruct("F.Success", {
|
|
97
132
|
id: S.Int,
|
|
98
133
|
success: S.TaggedUnion(Record.map(methods, ({ success: value }) => ({ value }))),
|
|
99
134
|
}) as never,
|
|
100
|
-
|
|
135
|
+
Failure: S.TaggedStruct("F.Failure", {
|
|
101
136
|
id: S.Int,
|
|
102
137
|
failure: S.TaggedUnion(Record.map(methods, ({ failure: value }) => ({ value }))),
|
|
103
138
|
}) as never,
|
|
104
139
|
}
|
|
105
140
|
|
|
106
|
-
const
|
|
141
|
+
const Event: T["Event"] = S.TaggedStruct("Event", {
|
|
107
142
|
event: S.TaggedUnion(events),
|
|
108
143
|
}) as never
|
|
109
144
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
event,
|
|
116
|
-
Disconnect,
|
|
117
|
-
]) as never
|
|
145
|
+
const Actor: T["Actor"] = S.Union([Audition.Success, Audition.Failure, F.Success, F.Failure, Event, Disconnect])
|
|
146
|
+
|
|
147
|
+
const encodeFPayload = encode(F.Payload)
|
|
148
|
+
const decodeEvent = decode(Event)
|
|
149
|
+
const decodeActor = decode(Actor)
|
|
118
150
|
|
|
119
|
-
return {
|
|
151
|
+
return {
|
|
152
|
+
Audition,
|
|
153
|
+
Event,
|
|
154
|
+
F,
|
|
155
|
+
Actor,
|
|
156
|
+
Disconnect,
|
|
157
|
+
encodeFPayload,
|
|
158
|
+
decodeEvent,
|
|
159
|
+
decodeActor,
|
|
160
|
+
}
|
|
120
161
|
}
|
package/Send.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { Schema as S, Effect } from "effect"
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
>(
|
|
3
|
+
import type { ProtocolDefinition } from "./Protocol.ts"
|
|
4
|
+
|
|
5
|
+
export type Send<ActorSelf, D extends ProtocolDefinition> = <K extends keyof D["events"]>(
|
|
6
6
|
tag: K,
|
|
7
|
-
payload: S.Struct<
|
|
8
|
-
) => Effect.Effect<
|
|
9
|
-
void,
|
|
10
|
-
S.SchemaError,
|
|
11
|
-
ActorSelf | ReturnType<typeof S.TaggedUnion<EventDefinitions>>["EncodingServices"]
|
|
12
|
-
>
|
|
7
|
+
payload: S.Struct<D["events"][K]>["Type"],
|
|
8
|
+
) => Effect.Effect<void, S.SchemaError, ActorSelf | ReturnType<typeof S.TaggedUnion<D["events"]>>["EncodingServices"]>
|
package/dist/Actor.d.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { Context, Schema as S, Effect } from "effect";
|
|
2
2
|
import type * as ActorClient from "./Client.ts";
|
|
3
3
|
import type * as ClientHandle from "./ClientHandle.ts";
|
|
4
|
-
import type {
|
|
4
|
+
import type { ProtocolDefinition } from "./Protocol.ts";
|
|
5
5
|
import type { Send } from "./Send.ts";
|
|
6
6
|
import * as Method from "./Method.ts";
|
|
7
7
|
export declare const TypeId: "~liminal/Actor";
|
|
8
|
-
export interface Service<ActorSelf, NameA, AttachmentFields extends S.Struct.Fields,
|
|
8
|
+
export interface Service<ActorSelf, NameA, AttachmentFields extends S.Struct.Fields, D extends ProtocolDefinition> {
|
|
9
9
|
readonly name: NameA;
|
|
10
|
-
readonly currentClient: ClientHandle.ClientHandle<ActorSelf, AttachmentFields,
|
|
11
|
-
readonly clients: ReadonlySet<ClientHandle.ClientHandle<ActorSelf, AttachmentFields,
|
|
10
|
+
readonly currentClient: ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>;
|
|
11
|
+
readonly clients: ReadonlySet<ClientHandle.ClientHandle<ActorSelf, AttachmentFields, D>>;
|
|
12
12
|
}
|
|
13
|
-
export interface ActorDefinition<NameA, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string,
|
|
13
|
+
export interface ActorDefinition<NameA, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string, D extends ProtocolDefinition> {
|
|
14
14
|
readonly name: S.Codec<NameA, string>;
|
|
15
15
|
readonly attachments: AttachmentFields;
|
|
16
|
-
readonly client: ActorClient.Client<ClientSelf, ClientId,
|
|
16
|
+
readonly client: ActorClient.Client<ClientSelf, ClientId, D>;
|
|
17
17
|
}
|
|
18
|
-
export interface Actor<ActorSelf, ActorId extends string, NameA, AttachmentFields extends S.Struct.Fields, ActorClientSelf, ActorClientId extends string,
|
|
19
|
-
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf, NameA, AttachmentFields,
|
|
18
|
+
export interface Actor<ActorSelf, ActorId extends string, NameA, AttachmentFields extends S.Struct.Fields, ActorClientSelf, ActorClientId extends string, D extends ProtocolDefinition> extends Context.Service<ActorSelf, Service<ActorSelf, NameA, AttachmentFields, D>> {
|
|
19
|
+
new (_: never): Context.ServiceClass.Shape<ActorId, Service<ActorSelf, NameA, AttachmentFields, D>>;
|
|
20
20
|
readonly [TypeId]: typeof TypeId;
|
|
21
|
-
readonly definition: ActorDefinition<NameA, AttachmentFields, ActorClientSelf, ActorClientId,
|
|
22
|
-
readonly
|
|
23
|
-
readonly
|
|
21
|
+
readonly definition: ActorDefinition<NameA, AttachmentFields, ActorClientSelf, ActorClientId, D>;
|
|
22
|
+
readonly protocol: {
|
|
23
|
+
readonly Attachments: S.Struct<AttachmentFields>;
|
|
24
24
|
};
|
|
25
|
-
readonly sendAll: Send<ActorSelf,
|
|
25
|
+
readonly sendAll: Send<ActorSelf, D>;
|
|
26
26
|
readonly disconnectAll: Effect.Effect<void, never, ActorSelf>;
|
|
27
|
-
readonly handler: <K extends keyof
|
|
27
|
+
readonly handler: <K extends keyof D["methods"], R>(tag: K, f: Method.Handler<D["methods"][K], R>) => Method.Handler<D["methods"][K], R>;
|
|
28
28
|
}
|
|
29
|
-
export declare const Service: <ActorSelf>() => <ActorId extends string, NameA, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string
|
|
29
|
+
export declare const Service: <ActorSelf>() => <ActorId extends string, NameA, D extends ProtocolDefinition, AttachmentFields extends S.Struct.Fields, ClientSelf, ClientId extends string>(id: ActorId, definition: ActorDefinition<NameA, AttachmentFields, ClientSelf, ClientId, D>) => Actor<ActorSelf, ActorId, NameA, AttachmentFields, ClientSelf, ClientId, D>;
|
package/dist/Actor.js
CHANGED
|
@@ -11,8 +11,8 @@ export const Service = () => (id, definition) => {
|
|
|
11
11
|
return Object.assign(tag, {
|
|
12
12
|
[TypeId]: TypeId,
|
|
13
13
|
definition,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
protocol: {
|
|
15
|
+
Attachments: S.Struct(definition.attachments),
|
|
16
16
|
},
|
|
17
17
|
sendAll,
|
|
18
18
|
disconnectAll,
|
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;AAErC,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAE3C,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,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;AAErC,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAE3C,MAAM,CAAC,MAAM,MAAM,GAAG,gBAAyB,CAAA;AAqD/C,MAAM,CAAC,MAAM,OAAO,GAClB,GAAc,EAAE,CAChB,CAQE,EAAW,EACX,UAA6E,EACA,EAAE;IAC/E,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAA6D,CAAC,EAAE,CAAC,CAAA;IAE5F,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,QAAQ,EAAE;YACR,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC;SAC9C;QACD,OAAO;QACP,aAAa;QACb,OAAO;KACR,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
package/dist/Audition.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Schema as S, Pipeable, Stream } from "effect";
|
|
2
2
|
import type { F } from "./F.ts";
|
|
3
|
-
import type
|
|
3
|
+
import type { ProtocolDefinition } from "./Protocol.ts";
|
|
4
4
|
import * as Client from "./Client.ts";
|
|
5
5
|
import { type ClientError } from "./errors.ts";
|
|
6
6
|
declare const TypeId: "~liminal/Audition";
|
|
7
|
-
export interface Audition<ClientSelf,
|
|
7
|
+
export interface Audition<ClientSelf, D extends ProtocolDefinition> extends Pipeable.Pipeable {
|
|
8
8
|
readonly [TypeId]: typeof TypeId;
|
|
9
|
-
readonly events: Stream.Stream<
|
|
10
|
-
readonly f: F<ClientSelf,
|
|
9
|
+
readonly events: Stream.Stream<ReturnType<typeof S.TaggedUnion<D["events"]>>["Type"], ClientError | S.SchemaError, ClientSelf>;
|
|
10
|
+
readonly f: F<ClientSelf, D>;
|
|
11
11
|
}
|
|
12
|
-
export declare const empty: Audition<never, never
|
|
12
|
+
export declare const empty: Audition<never, never>;
|
|
13
13
|
export declare const add: {
|
|
14
|
-
<ClientSelf, ClientId extends string,
|
|
15
|
-
<AuditionClientSelf,
|
|
14
|
+
<ClientSelf, ClientId extends string, ClientD extends ProtocolDefinition>(client: Client.Client<ClientSelf, ClientId, ClientD>): <AuditionSelf, AuditionD extends ProtocolDefinition>(audition: Audition<AuditionSelf, AuditionD>) => Audition<AuditionSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>>;
|
|
15
|
+
<AuditionClientSelf, AuditionD extends ProtocolDefinition, ClientSelf, ClientId extends string, ClientD extends ProtocolDefinition>(audition: Audition<AuditionClientSelf, AuditionD>, client: Client.Client<ClientSelf, ClientId, ClientD>): Audition<AuditionClientSelf | ClientSelf, ProtocolDefinition.Merge<AuditionD, ClientD>>;
|
|
16
16
|
};
|
|
17
17
|
export {};
|
package/dist/Audition.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Audition.js","sourceRoot":"","sources":["../Audition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAKxE,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAoB,aAAa,EAAE,MAAM,aAAa,CAAA;AAE7D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AAErD,MAAM,MAAM,GAAG,mBAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"Audition.js","sourceRoot":"","sources":["../Audition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAKxE,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAA;AACnD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAoB,aAAa,EAAE,MAAM,aAAa,CAAA;AAE7D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AAErD,MAAM,MAAM,GAAG,mBAA4B,CAAA;AAc3C,MAAM,CAAC,MAAM,KAAK,GAA2B;IAC3C,CAAC,MAAM,CAAC,EAAE,MAAM;IAChB,IAAI;QACF,OAAO,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAChD,CAAC;IACD,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,aAAa,EAAE,CAAC;IACxC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,aAAa,EAAE,CAAC,QAAQ,EAAE;CAC9C,CAAA;AAED,MAAM,CAAC,MAAM,GAAG,GAgBZ,QAAQ,CAAC,IAAI,CACf,CAAC,EACD,CAOE,QAA2C,EAC3C,MAAoD,EAC+B,EAAE;IACrF,MAAM,CAAC,GAA+E,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAC5G,QAAQ;SACL,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;SAClB,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EACjE,IAAI,CAAC,GAAG,CAAC,CACV,CAAA;IAEL,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CACjC,MAAM,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE,CACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAChC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,EACjE,MAAM,CAAC,MAAM,CACd,CACF,CACF,CAAA;IAED,OAAO;QACL,CAAC,MAAM,CAAC,EAAE,MAAM;QAChB,IAAI;YACF,OAAO,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QAChD,CAAC;QACD,MAAM;QACN,CAAC;KACF,CAAA;AACH,CAAC,CACF,CAAA"}
|
package/dist/Client.d.ts
CHANGED
|
@@ -1,46 +1,41 @@
|
|
|
1
1
|
import { Context, Effect, Layer, RcRef, Scope, Stream, Schema as S } from "effect";
|
|
2
2
|
import { Socket } from "effect/unstable/socket";
|
|
3
3
|
import { Worker } from "effect/unstable/workers";
|
|
4
|
-
import type
|
|
5
|
-
import { type ClientError, ConnectionError } from "./errors.ts";
|
|
4
|
+
import { type ClientError } from "./errors.ts";
|
|
6
5
|
import { type F } from "./F.ts";
|
|
7
|
-
import
|
|
6
|
+
import { Protocol, type ProtocolDefinition } from "./Protocol.ts";
|
|
8
7
|
export declare const TypeId: "~liminal/Client";
|
|
9
|
-
export interface ClientDefinition<MethodDefinitions extends Record<string, MethodDefinition.Any>, EventDefinitions extends Record<string, S.Struct.Fields>> {
|
|
10
|
-
readonly methods: MethodDefinitions;
|
|
11
|
-
readonly events: EventDefinitions;
|
|
12
|
-
}
|
|
13
8
|
export interface ReplayConfig {
|
|
14
9
|
readonly mode: "startup" | "all-subscribers";
|
|
15
10
|
readonly limit?: number | undefined;
|
|
16
11
|
}
|
|
17
|
-
export interface Session<
|
|
18
|
-
readonly events: Stream.Stream<ReturnType<typeof S.TaggedUnion<
|
|
19
|
-
readonly f: F<
|
|
12
|
+
export interface Session<Self, D extends ProtocolDefinition> {
|
|
13
|
+
readonly events: Stream.Stream<ReturnType<typeof S.TaggedUnion<D["events"]>>["Type"], ClientError | S.SchemaError>;
|
|
14
|
+
readonly f: F<Self, D>;
|
|
20
15
|
readonly end: Effect.Effect<void>;
|
|
21
16
|
}
|
|
22
|
-
export type Service<ClientSelf,
|
|
23
|
-
export interface Client<
|
|
24
|
-
new (_: never): Context.ServiceClass.Shape<ClientId, Service<
|
|
17
|
+
export type Service<ClientSelf, D extends ProtocolDefinition> = RcRef.RcRef<Session<ClientSelf, D>, ClientError>;
|
|
18
|
+
export interface Client<Self, ClientId extends string, D extends ProtocolDefinition> extends Context.Service<Self, Service<Self, D>> {
|
|
19
|
+
new (_: never): Context.ServiceClass.Shape<ClientId, Service<Self, D>>;
|
|
25
20
|
readonly [TypeId]: typeof TypeId;
|
|
26
|
-
readonly definition:
|
|
27
|
-
readonly
|
|
28
|
-
readonly events: Stream.Stream<ReturnType<typeof S.TaggedUnion<
|
|
29
|
-
readonly f: F<
|
|
30
|
-
readonly invalidate: Effect.Effect<void, never,
|
|
21
|
+
readonly definition: D;
|
|
22
|
+
readonly protocol: Protocol<D>;
|
|
23
|
+
readonly events: Stream.Stream<ReturnType<typeof S.TaggedUnion<D["events"]>>["Type"], ClientError | S.SchemaError, Self>;
|
|
24
|
+
readonly f: F<Self, D>;
|
|
25
|
+
readonly invalidate: Effect.Effect<void, never, Self>;
|
|
31
26
|
}
|
|
32
|
-
export declare const Service: <
|
|
33
|
-
export interface
|
|
34
|
-
readonly listen: (publish: (message: Protocol
|
|
35
|
-
readonly send: (message: Protocol
|
|
27
|
+
export declare const Service: <Self>() => <Id extends string, D extends ProtocolDefinition>(id: Id, definition: D) => Client<Self, Id, D>;
|
|
28
|
+
export interface ClientTransport<D extends ProtocolDefinition> {
|
|
29
|
+
readonly listen: (publish: (message: Protocol<D>["Actor"]["Type"]) => Effect.Effect<void, ClientError>) => Effect.Effect<void, ClientError | S.SchemaError, Scope.Scope | Protocol<D>["Actor"]["DecodingServices"]>;
|
|
30
|
+
readonly send: (message: Protocol<D>["F"]["Payload"]["Type"]) => Effect.Effect<void, ClientError | S.SchemaError, Protocol<D>["F"]["Payload"]["EncodingServices"]>;
|
|
36
31
|
}
|
|
37
|
-
export declare const layerSocket: <
|
|
38
|
-
readonly client: Client<
|
|
32
|
+
export declare const layerSocket: <Self, Id extends string, D extends ProtocolDefinition>({ client, url, protocols, replay, }: {
|
|
33
|
+
readonly client: Client<Self, Id, D>;
|
|
39
34
|
readonly url?: string | undefined;
|
|
40
35
|
readonly protocols?: string | Array<string> | undefined;
|
|
41
36
|
readonly replay?: ReplayConfig | undefined;
|
|
42
|
-
}) => Layer.Layer<
|
|
43
|
-
export declare const layerWorker: <
|
|
44
|
-
readonly client: Client<
|
|
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>({ client, replay, }: {
|
|
39
|
+
readonly client: Client<Self, Id, D>;
|
|
45
40
|
readonly replay?: ReplayConfig | undefined;
|
|
46
|
-
}) => Layer.Layer<
|
|
41
|
+
}) => Layer.Layer<Self, never, Worker.WorkerPlatform | Worker.Spawner | Protocol<D>["Actor"]["DecodingServices"] | Protocol<D>["F"]["Payload"]["EncodingServices"]>;
|
package/dist/Client.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Context, Encoding, Deferred, Effect, Layer, Option, PubSub, RcRef, Record, pipe, Ref, Scope, Stream, Take, Schema as S, Array, Struct, Fiber, Exit, Cause, Result, flow,
|
|
1
|
+
import { Context, Encoding, Deferred, Effect, Layer, Option, PubSub, RcRef, Record, pipe, Ref, Scope, Stream, Take, Schema as S, Array, Struct, Fiber, Exit, Cause, Result, flow, } from "effect";
|
|
2
2
|
import { Socket } from "effect/unstable/socket";
|
|
3
3
|
import { Worker } from "effect/unstable/workers";
|
|
4
4
|
import * as Diagnostic from "./_util/Diagnostic.js";
|
|
5
5
|
import { AuditionError, ConnectionError, UnresolvedError } from "./errors.js";
|
|
6
6
|
import {} from "./F.js";
|
|
7
|
-
import
|
|
7
|
+
import { Protocol } from "./Protocol.js";
|
|
8
8
|
const { debug, span } = Diagnostic.module("Client");
|
|
9
9
|
export const TypeId = "~liminal/Client";
|
|
10
10
|
export const Service = () => (id, definition) => {
|
|
11
11
|
const tag = Context.Service()(id);
|
|
12
|
+
const protocol = Protocol(definition);
|
|
12
13
|
const events = tag.asEffect().pipe(Effect.flatMap(RcRef.get), Effect.map(Struct.get("events")), Stream.unwrap);
|
|
13
14
|
const f = (_tag) => Effect.fnUntraced(function* (value) {
|
|
14
15
|
const { f } = yield* tag.asEffect().pipe(Effect.flatMap(RcRef.get));
|
|
@@ -18,7 +19,7 @@ export const Service = () => (id, definition) => {
|
|
|
18
19
|
return Object.assign(tag, {
|
|
19
20
|
[TypeId]: TypeId,
|
|
20
21
|
definition,
|
|
21
|
-
|
|
22
|
+
protocol,
|
|
22
23
|
events,
|
|
23
24
|
f,
|
|
24
25
|
invalidate,
|
|
@@ -62,33 +63,38 @@ const make = (client, build, replay) => Effect.gen(function* () {
|
|
|
62
63
|
const end = Scope.close(scope, Exit.void);
|
|
63
64
|
const fiber = yield* listen(Effect.fnUntraced(function* (message) {
|
|
64
65
|
switch (message._tag) {
|
|
65
|
-
case "
|
|
66
|
-
yield* debug("
|
|
66
|
+
case "Audition.Success": {
|
|
67
|
+
yield* debug("Audition.Succeeded");
|
|
67
68
|
yield* Deferred.succeed(audition, void 0);
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
71
|
+
case "Audition.Failure": {
|
|
72
|
+
const { client, routed } = message;
|
|
73
|
+
yield* debug("Audition.Failed", { client, routed });
|
|
74
|
+
return yield* new AuditionError({ value: { client, routed } });
|
|
75
|
+
}
|
|
70
76
|
case "Event": {
|
|
71
77
|
const { event } = message;
|
|
72
|
-
yield* debug("
|
|
78
|
+
yield* debug("Event.Emitted", { event });
|
|
73
79
|
yield* publishTake([event], true);
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
|
-
case "
|
|
77
|
-
case "
|
|
82
|
+
case "F.Success":
|
|
83
|
+
case "F.Failure": {
|
|
78
84
|
const { id } = message;
|
|
79
85
|
const deferred = inflights[id];
|
|
80
86
|
if (deferred) {
|
|
81
87
|
delete inflights[id];
|
|
82
88
|
switch (message._tag) {
|
|
83
|
-
case "
|
|
89
|
+
case "F.Success": {
|
|
84
90
|
const { _tag, value } = message.success;
|
|
85
|
-
yield* debug("
|
|
91
|
+
yield* debug("Call.Succeeded", { id, _tag, value });
|
|
86
92
|
yield* Deferred.succeed(deferred, value);
|
|
87
93
|
return;
|
|
88
94
|
}
|
|
89
|
-
case "
|
|
95
|
+
case "F.Failure": {
|
|
90
96
|
const { _tag, value } = message.failure;
|
|
91
|
-
yield* debug("
|
|
97
|
+
yield* debug("Call.Failed", { id, _tag, value });
|
|
92
98
|
yield* Deferred.fail(deferred, value);
|
|
93
99
|
return;
|
|
94
100
|
}
|
|
@@ -96,23 +102,13 @@ const make = (client, build, replay) => Effect.gen(function* () {
|
|
|
96
102
|
}
|
|
97
103
|
return;
|
|
98
104
|
}
|
|
99
|
-
case "AuditionFailure": {
|
|
100
|
-
const { client, routed } = message;
|
|
101
|
-
yield* debug("AuditionFailed", { client, routed });
|
|
102
|
-
return yield* new AuditionError({ value: { client, routed } });
|
|
103
|
-
}
|
|
104
105
|
case "Disconnect": {
|
|
105
106
|
yield* debug("Disconnected");
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
|
-
case "TransportFailure": {
|
|
109
|
-
const { cause } = message;
|
|
110
|
-
yield* debug("TransportFailed", { cause });
|
|
111
|
-
return yield* new ConnectionError({ cause });
|
|
112
|
-
}
|
|
113
109
|
}
|
|
114
110
|
})).pipe(Effect.ensuring(Effect.all([
|
|
115
|
-
debug("
|
|
111
|
+
debug("Client.Closed", { unresolved: Record.keys(inflights).length }),
|
|
116
112
|
Deferred.succeed(audition, void 0),
|
|
117
113
|
RcRef.invalidate(rcr),
|
|
118
114
|
], { concurrency: "unbounded" })), Effect.forkScoped, Effect.provideService(Scope.Scope, scope));
|
|
@@ -152,7 +148,7 @@ const make = (client, build, replay) => Effect.gen(function* () {
|
|
|
152
148
|
return yield* Exit.match(exit, {
|
|
153
149
|
onSuccess: () => new UnresolvedError(),
|
|
154
150
|
onFailure: flow(Cause.findError, Result.match({
|
|
155
|
-
onSuccess:
|
|
151
|
+
onSuccess: Effect.fail,
|
|
156
152
|
onFailure: () => new UnresolvedError(),
|
|
157
153
|
})),
|
|
158
154
|
});
|
|
@@ -161,7 +157,7 @@ const make = (client, build, replay) => Effect.gen(function* () {
|
|
|
161
157
|
const inflight = yield* Deferred.make();
|
|
162
158
|
inflights[id] = inflight;
|
|
163
159
|
yield* send({
|
|
164
|
-
_tag: "
|
|
160
|
+
_tag: "F.Payload",
|
|
165
161
|
id,
|
|
166
162
|
payload: { _tag, value },
|
|
167
163
|
});
|
|
@@ -179,41 +175,27 @@ const make = (client, build, replay) => Effect.gen(function* () {
|
|
|
179
175
|
return rcr;
|
|
180
176
|
}).pipe(Layer.effect(client));
|
|
181
177
|
export const layerSocket = ({ client, url, protocols, replay, }) => make(client, Effect.gen(function* () {
|
|
178
|
+
const { protocol } = client;
|
|
182
179
|
const socket = yield* Socket.makeWebSocket(url ?? "/", {
|
|
183
180
|
protocols: ["liminal", Encoding.encodeBase64Url(client.key), ...(protocols ? Array.ensure(protocols) : [])],
|
|
184
181
|
});
|
|
185
182
|
return {
|
|
186
183
|
listen: Effect.fnUntraced(function* (publish) {
|
|
187
184
|
yield* socket
|
|
188
|
-
.runRaw((raw) => pipe(raw instanceof Uint8Array ? new TextDecoder().decode(raw) : raw,
|
|
189
|
-
.pipe(Effect.
|
|
185
|
+
.runRaw((raw) => pipe(raw instanceof Uint8Array ? new TextDecoder().decode(raw) : raw, protocol.decodeActor, Effect.andThen(publish)))
|
|
186
|
+
.pipe(Effect.catchIf(Socket.isSocketError, Effect.fnUntraced(function* (cause) {
|
|
190
187
|
const { reason } = cause;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
case "SocketOpenError": {
|
|
195
|
-
yield* debug(reason._tag, { cause });
|
|
196
|
-
return yield* publish({ _tag: "TransportFailure", cause });
|
|
197
|
-
}
|
|
198
|
-
case "SocketCloseError": {
|
|
199
|
-
const { code, closeReason } = reason;
|
|
200
|
-
switch (code) {
|
|
201
|
-
case 1000: {
|
|
202
|
-
return yield* publish({ _tag: "Disconnect" });
|
|
203
|
-
}
|
|
204
|
-
case 4003: {
|
|
205
|
-
return yield* S.decodeUnknownEffect(S.fromJsonString(Protocol.AuditionFailure))(closeReason).pipe(Effect.andThen(publish));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
yield* debug("SocketCloseError", { cause });
|
|
209
|
-
return yield* publish({ _tag: "TransportFailure", cause });
|
|
210
|
-
}
|
|
188
|
+
if (reason._tag === "SocketCloseError" && reason.code === 1000) {
|
|
189
|
+
yield* debug("Socket.Disconnected");
|
|
190
|
+
return yield* publish({ _tag: "Disconnect" });
|
|
211
191
|
}
|
|
212
|
-
|
|
192
|
+
yield* debug(`SocketErrored.${reason._tag}`, { cause });
|
|
193
|
+
return yield* new ConnectionError({ cause });
|
|
194
|
+
})));
|
|
213
195
|
}, span("listen")),
|
|
214
196
|
send: Effect.fnUntraced(function* (v) {
|
|
215
197
|
const write = yield* socket.writer;
|
|
216
|
-
const message = yield*
|
|
198
|
+
const message = yield* protocol.encodeFPayload(v);
|
|
217
199
|
yield* write(message).pipe(Effect.catchTag("SocketError", (cause) => new ConnectionError({ cause }).asEffect()));
|
|
218
200
|
}, span("send"), Effect.scoped),
|
|
219
201
|
};
|
|
@@ -229,10 +211,10 @@ export const layerWorker = ({ client, replay, }) => make(client, Effect.gen(func
|
|
|
229
211
|
const stop = yield* Deferred.make();
|
|
230
212
|
yield* Effect.raceFirst(backing.run(Effect.fnUntraced(function* (message) {
|
|
231
213
|
yield* publish(message);
|
|
232
|
-
if (message._tag === "Disconnect" || message._tag === "
|
|
214
|
+
if (message._tag === "Disconnect" || message._tag === "Audition.Failure") {
|
|
233
215
|
yield* Deferred.succeed(stop, void 0);
|
|
234
216
|
}
|
|
235
|
-
}), { onSpawn: backing.send(client.key).pipe(Effect.orDie) }), Deferred.await(stop)).pipe(Effect.catchTag("WorkerError", (cause) =>
|
|
217
|
+
}), { onSpawn: backing.send(client.key).pipe(Effect.orDie) }), Deferred.await(stop)).pipe(Effect.catchTag("WorkerError", (cause) => new ConnectionError({ cause }).asEffect()));
|
|
236
218
|
}, span("listen")),
|
|
237
219
|
send,
|
|
238
220
|
};
|