ff-effect 0.0.2 → 0.0.4
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/dist/for/orpc/index.cjs +19 -3
- package/dist/for/orpc/index.cjs.map +1 -1
- package/dist/for/orpc/index.d.cts +16 -1
- package/dist/for/orpc/index.d.ts +16 -1
- package/dist/for/orpc/index.js +19 -3
- package/dist/for/orpc/index.js.map +1 -1
- package/dist/index.cjs +22 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/for/orpc/procedure.test.ts +80 -4
- package/src/for/orpc/procedure.ts +42 -6
- package/src/index.ts +1 -0
- package/src/wrap-client.test.ts +87 -0
- package/src/wrap-client.ts +32 -0
package/dist/for/orpc/index.cjs
CHANGED
|
@@ -52,12 +52,28 @@ async function runPromiseUnwrapped(effect) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// src/for/orpc/procedure.ts
|
|
55
|
+
var FfOrpcCtx;
|
|
56
|
+
((FfOrpcCtx2) => {
|
|
57
|
+
const TAG = "ff-orpc";
|
|
58
|
+
function create(input) {
|
|
59
|
+
return {
|
|
60
|
+
_tag: TAG,
|
|
61
|
+
runEffect: input.runEffect
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
FfOrpcCtx2.create = create;
|
|
65
|
+
function is(ctx) {
|
|
66
|
+
return typeof ctx === "object" && ctx !== null && "_tag" in ctx && ctx._tag === TAG;
|
|
67
|
+
}
|
|
68
|
+
FfOrpcCtx2.is = is;
|
|
69
|
+
})(FfOrpcCtx || (FfOrpcCtx = {}));
|
|
55
70
|
function createHandler(builder, handler) {
|
|
56
71
|
return import_effect3.Effect.gen(function* () {
|
|
57
72
|
const ext_handler = yield* extract(handler);
|
|
58
|
-
return builder.handler(
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
return builder.handler(async (opt) => {
|
|
74
|
+
const runEffect = FfOrpcCtx.is(opt.context.ff) ? opt.context.ff.runEffect : runPromiseUnwrapped;
|
|
75
|
+
return ext_handler(opt).pipe((e) => runEffect(e));
|
|
76
|
+
});
|
|
61
77
|
});
|
|
62
78
|
}
|
|
63
79
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/for/orpc/index.ts","../../../src/for/orpc/procedure.ts","../../../src/extract.ts","../../../src/run-promise-unwrapped.ts"],"sourcesContent":["import { createHandler } from './procedure';\n\nexport { createHandler };\n","import { Effect } from 'effect';\nimport { extract } from '../../extract';\nimport { runPromiseUnwrapped } from '../../run-promise-unwrapped';\n\ntype SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {\n\thandler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;\n};\n\n/**\n * Create a Effect-based handler\n *\n * @example\n * ```ts\n * // Before - Plain oRPC\n * const procedure = os\n * .input(v.object({ hello: v.string() }))\n * .handler(({ input }) => 'world');\n *\n * // After\n * const procedure = createHandler(\n * os.input(v.object({ hello: v.string() })),\n * Effect.fn(function* ({ input }) {\n * return 'world'\n * }),\n * );\n * ```\n **/\nexport function createHandler
|
|
1
|
+
{"version":3,"sources":["../../../src/for/orpc/index.ts","../../../src/for/orpc/procedure.ts","../../../src/extract.ts","../../../src/run-promise-unwrapped.ts"],"sourcesContent":["import { createHandler } from './procedure';\n\nexport { createHandler };\n","import { Effect } from 'effect';\nimport { extract } from '../../extract';\nimport { runPromiseUnwrapped } from '../../run-promise-unwrapped';\n\nexport namespace FfOrpcCtx {\n\tconst TAG = 'ff-orpc';\n\n\texport function create<R>(input: {\n\t\trunEffect: <A = unknown, E = unknown>(\n\t\t\teffect: Effect.Effect<A, E, R>,\n\t\t) => Promise<A>;\n\t}) {\n\t\treturn {\n\t\t\t_tag: TAG,\n\t\t\trunEffect: input.runEffect,\n\t\t};\n\t}\n\n\texport function is(ctx: unknown): ctx is FfOrpcCtx.Type<unknown> {\n\t\treturn (\n\t\t\ttypeof ctx === 'object' &&\n\t\t\tctx !== null &&\n\t\t\t'_tag' in ctx &&\n\t\t\tctx._tag === TAG\n\t\t);\n\t}\n\n\texport type Type<R> = ReturnType<typeof create<R>>;\n}\n\nexport type FfOrpcCtx<R> = FfOrpcCtx.Type<R>;\n\ntype SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {\n\thandler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;\n};\n\n/**\n * Create a Effect-based handler\n *\n * @example\n * ```ts\n * // Before - Plain oRPC\n * const procedure = os\n * .input(v.object({ hello: v.string() }))\n * .handler(({ input }) => 'world');\n *\n * // After\n * const procedure = createHandler(\n * os.input(v.object({ hello: v.string() })),\n * Effect.fn(function* ({ input }) {\n * return 'world'\n * }),\n * );\n * ```\n **/\nexport function createHandler<\n\tOPT extends { context: { ff?: FfOrpcCtx<never> } },\n\tOUTPUT,\n\tIMPLEMENTED_HANDLER,\n\tR,\n>(\n\tbuilder: SimpleBuilder<OPT, OUTPUT, IMPLEMENTED_HANDLER>,\n\thandler: (opt: OPT) => Effect.Effect<OUTPUT, unknown, R>,\n) {\n\treturn Effect.gen(function* () {\n\t\tconst ext_handler = yield* extract(handler);\n\t\treturn builder.handler(async (opt) => {\n\t\t\tconst runEffect = FfOrpcCtx.is(opt.context.ff)\n\t\t\t\t? opt.context.ff.runEffect\n\t\t\t\t: runPromiseUnwrapped;\n\t\t\treturn ext_handler(opt).pipe((e) => runEffect(e));\n\t\t});\n\t});\n}\n","import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,iBAAuB;;;ACAvB,oBAAsC;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,qBAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,qBAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,sBAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,eACV,oBAAK,OAAO,GAAG,MAAM,GAAG,qBAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,IAAAC,iBAAoC;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAM,sBAAO,eAAe,MAAM;AAC/C,SAAO,oBAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,qBAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;;;AFXO,IAAU;AAAA,CAAV,CAAUC,eAAV;AACN,QAAM,MAAM;AAEL,WAAS,OAAU,OAIvB;AACF,WAAO;AAAA,MACN,MAAM;AAAA,MACN,WAAW,MAAM;AAAA,IAClB;AAAA,EACD;AATO,EAAAA,WAAS;AAWT,WAAS,GAAG,KAA8C;AAChE,WACC,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,IAAI,SAAS;AAAA,EAEf;AAPO,EAAAA,WAAS;AAAA,GAdA;AAmDV,SAAS,cAMf,SACA,SACC;AACD,SAAO,sBAAO,IAAI,aAAa;AAC9B,UAAM,cAAc,OAAO,QAAQ,OAAO;AAC1C,WAAO,QAAQ,QAAQ,OAAO,QAAQ;AACrC,YAAM,YAAY,UAAU,GAAG,IAAI,QAAQ,EAAE,IAC1C,IAAI,QAAQ,GAAG,YACf;AACH,aAAO,YAAY,GAAG,EAAE,KAAK,CAAC,MAAM,UAAU,CAAC,CAAC;AAAA,IACjD,CAAC;AAAA,EACF,CAAC;AACF;","names":["import_effect","import_effect","FfOrpcCtx"]}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
|
|
3
|
+
declare namespace FfOrpcCtx {
|
|
4
|
+
function create<R>(input: {
|
|
5
|
+
runEffect: <A = unknown, E = unknown>(effect: Effect.Effect<A, E, R>) => Promise<A>;
|
|
6
|
+
}): {
|
|
7
|
+
_tag: string;
|
|
8
|
+
runEffect: <A = unknown, E = unknown>(effect: Effect.Effect<A, E, R>) => Promise<A>;
|
|
9
|
+
};
|
|
10
|
+
function is(ctx: unknown): ctx is FfOrpcCtx.Type<unknown>;
|
|
11
|
+
type Type<R> = ReturnType<typeof create<R>>;
|
|
12
|
+
}
|
|
13
|
+
type FfOrpcCtx<R> = FfOrpcCtx.Type<R>;
|
|
3
14
|
type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
4
15
|
handler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;
|
|
5
16
|
};
|
|
@@ -22,6 +33,10 @@ type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
|
22
33
|
* );
|
|
23
34
|
* ```
|
|
24
35
|
**/
|
|
25
|
-
declare function createHandler<
|
|
36
|
+
declare function createHandler<OPT extends {
|
|
37
|
+
context: {
|
|
38
|
+
ff?: FfOrpcCtx<never>;
|
|
39
|
+
};
|
|
40
|
+
}, OUTPUT, IMPLEMENTED_HANDLER, R>(builder: SimpleBuilder<OPT, OUTPUT, IMPLEMENTED_HANDLER>, handler: (opt: OPT) => Effect.Effect<OUTPUT, unknown, R>): Effect.Effect<IMPLEMENTED_HANDLER, never, Exclude<R, never>>;
|
|
26
41
|
|
|
27
42
|
export { createHandler };
|
package/dist/for/orpc/index.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
|
|
3
|
+
declare namespace FfOrpcCtx {
|
|
4
|
+
function create<R>(input: {
|
|
5
|
+
runEffect: <A = unknown, E = unknown>(effect: Effect.Effect<A, E, R>) => Promise<A>;
|
|
6
|
+
}): {
|
|
7
|
+
_tag: string;
|
|
8
|
+
runEffect: <A = unknown, E = unknown>(effect: Effect.Effect<A, E, R>) => Promise<A>;
|
|
9
|
+
};
|
|
10
|
+
function is(ctx: unknown): ctx is FfOrpcCtx.Type<unknown>;
|
|
11
|
+
type Type<R> = ReturnType<typeof create<R>>;
|
|
12
|
+
}
|
|
13
|
+
type FfOrpcCtx<R> = FfOrpcCtx.Type<R>;
|
|
3
14
|
type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
4
15
|
handler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;
|
|
5
16
|
};
|
|
@@ -22,6 +33,10 @@ type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
|
22
33
|
* );
|
|
23
34
|
* ```
|
|
24
35
|
**/
|
|
25
|
-
declare function createHandler<
|
|
36
|
+
declare function createHandler<OPT extends {
|
|
37
|
+
context: {
|
|
38
|
+
ff?: FfOrpcCtx<never>;
|
|
39
|
+
};
|
|
40
|
+
}, OUTPUT, IMPLEMENTED_HANDLER, R>(builder: SimpleBuilder<OPT, OUTPUT, IMPLEMENTED_HANDLER>, handler: (opt: OPT) => Effect.Effect<OUTPUT, unknown, R>): Effect.Effect<IMPLEMENTED_HANDLER, never, Exclude<R, never>>;
|
|
26
41
|
|
|
27
42
|
export { createHandler };
|
package/dist/for/orpc/index.js
CHANGED
|
@@ -26,12 +26,28 @@ async function runPromiseUnwrapped(effect) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// src/for/orpc/procedure.ts
|
|
29
|
+
var FfOrpcCtx;
|
|
30
|
+
((FfOrpcCtx2) => {
|
|
31
|
+
const TAG = "ff-orpc";
|
|
32
|
+
function create(input) {
|
|
33
|
+
return {
|
|
34
|
+
_tag: TAG,
|
|
35
|
+
runEffect: input.runEffect
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
FfOrpcCtx2.create = create;
|
|
39
|
+
function is(ctx) {
|
|
40
|
+
return typeof ctx === "object" && ctx !== null && "_tag" in ctx && ctx._tag === TAG;
|
|
41
|
+
}
|
|
42
|
+
FfOrpcCtx2.is = is;
|
|
43
|
+
})(FfOrpcCtx || (FfOrpcCtx = {}));
|
|
29
44
|
function createHandler(builder, handler) {
|
|
30
45
|
return Effect3.gen(function* () {
|
|
31
46
|
const ext_handler = yield* extract(handler);
|
|
32
|
-
return builder.handler(
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
return builder.handler(async (opt) => {
|
|
48
|
+
const runEffect = FfOrpcCtx.is(opt.context.ff) ? opt.context.ff.runEffect : runPromiseUnwrapped;
|
|
49
|
+
return ext_handler(opt).pipe((e) => runEffect(e));
|
|
50
|
+
});
|
|
35
51
|
});
|
|
36
52
|
}
|
|
37
53
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/for/orpc/procedure.ts","../../../src/extract.ts","../../../src/run-promise-unwrapped.ts"],"sourcesContent":["import { Effect } from 'effect';\nimport { extract } from '../../extract';\nimport { runPromiseUnwrapped } from '../../run-promise-unwrapped';\n\ntype SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {\n\thandler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;\n};\n\n/**\n * Create a Effect-based handler\n *\n * @example\n * ```ts\n * // Before - Plain oRPC\n * const procedure = os\n * .input(v.object({ hello: v.string() }))\n * .handler(({ input }) => 'world');\n *\n * // After\n * const procedure = createHandler(\n * os.input(v.object({ hello: v.string() })),\n * Effect.fn(function* ({ input }) {\n * return 'world'\n * }),\n * );\n * ```\n **/\nexport function createHandler
|
|
1
|
+
{"version":3,"sources":["../../../src/for/orpc/procedure.ts","../../../src/extract.ts","../../../src/run-promise-unwrapped.ts"],"sourcesContent":["import { Effect } from 'effect';\nimport { extract } from '../../extract';\nimport { runPromiseUnwrapped } from '../../run-promise-unwrapped';\n\nexport namespace FfOrpcCtx {\n\tconst TAG = 'ff-orpc';\n\n\texport function create<R>(input: {\n\t\trunEffect: <A = unknown, E = unknown>(\n\t\t\teffect: Effect.Effect<A, E, R>,\n\t\t) => Promise<A>;\n\t}) {\n\t\treturn {\n\t\t\t_tag: TAG,\n\t\t\trunEffect: input.runEffect,\n\t\t};\n\t}\n\n\texport function is(ctx: unknown): ctx is FfOrpcCtx.Type<unknown> {\n\t\treturn (\n\t\t\ttypeof ctx === 'object' &&\n\t\t\tctx !== null &&\n\t\t\t'_tag' in ctx &&\n\t\t\tctx._tag === TAG\n\t\t);\n\t}\n\n\texport type Type<R> = ReturnType<typeof create<R>>;\n}\n\nexport type FfOrpcCtx<R> = FfOrpcCtx.Type<R>;\n\ntype SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {\n\thandler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;\n};\n\n/**\n * Create a Effect-based handler\n *\n * @example\n * ```ts\n * // Before - Plain oRPC\n * const procedure = os\n * .input(v.object({ hello: v.string() }))\n * .handler(({ input }) => 'world');\n *\n * // After\n * const procedure = createHandler(\n * os.input(v.object({ hello: v.string() })),\n * Effect.fn(function* ({ input }) {\n * return 'world'\n * }),\n * );\n * ```\n **/\nexport function createHandler<\n\tOPT extends { context: { ff?: FfOrpcCtx<never> } },\n\tOUTPUT,\n\tIMPLEMENTED_HANDLER,\n\tR,\n>(\n\tbuilder: SimpleBuilder<OPT, OUTPUT, IMPLEMENTED_HANDLER>,\n\thandler: (opt: OPT) => Effect.Effect<OUTPUT, unknown, R>,\n) {\n\treturn Effect.gen(function* () {\n\t\tconst ext_handler = yield* extract(handler);\n\t\treturn builder.handler(async (opt) => {\n\t\t\tconst runEffect = FfOrpcCtx.is(opt.context.ff)\n\t\t\t\t? opt.context.ff.runEffect\n\t\t\t\t: runPromiseUnwrapped;\n\t\t\treturn ext_handler(opt).pipe((e) => runEffect(e));\n\t\t});\n\t});\n}\n","import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n"],"mappings":";AAAA,SAAS,UAAAA,eAAc;;;ACAvB,SAAS,SAAS,QAAQ,YAAY;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,OAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,OAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,QAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,WACV,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,SAAS,OAAO,UAAAC,SAAQ,YAAY;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAMA,QAAO,eAAe,MAAM;AAC/C,SAAO,KAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,MAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;;;AFXO,IAAU;AAAA,CAAV,CAAUC,eAAV;AACN,QAAM,MAAM;AAEL,WAAS,OAAU,OAIvB;AACF,WAAO;AAAA,MACN,MAAM;AAAA,MACN,WAAW,MAAM;AAAA,IAClB;AAAA,EACD;AATO,EAAAA,WAAS;AAWT,WAAS,GAAG,KAA8C;AAChE,WACC,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,IAAI,SAAS;AAAA,EAEf;AAPO,EAAAA,WAAS;AAAA,GAdA;AAmDV,SAAS,cAMf,SACA,SACC;AACD,SAAOC,QAAO,IAAI,aAAa;AAC9B,UAAM,cAAc,OAAO,QAAQ,OAAO;AAC1C,WAAO,QAAQ,QAAQ,OAAO,QAAQ;AACrC,YAAM,YAAY,UAAU,GAAG,IAAI,QAAQ,EAAE,IAC1C,IAAI,QAAQ,GAAG,YACf;AACH,aAAO,YAAY,GAAG,EAAE,KAAK,CAAC,MAAM,UAAU,CAAC,CAAC;AAAA,IACjD,CAAC;AAAA,EACF,CAAC;AACF;","names":["Effect","Effect","FfOrpcCtx","Effect"]}
|
package/dist/index.cjs
CHANGED
|
@@ -21,7 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
extract: () => extract,
|
|
24
|
-
runPromiseUnwrapped: () => runPromiseUnwrapped
|
|
24
|
+
runPromiseUnwrapped: () => runPromiseUnwrapped,
|
|
25
|
+
wrapClient: () => wrapClient
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(index_exports);
|
|
27
28
|
|
|
@@ -48,9 +49,28 @@ async function runPromiseUnwrapped(effect) {
|
|
|
48
49
|
}
|
|
49
50
|
});
|
|
50
51
|
}
|
|
52
|
+
|
|
53
|
+
// src/wrap-client.ts
|
|
54
|
+
var import_effect3 = require("effect");
|
|
55
|
+
function isMessage(x) {
|
|
56
|
+
return typeof x === "string";
|
|
57
|
+
}
|
|
58
|
+
function wrapClient(opts) {
|
|
59
|
+
return (func, overrides) => import_effect3.Effect.tryPromise({
|
|
60
|
+
try: () => func(opts.client),
|
|
61
|
+
catch: (cause) => {
|
|
62
|
+
const message = overrides?.error != null ? isMessage(overrides.error) ? overrides.error : overrides.error(cause) : void 0;
|
|
63
|
+
return opts.error({
|
|
64
|
+
cause,
|
|
65
|
+
...message != null && { message }
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
51
70
|
// Annotate the CommonJS export names for ESM import in node:
|
|
52
71
|
0 && (module.exports = {
|
|
53
72
|
extract,
|
|
54
|
-
runPromiseUnwrapped
|
|
73
|
+
runPromiseUnwrapped,
|
|
74
|
+
wrapClient
|
|
55
75
|
});
|
|
56
76
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/extract.ts","../src/run-promise-unwrapped.ts"],"sourcesContent":["export { extract } from './extract.js';\nexport { runPromiseUnwrapped } from './run-promise-unwrapped.js';\n","import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAsC;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,qBAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,qBAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,sBAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,eACV,oBAAK,OAAO,GAAG,MAAM,GAAG,qBAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,IAAAA,iBAAoC;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAM,sBAAO,eAAe,MAAM;AAC/C,SAAO,oBAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,qBAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;","names":["import_effect"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/extract.ts","../src/run-promise-unwrapped.ts","../src/wrap-client.ts"],"sourcesContent":["export { extract } from './extract.js';\nexport { runPromiseUnwrapped } from './run-promise-unwrapped.js';\nexport { wrapClient } from './wrap-client.js';\n","import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n","import { Effect } from 'effect';\n\ntype Cause = unknown;\ntype Message = string;\nfunction isMessage(x: unknown): x is Message {\n\treturn typeof x === 'string';\n}\n\nexport function wrapClient<CLIENT, ERROR extends Error>(opts: {\n\tclient: CLIENT;\n\terror: (ctx: { cause: Cause; message?: Message }) => ERROR;\n}) {\n\treturn <OUTPUT>(\n\t\tfunc: (client: CLIENT) => Promise<OUTPUT>,\n\t\toverrides?: { error?: ((cause: Cause) => Message) | Message },\n\t) =>\n\t\tEffect.tryPromise({\n\t\t\ttry: () => func(opts.client),\n\t\t\tcatch: (cause) => {\n\t\t\t\tconst message =\n\t\t\t\t\toverrides?.error != null\n\t\t\t\t\t\t? isMessage(overrides.error)\n\t\t\t\t\t\t\t? overrides.error\n\t\t\t\t\t\t\t: overrides.error(cause)\n\t\t\t\t\t\t: undefined;\n\t\t\t\treturn opts.error({\n\t\t\t\t\tcause,\n\t\t\t\t\t...(message != null && { message }),\n\t\t\t\t});\n\t\t\t},\n\t\t});\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAsC;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,qBAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,qBAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,sBAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,eACV,oBAAK,OAAO,GAAG,MAAM,GAAG,qBAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,IAAAA,iBAAoC;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAM,sBAAO,eAAe,MAAM;AAC/C,SAAO,oBAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,qBAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;;;ACfA,IAAAC,iBAAuB;AAIvB,SAAS,UAAU,GAA0B;AAC5C,SAAO,OAAO,MAAM;AACrB;AAEO,SAAS,WAAwC,MAGrD;AACF,SAAO,CACN,MACA,cAEA,sBAAO,WAAW;AAAA,IACjB,KAAK,MAAM,KAAK,KAAK,MAAM;AAAA,IAC3B,OAAO,CAAC,UAAU;AACjB,YAAM,UACL,WAAW,SAAS,OACjB,UAAU,UAAU,KAAK,IACxB,UAAU,QACV,UAAU,MAAM,KAAK,IACtB;AACJ,aAAO,KAAK,MAAM;AAAA,QACjB;AAAA,QACA,GAAI,WAAW,QAAQ,EAAE,QAAQ;AAAA,MAClC,CAAC;AAAA,IACF;AAAA,EACD,CAAC;AACH;","names":["import_effect","import_effect"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -10,4 +10,16 @@ declare function extract<P extends any[], A, E, R, INFERRED_EXCLUDED extends Con
|
|
|
10
10
|
**/
|
|
11
11
|
declare function runPromiseUnwrapped<A, E>(effect: Effect.Effect<A, E, never>): Promise<A>;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
type Cause = unknown;
|
|
14
|
+
type Message = string;
|
|
15
|
+
declare function wrapClient<CLIENT, ERROR extends Error>(opts: {
|
|
16
|
+
client: CLIENT;
|
|
17
|
+
error: (ctx: {
|
|
18
|
+
cause: Cause;
|
|
19
|
+
message?: Message;
|
|
20
|
+
}) => ERROR;
|
|
21
|
+
}): <OUTPUT>(func: (client: CLIENT) => Promise<OUTPUT>, overrides?: {
|
|
22
|
+
error?: ((cause: Cause) => Message) | Message;
|
|
23
|
+
}) => Effect.Effect<OUTPUT, ERROR, never>;
|
|
24
|
+
|
|
25
|
+
export { extract, runPromiseUnwrapped, wrapClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,4 +10,16 @@ declare function extract<P extends any[], A, E, R, INFERRED_EXCLUDED extends Con
|
|
|
10
10
|
**/
|
|
11
11
|
declare function runPromiseUnwrapped<A, E>(effect: Effect.Effect<A, E, never>): Promise<A>;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
type Cause = unknown;
|
|
14
|
+
type Message = string;
|
|
15
|
+
declare function wrapClient<CLIENT, ERROR extends Error>(opts: {
|
|
16
|
+
client: CLIENT;
|
|
17
|
+
error: (ctx: {
|
|
18
|
+
cause: Cause;
|
|
19
|
+
message?: Message;
|
|
20
|
+
}) => ERROR;
|
|
21
|
+
}): <OUTPUT>(func: (client: CLIENT) => Promise<OUTPUT>, overrides?: {
|
|
22
|
+
error?: ((cause: Cause) => Message) | Message;
|
|
23
|
+
}) => Effect.Effect<OUTPUT, ERROR, never>;
|
|
24
|
+
|
|
25
|
+
export { extract, runPromiseUnwrapped, wrapClient };
|
package/dist/index.js
CHANGED
|
@@ -21,8 +21,27 @@ async function runPromiseUnwrapped(effect) {
|
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
// src/wrap-client.ts
|
|
26
|
+
import { Effect as Effect3 } from "effect";
|
|
27
|
+
function isMessage(x) {
|
|
28
|
+
return typeof x === "string";
|
|
29
|
+
}
|
|
30
|
+
function wrapClient(opts) {
|
|
31
|
+
return (func, overrides) => Effect3.tryPromise({
|
|
32
|
+
try: () => func(opts.client),
|
|
33
|
+
catch: (cause) => {
|
|
34
|
+
const message = overrides?.error != null ? isMessage(overrides.error) ? overrides.error : overrides.error(cause) : void 0;
|
|
35
|
+
return opts.error({
|
|
36
|
+
cause,
|
|
37
|
+
...message != null && { message }
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
24
42
|
export {
|
|
25
43
|
extract,
|
|
26
|
-
runPromiseUnwrapped
|
|
44
|
+
runPromiseUnwrapped,
|
|
45
|
+
wrapClient
|
|
27
46
|
};
|
|
28
47
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/extract.ts","../src/run-promise-unwrapped.ts"],"sourcesContent":["import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n"],"mappings":";AAAA,SAAS,SAAS,QAAQ,YAAY;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,OAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,OAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,QAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,WACV,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,SAAS,OAAO,UAAAA,SAAQ,YAAY;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAMA,QAAO,eAAe,MAAM;AAC/C,SAAO,KAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,MAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;","names":["Effect"]}
|
|
1
|
+
{"version":3,"sources":["../src/extract.ts","../src/run-promise-unwrapped.ts","../src/wrap-client.ts"],"sourcesContent":["import { Context, Effect, pipe } from \"effect\";\n\ntype InferClass<T> = T extends new (...args: any[]) => infer R ? R : never;\n\n// biome-ignore lint/suspicious/noExplicitAny: intended\nexport function extract<\n\tP extends any[],\n\tA,\n\tE,\n\tR,\n\tINFERRED_EXCLUDED extends Context.Tag<any, any> = never,\n\tEXCLUDED = InferClass<INFERRED_EXCLUDED>,\n>(\n\teffect: (...params: P) => Effect.Effect<A, E, R>,\n\toptions?: { exclude?: Array<INFERRED_EXCLUDED> }\n): Effect.Effect<\n\t(...params: P) => Effect.Effect<A, E, Extract<R, EXCLUDED>>,\n\tnever,\n\tExclude<R, EXCLUDED>\n> {\n\t// @ts-expect-error quite hard to type, check unit test\n\treturn Effect.gen(function* () {\n\t\tconst runtime = yield* Effect.runtime();\n\n\t\tconst context = runtime.context.pipe(\n\t\t\toptions?.exclude ? Context.omit(...options.exclude) : (e) => e\n\t\t) as Context.Context<Exclude<R, EXCLUDED>>;\n\n\t\treturn (...params: P) =>\n\t\t\tpipe(effect(...params), Effect.provide(context));\n\t});\n}\n","import { Cause, Effect, Exit } from \"effect\";\n\n/**\n * A simple wrapper around Effect.runPromiseExit that throws the error if it's a failure\n **/\nexport async function runPromiseUnwrapped<A, E>(\n\teffect: Effect.Effect<A, E, never>\n) {\n\tconst exit = await Effect.runPromiseExit(effect);\n\treturn Exit.match(exit, {\n\t\tonSuccess: (value) => value,\n\t\tonFailure: (cause) => {\n\t\t\tthrow Cause.isFailType(cause) ? cause.error : cause;\n\t\t},\n\t});\n}\n","import { Effect } from 'effect';\n\ntype Cause = unknown;\ntype Message = string;\nfunction isMessage(x: unknown): x is Message {\n\treturn typeof x === 'string';\n}\n\nexport function wrapClient<CLIENT, ERROR extends Error>(opts: {\n\tclient: CLIENT;\n\terror: (ctx: { cause: Cause; message?: Message }) => ERROR;\n}) {\n\treturn <OUTPUT>(\n\t\tfunc: (client: CLIENT) => Promise<OUTPUT>,\n\t\toverrides?: { error?: ((cause: Cause) => Message) | Message },\n\t) =>\n\t\tEffect.tryPromise({\n\t\t\ttry: () => func(opts.client),\n\t\t\tcatch: (cause) => {\n\t\t\t\tconst message =\n\t\t\t\t\toverrides?.error != null\n\t\t\t\t\t\t? isMessage(overrides.error)\n\t\t\t\t\t\t\t? overrides.error\n\t\t\t\t\t\t\t: overrides.error(cause)\n\t\t\t\t\t\t: undefined;\n\t\t\t\treturn opts.error({\n\t\t\t\t\tcause,\n\t\t\t\t\t...(message != null && { message }),\n\t\t\t\t});\n\t\t\t},\n\t\t});\n}\n"],"mappings":";AAAA,SAAS,SAAS,QAAQ,YAAY;AAK/B,SAAS,QAQf,QACA,SAKC;AAED,SAAO,OAAO,IAAI,aAAa;AAC9B,UAAM,UAAU,OAAO,OAAO,QAAQ;AAEtC,UAAM,UAAU,QAAQ,QAAQ;AAAA,MAC/B,SAAS,UAAU,QAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI,CAAC,MAAM;AAAA,IAC9D;AAEA,WAAO,IAAI,WACV,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO,QAAQ,OAAO,CAAC;AAAA,EACjD,CAAC;AACF;;;AC/BA,SAAS,OAAO,UAAAA,SAAQ,YAAY;AAKpC,eAAsB,oBACrB,QACC;AACD,QAAM,OAAO,MAAMA,QAAO,eAAe,MAAM;AAC/C,SAAO,KAAK,MAAM,MAAM;AAAA,IACvB,WAAW,CAAC,UAAU;AAAA,IACtB,WAAW,CAAC,UAAU;AACrB,YAAM,MAAM,WAAW,KAAK,IAAI,MAAM,QAAQ;AAAA,IAC/C;AAAA,EACD,CAAC;AACF;;;ACfA,SAAS,UAAAC,eAAc;AAIvB,SAAS,UAAU,GAA0B;AAC5C,SAAO,OAAO,MAAM;AACrB;AAEO,SAAS,WAAwC,MAGrD;AACF,SAAO,CACN,MACA,cAEAA,QAAO,WAAW;AAAA,IACjB,KAAK,MAAM,KAAK,KAAK,MAAM;AAAA,IAC3B,OAAO,CAAC,UAAU;AACjB,YAAM,UACL,WAAW,SAAS,OACjB,UAAU,UAAU,KAAK,IACxB,UAAU,QACV,UAAU,MAAM,KAAK,IACtB;AACJ,aAAO,KAAK,MAAM;AAAA,QACjB;AAAA,QACA,GAAI,WAAW,QAAQ,EAAE,QAAQ;AAAA,MAClC,CAAC;AAAA,IACF;AAAA,EACD,CAAC;AACH;","names":["Effect","Effect"]}
|
package/package.json
CHANGED
|
@@ -2,17 +2,30 @@ import { layer } from '@effect/vitest';
|
|
|
2
2
|
import { call, implement, os } from '@orpc/server';
|
|
3
3
|
import { Effect } from 'effect';
|
|
4
4
|
import * as v from 'valibot';
|
|
5
|
-
import { expect, expectTypeOf } from 'vitest';
|
|
6
|
-
import { createHandler } from './procedure.js';
|
|
5
|
+
import { expect, expectTypeOf, test } from 'vitest';
|
|
6
|
+
import { createHandler, FfOrpcCtx } from './procedure.js';
|
|
7
7
|
|
|
8
8
|
class Deps extends Effect.Service<Deps>()('deps', {
|
|
9
9
|
effect: Effect.gen(function* () {
|
|
10
|
-
return {
|
|
10
|
+
return yield* Effect.succeed({
|
|
11
11
|
value: 'world',
|
|
12
|
-
};
|
|
12
|
+
});
|
|
13
13
|
}),
|
|
14
14
|
}) {}
|
|
15
15
|
|
|
16
|
+
test('FfOrpcCtx.is', () => {
|
|
17
|
+
const validCtx = {
|
|
18
|
+
_tag: 'ff-orpc',
|
|
19
|
+
runEffect: async () => {},
|
|
20
|
+
};
|
|
21
|
+
expect(FfOrpcCtx.is(validCtx)).toBe(true);
|
|
22
|
+
|
|
23
|
+
expect(FfOrpcCtx.is(null)).toBe(false);
|
|
24
|
+
expect(FfOrpcCtx.is(undefined)).toBe(false);
|
|
25
|
+
expect(FfOrpcCtx.is({})).toBe(false);
|
|
26
|
+
expect(FfOrpcCtx.is({ _tag: 'other' })).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
16
29
|
layer(Deps.Default)((it) => {
|
|
17
30
|
it(
|
|
18
31
|
'basic',
|
|
@@ -56,4 +69,67 @@ layer(Deps.Default)((it) => {
|
|
|
56
69
|
>();
|
|
57
70
|
}),
|
|
58
71
|
);
|
|
72
|
+
|
|
73
|
+
it(
|
|
74
|
+
'with custom runEffect',
|
|
75
|
+
Effect.fn(function* () {
|
|
76
|
+
let runEffectCalled = false;
|
|
77
|
+
|
|
78
|
+
const deps = yield* Deps;
|
|
79
|
+
const customRunEffect = async <A, E>(
|
|
80
|
+
effect: Effect.Effect<A, E, Deps>,
|
|
81
|
+
): Promise<A> => {
|
|
82
|
+
runEffectCalled = true;
|
|
83
|
+
return Effect.runSync(effect.pipe(Effect.provideService(Deps, deps)));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const effectProcedure = createHandler(
|
|
87
|
+
os
|
|
88
|
+
.$context<{ ff: FfOrpcCtx<Deps> }>()
|
|
89
|
+
.input(v.object({ message: v.string() })),
|
|
90
|
+
Effect.fn(function* ({ input }) {
|
|
91
|
+
return `${input.message} ${(yield* Deps).value}`;
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
const procedure = yield* effectProcedure;
|
|
95
|
+
|
|
96
|
+
const result = yield* Effect.promise(() =>
|
|
97
|
+
call(
|
|
98
|
+
procedure,
|
|
99
|
+
{ message: 'hello' },
|
|
100
|
+
{
|
|
101
|
+
context: {
|
|
102
|
+
ff: FfOrpcCtx.create({
|
|
103
|
+
runEffect: customRunEffect,
|
|
104
|
+
}),
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(result).toBe('hello world');
|
|
111
|
+
expect(runEffectCalled).toBe(true);
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
it(
|
|
116
|
+
'fallback to runPromiseUnwrapped when no ff context',
|
|
117
|
+
Effect.fn(function* () {
|
|
118
|
+
const effectProcedure = createHandler(
|
|
119
|
+
os
|
|
120
|
+
.$context<{ ff?: FfOrpcCtx<Deps> }>()
|
|
121
|
+
.input(v.object({ message: v.string() })),
|
|
122
|
+
Effect.fn(function* ({ input }) {
|
|
123
|
+
return `${input.message} ${(yield* Deps).value}`;
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
const procedure = yield* effectProcedure;
|
|
127
|
+
|
|
128
|
+
const result = yield* Effect.promise(() =>
|
|
129
|
+
call(procedure, { message: 'hello' }, { context: {} }),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(result).toBe('hello world');
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
59
135
|
});
|
|
@@ -2,6 +2,34 @@ import { Effect } from 'effect';
|
|
|
2
2
|
import { extract } from '../../extract';
|
|
3
3
|
import { runPromiseUnwrapped } from '../../run-promise-unwrapped';
|
|
4
4
|
|
|
5
|
+
export namespace FfOrpcCtx {
|
|
6
|
+
const TAG = 'ff-orpc';
|
|
7
|
+
|
|
8
|
+
export function create<R>(input: {
|
|
9
|
+
runEffect: <A = unknown, E = unknown>(
|
|
10
|
+
effect: Effect.Effect<A, E, R>,
|
|
11
|
+
) => Promise<A>;
|
|
12
|
+
}) {
|
|
13
|
+
return {
|
|
14
|
+
_tag: TAG,
|
|
15
|
+
runEffect: input.runEffect,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function is(ctx: unknown): ctx is FfOrpcCtx.Type<unknown> {
|
|
20
|
+
return (
|
|
21
|
+
typeof ctx === 'object' &&
|
|
22
|
+
ctx !== null &&
|
|
23
|
+
'_tag' in ctx &&
|
|
24
|
+
ctx._tag === TAG
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type Type<R> = ReturnType<typeof create<R>>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type FfOrpcCtx<R> = FfOrpcCtx.Type<R>;
|
|
32
|
+
|
|
5
33
|
type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
6
34
|
handler: (handler: (_: INPUT) => Promise<OUTPUT>) => IMPLEMENTED_HANDLER;
|
|
7
35
|
};
|
|
@@ -25,14 +53,22 @@ type SimpleBuilder<INPUT, OUTPUT, IMPLEMENTED_HANDLER> = {
|
|
|
25
53
|
* );
|
|
26
54
|
* ```
|
|
27
55
|
**/
|
|
28
|
-
export function createHandler<
|
|
29
|
-
|
|
30
|
-
|
|
56
|
+
export function createHandler<
|
|
57
|
+
OPT extends { context: { ff?: FfOrpcCtx<never> } },
|
|
58
|
+
OUTPUT,
|
|
59
|
+
IMPLEMENTED_HANDLER,
|
|
60
|
+
R,
|
|
61
|
+
>(
|
|
62
|
+
builder: SimpleBuilder<OPT, OUTPUT, IMPLEMENTED_HANDLER>,
|
|
63
|
+
handler: (opt: OPT) => Effect.Effect<OUTPUT, unknown, R>,
|
|
31
64
|
) {
|
|
32
65
|
return Effect.gen(function* () {
|
|
33
66
|
const ext_handler = yield* extract(handler);
|
|
34
|
-
return builder.handler(async (opt) =>
|
|
35
|
-
|
|
36
|
-
|
|
67
|
+
return builder.handler(async (opt) => {
|
|
68
|
+
const runEffect = FfOrpcCtx.is(opt.context.ff)
|
|
69
|
+
? opt.context.ff.runEffect
|
|
70
|
+
: runPromiseUnwrapped;
|
|
71
|
+
return ext_handler(opt).pipe((e) => runEffect(e));
|
|
72
|
+
});
|
|
37
73
|
});
|
|
38
74
|
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
import { wrapClient } from './wrap-client.js';
|
|
4
|
+
|
|
5
|
+
class TestError extends Error {
|
|
6
|
+
constructor(
|
|
7
|
+
public _cause: unknown,
|
|
8
|
+
public _message?: string,
|
|
9
|
+
) {
|
|
10
|
+
super('error');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type TestClient = {
|
|
15
|
+
value: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
test('resolves successfully', () =>
|
|
19
|
+
Effect.gen(function* () {
|
|
20
|
+
const client: TestClient = { value: 'test-value' };
|
|
21
|
+
const wrap = wrapClient({
|
|
22
|
+
client,
|
|
23
|
+
error: ({ cause, message }) => new TestError(cause, message),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const result = yield* wrap((c) => Promise.resolve(c.value));
|
|
27
|
+
|
|
28
|
+
expect(result).toBe('test-value');
|
|
29
|
+
}).pipe(Effect.runPromise));
|
|
30
|
+
|
|
31
|
+
test('rejects without message when no overrides provided', () =>
|
|
32
|
+
Effect.gen(function* () {
|
|
33
|
+
const client: TestClient = { value: 'test-value' };
|
|
34
|
+
const wrap = wrapClient({
|
|
35
|
+
client,
|
|
36
|
+
error: ({ cause, message }) => new TestError(cause, message),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const causedBy = new Error('original error');
|
|
40
|
+
const effect = wrap(() => Promise.reject(causedBy));
|
|
41
|
+
|
|
42
|
+
const result = yield* Effect.flip(effect);
|
|
43
|
+
|
|
44
|
+
expect(result).toBeInstanceOf(TestError);
|
|
45
|
+
expect(result._cause).toBe(causedBy);
|
|
46
|
+
expect(result._message).toBeUndefined();
|
|
47
|
+
}).pipe(Effect.runPromise));
|
|
48
|
+
|
|
49
|
+
test('rejects with string override', () =>
|
|
50
|
+
Effect.gen(function* () {
|
|
51
|
+
const client: TestClient = { value: 'test-value' };
|
|
52
|
+
const wrap = wrapClient({
|
|
53
|
+
client,
|
|
54
|
+
error: ({ cause, message }) => new TestError(cause, message),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const causedBy = new Error('original error');
|
|
58
|
+
const effect = wrap(() => Promise.reject(causedBy), {
|
|
59
|
+
error: 'custom message',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const result = yield* Effect.flip(effect);
|
|
63
|
+
|
|
64
|
+
expect(result).toBeInstanceOf(TestError);
|
|
65
|
+
expect(result._cause).toBe(causedBy);
|
|
66
|
+
expect(result._message).toBe('custom message');
|
|
67
|
+
}).pipe(Effect.runPromise));
|
|
68
|
+
|
|
69
|
+
test('rejects with function override', () =>
|
|
70
|
+
Effect.gen(function* () {
|
|
71
|
+
const client: TestClient = { value: 'test-value' };
|
|
72
|
+
const wrap = wrapClient({
|
|
73
|
+
client,
|
|
74
|
+
error: ({ cause, message }) => new TestError(cause, message),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const causedBy = new Error('original error');
|
|
78
|
+
const effect = wrap(() => Promise.reject(causedBy), {
|
|
79
|
+
error: (cause) => `Error: ${(cause as Error).message}`,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const result = yield* Effect.flip(effect);
|
|
83
|
+
|
|
84
|
+
expect(result).toBeInstanceOf(TestError);
|
|
85
|
+
expect(result._cause).toBe(causedBy);
|
|
86
|
+
expect(result._message).toBe('Error: original error');
|
|
87
|
+
}).pipe(Effect.runPromise));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
|
|
3
|
+
type Cause = unknown;
|
|
4
|
+
type Message = string;
|
|
5
|
+
function isMessage(x: unknown): x is Message {
|
|
6
|
+
return typeof x === 'string';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function wrapClient<CLIENT, ERROR extends Error>(opts: {
|
|
10
|
+
client: CLIENT;
|
|
11
|
+
error: (ctx: { cause: Cause; message?: Message }) => ERROR;
|
|
12
|
+
}) {
|
|
13
|
+
return <OUTPUT>(
|
|
14
|
+
func: (client: CLIENT) => Promise<OUTPUT>,
|
|
15
|
+
overrides?: { error?: ((cause: Cause) => Message) | Message },
|
|
16
|
+
) =>
|
|
17
|
+
Effect.tryPromise({
|
|
18
|
+
try: () => func(opts.client),
|
|
19
|
+
catch: (cause) => {
|
|
20
|
+
const message =
|
|
21
|
+
overrides?.error != null
|
|
22
|
+
? isMessage(overrides.error)
|
|
23
|
+
? overrides.error
|
|
24
|
+
: overrides.error(cause)
|
|
25
|
+
: undefined;
|
|
26
|
+
return opts.error({
|
|
27
|
+
cause,
|
|
28
|
+
...(message != null && { message }),
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|