effect-orpc 0.2.2 → 0.4.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/README.md +225 -105
- package/dist/{chunk-VOWRLWZZ.js → chunk-IJP6L2XR.js} +6 -2
- package/dist/chunk-IJP6L2XR.js.map +1 -0
- package/dist/index.js +770 -282
- package/dist/index.js.map +1 -1
- package/dist/node.js +4 -3
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/src/contract.ts +46 -11
- package/src/effect-builder.ts +295 -33
- package/src/effect-enhance-router.ts +3 -3
- package/src/effect-procedure.ts +205 -11
- package/src/effect-runtime.ts +445 -23
- package/src/extension/create-node-proxy.ts +17 -1
- package/src/extension/state.ts +16 -20
- package/src/fiber-context-bridge.ts +13 -0
- package/src/index.ts +1 -0
- package/src/node.ts +2 -1
- package/src/runtime-source.ts +76 -0
- package/src/tagged-error.ts +1 -10
- package/src/tests/contract.test.ts +21 -0
- package/src/tests/effect-builder.proxy.test.ts +4 -4
- package/src/tests/effect-builder.test.ts +544 -7
- package/src/tests/effect-error-map.test.ts +10 -10
- package/src/tests/effect-procedure.test.ts +9 -6
- package/src/tests/node-side-effect.test.ts +80 -0
- package/src/tests/parity.effect-builder.test.ts +10 -3
- package/src/tests/parity.effect-procedure.test.ts +24 -8
- package/src/tests/shared.ts +1 -25
- package/src/types/effect-builder-surface.ts +117 -1
- package/src/types/effect-procedure-surface.ts +98 -1
- package/src/types/index.ts +291 -5
- package/src/types/variants.ts +351 -18
- package/dist/chunk-VOWRLWZZ.js.map +0 -1
package/dist/node.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installFiberContextBridge
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IJP6L2XR.js";
|
|
4
4
|
|
|
5
5
|
// src/node.ts
|
|
6
6
|
import { AsyncLocalStorage } from "async_hooks";
|
|
7
7
|
import { Effect } from "effect";
|
|
8
8
|
var fiberRefsStorage = new AsyncLocalStorage();
|
|
9
9
|
var bridge = {
|
|
10
|
-
getCurrentFiberRefs: () => fiberRefsStorage.getStore()
|
|
10
|
+
getCurrentFiberRefs: () => fiberRefsStorage.getStore(),
|
|
11
|
+
runWithFiberRefs: (fiberRefs, fn) => fiberRefsStorage.run(fiberRefs, fn)
|
|
11
12
|
};
|
|
12
13
|
installFiberContextBridge(bridge);
|
|
13
14
|
function withFiberContext(fn) {
|
|
14
15
|
return Effect.flatMap(
|
|
15
16
|
Effect.getFiberRefs,
|
|
16
|
-
(fiberRefs) => Effect.promise(() =>
|
|
17
|
+
(fiberRefs) => Effect.promise(() => bridge.runWithFiberRefs(fiberRefs, fn))
|
|
17
18
|
);
|
|
18
19
|
}
|
|
19
20
|
export {
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/node.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { FiberRefs } from \"effect\";\nimport { Effect } from \"effect\";\n\nimport {\n installFiberContextBridge,\n type FiberContextBridge,\n} from \"./fiber-context-bridge\";\n\nconst fiberRefsStorage = new AsyncLocalStorage<FiberRefs.FiberRefs>();\n\nconst bridge: FiberContextBridge = {\n getCurrentFiberRefs: () => fiberRefsStorage.getStore(),\n};\n\ninstallFiberContextBridge(bridge);\n\nexport function withFiberContext<T>(fn: () => Promise<T>): Effect.Effect<T> {\n return Effect.flatMap(Effect.getFiberRefs, (fiberRefs) =>\n Effect.promise(() =>
|
|
1
|
+
{"version":3,"sources":["../src/node.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { FiberRefs } from \"effect\";\nimport { Effect } from \"effect\";\n\nimport {\n installFiberContextBridge,\n type FiberContextBridge,\n} from \"./fiber-context-bridge\";\n\nconst fiberRefsStorage = new AsyncLocalStorage<FiberRefs.FiberRefs>();\n\nconst bridge: FiberContextBridge = {\n getCurrentFiberRefs: () => fiberRefsStorage.getStore(),\n runWithFiberRefs: (fiberRefs, fn) => fiberRefsStorage.run(fiberRefs, fn),\n};\n\ninstallFiberContextBridge(bridge);\n\nexport function withFiberContext<T>(fn: () => Promise<T>): Effect.Effect<T> {\n return Effect.flatMap(Effect.getFiberRefs, (fiberRefs) =>\n Effect.promise(() => bridge.runWithFiberRefs!(fiberRefs, fn)),\n );\n}\n"],"mappings":";;;;;AAAA,SAAS,yBAAyB;AAGlC,SAAS,cAAc;AAOvB,IAAM,mBAAmB,IAAI,kBAAuC;AAEpE,IAAM,SAA6B;AAAA,EACjC,qBAAqB,MAAM,iBAAiB,SAAS;AAAA,EACrD,kBAAkB,CAAC,WAAW,OAAO,iBAAiB,IAAI,WAAW,EAAE;AACzE;AAEA,0BAA0B,MAAM;AAEzB,SAAS,iBAAoB,IAAwC;AAC1E,SAAO,OAAO;AAAA,IAAQ,OAAO;AAAA,IAAc,CAAC,cAC1C,OAAO,QAAQ,MAAM,OAAO,iBAAkB,WAAW,EAAE,CAAC;AAAA,EAC9D;AACF;","names":[]}
|
package/package.json
CHANGED
package/src/contract.ts
CHANGED
|
@@ -27,13 +27,18 @@ import type {
|
|
|
27
27
|
} from "@orpc/server";
|
|
28
28
|
import { implement } from "@orpc/server";
|
|
29
29
|
import type { IntersectPick } from "@orpc/shared";
|
|
30
|
-
import type { ManagedRuntime } from "effect";
|
|
30
|
+
import type { Layer, ManagedRuntime } from "effect";
|
|
31
31
|
|
|
32
32
|
import { addSpanStackTrace } from "./effect-builder";
|
|
33
33
|
import { enhanceEffectRouter } from "./effect-enhance-router";
|
|
34
34
|
import { EffectDecoratedProcedure } from "./effect-procedure";
|
|
35
35
|
import { createEffectProcedureHandler } from "./effect-runtime";
|
|
36
36
|
import { effectContractSymbol, getEffectContractErrorMap } from "./eoc";
|
|
37
|
+
import type {
|
|
38
|
+
EffectRuntimeRunner,
|
|
39
|
+
EffectRuntimeSource,
|
|
40
|
+
} from "./runtime-source";
|
|
41
|
+
import { makeEffectRuntimeRunner } from "./runtime-source";
|
|
37
42
|
import type { EffectErrorMap } from "./tagged-error";
|
|
38
43
|
import { effectErrorMapToErrorMap } from "./tagged-error";
|
|
39
44
|
import type { EffectErrorMapToErrorMap, EffectProcedureHandler } from "./types";
|
|
@@ -314,13 +319,13 @@ const CONTRACT_HIDDEN_METHODS = new Set([
|
|
|
314
319
|
]);
|
|
315
320
|
|
|
316
321
|
function makeEnhanceOptions<TRequirementsProvided, TRuntimeError>(
|
|
317
|
-
|
|
322
|
+
runner: EffectRuntimeRunner<TRequirementsProvided, TRuntimeError>,
|
|
318
323
|
) {
|
|
319
324
|
return {
|
|
320
325
|
middlewares: [],
|
|
321
326
|
errorMap: {},
|
|
322
327
|
dedupeLeadingMiddlewares: true,
|
|
323
|
-
|
|
328
|
+
runner,
|
|
324
329
|
} as const;
|
|
325
330
|
}
|
|
326
331
|
|
|
@@ -331,7 +336,7 @@ function wrapContractNode<
|
|
|
331
336
|
>(
|
|
332
337
|
contract: TContract,
|
|
333
338
|
target: any,
|
|
334
|
-
|
|
339
|
+
runner: EffectRuntimeRunner<TRequirementsProvided, TRuntimeError>,
|
|
335
340
|
): EffectImplementerInternal<
|
|
336
341
|
TContract,
|
|
337
342
|
Context,
|
|
@@ -360,9 +365,9 @@ function wrapContractNode<
|
|
|
360
365
|
...currentTarget["~orpc"],
|
|
361
366
|
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
362
367
|
effectErrorMap,
|
|
363
|
-
|
|
368
|
+
runner,
|
|
364
369
|
handler: createEffectProcedureHandler({
|
|
365
|
-
|
|
370
|
+
runner,
|
|
366
371
|
effectErrorMap,
|
|
367
372
|
effectFn,
|
|
368
373
|
defaultCaptureStackTrace: addSpanStackTrace(),
|
|
@@ -383,7 +388,7 @@ function wrapContractNode<
|
|
|
383
388
|
currentTarget,
|
|
384
389
|
args,
|
|
385
390
|
),
|
|
386
|
-
|
|
391
|
+
runner,
|
|
387
392
|
);
|
|
388
393
|
|
|
389
394
|
cache.set(prop, use);
|
|
@@ -403,7 +408,7 @@ function wrapContractNode<
|
|
|
403
408
|
currentTarget,
|
|
404
409
|
args,
|
|
405
410
|
),
|
|
406
|
-
|
|
411
|
+
runner,
|
|
407
412
|
);
|
|
408
413
|
|
|
409
414
|
cache.set(prop, wrappedMethod);
|
|
@@ -418,7 +423,7 @@ function wrapContractNode<
|
|
|
418
423
|
currentTarget,
|
|
419
424
|
args,
|
|
420
425
|
) as any,
|
|
421
|
-
makeEnhanceOptions(
|
|
426
|
+
makeEnhanceOptions(runner),
|
|
422
427
|
);
|
|
423
428
|
|
|
424
429
|
cache.set(prop, wrappedMethod);
|
|
@@ -429,7 +434,7 @@ function wrapContractNode<
|
|
|
429
434
|
const child = wrapContractNode(
|
|
430
435
|
(contract as Record<string, AnyContractRouter>)[prop]!,
|
|
431
436
|
Reflect.get(currentTarget, prop, receiver),
|
|
432
|
-
|
|
437
|
+
runner,
|
|
433
438
|
);
|
|
434
439
|
|
|
435
440
|
cache.set(prop, child);
|
|
@@ -463,6 +468,21 @@ function wrapContractNode<
|
|
|
463
468
|
>;
|
|
464
469
|
}
|
|
465
470
|
|
|
471
|
+
export function implementEffect<
|
|
472
|
+
TContract extends AnyContractRouter,
|
|
473
|
+
TRequirementsProvided,
|
|
474
|
+
TRuntimeError,
|
|
475
|
+
>(
|
|
476
|
+
contract: TContract,
|
|
477
|
+
layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
|
|
478
|
+
): EffectImplementer<
|
|
479
|
+
TContract,
|
|
480
|
+
Record<never, never>,
|
|
481
|
+
Record<never, never>,
|
|
482
|
+
TRequirementsProvided,
|
|
483
|
+
TRuntimeError
|
|
484
|
+
>;
|
|
485
|
+
|
|
466
486
|
export function implementEffect<
|
|
467
487
|
TContract extends AnyContractRouter,
|
|
468
488
|
TRequirementsProvided,
|
|
@@ -476,11 +496,26 @@ export function implementEffect<
|
|
|
476
496
|
Record<never, never>,
|
|
477
497
|
TRequirementsProvided,
|
|
478
498
|
TRuntimeError
|
|
499
|
+
>;
|
|
500
|
+
|
|
501
|
+
export function implementEffect<
|
|
502
|
+
TContract extends AnyContractRouter,
|
|
503
|
+
TRequirementsProvided,
|
|
504
|
+
TRuntimeError,
|
|
505
|
+
>(
|
|
506
|
+
contract: TContract,
|
|
507
|
+
source: EffectRuntimeSource<TRequirementsProvided, TRuntimeError>,
|
|
508
|
+
): EffectImplementer<
|
|
509
|
+
TContract,
|
|
510
|
+
Record<never, never>,
|
|
511
|
+
Record<never, never>,
|
|
512
|
+
TRequirementsProvided,
|
|
513
|
+
TRuntimeError
|
|
479
514
|
> {
|
|
480
515
|
return wrapContractNode(
|
|
481
516
|
contract,
|
|
482
517
|
implement(contract),
|
|
483
|
-
|
|
518
|
+
makeEffectRuntimeRunner(source),
|
|
484
519
|
) as EffectImplementer<
|
|
485
520
|
TContract,
|
|
486
521
|
Record<never, never>,
|
package/src/effect-builder.ts
CHANGED
|
@@ -7,11 +7,15 @@ import type {
|
|
|
7
7
|
} from "@orpc/contract";
|
|
8
8
|
import type { Context, Router } from "@orpc/server";
|
|
9
9
|
import { Builder, fallbackConfig, lazy } from "@orpc/server";
|
|
10
|
-
import
|
|
10
|
+
import { Layer, ManagedRuntime } from "effect";
|
|
11
11
|
|
|
12
12
|
import { enhanceEffectRouter } from "./effect-enhance-router";
|
|
13
13
|
import { EffectDecoratedProcedure } from "./effect-procedure";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
createEffectPipelineMiddleware,
|
|
16
|
+
createEffectProcedureHandler,
|
|
17
|
+
isEffectMiddleware,
|
|
18
|
+
} from "./effect-runtime";
|
|
15
19
|
import {
|
|
16
20
|
createNodeProxy,
|
|
17
21
|
unhandled,
|
|
@@ -23,6 +27,8 @@ import {
|
|
|
23
27
|
unwrapEffectUpstream,
|
|
24
28
|
type EffectProxyTarget,
|
|
25
29
|
} from "./extension/state";
|
|
30
|
+
import type { EffectRuntimeSource } from "./runtime-source";
|
|
31
|
+
import { makeEffectRuntimeRunner } from "./runtime-source";
|
|
26
32
|
import type { EffectErrorMap, MergedEffectErrorMap } from "./tagged-error";
|
|
27
33
|
import { effectErrorMapToErrorMap } from "./tagged-error";
|
|
28
34
|
import type {
|
|
@@ -43,6 +49,9 @@ const builderVirtualDescriptors = {
|
|
|
43
49
|
errors: { enumerable: false },
|
|
44
50
|
handler: { enumerable: false },
|
|
45
51
|
lazy: { enumerable: false },
|
|
52
|
+
middleware: { enumerable: false },
|
|
53
|
+
provide: { enumerable: false },
|
|
54
|
+
provideOptional: { enumerable: false },
|
|
46
55
|
router: { enumerable: false },
|
|
47
56
|
traced: { enumerable: false },
|
|
48
57
|
} as const;
|
|
@@ -51,6 +60,9 @@ const builderVirtualKeys = [
|
|
|
51
60
|
"~effect",
|
|
52
61
|
"errors",
|
|
53
62
|
"effect",
|
|
63
|
+
"middleware",
|
|
64
|
+
"provide",
|
|
65
|
+
"provideOptional",
|
|
54
66
|
"traced",
|
|
55
67
|
"handler",
|
|
56
68
|
"router",
|
|
@@ -94,8 +106,10 @@ function getEffectBuilderDef(
|
|
|
94
106
|
return {
|
|
95
107
|
...context.upstream["~orpc"],
|
|
96
108
|
effectErrorMap: context.state.effectErrorMap,
|
|
97
|
-
|
|
109
|
+
runner: context.state.runner,
|
|
98
110
|
spanConfig: context.state.spanConfig,
|
|
111
|
+
effectSteps: context.state.effectSteps,
|
|
112
|
+
effectHandler: context.state.effectHandler,
|
|
99
113
|
};
|
|
100
114
|
}
|
|
101
115
|
|
|
@@ -107,13 +121,57 @@ function wrapBuilderLike(
|
|
|
107
121
|
{
|
|
108
122
|
...builder["~orpc"],
|
|
109
123
|
effectErrorMap: state.effectErrorMap,
|
|
110
|
-
|
|
124
|
+
runner: state.runner,
|
|
111
125
|
spanConfig: state.spanConfig,
|
|
126
|
+
effectSteps: state.effectSteps,
|
|
127
|
+
effectHandler: state.effectHandler,
|
|
112
128
|
},
|
|
113
129
|
unwrapEffectUpstream(builder),
|
|
114
130
|
);
|
|
115
131
|
}
|
|
116
132
|
|
|
133
|
+
function appendEffectStep(
|
|
134
|
+
state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"],
|
|
135
|
+
step: NonNullable<
|
|
136
|
+
NodeProxyContext<
|
|
137
|
+
EffectBuilderTarget,
|
|
138
|
+
AnyBuilderLike
|
|
139
|
+
>["state"]["effectSteps"]
|
|
140
|
+
>[number],
|
|
141
|
+
): NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"] {
|
|
142
|
+
return {
|
|
143
|
+
...state,
|
|
144
|
+
effectSteps: [...(state.effectSteps ?? []), step],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function flushEffectSteps(
|
|
149
|
+
builder: AnyBuilderLike,
|
|
150
|
+
state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"],
|
|
151
|
+
): {
|
|
152
|
+
builder: AnyBuilderLike;
|
|
153
|
+
state: NodeProxyContext<EffectBuilderTarget, AnyBuilderLike>["state"];
|
|
154
|
+
} {
|
|
155
|
+
if (!state.effectSteps?.length) {
|
|
156
|
+
return { builder, state };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const middleware = createEffectPipelineMiddleware({
|
|
160
|
+
effectErrorMap: state.effectErrorMap,
|
|
161
|
+
runner: state.runner,
|
|
162
|
+
steps: state.effectSteps,
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
builder: Reflect.apply(Reflect.get(builder, "use", builder), builder, [
|
|
166
|
+
middleware,
|
|
167
|
+
]) as AnyBuilderLike,
|
|
168
|
+
state: {
|
|
169
|
+
...state,
|
|
170
|
+
effectSteps: undefined,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
117
175
|
function createEffectBuilderProxy(
|
|
118
176
|
target: EffectBuilderTarget,
|
|
119
177
|
): EffectBuilderTarget {
|
|
@@ -166,20 +224,103 @@ function createEffectBuilderProxy(
|
|
|
166
224
|
>[0],
|
|
167
225
|
) => {
|
|
168
226
|
const defaultCaptureStackTrace = addSpanStackTrace();
|
|
227
|
+
const effectHandler = {
|
|
228
|
+
defaultCaptureStackTrace,
|
|
229
|
+
effectFn,
|
|
230
|
+
spanConfig: state.spanConfig,
|
|
231
|
+
};
|
|
169
232
|
return new EffectDecoratedProcedure({
|
|
170
233
|
...effectDef,
|
|
234
|
+
effectHandler,
|
|
171
235
|
handler: async (opts) => {
|
|
172
236
|
return createEffectProcedureHandler({
|
|
173
237
|
defaultCaptureStackTrace,
|
|
174
238
|
effectErrorMap: state.effectErrorMap,
|
|
175
239
|
effectFn,
|
|
176
|
-
|
|
240
|
+
effectSteps: state.effectSteps,
|
|
241
|
+
runner: state.runner,
|
|
177
242
|
spanConfig: state.spanConfig,
|
|
178
243
|
})(opts as any);
|
|
179
244
|
},
|
|
180
245
|
});
|
|
181
246
|
};
|
|
182
247
|
});
|
|
248
|
+
case "middleware":
|
|
249
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
250
|
+
return (middleware: any) => {
|
|
251
|
+
if (isEffectMiddleware(middleware)) {
|
|
252
|
+
const effectMiddleware = createEffectPipelineMiddleware({
|
|
253
|
+
effectErrorMap: state.effectErrorMap,
|
|
254
|
+
runner: state.runner,
|
|
255
|
+
steps: [
|
|
256
|
+
...(state.effectSteps ?? []),
|
|
257
|
+
{ _tag: "middleware" as const, middleware },
|
|
258
|
+
],
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
return Reflect.apply(
|
|
262
|
+
Reflect.get(source, "middleware", source),
|
|
263
|
+
source,
|
|
264
|
+
[effectMiddleware],
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return Reflect.apply(
|
|
269
|
+
Reflect.get(source, "middleware", source),
|
|
270
|
+
source,
|
|
271
|
+
[middleware],
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
case "provide":
|
|
276
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
277
|
+
return (tagOrLayer: any, provider?: any) => {
|
|
278
|
+
return wrapBuilderLike(
|
|
279
|
+
source,
|
|
280
|
+
appendEffectStep(
|
|
281
|
+
state,
|
|
282
|
+
Layer.isLayer(tagOrLayer)
|
|
283
|
+
? { _tag: "provideLayer", layer: tagOrLayer }
|
|
284
|
+
: { _tag: "provide", provider, tag: tagOrLayer },
|
|
285
|
+
),
|
|
286
|
+
);
|
|
287
|
+
};
|
|
288
|
+
});
|
|
289
|
+
case "provideOptional":
|
|
290
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
291
|
+
return (tag: any, provider: any) => {
|
|
292
|
+
return wrapBuilderLike(
|
|
293
|
+
source,
|
|
294
|
+
appendEffectStep(state, {
|
|
295
|
+
_tag: "provideOptional",
|
|
296
|
+
provider,
|
|
297
|
+
tag,
|
|
298
|
+
}),
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
});
|
|
302
|
+
case "use":
|
|
303
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
304
|
+
return (middleware: any, ...rest: unknown[]) => {
|
|
305
|
+
if (isEffectMiddleware(middleware) && rest.length === 0) {
|
|
306
|
+
return wrapBuilderLike(
|
|
307
|
+
source,
|
|
308
|
+
appendEffectStep(state, {
|
|
309
|
+
_tag: "middleware",
|
|
310
|
+
middleware,
|
|
311
|
+
}),
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const flushed = flushEffectSteps(source, state);
|
|
316
|
+
const nextBuilder: AnyBuilderLike = Reflect.apply(
|
|
317
|
+
Reflect.get(flushed.builder, "use", flushed.builder),
|
|
318
|
+
flushed.builder,
|
|
319
|
+
[middleware, ...rest],
|
|
320
|
+
);
|
|
321
|
+
return wrapBuilderLike(nextBuilder, flushed.state);
|
|
322
|
+
};
|
|
323
|
+
});
|
|
183
324
|
case "traced":
|
|
184
325
|
return getOrCreateVirtualMethod(context, prop, () => {
|
|
185
326
|
return (spanName: string) =>
|
|
@@ -457,6 +598,32 @@ export class EffectBuilder<
|
|
|
457
598
|
TRequirementsProvided,
|
|
458
599
|
TRuntimeError
|
|
459
600
|
>["use"];
|
|
601
|
+
/**
|
|
602
|
+
* Provides a request-scoped Effect service to downstream procedures.
|
|
603
|
+
*/
|
|
604
|
+
declare provide: EffectBuilderSurface<
|
|
605
|
+
TInitialContext,
|
|
606
|
+
TCurrentContext,
|
|
607
|
+
TInputSchema,
|
|
608
|
+
TOutputSchema,
|
|
609
|
+
TEffectErrorMap,
|
|
610
|
+
TMeta,
|
|
611
|
+
TRequirementsProvided,
|
|
612
|
+
TRuntimeError
|
|
613
|
+
>["provide"];
|
|
614
|
+
/**
|
|
615
|
+
* Optionally provides a request-scoped Effect service to downstream procedures.
|
|
616
|
+
*/
|
|
617
|
+
declare provideOptional: EffectBuilderSurface<
|
|
618
|
+
TInitialContext,
|
|
619
|
+
TCurrentContext,
|
|
620
|
+
TInputSchema,
|
|
621
|
+
TOutputSchema,
|
|
622
|
+
TEffectErrorMap,
|
|
623
|
+
TMeta,
|
|
624
|
+
TRequirementsProvided,
|
|
625
|
+
TRuntimeError
|
|
626
|
+
>["provideOptional"];
|
|
460
627
|
/**
|
|
461
628
|
* Sets or updates the metadata.
|
|
462
629
|
* The provided metadata is spared-merged with any existing metadata.
|
|
@@ -531,7 +698,7 @@ export class EffectBuilder<
|
|
|
531
698
|
*
|
|
532
699
|
* @example
|
|
533
700
|
* ```ts
|
|
534
|
-
* const getUser =
|
|
701
|
+
* const getUser = effectProcedure
|
|
535
702
|
* .input(z.object({ id: z.string() }))
|
|
536
703
|
* .traced('users.getUser')
|
|
537
704
|
* .effect(function* ({ input }) {
|
|
@@ -567,7 +734,7 @@ export class EffectBuilder<
|
|
|
567
734
|
>["handler"];
|
|
568
735
|
/**
|
|
569
736
|
* Defines the handler of the procedure using an Effect.
|
|
570
|
-
* The Effect is executed using the
|
|
737
|
+
* The Effect is executed using the configured Effect runtime source.
|
|
571
738
|
* The effect is automatically wrapped with `Effect.withSpan`.
|
|
572
739
|
*
|
|
573
740
|
* @see {@link https://orpc.dev/docs/procedure Procedure Docs}
|
|
@@ -659,11 +826,13 @@ export class EffectBuilder<
|
|
|
659
826
|
>,
|
|
660
827
|
builder?: AnyBuilderLike,
|
|
661
828
|
) {
|
|
662
|
-
const {
|
|
829
|
+
const { runner, spanConfig, effectErrorMap, effectSteps, ...orpcDef } = def;
|
|
663
830
|
|
|
664
831
|
attachEffectState(this, builder ?? new Builder(orpcDef), {
|
|
832
|
+
effectSteps,
|
|
833
|
+
effectHandler: def.effectHandler,
|
|
665
834
|
effectErrorMap,
|
|
666
|
-
|
|
835
|
+
runner,
|
|
667
836
|
spanConfig,
|
|
668
837
|
});
|
|
669
838
|
|
|
@@ -672,23 +841,76 @@ export class EffectBuilder<
|
|
|
672
841
|
}
|
|
673
842
|
|
|
674
843
|
/**
|
|
675
|
-
* Creates an Effect-aware procedure builder with the specified
|
|
844
|
+
* Creates an Effect-aware procedure builder with the specified Layer.
|
|
676
845
|
* Uses the default builder shape from `@orpc/server`.
|
|
677
846
|
*
|
|
678
|
-
* @param
|
|
847
|
+
* @param layer - The Layer that provides services for Effect procedures
|
|
679
848
|
* @returns An EffectBuilder instance for creating Effect-native procedures
|
|
680
849
|
*
|
|
681
850
|
* @example
|
|
682
851
|
* ```ts
|
|
683
852
|
* import { makeEffectORPC } from '@orpc/effect'
|
|
684
|
-
* import { Effect, Layer
|
|
853
|
+
* import { Effect, Layer } from 'effect'
|
|
685
854
|
*
|
|
686
|
-
* const
|
|
687
|
-
* const effectOs = makeEffectORPC(runtime)
|
|
855
|
+
* const effectProcedure = makeEffectORPC(Layer.empty)
|
|
688
856
|
*
|
|
689
|
-
* const hello =
|
|
857
|
+
* const hello = effectProcedure.effect(() => Effect.succeed('Hello!'))
|
|
690
858
|
* ```
|
|
691
859
|
*/
|
|
860
|
+
export function makeEffectORPC(): EffectBuilder<
|
|
861
|
+
Context,
|
|
862
|
+
Context,
|
|
863
|
+
Schema<unknown, unknown>,
|
|
864
|
+
Schema<unknown, unknown>,
|
|
865
|
+
Record<never, never>,
|
|
866
|
+
Record<never, never>,
|
|
867
|
+
never,
|
|
868
|
+
never
|
|
869
|
+
>;
|
|
870
|
+
|
|
871
|
+
export function makeEffectORPC<
|
|
872
|
+
TBuilder extends AnyBuilderLike<
|
|
873
|
+
TInputSchema,
|
|
874
|
+
TOutputSchema,
|
|
875
|
+
TErrorMap,
|
|
876
|
+
TMeta
|
|
877
|
+
>,
|
|
878
|
+
TInputSchema extends AnySchema,
|
|
879
|
+
TOutputSchema extends AnySchema,
|
|
880
|
+
TErrorMap extends ErrorMap,
|
|
881
|
+
TMeta extends Meta,
|
|
882
|
+
>(
|
|
883
|
+
builder: TBuilder,
|
|
884
|
+
): EffectBuilder<
|
|
885
|
+
InferBuilderInitialContext<TBuilder>,
|
|
886
|
+
InferBuilderCurrentContext<TBuilder>,
|
|
887
|
+
InferBuilderInputSchema<TBuilder>,
|
|
888
|
+
InferBuilderOutputSchema<TBuilder>,
|
|
889
|
+
InferBuilderErrorMap<TBuilder>,
|
|
890
|
+
InferBuilderMeta<TBuilder>,
|
|
891
|
+
never,
|
|
892
|
+
never
|
|
893
|
+
>;
|
|
894
|
+
|
|
895
|
+
export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
|
|
896
|
+
layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
|
|
897
|
+
): EffectBuilder<
|
|
898
|
+
Context,
|
|
899
|
+
Context,
|
|
900
|
+
Schema<unknown, unknown>,
|
|
901
|
+
Schema<unknown, unknown>,
|
|
902
|
+
Record<never, never>,
|
|
903
|
+
Record<never, never>,
|
|
904
|
+
TRequirementsProvided,
|
|
905
|
+
TRuntimeError
|
|
906
|
+
>;
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Creates an Effect-aware procedure builder with the specified ManagedRuntime.
|
|
910
|
+
* Uses the default builder shape from `@orpc/server`.
|
|
911
|
+
*
|
|
912
|
+
* @param runtime - The ManagedRuntime that provides services for Effect procedures
|
|
913
|
+
*/
|
|
692
914
|
export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
|
|
693
915
|
runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
|
|
694
916
|
): EffectBuilder<
|
|
@@ -704,9 +926,9 @@ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
|
|
|
704
926
|
|
|
705
927
|
/**
|
|
706
928
|
* Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder
|
|
707
|
-
* with the specified
|
|
929
|
+
* with the specified Layer.
|
|
708
930
|
*
|
|
709
|
-
* @param
|
|
931
|
+
* @param layer - The Layer that provides services for Effect procedures
|
|
710
932
|
* @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)
|
|
711
933
|
* @returns An EffectBuilder instance that extends the original builder with Effect support
|
|
712
934
|
*
|
|
@@ -714,16 +936,15 @@ export function makeEffectORPC<TRequirementsProvided, TRuntimeError>(
|
|
|
714
936
|
* ```ts
|
|
715
937
|
* import { makeEffectORPC } from '@orpc/effect'
|
|
716
938
|
* import { os } from '@orpc/server'
|
|
717
|
-
* import { Effect, Layer
|
|
939
|
+
* import { Effect, Layer } from 'effect'
|
|
718
940
|
*
|
|
719
941
|
* // Create a customized builder
|
|
720
942
|
* const authedOs = os.use(authMiddleware)
|
|
721
943
|
*
|
|
722
944
|
* // Wrap it with Effect support
|
|
723
|
-
* const
|
|
724
|
-
* const effectOs = makeEffectORPC(runtime, authedOs)
|
|
945
|
+
* const effectProcedure = makeEffectORPC(UserServiceLive, authedOs)
|
|
725
946
|
*
|
|
726
|
-
* const getUser =
|
|
947
|
+
* const getUser = effectProcedure
|
|
727
948
|
* .input(z.object({ id: z.string() }))
|
|
728
949
|
* .effect(
|
|
729
950
|
* Effect.fn(function* ({ input }) {
|
|
@@ -747,7 +968,7 @@ export function makeEffectORPC<
|
|
|
747
968
|
TRequirementsProvided,
|
|
748
969
|
TRuntimeError,
|
|
749
970
|
>(
|
|
750
|
-
|
|
971
|
+
layer: Layer.Layer<TRequirementsProvided, TRuntimeError, never>,
|
|
751
972
|
builder: TBuilder,
|
|
752
973
|
): EffectBuilder<
|
|
753
974
|
InferBuilderInitialContext<TBuilder>,
|
|
@@ -760,27 +981,59 @@ export function makeEffectORPC<
|
|
|
760
981
|
TRuntimeError
|
|
761
982
|
>;
|
|
762
983
|
|
|
763
|
-
|
|
984
|
+
/**
|
|
985
|
+
* Creates an Effect-aware procedure builder by wrapping an existing oRPC Builder
|
|
986
|
+
* with the specified ManagedRuntime.
|
|
987
|
+
*
|
|
988
|
+
* @param runtime - The ManagedRuntime that provides services for Effect procedures
|
|
989
|
+
* @param builder - The oRPC Builder instance to wrap (e.g., a customized `os`)
|
|
990
|
+
*/
|
|
991
|
+
export function makeEffectORPC<
|
|
992
|
+
TBuilder extends AnyBuilderLike<
|
|
993
|
+
TInputSchema,
|
|
994
|
+
TOutputSchema,
|
|
995
|
+
TErrorMap,
|
|
996
|
+
TMeta
|
|
997
|
+
>,
|
|
998
|
+
TInputSchema extends AnySchema,
|
|
999
|
+
TOutputSchema extends AnySchema,
|
|
1000
|
+
TErrorMap extends ErrorMap,
|
|
1001
|
+
TMeta extends Meta,
|
|
1002
|
+
TRequirementsProvided,
|
|
1003
|
+
TRuntimeError,
|
|
1004
|
+
>(
|
|
764
1005
|
runtime: ManagedRuntime.ManagedRuntime<TRequirementsProvided, TRuntimeError>,
|
|
765
|
-
builder
|
|
1006
|
+
builder: TBuilder,
|
|
766
1007
|
): EffectBuilder<
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
1008
|
+
InferBuilderInitialContext<TBuilder>,
|
|
1009
|
+
InferBuilderCurrentContext<TBuilder>,
|
|
1010
|
+
InferBuilderInputSchema<TBuilder>,
|
|
1011
|
+
InferBuilderOutputSchema<TBuilder>,
|
|
1012
|
+
InferBuilderErrorMap<TBuilder>,
|
|
1013
|
+
InferBuilderMeta<TBuilder>,
|
|
773
1014
|
TRequirementsProvided,
|
|
774
1015
|
TRuntimeError
|
|
775
|
-
|
|
776
|
-
|
|
1016
|
+
>;
|
|
1017
|
+
|
|
1018
|
+
export function makeEffectORPC(
|
|
1019
|
+
source?: EffectRuntimeSource<any, any> | AnyBuilderLike,
|
|
1020
|
+
builder?: AnyBuilderLike,
|
|
1021
|
+
): any {
|
|
1022
|
+
const sourceIsBuilder = source !== undefined && isBuilderLike(source);
|
|
1023
|
+
const resolvedBuilder = sourceIsBuilder
|
|
1024
|
+
? source
|
|
1025
|
+
: (builder ?? emptyBuilder());
|
|
777
1026
|
const effectErrorMap = getEffectErrorMap(resolvedBuilder);
|
|
1027
|
+
const runner =
|
|
1028
|
+
sourceIsBuilder || source === undefined
|
|
1029
|
+
? makeEffectRuntimeRunner()
|
|
1030
|
+
: makeEffectRuntimeRunner(source);
|
|
778
1031
|
return new EffectBuilder(
|
|
779
1032
|
{
|
|
780
1033
|
...resolvedBuilder["~orpc"],
|
|
781
1034
|
effectErrorMap: effectErrorMap,
|
|
782
1035
|
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
783
|
-
|
|
1036
|
+
runner,
|
|
784
1037
|
},
|
|
785
1038
|
unwrapEffectUpstream(resolvedBuilder),
|
|
786
1039
|
);
|
|
@@ -798,3 +1051,12 @@ function emptyBuilder(): AnyBuilderLike {
|
|
|
798
1051
|
route: {},
|
|
799
1052
|
});
|
|
800
1053
|
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Runtime-less Effect oRPC builder, analogous to oRPC's `os` export.
|
|
1057
|
+
*
|
|
1058
|
+
* Provide application services with `.provide(layer)` or use
|
|
1059
|
+
* `makeEffectORPC(runtime)` when you need explicit ManagedRuntime lifecycle
|
|
1060
|
+
* control.
|
|
1061
|
+
*/
|
|
1062
|
+
export const eos = makeEffectORPC();
|