@orpc/experimental-effect 2.0.0-beta.4 → 2.0.0-beta.41
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 +97 -94
- package/dist/extensions/effect.d.mts +8 -9
- package/dist/extensions/effect.d.ts +8 -9
- package/dist/extensions/effect.mjs +1 -1
- package/dist/extensions/input-output.d.mts +18 -18
- package/dist/extensions/input-output.d.ts +18 -18
- package/dist/extensions/input-output.mjs +8 -5
- package/dist/index.d.mts +155 -13
- package/dist/index.d.ts +155 -13
- package/dist/index.mjs +86 -16
- package/dist/shared/experimental-effect.D0zFxpKr.d.mts +77 -0
- package/dist/shared/experimental-effect.D0zFxpKr.d.ts +77 -0
- package/dist/shared/{experimental-effect.B68ZlIzV.mjs → experimental-effect.YQKompVf.mjs} +1 -1
- package/dist/shared/experimental-effect._sKLzweg.mjs +32 -0
- package/package.json +18 -9
- package/dist/shared/experimental-effect.CuTs7Ks0.d.mts +0 -59
- package/dist/shared/experimental-effect.CuTs7Ks0.d.ts +0 -59
- package/dist/shared/experimental-effect.dulfW-wX.mjs +0 -40
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Context, AnyProcedure, ORPCErrorConstructorMap, ProcedureHandlerOptions, ProcedureHandler } from '@orpc/server';
|
|
2
|
+
import { Context as Context$1, Effect } from 'effect';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A context shape that provides Effect services to effectful handlers
|
|
6
|
+
* through the oRPC context in a typesafe way.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effect-services | Effect Integration - Effect Services}
|
|
9
|
+
*/
|
|
10
|
+
interface WithEffectContext<Services> {
|
|
11
|
+
/**
|
|
12
|
+
* A pre-built Effect context providing the services available within this oRPC context.
|
|
13
|
+
* Automatically provided to any effect that runs under this context.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Context } from 'effect'
|
|
18
|
+
*
|
|
19
|
+
* interface ServerContext extends WithEffectContext<Random | Logger> {}
|
|
20
|
+
*
|
|
21
|
+
* const context: ServerContext = {
|
|
22
|
+
* 'effect/context': Context.empty().pipe(
|
|
23
|
+
* Context.add(Random, { next: Effect.sync(() => Math.random()) }),
|
|
24
|
+
* ),
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
['effect/context']: Context$1.Context<Services>;
|
|
29
|
+
/**
|
|
30
|
+
* An optional hook to wrap any effect before it is executed within this oRPC context.
|
|
31
|
+
* Useful for adding observability, tracing, or error handling.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { Resource, Tracer } from '@effect/opentelemetry'
|
|
36
|
+
* import { Context, Effect, Layer } from 'effect'
|
|
37
|
+
*
|
|
38
|
+
* interface ServerContext extends WithEffectContext<never> {}
|
|
39
|
+
*
|
|
40
|
+
* const TracingLive = Tracer.layerGlobal.pipe(
|
|
41
|
+
* Layer.provide(Resource.layerFromEnv()),
|
|
42
|
+
* )
|
|
43
|
+
*
|
|
44
|
+
* const context: ServerContext = {
|
|
45
|
+
* 'effect/context': Context.empty(),
|
|
46
|
+
* 'effect/wrap': (effect) => effect.pipe(Effect.provide(TracingLive)),
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
['effect/wrap']?: <A, E>(effect: Effect.Effect<A, E>, opts: {
|
|
51
|
+
path: string[];
|
|
52
|
+
procedure: AnyProcedure;
|
|
53
|
+
signal?: undefined | AbortSignal;
|
|
54
|
+
}) => Effect.Effect<A, E>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Infers the Effect services available in an oRPC context that extends `WithEffectContext`.
|
|
58
|
+
*
|
|
59
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effect-services | Effect Integration - Effect Services}
|
|
60
|
+
*/
|
|
61
|
+
type InferEffectServices<T extends Context> = T extends WithEffectContext<infer Services> ? Services : never;
|
|
62
|
+
|
|
63
|
+
type InferYieldError<Eff> = [Eff] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never;
|
|
64
|
+
interface HandlerGen<TCurrentContext extends Context, TInput, TYield extends Effect.Effect<any, any, InferEffectServices<TCurrentContext>>, TReturn, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
65
|
+
(opts: ProcedureHandlerOptions<TCurrentContext, TInput, TErrorConstructorMap>, input: TInput): Generator<TYield, TReturn, never>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates a procedure handler from an Effect generator function.
|
|
69
|
+
* Inside the generator you can yield Effect operations, and `handlerGen`
|
|
70
|
+
* handles the execution and error handling for you.
|
|
71
|
+
*
|
|
72
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effectful-handlers | Effect Integration - Effectful Handlers}
|
|
73
|
+
*/
|
|
74
|
+
declare function handlerGen<TCurrentContext extends Context, TInput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>, TYield extends Effect.Effect<any, any, InferEffectServices<TCurrentContext>>, TReturn>(handler: HandlerGen<TCurrentContext, TInput, TYield, TReturn, TErrorConstructorMap>): ProcedureHandler<TCurrentContext, TInput, TReturn, TErrorConstructorMap>;
|
|
75
|
+
|
|
76
|
+
export { handlerGen as h };
|
|
77
|
+
export type { HandlerGen as H, InferEffectServices as I, WithEffectContext as W, InferYieldError as a };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Context, AnyProcedure, ORPCErrorConstructorMap, ProcedureHandlerOptions, ProcedureHandler } from '@orpc/server';
|
|
2
|
+
import { Context as Context$1, Effect } from 'effect';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A context shape that provides Effect services to effectful handlers
|
|
6
|
+
* through the oRPC context in a typesafe way.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effect-services | Effect Integration - Effect Services}
|
|
9
|
+
*/
|
|
10
|
+
interface WithEffectContext<Services> {
|
|
11
|
+
/**
|
|
12
|
+
* A pre-built Effect context providing the services available within this oRPC context.
|
|
13
|
+
* Automatically provided to any effect that runs under this context.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Context } from 'effect'
|
|
18
|
+
*
|
|
19
|
+
* interface ServerContext extends WithEffectContext<Random | Logger> {}
|
|
20
|
+
*
|
|
21
|
+
* const context: ServerContext = {
|
|
22
|
+
* 'effect/context': Context.empty().pipe(
|
|
23
|
+
* Context.add(Random, { next: Effect.sync(() => Math.random()) }),
|
|
24
|
+
* ),
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
['effect/context']: Context$1.Context<Services>;
|
|
29
|
+
/**
|
|
30
|
+
* An optional hook to wrap any effect before it is executed within this oRPC context.
|
|
31
|
+
* Useful for adding observability, tracing, or error handling.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { Resource, Tracer } from '@effect/opentelemetry'
|
|
36
|
+
* import { Context, Effect, Layer } from 'effect'
|
|
37
|
+
*
|
|
38
|
+
* interface ServerContext extends WithEffectContext<never> {}
|
|
39
|
+
*
|
|
40
|
+
* const TracingLive = Tracer.layerGlobal.pipe(
|
|
41
|
+
* Layer.provide(Resource.layerFromEnv()),
|
|
42
|
+
* )
|
|
43
|
+
*
|
|
44
|
+
* const context: ServerContext = {
|
|
45
|
+
* 'effect/context': Context.empty(),
|
|
46
|
+
* 'effect/wrap': (effect) => effect.pipe(Effect.provide(TracingLive)),
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
['effect/wrap']?: <A, E>(effect: Effect.Effect<A, E>, opts: {
|
|
51
|
+
path: string[];
|
|
52
|
+
procedure: AnyProcedure;
|
|
53
|
+
signal?: undefined | AbortSignal;
|
|
54
|
+
}) => Effect.Effect<A, E>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Infers the Effect services available in an oRPC context that extends `WithEffectContext`.
|
|
58
|
+
*
|
|
59
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effect-services | Effect Integration - Effect Services}
|
|
60
|
+
*/
|
|
61
|
+
type InferEffectServices<T extends Context> = T extends WithEffectContext<infer Services> ? Services : never;
|
|
62
|
+
|
|
63
|
+
type InferYieldError<Eff> = [Eff] extends [never] ? never : [Eff] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never;
|
|
64
|
+
interface HandlerGen<TCurrentContext extends Context, TInput, TYield extends Effect.Effect<any, any, InferEffectServices<TCurrentContext>>, TReturn, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
65
|
+
(opts: ProcedureHandlerOptions<TCurrentContext, TInput, TErrorConstructorMap>, input: TInput): Generator<TYield, TReturn, never>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Creates a procedure handler from an Effect generator function.
|
|
69
|
+
* Inside the generator you can yield Effect operations, and `handlerGen`
|
|
70
|
+
* handles the execution and error handling for you.
|
|
71
|
+
*
|
|
72
|
+
* @see {@link https://orpc.dev/docs/integrations/effect#effectful-handlers | Effect Integration - Effectful Handlers}
|
|
73
|
+
*/
|
|
74
|
+
declare function handlerGen<TCurrentContext extends Context, TInput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>, TYield extends Effect.Effect<any, any, InferEffectServices<TCurrentContext>>, TReturn>(handler: HandlerGen<TCurrentContext, TInput, TYield, TReturn, TErrorConstructorMap>): ProcedureHandler<TCurrentContext, TInput, TReturn, TErrorConstructorMap>;
|
|
75
|
+
|
|
76
|
+
export { handlerGen as h };
|
|
77
|
+
export type { HandlerGen as H, InferEffectServices as I, WithEffectContext as W, InferYieldError as a };
|
|
@@ -2,7 +2,7 @@ import { getHiddenMetaPlugins, setHiddenMetaPlugins } from '@orpc/contract';
|
|
|
2
2
|
import { Schema } from 'effect';
|
|
3
3
|
|
|
4
4
|
function toStandardSchema(schema) {
|
|
5
|
-
const converted = Schema.
|
|
5
|
+
const converted = Schema.toStandardSchemaV1(schema);
|
|
6
6
|
const metaPlugins = getHiddenMetaPlugins(schema);
|
|
7
7
|
if (metaPlugins) {
|
|
8
8
|
setHiddenMetaPlugins(converted, metaPlugins);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect, Exit, Cause, Context } from 'effect';
|
|
2
|
+
import { AbortError } from '@orpc/shared';
|
|
3
|
+
|
|
4
|
+
async function runPromise(effect, options = {}) {
|
|
5
|
+
const exit = await Effect.runPromiseExit(effect, options);
|
|
6
|
+
if (Exit.isSuccess(exit)) {
|
|
7
|
+
return exit.value;
|
|
8
|
+
}
|
|
9
|
+
if (Cause.hasInterruptsOnly(exit.cause)) {
|
|
10
|
+
if (options.signal?.aborted) {
|
|
11
|
+
throw options.signal.reason;
|
|
12
|
+
}
|
|
13
|
+
throw new AbortError("All fibers interrupted without error");
|
|
14
|
+
}
|
|
15
|
+
throw Cause.squash(exit.cause);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function handlerGen(handler) {
|
|
19
|
+
return (opts, input) => {
|
|
20
|
+
let ef = Effect.gen(() => handler(opts, input));
|
|
21
|
+
if (Context.isContext(opts.context["effect/context"])) {
|
|
22
|
+
ef = ef.pipe(Effect.provide(opts.context["effect/context"]));
|
|
23
|
+
}
|
|
24
|
+
if (typeof opts.context["effect/wrap"] === "function") {
|
|
25
|
+
const intercept = opts.context["effect/wrap"];
|
|
26
|
+
ef = intercept(ef, opts);
|
|
27
|
+
}
|
|
28
|
+
return runPromise(ef, { signal: opts.signal });
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { handlerGen as h, runPromise as r };
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orpc/experimental-effect",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.41",
|
|
5
|
+
"description": "Effect integration for oRPC: build typesafe procedures with Effect",
|
|
5
6
|
"license": "MIT",
|
|
7
|
+
"funding": [
|
|
8
|
+
"https://github.com/sponsors/dinwwwh",
|
|
9
|
+
"https://opencollective.com/middleapi"
|
|
10
|
+
],
|
|
6
11
|
"homepage": "https://orpc.dev",
|
|
7
12
|
"repository": {
|
|
8
13
|
"type": "git",
|
|
@@ -11,7 +16,11 @@
|
|
|
11
16
|
},
|
|
12
17
|
"keywords": [
|
|
13
18
|
"orpc",
|
|
14
|
-
"effect"
|
|
19
|
+
"effect",
|
|
20
|
+
"effect-ts",
|
|
21
|
+
"rpc",
|
|
22
|
+
"typescript",
|
|
23
|
+
"typesafe"
|
|
15
24
|
],
|
|
16
25
|
"sideEffects": [
|
|
17
26
|
"./dist/extensions/effect.mjs",
|
|
@@ -39,19 +48,19 @@
|
|
|
39
48
|
"dist"
|
|
40
49
|
],
|
|
41
50
|
"peerDependencies": {
|
|
42
|
-
"effect": ">=
|
|
51
|
+
"effect": ">=4.0.0"
|
|
43
52
|
},
|
|
44
53
|
"dependencies": {
|
|
45
|
-
"@orpc/
|
|
46
|
-
"@orpc/
|
|
47
|
-
"@orpc/
|
|
48
|
-
"@orpc/
|
|
54
|
+
"@orpc/client": "2.0.0-beta.41",
|
|
55
|
+
"@orpc/contract": "2.0.0-beta.41",
|
|
56
|
+
"@orpc/json-schema": "2.0.0-beta.41",
|
|
57
|
+
"@orpc/server": "2.0.0-beta.41",
|
|
58
|
+
"@orpc/shared": "2.0.0-beta.41"
|
|
49
59
|
},
|
|
50
60
|
"devDependencies": {
|
|
51
|
-
"effect": "^
|
|
61
|
+
"effect": "^4.0.0"
|
|
52
62
|
},
|
|
53
63
|
"scripts": {
|
|
54
|
-
"build": "unbuild",
|
|
55
64
|
"type:check": "tsc -b"
|
|
56
65
|
}
|
|
57
66
|
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { AnyProcedure, Context as Context$1, ORPCErrorConstructorMap, ProcedureHandlerOptions, ProcedureHandler, AnyORPCError } from '@orpc/server';
|
|
2
|
-
import { YieldWrap } from 'effect/Utils';
|
|
3
|
-
import { Context, Effect } from 'effect';
|
|
4
|
-
|
|
5
|
-
interface WithEffectContext<Services> {
|
|
6
|
-
/**
|
|
7
|
-
* A pre-built Effect context providing the services available within this oRPC context.
|
|
8
|
-
* Automatically provided to any effect that runs under this context.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { Context } from 'effect'
|
|
13
|
-
*
|
|
14
|
-
* interface ServerContext extends WithEffectContext<Random | Logger> {}
|
|
15
|
-
*
|
|
16
|
-
* const context: ServerContext = {
|
|
17
|
-
* '~effect/context': Context.empty().pipe(
|
|
18
|
-
* Context.add(Random, { next: Effect.sync(() => Math.random()) }),
|
|
19
|
-
* ),
|
|
20
|
-
* }
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
['~effect/context']: Context.Context<Services>;
|
|
24
|
-
/**
|
|
25
|
-
* An optional hook to wrap any effect before it is executed within this oRPC context.
|
|
26
|
-
* Useful for adding observability, tracing, or error handling.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* import { Resource, Tracer } from '@effect/opentelemetry'
|
|
31
|
-
* import { Context, Effect, Layer } from 'effect'
|
|
32
|
-
*
|
|
33
|
-
* interface ServerContext extends WithEffectContext<never> {}
|
|
34
|
-
*
|
|
35
|
-
* const TracingLive = Tracer.layerGlobal.pipe(
|
|
36
|
-
* Layer.provide(Resource.layerFromEnv()),
|
|
37
|
-
* )
|
|
38
|
-
*
|
|
39
|
-
* const context: ServerContext = {
|
|
40
|
-
* '~effect/context': Context.empty(),
|
|
41
|
-
* '~effect/wrap': (effect) => effect.pipe(Effect.provide(TracingLive)),
|
|
42
|
-
* }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
['~effect/wrap']?: <A, E>(effect: Effect.Effect<A, E>, opts: {
|
|
46
|
-
path: string[];
|
|
47
|
-
procedure: AnyProcedure;
|
|
48
|
-
signal?: undefined | AbortSignal;
|
|
49
|
-
}) => Effect.Effect<A, E>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
type InferYieldError<Eff> = [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect.Effect<infer _A, infer E, infer _R>>] ? E : never;
|
|
53
|
-
interface HandlerGen<TCurrentContext extends Context$1, TInput, TYield extends YieldWrap<Effect.Effect<any, any, TCurrentContext extends WithEffectContext<infer S> ? S : never>>, TReturn, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
54
|
-
(opts: ProcedureHandlerOptions<TCurrentContext, TInput, TErrorConstructorMap>, input: TInput): Generator<TYield, TReturn, never>;
|
|
55
|
-
}
|
|
56
|
-
declare function handlerGen<TCurrentContext extends Context$1, TInput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>, TYield extends YieldWrap<Effect.Effect<any, any, TCurrentContext extends WithEffectContext<infer S> ? S : never>>, TReturn>(handler: HandlerGen<TCurrentContext, TInput, TYield, TReturn, TErrorConstructorMap>): ProcedureHandler<TCurrentContext, TInput, TReturn | Extract<InferYieldError<TYield>, AnyORPCError>, TErrorConstructorMap>;
|
|
57
|
-
|
|
58
|
-
export { handlerGen as h };
|
|
59
|
-
export type { HandlerGen as H, InferYieldError as I, WithEffectContext as W };
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { AnyProcedure, Context as Context$1, ORPCErrorConstructorMap, ProcedureHandlerOptions, ProcedureHandler, AnyORPCError } from '@orpc/server';
|
|
2
|
-
import { YieldWrap } from 'effect/Utils';
|
|
3
|
-
import { Context, Effect } from 'effect';
|
|
4
|
-
|
|
5
|
-
interface WithEffectContext<Services> {
|
|
6
|
-
/**
|
|
7
|
-
* A pre-built Effect context providing the services available within this oRPC context.
|
|
8
|
-
* Automatically provided to any effect that runs under this context.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { Context } from 'effect'
|
|
13
|
-
*
|
|
14
|
-
* interface ServerContext extends WithEffectContext<Random | Logger> {}
|
|
15
|
-
*
|
|
16
|
-
* const context: ServerContext = {
|
|
17
|
-
* '~effect/context': Context.empty().pipe(
|
|
18
|
-
* Context.add(Random, { next: Effect.sync(() => Math.random()) }),
|
|
19
|
-
* ),
|
|
20
|
-
* }
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
['~effect/context']: Context.Context<Services>;
|
|
24
|
-
/**
|
|
25
|
-
* An optional hook to wrap any effect before it is executed within this oRPC context.
|
|
26
|
-
* Useful for adding observability, tracing, or error handling.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* import { Resource, Tracer } from '@effect/opentelemetry'
|
|
31
|
-
* import { Context, Effect, Layer } from 'effect'
|
|
32
|
-
*
|
|
33
|
-
* interface ServerContext extends WithEffectContext<never> {}
|
|
34
|
-
*
|
|
35
|
-
* const TracingLive = Tracer.layerGlobal.pipe(
|
|
36
|
-
* Layer.provide(Resource.layerFromEnv()),
|
|
37
|
-
* )
|
|
38
|
-
*
|
|
39
|
-
* const context: ServerContext = {
|
|
40
|
-
* '~effect/context': Context.empty(),
|
|
41
|
-
* '~effect/wrap': (effect) => effect.pipe(Effect.provide(TracingLive)),
|
|
42
|
-
* }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
['~effect/wrap']?: <A, E>(effect: Effect.Effect<A, E>, opts: {
|
|
46
|
-
path: string[];
|
|
47
|
-
procedure: AnyProcedure;
|
|
48
|
-
signal?: undefined | AbortSignal;
|
|
49
|
-
}) => Effect.Effect<A, E>;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
type InferYieldError<Eff> = [Eff] extends [never] ? never : [Eff] extends [YieldWrap<Effect.Effect<infer _A, infer E, infer _R>>] ? E : never;
|
|
53
|
-
interface HandlerGen<TCurrentContext extends Context$1, TInput, TYield extends YieldWrap<Effect.Effect<any, any, TCurrentContext extends WithEffectContext<infer S> ? S : never>>, TReturn, TErrorConstructorMap extends ORPCErrorConstructorMap<any>> {
|
|
54
|
-
(opts: ProcedureHandlerOptions<TCurrentContext, TInput, TErrorConstructorMap>, input: TInput): Generator<TYield, TReturn, never>;
|
|
55
|
-
}
|
|
56
|
-
declare function handlerGen<TCurrentContext extends Context$1, TInput, TErrorConstructorMap extends ORPCErrorConstructorMap<any>, TYield extends YieldWrap<Effect.Effect<any, any, TCurrentContext extends WithEffectContext<infer S> ? S : never>>, TReturn>(handler: HandlerGen<TCurrentContext, TInput, TYield, TReturn, TErrorConstructorMap>): ProcedureHandler<TCurrentContext, TInput, TReturn | Extract<InferYieldError<TYield>, AnyORPCError>, TErrorConstructorMap>;
|
|
57
|
-
|
|
58
|
-
export { handlerGen as h };
|
|
59
|
-
export type { HandlerGen as H, InferYieldError as I, WithEffectContext as W };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { ORPCError } from '@orpc/server';
|
|
2
|
-
import { Effect, Exit, Cause, FiberId, Context } from 'effect';
|
|
3
|
-
import { AbortError } from '@orpc/shared';
|
|
4
|
-
|
|
5
|
-
function extractErrorFromCause(cause) {
|
|
6
|
-
return Cause.match(cause, {
|
|
7
|
-
onFail: (error) => error,
|
|
8
|
-
onDie: (defect) => defect,
|
|
9
|
-
onInterrupt: (fiberId) => new AbortError(`Fiber interrupted: ${FiberId.threadName(fiberId)}`),
|
|
10
|
-
onEmpty: new Error("Effect failed with no error information"),
|
|
11
|
-
// Mirrors native try/finally: if the finalizer (right) also throws,
|
|
12
|
-
// it overwrites the original (left) — same behaviour as JS would produce
|
|
13
|
-
onSequential: (_left, right) => right,
|
|
14
|
-
onParallel: (left, _right) => left
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
async function runPromise(effect, options = {}) {
|
|
18
|
-
const exit = await Effect.runPromiseExit(effect, options);
|
|
19
|
-
if (Exit.isSuccess(exit)) {
|
|
20
|
-
return exit.value;
|
|
21
|
-
}
|
|
22
|
-
throw extractErrorFromCause(exit.cause);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const succeedOnORPCError = Effect.catchAll((error) => error instanceof ORPCError ? Effect.succeed(error) : Effect.fail(error));
|
|
26
|
-
function handlerGen(handler) {
|
|
27
|
-
return (opts, input) => {
|
|
28
|
-
let ef = Effect.gen(() => handler(opts, input)).pipe(succeedOnORPCError);
|
|
29
|
-
if (Context.isContext(opts.context["~effect/context"])) {
|
|
30
|
-
ef = ef.pipe(Effect.provide(opts.context["~effect/context"]));
|
|
31
|
-
}
|
|
32
|
-
if (typeof opts.context["~effect/wrap"] === "function") {
|
|
33
|
-
const intercept = opts.context["~effect/wrap"];
|
|
34
|
-
ef = intercept(ef, opts);
|
|
35
|
-
}
|
|
36
|
-
return runPromise(ef, { signal: opts.signal });
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export { extractErrorFromCause as e, handlerGen as h, runPromise as r };
|