effect-cf 0.6.0 → 0.8.0
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/CHANGELOG.md +16 -0
- package/README.md +121 -29
- package/dist/Hyperdrive-By6DrSS_.d.mts +140 -0
- package/dist/Hyperdrive-LuQaVhXU.mjs +86 -0
- package/dist/HyperdrivePg.d.mts +14 -0
- package/dist/HyperdrivePg.mjs +13 -0
- package/dist/index.d.mts +1029 -1162
- package/dist/index.mjs +497 -515
- package/package.json +13 -1
- package/src/Binding.ts +17 -10
- package/src/D1.ts +3 -59
- package/src/DurableObject.ts +117 -23
- package/src/DurableObjectDefinition.ts +251 -72
- package/src/DurableObjectNamespace.ts +239 -287
- package/src/Hyperdrive.ts +82 -0
- package/src/HyperdrivePg.ts +27 -0
- package/src/Images.ts +332 -0
- package/src/Kv.ts +152 -240
- package/src/Queue.ts +18 -4
- package/src/QueueBinding.ts +45 -97
- package/src/QueueDefinition.ts +87 -41
- package/src/R2.ts +230 -0
- package/src/ServiceBinding.ts +260 -116
- package/src/Worker.ts +114 -20
- package/src/WorkerDefinition.ts +187 -63
- package/src/Workflow.ts +23 -4
- package/src/WorkflowBinding.ts +100 -109
- package/src/WorkflowDefinition.ts +116 -51
- package/src/index.ts +3 -0
package/src/WorkerDefinition.ts
CHANGED
|
@@ -1,28 +1,77 @@
|
|
|
1
|
-
import { Effect, type Layer } from "effect";
|
|
1
|
+
import { Context, Effect, type Layer } from "effect";
|
|
2
|
+
import type { Schema as S } from "effect";
|
|
2
3
|
|
|
4
|
+
import * as Binding from "./Binding";
|
|
3
5
|
import type { WorkerEnvironment } from "./Environment";
|
|
4
6
|
import * as WorkerEntrypoint from "./Worker";
|
|
5
7
|
import type { WorkerRpcHandler } from "./Worker";
|
|
8
|
+
import type * as Rpc from "./Rpc";
|
|
6
9
|
import * as RpcDefinition from "./RpcDefinition";
|
|
7
10
|
import * as ServiceBinding from "./ServiceBinding";
|
|
8
11
|
|
|
12
|
+
export type ServiceFreeSchema = S.Codec<any, any, never, never>;
|
|
13
|
+
|
|
14
|
+
export interface Method<
|
|
15
|
+
Args extends ReadonlyArray<ServiceFreeSchema> = ReadonlyArray<ServiceFreeSchema>,
|
|
16
|
+
Success extends ServiceFreeSchema = ServiceFreeSchema,
|
|
17
|
+
> {
|
|
18
|
+
readonly args: Args;
|
|
19
|
+
readonly success: Success;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export namespace Method {
|
|
23
|
+
export type Any = Method<ReadonlyArray<ServiceFreeSchema>, ServiceFreeSchema>;
|
|
24
|
+
|
|
25
|
+
type ArgsFromSchemas<Args extends ReadonlyArray<ServiceFreeSchema>> = Args extends readonly []
|
|
26
|
+
? []
|
|
27
|
+
: Args extends readonly [
|
|
28
|
+
infer Head extends ServiceFreeSchema,
|
|
29
|
+
...infer Tail extends ReadonlyArray<ServiceFreeSchema>,
|
|
30
|
+
]
|
|
31
|
+
? [S.Schema.Type<Head>, ...ArgsFromSchemas<Tail>]
|
|
32
|
+
: Array<S.Schema.Type<Args[number]>>;
|
|
33
|
+
|
|
34
|
+
type EncodedArgsFromSchemas<Args extends ReadonlyArray<ServiceFreeSchema>> =
|
|
35
|
+
Args extends readonly []
|
|
36
|
+
? []
|
|
37
|
+
: Args extends readonly [
|
|
38
|
+
infer Head extends ServiceFreeSchema,
|
|
39
|
+
...infer Tail extends ReadonlyArray<ServiceFreeSchema>,
|
|
40
|
+
]
|
|
41
|
+
? [S.Codec.Encoded<Head>, ...EncodedArgsFromSchemas<Tail>]
|
|
42
|
+
: Array<S.Codec.Encoded<Args[number]>>;
|
|
43
|
+
|
|
44
|
+
export type Args<Self extends Any> = ArgsFromSchemas<Self["args"]>;
|
|
45
|
+
|
|
46
|
+
export type EncodedArgs<Self extends Any> = EncodedArgsFromSchemas<Self["args"]>;
|
|
47
|
+
|
|
48
|
+
export type Success<Self extends Any> = S.Schema.Type<Self["success"]>;
|
|
49
|
+
|
|
50
|
+
export type EncodedSuccess<Self extends Any> = S.Codec.Encoded<Self["success"]>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type Methods = Record<string, Method.Any>;
|
|
54
|
+
|
|
9
55
|
/**
|
|
10
56
|
* RPC contract for a Worker service.
|
|
11
57
|
*
|
|
12
58
|
* Create with {@link make} and reuse to type both worker implementations and
|
|
13
59
|
* service bindings in other workers.
|
|
14
60
|
*/
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
61
|
+
export interface Definition<Id extends string = string, MethodsShape extends Methods = Methods> {
|
|
62
|
+
readonly id: Id;
|
|
63
|
+
readonly methods: MethodsShape;
|
|
64
|
+
}
|
|
19
65
|
|
|
20
66
|
export namespace Definition {
|
|
21
|
-
export type Any =
|
|
67
|
+
export type Any = Definition<string, Methods>;
|
|
22
68
|
}
|
|
23
69
|
|
|
24
70
|
export type ReservedMethodName = WorkerEntrypoint.ReservedMethodName;
|
|
25
71
|
|
|
72
|
+
export type NoReservedMethods<MethodsShape extends Methods> =
|
|
73
|
+
Extract<keyof MethodsShape, ReservedMethodName> extends never ? MethodsShape : never;
|
|
74
|
+
|
|
26
75
|
const reservedMethodNames = new Set<string>([
|
|
27
76
|
"constructor",
|
|
28
77
|
"dup",
|
|
@@ -43,38 +92,27 @@ const reservedMethodNames = new Set<string>([
|
|
|
43
92
|
/**
|
|
44
93
|
* Promise-based client API derived from a {@link Definition}.
|
|
45
94
|
*/
|
|
46
|
-
export type ServerApi<Self extends Definition.Any> =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Self
|
|
50
|
-
|
|
51
|
-
>;
|
|
52
|
-
|
|
53
|
-
declare const BindingServiceTypeId: unique symbol;
|
|
95
|
+
export type ServerApi<Self extends Definition.Any> = {
|
|
96
|
+
readonly [Key in keyof Self["methods"]]: (
|
|
97
|
+
...args: Method.Args<Self["methods"][Key]>
|
|
98
|
+
) => Promise<Method.Success<Self["methods"][Key]>>;
|
|
99
|
+
};
|
|
54
100
|
|
|
55
|
-
|
|
56
|
-
* Nominal service marker for a worker binding created with {@link make}.
|
|
57
|
-
*/
|
|
58
|
-
export interface BindingService<Id extends string, Self extends Definition.Any> {
|
|
59
|
-
readonly [BindingServiceTypeId]: {
|
|
60
|
-
readonly id: Id;
|
|
61
|
-
readonly definition: Self;
|
|
62
|
-
};
|
|
63
|
-
}
|
|
101
|
+
export type Api<Self extends Definition.Any> = Rpc.Provider<ServerApi<Self>, ReservedMethodName>;
|
|
64
102
|
|
|
65
103
|
/**
|
|
66
104
|
* Effect handlers for each RPC method in a worker definition.
|
|
67
105
|
*/
|
|
68
106
|
export type Handlers<ROut, Self extends Definition.Any> = {
|
|
69
107
|
readonly [Key in keyof Self["methods"]]: (
|
|
70
|
-
...args:
|
|
71
|
-
) => WorkerRpcHandler<ROut,
|
|
108
|
+
...args: Method.Args<Self["methods"][Key]>
|
|
109
|
+
) => WorkerRpcHandler<ROut, Method.Success<Self["methods"][Key]>>;
|
|
72
110
|
};
|
|
73
111
|
|
|
74
112
|
type BoundaryHandlers<ROut, Self extends Definition.Any> = {
|
|
75
113
|
readonly [Key in keyof Self["methods"]]: (
|
|
76
114
|
...args: Array<unknown>
|
|
77
|
-
) => WorkerRpcHandler<ROut,
|
|
115
|
+
) => WorkerRpcHandler<ROut, Method.EncodedSuccess<Self["methods"][Key]>>;
|
|
78
116
|
};
|
|
79
117
|
|
|
80
118
|
/**
|
|
@@ -87,10 +125,57 @@ export interface Options<ROut, Self extends Definition.Any> extends Omit<
|
|
|
87
125
|
readonly rpc: Handlers<ROut, Self>;
|
|
88
126
|
}
|
|
89
127
|
|
|
128
|
+
export type LayerOptions = {
|
|
129
|
+
readonly binding: string;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Context.ServiceClass<
|
|
133
|
+
Self,
|
|
134
|
+
Id,
|
|
135
|
+
ServiceBinding.ServiceBindingEffectClient<
|
|
136
|
+
Api<Definition<Id, MethodsShape>>,
|
|
137
|
+
Definition<Id, MethodsShape>
|
|
138
|
+
>
|
|
139
|
+
> &
|
|
140
|
+
ServiceBinding.ServiceBindingStaticClient<
|
|
141
|
+
Self,
|
|
142
|
+
Api<Definition<Id, MethodsShape>>,
|
|
143
|
+
Definition<Id, MethodsShape>
|
|
144
|
+
> & {
|
|
145
|
+
readonly id: Id;
|
|
146
|
+
readonly methods: MethodsShape;
|
|
147
|
+
readonly make: <ROut, LayerError>(
|
|
148
|
+
layer: Layer.Layer<
|
|
149
|
+
ROut,
|
|
150
|
+
LayerError,
|
|
151
|
+
WorkerEntrypoint.ExecutionContext | WorkerEntrypoint.WorkerContext | WorkerEnvironment
|
|
152
|
+
>,
|
|
153
|
+
options: Options<ROut, Definition<Id, MethodsShape>>,
|
|
154
|
+
) => WorkerEntrypoint.WorkerClass<Handlers<ROut, Definition<Id, MethodsShape>>, ROut>;
|
|
155
|
+
readonly layer: (
|
|
156
|
+
options: LayerOptions,
|
|
157
|
+
) => Layer.Layer<
|
|
158
|
+
Self,
|
|
159
|
+
Binding.BindingNotFoundError | Binding.BindingValidationError,
|
|
160
|
+
WorkerEnvironment
|
|
161
|
+
>;
|
|
162
|
+
};
|
|
163
|
+
|
|
90
164
|
/**
|
|
91
165
|
* Defines a single RPC method schema in a worker definition.
|
|
92
166
|
*/
|
|
93
|
-
export const method = RpcDefinition.method
|
|
167
|
+
export const method = RpcDefinition.method as {
|
|
168
|
+
<Success extends ServiceFreeSchema>(definition: {
|
|
169
|
+
readonly success: Success;
|
|
170
|
+
}): Method<readonly [], Success>;
|
|
171
|
+
<
|
|
172
|
+
const Args extends ReadonlyArray<ServiceFreeSchema>,
|
|
173
|
+
Success extends ServiceFreeSchema,
|
|
174
|
+
>(definition: {
|
|
175
|
+
readonly args: Args;
|
|
176
|
+
readonly success: Success;
|
|
177
|
+
}): Method<Args, Success>;
|
|
178
|
+
};
|
|
94
179
|
|
|
95
180
|
/**
|
|
96
181
|
* Creates a typed worker RPC definition plus helpers for implementation and bindings.
|
|
@@ -105,9 +190,9 @@ export const method = RpcDefinition.method;
|
|
|
105
190
|
* });
|
|
106
191
|
* ```
|
|
107
192
|
*/
|
|
108
|
-
const makeDefinition = <Id extends string, const MethodsShape extends
|
|
193
|
+
const makeDefinition = <Id extends string, const MethodsShape extends Methods>(
|
|
109
194
|
id: Id,
|
|
110
|
-
methods: MethodsShape &
|
|
195
|
+
methods: MethodsShape & NoReservedMethods<MethodsShape>,
|
|
111
196
|
) => {
|
|
112
197
|
type SelfDefinition = Definition<Id, MethodsShape>;
|
|
113
198
|
RpcDefinition.assertNoReservedMethods("Worker", methods, reservedMethodNames);
|
|
@@ -126,49 +211,88 @@ const makeDefinition = <Id extends string, const MethodsShape extends RpcDefinit
|
|
|
126
211
|
...options,
|
|
127
212
|
rpc: wrapHandlers(definition, options.rpc),
|
|
128
213
|
}),
|
|
129
|
-
Binding:
|
|
130
|
-
<Self>() =>
|
|
131
|
-
<BindingId extends string>(
|
|
132
|
-
bindingId: BindingId,
|
|
133
|
-
binding: Omit<ServiceBinding.ServiceBindingDefinition<SelfDefinition>, "definition">,
|
|
134
|
-
) =>
|
|
135
|
-
ServiceBinding.Service<Self, Api<SelfDefinition>>()<BindingId, SelfDefinition>(bindingId, {
|
|
136
|
-
...binding,
|
|
137
|
-
definition,
|
|
138
|
-
}),
|
|
139
|
-
binding: <BindingId extends string>(
|
|
140
|
-
bindingId: BindingId,
|
|
141
|
-
binding: Omit<ServiceBinding.ServiceBindingDefinition<SelfDefinition>, "definition">,
|
|
142
|
-
) =>
|
|
143
|
-
ServiceBinding.Service<BindingService<BindingId, SelfDefinition>, Api<SelfDefinition>>()<
|
|
144
|
-
BindingId,
|
|
145
|
-
SelfDefinition
|
|
146
|
-
>(bindingId, {
|
|
147
|
-
...binding,
|
|
148
|
-
definition,
|
|
149
|
-
}),
|
|
150
214
|
});
|
|
151
215
|
};
|
|
152
216
|
|
|
153
|
-
export const make =
|
|
217
|
+
export const make = <Id extends string, const MethodsShape extends Methods>(
|
|
218
|
+
id: Id,
|
|
219
|
+
methods: MethodsShape & NoReservedMethods<MethodsShape>,
|
|
220
|
+
) =>
|
|
221
|
+
Tag<Definition<Id, MethodsShape>>()<Id, MethodsShape>(
|
|
222
|
+
id,
|
|
223
|
+
methods as MethodsShape & NoReservedMethods<MethodsShape>,
|
|
224
|
+
);
|
|
154
225
|
|
|
155
226
|
export const Tag =
|
|
156
|
-
<
|
|
157
|
-
<Id extends string, const MethodsShape extends
|
|
227
|
+
<Self>() =>
|
|
228
|
+
<Id extends string, const MethodsShape extends Methods>(
|
|
158
229
|
id: Id,
|
|
159
|
-
methods: MethodsShape &
|
|
230
|
+
methods: MethodsShape & NoReservedMethods<MethodsShape>,
|
|
160
231
|
) => {
|
|
161
232
|
const definition = makeDefinition<Id, MethodsShape>(id, methods);
|
|
233
|
+
type SelfDefinition = Definition<Id, MethodsShape>;
|
|
234
|
+
type ClientApi = Api<SelfDefinition>;
|
|
235
|
+
const tag = Context.Service<
|
|
236
|
+
Self,
|
|
237
|
+
ServiceBinding.ServiceBindingEffectClient<ClientApi, SelfDefinition>
|
|
238
|
+
>()(id);
|
|
239
|
+
|
|
240
|
+
const bindingDefinition = (binding: LayerOptions) => ({
|
|
241
|
+
...binding,
|
|
242
|
+
definition,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const layer = (binding: LayerOptions) =>
|
|
246
|
+
ServiceBinding.layer<Self, ClientApi, SelfDefinition>(tag, bindingDefinition(binding));
|
|
247
|
+
|
|
248
|
+
const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
|
|
249
|
+
Effect.gen(function* () {
|
|
250
|
+
const service = yield* tag;
|
|
251
|
+
return yield* service.fetch(input, init);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const rpc = <Method extends keyof ClientApi>(
|
|
255
|
+
method: Method,
|
|
256
|
+
...args: ClientApi[Method] extends (...args: infer Args) => unknown ? Args : never
|
|
257
|
+
) =>
|
|
258
|
+
Effect.gen(function* () {
|
|
259
|
+
const service = yield* tag;
|
|
260
|
+
return yield* service.rpc(method as never, ...(args as never));
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const call = <Method extends keyof ClientApi>(
|
|
264
|
+
method: Method,
|
|
265
|
+
...args: ClientApi[Method] extends (...args: infer Args) => unknown ? Args : never
|
|
266
|
+
) =>
|
|
267
|
+
Effect.gen(function* () {
|
|
268
|
+
const service = yield* tag;
|
|
269
|
+
return yield* service.call(method as never, ...(args as never));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const scopedCall = <Method extends keyof ClientApi>(
|
|
273
|
+
method: Method,
|
|
274
|
+
...args: ClientApi[Method] extends (...args: infer Args) => unknown ? Args : never
|
|
275
|
+
) =>
|
|
276
|
+
Effect.gen(function* () {
|
|
277
|
+
const service = yield* tag;
|
|
278
|
+
return yield* service.scopedCall(method as never, ...(args as never));
|
|
279
|
+
});
|
|
162
280
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
static readonly Binding = definition.Binding;
|
|
168
|
-
static readonly binding = definition.binding;
|
|
169
|
-
}
|
|
281
|
+
const directMethods = ServiceBinding.makeDirectMethods<Self, ClientApi, SelfDefinition>(
|
|
282
|
+
definition,
|
|
283
|
+
call as never,
|
|
284
|
+
);
|
|
170
285
|
|
|
171
|
-
return
|
|
286
|
+
return Object.assign(tag, directMethods, {
|
|
287
|
+
id: definition.id,
|
|
288
|
+
methods: definition.methods,
|
|
289
|
+
make: definition.make,
|
|
290
|
+
layer,
|
|
291
|
+
fetch,
|
|
292
|
+
rpc,
|
|
293
|
+
call,
|
|
294
|
+
scopedCall,
|
|
295
|
+
}) as unknown as TagClass<Self, Id, MethodsShape>;
|
|
172
296
|
};
|
|
173
297
|
|
|
174
298
|
export const Worker = Tag;
|
|
@@ -209,4 +333,4 @@ export type HandlerEffect<
|
|
|
209
333
|
ROut,
|
|
210
334
|
Self extends Definition.Any,
|
|
211
335
|
Key extends keyof Self["methods"],
|
|
212
|
-
> = WorkerRpcHandler<ROut,
|
|
336
|
+
> = WorkerRpcHandler<ROut, Method.Success<Self["methods"][Key]>>;
|
package/src/Workflow.ts
CHANGED
|
@@ -252,10 +252,6 @@ export const waitForEvent = <Payload>(
|
|
|
252
252
|
workflowStep.waitForEvent<Payload>(name, options),
|
|
253
253
|
);
|
|
254
254
|
|
|
255
|
-
export const Tag = WorkflowDefinition.Tag;
|
|
256
|
-
|
|
257
|
-
export const implement = WorkflowDefinition.implement;
|
|
258
|
-
|
|
259
255
|
export type Definition<
|
|
260
256
|
Id extends string = string,
|
|
261
257
|
Payload extends WorkflowDefinition.Definition.Any["payload"] =
|
|
@@ -268,6 +264,29 @@ export namespace Definition {
|
|
|
268
264
|
export type Any = WorkflowDefinition.Definition.Any;
|
|
269
265
|
}
|
|
270
266
|
|
|
267
|
+
export type LayerOptions = WorkflowDefinition.LayerOptions;
|
|
268
|
+
|
|
269
|
+
export type TagClass<
|
|
270
|
+
Self,
|
|
271
|
+
Id extends string,
|
|
272
|
+
Payload extends WorkflowDefinition.Definition.Any["payload"],
|
|
273
|
+
Result extends WorkflowDefinition.Definition.Any["result"],
|
|
274
|
+
> = WorkflowDefinition.TagClass<Self, Id, Payload, Result>;
|
|
275
|
+
|
|
276
|
+
export const Tag: <Self>() => <
|
|
277
|
+
Id extends string,
|
|
278
|
+
Payload extends WorkflowDefinition.Definition.Any["payload"],
|
|
279
|
+
Result extends WorkflowDefinition.Definition.Any["result"],
|
|
280
|
+
>(
|
|
281
|
+
id: Id,
|
|
282
|
+
definition: {
|
|
283
|
+
readonly payload: Payload;
|
|
284
|
+
readonly result: Result;
|
|
285
|
+
},
|
|
286
|
+
) => TagClass<Self, Id, Payload, Result> = WorkflowDefinition.Tag;
|
|
287
|
+
|
|
288
|
+
export const implement = WorkflowDefinition.implement;
|
|
289
|
+
|
|
271
290
|
export type Handler<
|
|
272
291
|
ROut,
|
|
273
292
|
Self extends WorkflowDefinition.Definition.Any,
|
package/src/WorkflowBinding.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { Data, Effect, Option, Schema as S } from "effect";
|
|
1
|
+
import { Context, Data, Effect, Option, Schema as S } from "effect";
|
|
2
2
|
|
|
3
3
|
import * as Binding from "./Binding";
|
|
4
4
|
import type * as RpcDefinition from "./RpcDefinition";
|
|
5
5
|
|
|
6
|
-
const TypeId = "effect-cf/WorkflowBinding" as const;
|
|
7
|
-
|
|
8
6
|
export type WorkflowInstanceCreateOptions<Payload> = Omit<
|
|
9
7
|
globalThis.WorkflowInstanceCreateOptions<Payload>,
|
|
10
8
|
"params"
|
|
@@ -66,20 +64,27 @@ export interface WorkflowBindingDefinition<
|
|
|
66
64
|
readonly result: Result;
|
|
67
65
|
}
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
export interface WorkflowService<
|
|
72
|
-
Id extends string,
|
|
67
|
+
export interface WorkflowBindingClient<
|
|
73
68
|
Payload extends RpcDefinition.ServiceFreeSchema,
|
|
74
69
|
Result extends RpcDefinition.ServiceFreeSchema,
|
|
75
70
|
> {
|
|
76
|
-
readonly
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
readonly create: (
|
|
72
|
+
payload: S.Schema.Type<Payload>,
|
|
73
|
+
options?: WorkflowInstanceCreateOptions<S.Codec.Encoded<Payload>>,
|
|
74
|
+
) => Effect.Effect<
|
|
75
|
+
WorkflowInstance<S.Schema.Type<Result>>,
|
|
76
|
+
WorkflowOperationError | S.SchemaError
|
|
77
|
+
>;
|
|
78
|
+
readonly createBatch: (
|
|
79
|
+
batch: WorkflowInstanceCreateBatchOptions<S.Schema.Type<Payload>, S.Codec.Encoded<Payload>>,
|
|
80
|
+
) => Effect.Effect<
|
|
81
|
+
ReadonlyArray<WorkflowInstance<S.Schema.Type<Result>>>,
|
|
82
|
+
WorkflowOperationError | S.SchemaError
|
|
83
|
+
>;
|
|
84
|
+
readonly get: (
|
|
85
|
+
instanceId: string,
|
|
86
|
+
) => Effect.Effect<WorkflowInstance<S.Schema.Type<Result>>, WorkflowOperationError>;
|
|
87
|
+
readonly unsafeRaw: Effect.Effect<globalThis.Workflow<S.Codec.Encoded<Payload>>>;
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
export class WorkflowOperationError extends Data.TaggedError("WorkflowOperationError")<{
|
|
@@ -107,7 +112,7 @@ const tryWorkflowPromise = <A>(
|
|
|
107
112
|
catch: (cause) => workflowError(binding, operation, cause),
|
|
108
113
|
});
|
|
109
114
|
|
|
110
|
-
const isWorkflow = <Payload>(value: unknown): value is globalThis.Workflow<Payload> => {
|
|
115
|
+
export const isWorkflow = <Payload>(value: unknown): value is globalThis.Workflow<Payload> => {
|
|
111
116
|
if (typeof value !== "object" || value === null) {
|
|
112
117
|
return false;
|
|
113
118
|
}
|
|
@@ -121,102 +126,83 @@ const isWorkflow = <Payload>(value: unknown): value is globalThis.Workflow<Paylo
|
|
|
121
126
|
);
|
|
122
127
|
};
|
|
123
128
|
|
|
124
|
-
export const
|
|
125
|
-
Id extends string,
|
|
129
|
+
export const makeClient = <
|
|
126
130
|
Payload extends RpcDefinition.ServiceFreeSchema,
|
|
127
131
|
Result extends RpcDefinition.ServiceFreeSchema,
|
|
128
132
|
>(
|
|
129
|
-
id: Id,
|
|
130
133
|
definition: WorkflowBindingDefinition<Payload, Result>,
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
<
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const wrapInstance = (raw: globalThis.WorkflowInstance): WorkflowInstance<ResultValue> => {
|
|
157
|
-
const operation = <A>(name: string, evaluate: () => Promise<A>) =>
|
|
158
|
-
tryWorkflowPromise(definition.binding, name, evaluate);
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
raw,
|
|
162
|
-
id: raw.id,
|
|
163
|
-
pause: operation("pause", () => raw.pause()),
|
|
164
|
-
resume: operation("resume", () => raw.resume()),
|
|
165
|
-
terminate: operation("terminate", () => raw.terminate()),
|
|
166
|
-
restart: (options) =>
|
|
167
|
-
operation("restart", () =>
|
|
168
|
-
(raw as { restart(options?: WorkflowInstanceRestartOptions): Promise<void> }).restart(
|
|
169
|
-
options,
|
|
170
|
-
),
|
|
134
|
+
): ((
|
|
135
|
+
workflow: globalThis.Workflow<S.Codec.Encoded<Payload>>,
|
|
136
|
+
) => WorkflowBindingClient<Payload, Result>) => {
|
|
137
|
+
type PayloadValue = S.Schema.Type<Payload>;
|
|
138
|
+
type EncodedPayload = S.Codec.Encoded<Payload>;
|
|
139
|
+
type ResultValue = S.Schema.Type<Result>;
|
|
140
|
+
|
|
141
|
+
const encodePayload = S.encodeEffect(definition.payload);
|
|
142
|
+
const decodeResult = S.decodeUnknownEffect(definition.result);
|
|
143
|
+
|
|
144
|
+
const wrapInstance = (raw: globalThis.WorkflowInstance): WorkflowInstance<ResultValue> => {
|
|
145
|
+
const operation = <A>(name: string, evaluate: () => Promise<A>) =>
|
|
146
|
+
tryWorkflowPromise(definition.binding, name, evaluate);
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
raw,
|
|
150
|
+
id: raw.id,
|
|
151
|
+
pause: operation("pause", () => raw.pause()),
|
|
152
|
+
resume: operation("resume", () => raw.resume()),
|
|
153
|
+
terminate: operation("terminate", () => raw.terminate()),
|
|
154
|
+
restart: (options) =>
|
|
155
|
+
operation("restart", () =>
|
|
156
|
+
(raw as { restart(options?: WorkflowInstanceRestartOptions): Promise<void> }).restart(
|
|
157
|
+
options,
|
|
171
158
|
),
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
159
|
+
),
|
|
160
|
+
status: operation("status", () => raw.status()).pipe(
|
|
161
|
+
Effect.flatMap((status) =>
|
|
162
|
+
Effect.gen(function* () {
|
|
163
|
+
const output =
|
|
164
|
+
status.output === undefined
|
|
165
|
+
? Option.none<ResultValue>()
|
|
166
|
+
: Option.some(
|
|
167
|
+
yield* decodeResult(status.output).pipe(
|
|
168
|
+
Effect.mapError(
|
|
169
|
+
(cause) =>
|
|
170
|
+
new WorkflowResultDecodeError({
|
|
171
|
+
binding: definition.binding,
|
|
172
|
+
instanceId: raw.id,
|
|
173
|
+
cause,
|
|
174
|
+
}),
|
|
188
175
|
),
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
),
|
|
176
|
+
),
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
status: status.status,
|
|
181
|
+
output,
|
|
182
|
+
error: status.error === undefined ? Option.none() : Option.some(status.error),
|
|
183
|
+
};
|
|
184
|
+
}),
|
|
198
185
|
),
|
|
199
|
-
|
|
200
|
-
|
|
186
|
+
),
|
|
187
|
+
sendEvent: (event) => operation("sendEvent", () => raw.sendEvent(event)),
|
|
201
188
|
};
|
|
189
|
+
};
|
|
202
190
|
|
|
203
|
-
|
|
191
|
+
return (workflow) => ({
|
|
192
|
+
create: Effect.fnUntraced(function* (
|
|
204
193
|
payload: PayloadValue,
|
|
205
194
|
options?: WorkflowInstanceCreateOptions<EncodedPayload>,
|
|
206
195
|
) {
|
|
207
|
-
const workflow = yield* tag;
|
|
208
196
|
const encoded = yield* encodePayload(payload);
|
|
209
197
|
const raw = yield* tryWorkflowPromise(definition.binding, "create", () =>
|
|
210
198
|
workflow.create({ ...options, params: encoded }),
|
|
211
199
|
);
|
|
212
200
|
|
|
213
201
|
return wrapInstance(raw);
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
const createBatch = Effect.fnUntraced(function* (
|
|
202
|
+
}),
|
|
203
|
+
createBatch: Effect.fnUntraced(function* (
|
|
217
204
|
batch: WorkflowInstanceCreateBatchOptions<PayloadValue, EncodedPayload>,
|
|
218
205
|
) {
|
|
219
|
-
const workflow = yield* tag;
|
|
220
206
|
const encodedBatch: Array<globalThis.WorkflowInstanceCreateOptions<EncodedPayload>> = [];
|
|
221
207
|
|
|
222
208
|
for (const item of batch) {
|
|
@@ -233,22 +219,27 @@ export const Service =
|
|
|
233
219
|
);
|
|
234
220
|
|
|
235
221
|
return rawInstances.map(wrapInstance);
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
222
|
+
}),
|
|
223
|
+
get: (instanceId) =>
|
|
224
|
+
tryWorkflowPromise(definition.binding, "get", () => workflow.get(instanceId)).pipe(
|
|
225
|
+
Effect.map(wrapInstance),
|
|
226
|
+
),
|
|
227
|
+
unsafeRaw: Effect.succeed(workflow),
|
|
228
|
+
});
|
|
229
|
+
};
|
|
243
230
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
231
|
+
export const layer = <
|
|
232
|
+
Self,
|
|
233
|
+
Payload extends RpcDefinition.ServiceFreeSchema,
|
|
234
|
+
Result extends RpcDefinition.ServiceFreeSchema,
|
|
235
|
+
>(
|
|
236
|
+
tag: Context.Service<Self, WorkflowBindingClient<Payload, Result>>,
|
|
237
|
+
definition: WorkflowBindingDefinition<Payload, Result>,
|
|
238
|
+
) =>
|
|
239
|
+
Binding.layer(
|
|
240
|
+
tag,
|
|
241
|
+
definition.binding,
|
|
242
|
+
(value): value is globalThis.Workflow<S.Codec.Encoded<Payload>> =>
|
|
243
|
+
isWorkflow<S.Codec.Encoded<Payload>>(value),
|
|
244
|
+
makeClient(definition),
|
|
245
|
+
);
|