effect-orpc 1.0.0-effect-v4.3 → 1.0.0-effect-v4.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/README.md +100 -5
- package/dist/{chunk-E5YLLTJI.js → chunk-I5EWBI42.js} +1 -1
- package/dist/chunk-I5EWBI42.js.map +1 -0
- package/dist/index.js +336 -65
- package/dist/index.js.map +1 -1
- package/dist/node.js +2 -2
- package/dist/node.js.map +1 -1
- package/package.json +4 -4
- package/src/contract.ts +491 -0
- package/src/effect-builder.ts +41 -110
- package/src/effect-runtime.ts +144 -0
- package/src/eoc.ts +499 -0
- package/src/index.ts +18 -3
- package/src/node.ts +3 -3
- package/src/service-context-bridge.ts +3 -3
- package/src/tagged-error.ts +24 -4
- package/src/tests/contract.test.ts +348 -0
- package/src/tests/effect-builder.test.ts +5 -5
- package/src/tests/effect-error-map.test.ts +22 -3
- package/src/tests/parity-shared.ts +32 -0
- package/src/tests/parity.contract-builder-variants.test.ts +192 -0
- package/src/tests/parity.contract-builder.test.ts +222 -0
- package/src/tests/parity.effect-builder.test.ts +193 -0
- package/src/tests/parity.effect-procedure.test.ts +124 -0
- package/src/tests/parity.implementer-variants.test.ts +249 -0
- package/src/tests/parity.implementer.test.ts +280 -0
- package/src/tests/shared.ts +2 -0
- package/src/types/index.ts +0 -16
- package/src/types/variants.ts +25 -16
- package/dist/chunk-E5YLLTJI.js.map +0 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Runnable demos live in the repository's `examples/` directory.
|
|
|
29
29
|
|
|
30
30
|
```ts
|
|
31
31
|
import { os } from "@orpc/server";
|
|
32
|
-
import { Effect, Layer, ManagedRuntime,
|
|
32
|
+
import { Effect, Layer, ManagedRuntime, Context } from "effect";
|
|
33
33
|
import { makeEffectORPC, ORPCTaggedError } from "effect-orpc";
|
|
34
34
|
|
|
35
35
|
interface User {
|
|
@@ -53,7 +53,7 @@ const authedOs = os
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
// Define your services
|
|
56
|
-
class UsersRepo extends
|
|
56
|
+
class UsersRepo extends Context.Service<
|
|
57
57
|
UsersRepo,
|
|
58
58
|
{
|
|
59
59
|
readonly get: (id: number) => User | undefined;
|
|
@@ -99,17 +99,17 @@ export type Router = typeof router;
|
|
|
99
99
|
The wrapper enforces that Effect procedures only use services provided by the `ManagedRuntime`. If you try to use a service that isn't in the runtime, you'll get a compile-time error:
|
|
100
100
|
|
|
101
101
|
```ts
|
|
102
|
-
import { Effect, Layer, ManagedRuntime,
|
|
102
|
+
import { Effect, Layer, ManagedRuntime, Context } from "effect";
|
|
103
103
|
import { makeEffectORPC } from "effect-orpc";
|
|
104
104
|
|
|
105
|
-
class ProvidedService extends
|
|
105
|
+
class ProvidedService extends Context.Service<
|
|
106
106
|
ProvidedService,
|
|
107
107
|
{
|
|
108
108
|
readonly doSomething: () => Effect.Effect<string>;
|
|
109
109
|
}
|
|
110
110
|
>()("ProvidedService") {}
|
|
111
111
|
|
|
112
|
-
class MissingService extends
|
|
112
|
+
class MissingService extends Context.Service<
|
|
113
113
|
MissingService,
|
|
114
114
|
{
|
|
115
115
|
readonly doSomething: () => Effect.Effect<string>;
|
|
@@ -327,6 +327,55 @@ runtime-agnostic.
|
|
|
327
327
|
If you do not need framework-to-handler fiber propagation, you do not need the
|
|
328
328
|
`/node` entrypoint at all.
|
|
329
329
|
|
|
330
|
+
## Contract-First Usage
|
|
331
|
+
|
|
332
|
+
Use `implementEffect(contract, runtime)` when you already have an oRPC contract
|
|
333
|
+
and want to keep contract-first enforcement while adding Effect-native handlers.
|
|
334
|
+
Use `makeEffectORPC(runtime, builder?)` when you want to build procedures
|
|
335
|
+
directly from an oRPC builder.
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
import { Effect, ManagedRuntime } from "effect";
|
|
339
|
+
import { eoc, implementEffect } from "effect-orpc";
|
|
340
|
+
import z from "zod";
|
|
341
|
+
|
|
342
|
+
class UsersRepo extends Effect.Service<UsersRepo>()("UsersRepo", {
|
|
343
|
+
accessors: true,
|
|
344
|
+
sync: () => ({
|
|
345
|
+
list: (amount: number) =>
|
|
346
|
+
Array.from({ length: amount }, (_, index) => `user-${index + 1}`),
|
|
347
|
+
}),
|
|
348
|
+
}) {}
|
|
349
|
+
|
|
350
|
+
const contract = {
|
|
351
|
+
users: {
|
|
352
|
+
list: eoc
|
|
353
|
+
.input(z.object({ amount: z.number().int().positive() }))
|
|
354
|
+
.output(z.array(z.string())),
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const runtime = ManagedRuntime.make(UsersRepo.Default);
|
|
359
|
+
const oe = implementEffect(contract, runtime);
|
|
360
|
+
|
|
361
|
+
export const router = oe.router({
|
|
362
|
+
users: {
|
|
363
|
+
list: oe.users.list.effect(function* ({ input }) {
|
|
364
|
+
return yield* UsersRepo.list(input.amount);
|
|
365
|
+
}),
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Contract leaves keep the contract-defined input, output, and error surface.
|
|
371
|
+
They add `.effect(...)` alongside existing implementer methods such as
|
|
372
|
+
`.handler(...)` and `.use(...)`, but do not expose contract-changing builder
|
|
373
|
+
methods like `.input(...)` or `.output(...)`.
|
|
374
|
+
|
|
375
|
+
If your contract declares tagged Effect error classes, prefer `eoc.errors(...)`
|
|
376
|
+
instead of raw `oc.errors(...)` so the error schema and metadata are derived
|
|
377
|
+
directly from the `ORPCTaggedError` class.
|
|
378
|
+
|
|
330
379
|
## API Reference
|
|
331
380
|
|
|
332
381
|
### `makeEffectORPC(runtime, builder?)`
|
|
@@ -346,6 +395,52 @@ const effectOs = makeEffectORPC(runtime);
|
|
|
346
395
|
const effectAuthedOs = makeEffectORPC(runtime, authedBuilder);
|
|
347
396
|
```
|
|
348
397
|
|
|
398
|
+
### `implementEffect(contract, runtime)`
|
|
399
|
+
|
|
400
|
+
Creates an Effect-aware contract implementer.
|
|
401
|
+
|
|
402
|
+
- `contract` - An oRPC contract router built with `oc`
|
|
403
|
+
- `runtime` - A `ManagedRuntime<R, E>` instance that provides services for Effect procedures
|
|
404
|
+
|
|
405
|
+
Returns a contract-shaped implementer tree whose leaves support `.effect(...)`.
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const oe = implementEffect(contract, runtime);
|
|
409
|
+
|
|
410
|
+
const router = oe.router({
|
|
411
|
+
users: {
|
|
412
|
+
list: oe.users.list.effect(function* ({ input }) {
|
|
413
|
+
return yield* UsersRepo.list(input.amount);
|
|
414
|
+
}),
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### `eoc`
|
|
420
|
+
|
|
421
|
+
An Effect-aware wrapper around oRPC's `oc` contract builder.
|
|
422
|
+
|
|
423
|
+
Use it when you want contract definitions to accept `ORPCTaggedError` classes
|
|
424
|
+
directly in `.errors(...)` without duplicating the error schema.
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
class UserNotFoundError extends ORPCTaggedError("UserNotFoundError", {
|
|
428
|
+
code: "NOT_FOUND",
|
|
429
|
+
schema: z.object({ userId: z.string() }),
|
|
430
|
+
}) {}
|
|
431
|
+
|
|
432
|
+
const contract = {
|
|
433
|
+
users: {
|
|
434
|
+
find: eoc
|
|
435
|
+
.errors({
|
|
436
|
+
NOT_FOUND: UserNotFoundError,
|
|
437
|
+
})
|
|
438
|
+
.input(z.object({ userId: z.string() }))
|
|
439
|
+
.output(z.object({ userId: z.string() })),
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
```
|
|
443
|
+
|
|
349
444
|
### `EffectBuilder`
|
|
350
445
|
|
|
351
446
|
Wraps an oRPC Builder with Effect support. Available methods:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/service-context-bridge.ts"],"sourcesContent":["import type { Context } from \"effect\";\n\nexport interface ServiceContextBridge {\n readonly getCurrentServices: () => Context.Context<any> | undefined;\n}\n\nlet bridge: ServiceContextBridge | undefined;\n\nexport function installServiceContextBridge(\n nextBridge: ServiceContextBridge | undefined,\n): void {\n bridge = nextBridge;\n}\n\nexport function getCurrentServices(): Context.Context<any> | undefined {\n return bridge?.getCurrentServices();\n}\n"],"mappings":";AAMA,IAAI;AAEG,SAAS,4BACd,YACM;AACN,WAAS;AACX;AAEO,SAAS,qBAAuD;AACrE,SAAO,QAAQ,mBAAmB;AACpC;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCurrentServices
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-I5EWBI42.js";
|
|
4
|
+
|
|
5
|
+
// src/contract.ts
|
|
6
|
+
import { isContractProcedure as isContractProcedure2 } from "@orpc/contract";
|
|
7
|
+
import { implement } from "@orpc/server";
|
|
4
8
|
|
|
5
9
|
// src/effect-builder.ts
|
|
6
|
-
import {
|
|
7
|
-
mergeMeta as mergeMeta2,
|
|
8
|
-
mergePrefix as mergePrefix2,
|
|
9
|
-
mergeRoute as mergeRoute2,
|
|
10
|
-
mergeTags,
|
|
11
|
-
ORPCError as ORPCError2
|
|
12
|
-
} from "@orpc/contract";
|
|
10
|
+
import { mergeMeta as mergeMeta2, mergePrefix as mergePrefix2, mergeRoute as mergeRoute2, mergeTags } from "@orpc/contract";
|
|
13
11
|
import {
|
|
14
12
|
addMiddleware as addMiddleware2,
|
|
15
13
|
Builder,
|
|
@@ -17,13 +15,6 @@ import {
|
|
|
17
15
|
fallbackConfig,
|
|
18
16
|
lazy as lazy2
|
|
19
17
|
} from "@orpc/server";
|
|
20
|
-
import {
|
|
21
|
-
Cause as Cause2,
|
|
22
|
-
Effect,
|
|
23
|
-
Exit,
|
|
24
|
-
Result,
|
|
25
|
-
ServiceMap
|
|
26
|
-
} from "effect";
|
|
27
18
|
|
|
28
19
|
// src/effect-enhance-router.ts
|
|
29
20
|
import {
|
|
@@ -329,27 +320,9 @@ function enhanceEffectRouter(router, options) {
|
|
|
329
320
|
return enhanced;
|
|
330
321
|
}
|
|
331
322
|
|
|
332
|
-
// src/effect-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const limit = ErrorConstructor.stackTraceLimit;
|
|
336
|
-
ErrorConstructor.stackTraceLimit = 3;
|
|
337
|
-
const traceError = new Error();
|
|
338
|
-
ErrorConstructor.stackTraceLimit = limit;
|
|
339
|
-
let cache = false;
|
|
340
|
-
return () => {
|
|
341
|
-
if (cache !== false) {
|
|
342
|
-
return cache;
|
|
343
|
-
}
|
|
344
|
-
if (traceError.stack !== void 0) {
|
|
345
|
-
const stack = traceError.stack.split("\n");
|
|
346
|
-
if (stack[3] !== void 0) {
|
|
347
|
-
cache = stack[3].trim();
|
|
348
|
-
return cache;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
}
|
|
323
|
+
// src/effect-runtime.ts
|
|
324
|
+
import { ORPCError as ORPCError2 } from "@orpc/contract";
|
|
325
|
+
import { Cause as Cause2, Effect, Exit, Result, Context } from "effect";
|
|
353
326
|
function toORPCErrorFromCause(cause) {
|
|
354
327
|
if (Cause2.hasFails(cause)) {
|
|
355
328
|
const reason = Cause2.findFail(cause);
|
|
@@ -391,6 +364,66 @@ function toORPCErrorFromCause(cause) {
|
|
|
391
364
|
}
|
|
392
365
|
return new ORPCError2("INTERNAL_SERVER_ERROR");
|
|
393
366
|
}
|
|
367
|
+
function createEffectProcedureHandler(options) {
|
|
368
|
+
const {
|
|
369
|
+
runtime,
|
|
370
|
+
effectErrorMap,
|
|
371
|
+
effectFn,
|
|
372
|
+
spanConfig,
|
|
373
|
+
defaultCaptureStackTrace
|
|
374
|
+
} = options;
|
|
375
|
+
return async (opts) => {
|
|
376
|
+
const effectOpts = {
|
|
377
|
+
context: opts.context,
|
|
378
|
+
input: opts.input,
|
|
379
|
+
path: opts.path,
|
|
380
|
+
procedure: opts.procedure,
|
|
381
|
+
signal: opts.signal,
|
|
382
|
+
lastEventId: opts.lastEventId,
|
|
383
|
+
errors: createEffectErrorConstructorMap(effectErrorMap)
|
|
384
|
+
};
|
|
385
|
+
const spanName = spanConfig?.name ?? opts.path.join(".");
|
|
386
|
+
const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
|
|
387
|
+
const resolver = Effect.fnUntraced(effectFn);
|
|
388
|
+
const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {
|
|
389
|
+
captureStackTrace
|
|
390
|
+
});
|
|
391
|
+
const parentServices = getCurrentServices();
|
|
392
|
+
const exit = parentServices ? await Effect.runPromiseExitWith(
|
|
393
|
+
Context.merge(await runtime.context(), parentServices)
|
|
394
|
+
)(tracedEffect, {
|
|
395
|
+
signal: opts.signal
|
|
396
|
+
}) : await runtime.runPromiseExit(tracedEffect, {
|
|
397
|
+
signal: opts.signal
|
|
398
|
+
});
|
|
399
|
+
if (Exit.isFailure(exit)) {
|
|
400
|
+
throw toORPCErrorFromCause(exit.cause);
|
|
401
|
+
}
|
|
402
|
+
return exit.value;
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// src/effect-builder.ts
|
|
407
|
+
function addSpanStackTrace() {
|
|
408
|
+
const ErrorConstructor = Error;
|
|
409
|
+
const limit = ErrorConstructor.stackTraceLimit;
|
|
410
|
+
ErrorConstructor.stackTraceLimit = 3;
|
|
411
|
+
const traceError = new Error();
|
|
412
|
+
ErrorConstructor.stackTraceLimit = limit;
|
|
413
|
+
let cache = false;
|
|
414
|
+
return () => {
|
|
415
|
+
if (cache !== false) {
|
|
416
|
+
return cache;
|
|
417
|
+
}
|
|
418
|
+
if (traceError.stack !== void 0) {
|
|
419
|
+
const stack = traceError.stack.split("\n");
|
|
420
|
+
if (stack[3] !== void 0) {
|
|
421
|
+
cache = stack[3].trim();
|
|
422
|
+
return cache;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
394
427
|
var EffectBuilder = class _EffectBuilder {
|
|
395
428
|
constructor(def) {
|
|
396
429
|
const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
|
|
@@ -483,6 +516,14 @@ var EffectBuilder = class _EffectBuilder {
|
|
|
483
516
|
inputSchema: initialInputSchema
|
|
484
517
|
});
|
|
485
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Creates a middleware.
|
|
521
|
+
*
|
|
522
|
+
* @see {@link https://orpc.dev/docs/middleware Middleware Docs}
|
|
523
|
+
*/
|
|
524
|
+
middleware(middleware) {
|
|
525
|
+
return decorateMiddleware2(middleware);
|
|
526
|
+
}
|
|
486
527
|
/**
|
|
487
528
|
* Adds type-safe custom errors.
|
|
488
529
|
* Supports both traditional oRPC error definitions and ORPCTaggedError classes.
|
|
@@ -630,35 +671,13 @@ var EffectBuilder = class _EffectBuilder {
|
|
|
630
671
|
return new EffectDecoratedProcedure({
|
|
631
672
|
...this["~effect"],
|
|
632
673
|
handler: async (opts) => {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
errors: createEffectErrorConstructorMap(
|
|
641
|
-
this["~effect"].effectErrorMap
|
|
642
|
-
)
|
|
643
|
-
};
|
|
644
|
-
const spanName = spanConfig?.name ?? opts.path.join(".");
|
|
645
|
-
const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
|
|
646
|
-
const resolver = Effect.fnUntraced(effectFn);
|
|
647
|
-
const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {
|
|
648
|
-
captureStackTrace
|
|
649
|
-
});
|
|
650
|
-
const parentServices = getCurrentServices();
|
|
651
|
-
const exit = parentServices ? await Effect.runPromiseExitWith(
|
|
652
|
-
ServiceMap.merge(await runtime.services(), parentServices)
|
|
653
|
-
)(tracedEffect, {
|
|
654
|
-
signal: opts.signal
|
|
655
|
-
}) : await runtime.runPromiseExit(tracedEffect, {
|
|
656
|
-
signal: opts.signal
|
|
657
|
-
});
|
|
658
|
-
if (Exit.isFailure(exit)) {
|
|
659
|
-
throw toORPCErrorFromCause(exit.cause);
|
|
660
|
-
}
|
|
661
|
-
return exit.value;
|
|
674
|
+
return createEffectProcedureHandler({
|
|
675
|
+
runtime,
|
|
676
|
+
effectErrorMap: this["~effect"].effectErrorMap,
|
|
677
|
+
effectFn,
|
|
678
|
+
spanConfig,
|
|
679
|
+
defaultCaptureStackTrace
|
|
680
|
+
})(opts);
|
|
662
681
|
}
|
|
663
682
|
});
|
|
664
683
|
}
|
|
@@ -731,6 +750,256 @@ function emptyBuilder() {
|
|
|
731
750
|
dedupeLeadingMiddlewares: true
|
|
732
751
|
});
|
|
733
752
|
}
|
|
753
|
+
|
|
754
|
+
// src/eoc.ts
|
|
755
|
+
import { isContractProcedure, oc } from "@orpc/contract";
|
|
756
|
+
var effectContractSymbol = /* @__PURE__ */ Symbol.for(
|
|
757
|
+
"@orpc/effect/contract"
|
|
758
|
+
);
|
|
759
|
+
function isWrappableContractBuilder(value) {
|
|
760
|
+
return typeof value === "object" && value !== null && "~orpc" in value;
|
|
761
|
+
}
|
|
762
|
+
function mergeEffectErrorMaps(left, right) {
|
|
763
|
+
if (!left) {
|
|
764
|
+
return right;
|
|
765
|
+
}
|
|
766
|
+
if (!right) {
|
|
767
|
+
return left;
|
|
768
|
+
}
|
|
769
|
+
return {
|
|
770
|
+
...left,
|
|
771
|
+
...right
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
function setEffectContractErrorMap(value, effectErrorMap) {
|
|
775
|
+
if (!effectErrorMap) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
Object.defineProperty(value, effectContractSymbol, {
|
|
779
|
+
value: { errorMap: effectErrorMap },
|
|
780
|
+
enumerable: false,
|
|
781
|
+
configurable: true
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
function getEffectContractErrorMap(value) {
|
|
785
|
+
if (typeof value !== "object" || value === null) {
|
|
786
|
+
return void 0;
|
|
787
|
+
}
|
|
788
|
+
return value[effectContractSymbol]?.errorMap;
|
|
789
|
+
}
|
|
790
|
+
function applyEffectContractErrorMapToRouter(router, source, inheritedEffectErrorMap) {
|
|
791
|
+
const routerRecord = router;
|
|
792
|
+
const sourceRecord = source;
|
|
793
|
+
for (const key of Object.keys(routerRecord)) {
|
|
794
|
+
const routerValue = routerRecord[key];
|
|
795
|
+
const sourceValue = sourceRecord && typeof sourceRecord === "object" ? sourceRecord[key] : void 0;
|
|
796
|
+
if (!routerValue) {
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
if (isContractProcedure(routerValue)) {
|
|
800
|
+
const sourceEffectErrorMap = getEffectContractErrorMap(sourceValue);
|
|
801
|
+
setEffectContractErrorMap(
|
|
802
|
+
routerValue,
|
|
803
|
+
mergeEffectErrorMaps(inheritedEffectErrorMap, sourceEffectErrorMap)
|
|
804
|
+
);
|
|
805
|
+
continue;
|
|
806
|
+
}
|
|
807
|
+
if (typeof routerValue === "object") {
|
|
808
|
+
applyEffectContractErrorMapToRouter(
|
|
809
|
+
routerValue,
|
|
810
|
+
sourceValue,
|
|
811
|
+
inheritedEffectErrorMap
|
|
812
|
+
);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function wrapEffectContractBuilder(builder, inheritedEffectErrorMap) {
|
|
817
|
+
const currentEffectErrorMap = inheritedEffectErrorMap ?? getEffectContractErrorMap(builder);
|
|
818
|
+
if (typeof builder === "object" && builder !== null) {
|
|
819
|
+
setEffectContractErrorMap(builder, currentEffectErrorMap);
|
|
820
|
+
}
|
|
821
|
+
const proxy = new Proxy(builder, {
|
|
822
|
+
get(target, prop, receiver) {
|
|
823
|
+
if (prop === effectContractSymbol) {
|
|
824
|
+
return currentEffectErrorMap ? { errorMap: currentEffectErrorMap } : void 0;
|
|
825
|
+
}
|
|
826
|
+
if (prop === "errors") {
|
|
827
|
+
return (errors) => {
|
|
828
|
+
const nextEffectErrorMap = mergeEffectErrorMaps(
|
|
829
|
+
currentEffectErrorMap,
|
|
830
|
+
errors
|
|
831
|
+
);
|
|
832
|
+
return wrapEffectContractBuilder(
|
|
833
|
+
Reflect.apply(Reflect.get(target, prop, receiver), target, [
|
|
834
|
+
effectErrorMapToErrorMap(errors)
|
|
835
|
+
]),
|
|
836
|
+
nextEffectErrorMap
|
|
837
|
+
);
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
if (prop === "router") {
|
|
841
|
+
return (router) => {
|
|
842
|
+
const result = Reflect.apply(
|
|
843
|
+
Reflect.get(target, prop, receiver),
|
|
844
|
+
target,
|
|
845
|
+
[router]
|
|
846
|
+
);
|
|
847
|
+
applyEffectContractErrorMapToRouter(
|
|
848
|
+
result,
|
|
849
|
+
router,
|
|
850
|
+
currentEffectErrorMap
|
|
851
|
+
);
|
|
852
|
+
return result;
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const value = Reflect.get(target, prop, receiver);
|
|
856
|
+
if (typeof value !== "function") {
|
|
857
|
+
return value;
|
|
858
|
+
}
|
|
859
|
+
return (...args) => {
|
|
860
|
+
const result = Reflect.apply(value, target, args);
|
|
861
|
+
return isWrappableContractBuilder(result) ? wrapEffectContractBuilder(result, currentEffectErrorMap) : result;
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
setEffectContractErrorMap(proxy, currentEffectErrorMap);
|
|
866
|
+
return proxy;
|
|
867
|
+
}
|
|
868
|
+
var eoc = wrapEffectContractBuilder(
|
|
869
|
+
oc,
|
|
870
|
+
{}
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
// src/contract.ts
|
|
874
|
+
var CONTRACT_HIDDEN_METHODS = /* @__PURE__ */ new Set([
|
|
875
|
+
"$config",
|
|
876
|
+
"$context",
|
|
877
|
+
"$input",
|
|
878
|
+
"$meta",
|
|
879
|
+
"$route",
|
|
880
|
+
"errors",
|
|
881
|
+
"input",
|
|
882
|
+
"lazy",
|
|
883
|
+
"meta",
|
|
884
|
+
"middleware",
|
|
885
|
+
"output",
|
|
886
|
+
"prefix",
|
|
887
|
+
"route",
|
|
888
|
+
"router",
|
|
889
|
+
"tag"
|
|
890
|
+
]);
|
|
891
|
+
function makeEnhanceOptions(runtime) {
|
|
892
|
+
return {
|
|
893
|
+
middlewares: [],
|
|
894
|
+
errorMap: {},
|
|
895
|
+
dedupeLeadingMiddlewares: true,
|
|
896
|
+
runtime
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function wrapContractNode(contract, target, runtime) {
|
|
900
|
+
const cache = /* @__PURE__ */ new Map();
|
|
901
|
+
return new Proxy(target, {
|
|
902
|
+
get(currentTarget, prop, receiver) {
|
|
903
|
+
if (cache.has(prop)) {
|
|
904
|
+
return cache.get(prop);
|
|
905
|
+
}
|
|
906
|
+
if (isContractProcedure2(contract)) {
|
|
907
|
+
if (prop === "effect") {
|
|
908
|
+
const effect = (effectFn) => {
|
|
909
|
+
const effectErrorMap = getEffectContractErrorMap(contract) ?? currentTarget["~orpc"].errorMap;
|
|
910
|
+
return new EffectDecoratedProcedure({
|
|
911
|
+
...currentTarget["~orpc"],
|
|
912
|
+
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
913
|
+
effectErrorMap,
|
|
914
|
+
runtime,
|
|
915
|
+
handler: createEffectProcedureHandler({
|
|
916
|
+
runtime,
|
|
917
|
+
effectErrorMap,
|
|
918
|
+
effectFn,
|
|
919
|
+
defaultCaptureStackTrace: addSpanStackTrace()
|
|
920
|
+
})
|
|
921
|
+
});
|
|
922
|
+
};
|
|
923
|
+
cache.set(prop, effect);
|
|
924
|
+
return effect;
|
|
925
|
+
}
|
|
926
|
+
if (prop === "use") {
|
|
927
|
+
const use = (...args) => wrapContractNode(
|
|
928
|
+
contract,
|
|
929
|
+
Reflect.apply(
|
|
930
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
931
|
+
currentTarget,
|
|
932
|
+
args
|
|
933
|
+
),
|
|
934
|
+
runtime
|
|
935
|
+
);
|
|
936
|
+
cache.set(prop, use);
|
|
937
|
+
return use;
|
|
938
|
+
}
|
|
939
|
+
if (CONTRACT_HIDDEN_METHODS.has(String(prop))) {
|
|
940
|
+
return void 0;
|
|
941
|
+
}
|
|
942
|
+
} else {
|
|
943
|
+
if (prop === "$context" || prop === "$config" || prop === "use") {
|
|
944
|
+
const wrappedMethod = (...args) => wrapContractNode(
|
|
945
|
+
contract,
|
|
946
|
+
Reflect.apply(
|
|
947
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
948
|
+
currentTarget,
|
|
949
|
+
args
|
|
950
|
+
),
|
|
951
|
+
runtime
|
|
952
|
+
);
|
|
953
|
+
cache.set(prop, wrappedMethod);
|
|
954
|
+
return wrappedMethod;
|
|
955
|
+
}
|
|
956
|
+
if (prop === "router" || prop === "lazy") {
|
|
957
|
+
const wrappedMethod = (...args) => enhanceEffectRouter(
|
|
958
|
+
Reflect.apply(
|
|
959
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
960
|
+
currentTarget,
|
|
961
|
+
args
|
|
962
|
+
),
|
|
963
|
+
makeEnhanceOptions(runtime)
|
|
964
|
+
);
|
|
965
|
+
cache.set(prop, wrappedMethod);
|
|
966
|
+
return wrappedMethod;
|
|
967
|
+
}
|
|
968
|
+
if (typeof prop === "string" && prop in contract) {
|
|
969
|
+
const child = wrapContractNode(
|
|
970
|
+
contract[prop],
|
|
971
|
+
Reflect.get(currentTarget, prop, receiver),
|
|
972
|
+
runtime
|
|
973
|
+
);
|
|
974
|
+
cache.set(prop, child);
|
|
975
|
+
return child;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
const value = Reflect.get(currentTarget, prop, receiver);
|
|
979
|
+
return typeof value === "function" ? value.bind(currentTarget) : value;
|
|
980
|
+
},
|
|
981
|
+
has(currentTarget, prop) {
|
|
982
|
+
if (isContractProcedure2(contract)) {
|
|
983
|
+
if (prop === "effect") {
|
|
984
|
+
return true;
|
|
985
|
+
}
|
|
986
|
+
if (CONTRACT_HIDDEN_METHODS.has(String(prop))) {
|
|
987
|
+
return false;
|
|
988
|
+
}
|
|
989
|
+
} else if (typeof prop === "string" && prop in contract) {
|
|
990
|
+
return true;
|
|
991
|
+
}
|
|
992
|
+
return Reflect.has(currentTarget, prop);
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
function implementEffect(contract, runtime) {
|
|
997
|
+
return wrapContractNode(
|
|
998
|
+
contract,
|
|
999
|
+
implement(contract),
|
|
1000
|
+
runtime
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
734
1003
|
export {
|
|
735
1004
|
EffectBuilder,
|
|
736
1005
|
EffectDecoratedProcedure,
|
|
@@ -739,6 +1008,8 @@ export {
|
|
|
739
1008
|
addSpanStackTrace,
|
|
740
1009
|
createEffectErrorConstructorMap,
|
|
741
1010
|
effectErrorMapToErrorMap,
|
|
1011
|
+
eoc,
|
|
1012
|
+
implementEffect,
|
|
742
1013
|
isORPCTaggedError,
|
|
743
1014
|
isORPCTaggedErrorClass,
|
|
744
1015
|
makeEffectORPC,
|