effect-orpc 0.1.4 → 0.2.1
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 +95 -0
- package/dist/index.js +806 -476
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/contract.ts +491 -0
- package/src/effect-builder.ts +349 -619
- package/src/effect-enhance-router.ts +20 -21
- package/src/effect-procedure.ts +274 -263
- package/src/effect-runtime.ts +134 -0
- package/src/eoc.ts +499 -0
- package/src/extension/compose-surfaces.ts +15 -0
- package/src/extension/create-node-proxy.ts +270 -0
- package/src/extension/state.ts +108 -0
- package/src/index.ts +20 -3
- package/src/tagged-error.ts +24 -4
- package/src/tests/contract.test.ts +346 -0
- package/src/tests/effect-builder.proxy.test.ts +253 -0
- 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 +210 -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/effect-builder-surface.ts +441 -0
- package/src/types/effect-procedure-surface.ts +243 -0
- package/src/types/index.ts +22 -26
- package/src/types/variants.ts +100 -16
package/dist/index.js
CHANGED
|
@@ -2,22 +2,12 @@ import {
|
|
|
2
2
|
getCurrentFiberRefs
|
|
3
3
|
} from "./chunk-VOWRLWZZ.js";
|
|
4
4
|
|
|
5
|
+
// src/contract.ts
|
|
6
|
+
import { isContractProcedure as isContractProcedure2 } from "@orpc/contract";
|
|
7
|
+
import { implement } from "@orpc/server";
|
|
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";
|
|
13
|
-
import {
|
|
14
|
-
addMiddleware as addMiddleware2,
|
|
15
|
-
Builder,
|
|
16
|
-
decorateMiddleware as decorateMiddleware2,
|
|
17
|
-
fallbackConfig,
|
|
18
|
-
lazy as lazy2
|
|
19
|
-
} from "@orpc/server";
|
|
20
|
-
import { Cause as Cause2, Effect, Exit, FiberRefs } from "effect";
|
|
10
|
+
import { Builder, fallbackConfig, lazy as lazy2 } from "@orpc/server";
|
|
21
11
|
|
|
22
12
|
// src/effect-enhance-router.ts
|
|
23
13
|
import {
|
|
@@ -44,6 +34,177 @@ import {
|
|
|
44
34
|
Procedure
|
|
45
35
|
} from "@orpc/server";
|
|
46
36
|
|
|
37
|
+
// src/extension/compose-surfaces.ts
|
|
38
|
+
function composeSurfaceProxy(surface, target) {
|
|
39
|
+
return new Proxy(target, {
|
|
40
|
+
get(currentTarget, prop, receiver) {
|
|
41
|
+
return Reflect.has(surface, prop) ? Reflect.get(surface, prop, surface) : Reflect.get(currentTarget, prop, receiver);
|
|
42
|
+
},
|
|
43
|
+
has(currentTarget, prop) {
|
|
44
|
+
return Reflect.has(surface, prop) || Reflect.has(currentTarget, prop);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/extension/state.ts
|
|
50
|
+
var effectInternalsSymbol = /* @__PURE__ */ Symbol("effect-orpc/internals");
|
|
51
|
+
function attachEffectState(target, upstream, state) {
|
|
52
|
+
Object.defineProperties(target, {
|
|
53
|
+
[effectInternalsSymbol]: {
|
|
54
|
+
configurable: true,
|
|
55
|
+
value: {
|
|
56
|
+
methodCache: /* @__PURE__ */ new Map(),
|
|
57
|
+
state,
|
|
58
|
+
upstream
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function getEffectInternals(target) {
|
|
64
|
+
return target[effectInternalsSymbol];
|
|
65
|
+
}
|
|
66
|
+
function getEffectUpstream(target) {
|
|
67
|
+
return getEffectInternals(target).upstream;
|
|
68
|
+
}
|
|
69
|
+
function hasEffectState(value) {
|
|
70
|
+
return typeof value === "object" && value !== null && effectInternalsSymbol in value;
|
|
71
|
+
}
|
|
72
|
+
function assertEffectState(value) {
|
|
73
|
+
if (!hasEffectState(value)) {
|
|
74
|
+
throw new Error("Expected effect state to be attached");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function getEffectErrorMap(value) {
|
|
78
|
+
return value["~effect"]?.effectErrorMap ?? value["~orpc"].errorMap;
|
|
79
|
+
}
|
|
80
|
+
function unwrapEffectUpstream(value) {
|
|
81
|
+
return hasEffectState(value) ? getEffectUpstream(value) : value;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/extension/create-node-proxy.ts
|
|
85
|
+
var unhandledProperty = /* @__PURE__ */ Symbol("effect-orpc/unhandledProperty");
|
|
86
|
+
function createNodeProxyContext(target) {
|
|
87
|
+
const internals = getEffectInternals(target);
|
|
88
|
+
return {
|
|
89
|
+
methodCache: internals.methodCache,
|
|
90
|
+
state: internals.state,
|
|
91
|
+
target,
|
|
92
|
+
upstream: internals.upstream
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function createBoundMethod(context, prop, value, config, receiver) {
|
|
96
|
+
const cache = context.methodCache;
|
|
97
|
+
if (cache.has(prop)) {
|
|
98
|
+
return cache.get(prop);
|
|
99
|
+
}
|
|
100
|
+
const wrapped = (...args) => {
|
|
101
|
+
const result = Reflect.apply(value, context.upstream, args);
|
|
102
|
+
return config.wrapResult?.(context, prop, result, receiver) ?? result;
|
|
103
|
+
};
|
|
104
|
+
cache.set(prop, wrapped);
|
|
105
|
+
return wrapped;
|
|
106
|
+
}
|
|
107
|
+
function createNodeProxy(target, config) {
|
|
108
|
+
const privateKeys = /* @__PURE__ */ new Set([effectInternalsSymbol]);
|
|
109
|
+
const virtualKeys = new Set(config.virtualKeys ?? []);
|
|
110
|
+
return new Proxy(target, {
|
|
111
|
+
get(currentTarget, prop, receiver) {
|
|
112
|
+
if (privateKeys.has(prop)) {
|
|
113
|
+
return Reflect.get(currentTarget, prop, receiver);
|
|
114
|
+
}
|
|
115
|
+
const context = createNodeProxyContext(
|
|
116
|
+
currentTarget
|
|
117
|
+
);
|
|
118
|
+
const virtualValue = config.getVirtual?.(context, prop, receiver);
|
|
119
|
+
if (virtualValue !== void 0 && virtualValue !== unhandledProperty) {
|
|
120
|
+
return virtualValue;
|
|
121
|
+
}
|
|
122
|
+
const propertyValue = config.getProperty?.(context, prop, receiver);
|
|
123
|
+
if (propertyValue !== void 0 && propertyValue !== unhandledProperty) {
|
|
124
|
+
return propertyValue;
|
|
125
|
+
}
|
|
126
|
+
const sourceValue = Reflect.get(context.upstream, prop, context.upstream);
|
|
127
|
+
if (Reflect.has(context.upstream, prop)) {
|
|
128
|
+
if (typeof sourceValue === "function") {
|
|
129
|
+
return createBoundMethod(
|
|
130
|
+
context,
|
|
131
|
+
prop,
|
|
132
|
+
sourceValue,
|
|
133
|
+
config,
|
|
134
|
+
receiver
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return sourceValue;
|
|
138
|
+
}
|
|
139
|
+
return Reflect.get(currentTarget, prop, receiver);
|
|
140
|
+
},
|
|
141
|
+
has(currentTarget, prop) {
|
|
142
|
+
if (virtualKeys.has(prop)) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
const context = createNodeProxyContext(currentTarget);
|
|
146
|
+
return Reflect.has(context.upstream, prop) || Reflect.has(currentTarget, prop);
|
|
147
|
+
},
|
|
148
|
+
ownKeys(currentTarget) {
|
|
149
|
+
const keys = /* @__PURE__ */ new Set();
|
|
150
|
+
for (const key of Reflect.ownKeys(currentTarget)) {
|
|
151
|
+
if (!privateKeys.has(key)) {
|
|
152
|
+
keys.add(key);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const context = createNodeProxyContext(
|
|
156
|
+
currentTarget
|
|
157
|
+
);
|
|
158
|
+
for (const key of Reflect.ownKeys(context.upstream)) {
|
|
159
|
+
keys.add(key);
|
|
160
|
+
}
|
|
161
|
+
for (const key of virtualKeys) {
|
|
162
|
+
keys.add(key);
|
|
163
|
+
}
|
|
164
|
+
return [...keys];
|
|
165
|
+
},
|
|
166
|
+
getOwnPropertyDescriptor(currentTarget, prop) {
|
|
167
|
+
const context = createNodeProxyContext(
|
|
168
|
+
currentTarget
|
|
169
|
+
);
|
|
170
|
+
if (virtualKeys.has(prop)) {
|
|
171
|
+
const value = config.getVirtual?.(context, prop, currentTarget);
|
|
172
|
+
if (value !== void 0 && value !== unhandledProperty) {
|
|
173
|
+
return {
|
|
174
|
+
configurable: true,
|
|
175
|
+
enumerable: config.virtualDescriptors?.[prop]?.enumerable ?? false,
|
|
176
|
+
value,
|
|
177
|
+
writable: false
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(
|
|
182
|
+
context.upstream,
|
|
183
|
+
prop
|
|
184
|
+
);
|
|
185
|
+
if (descriptor === void 0) {
|
|
186
|
+
return Reflect.getOwnPropertyDescriptor(currentTarget, prop);
|
|
187
|
+
}
|
|
188
|
+
if ("value" in descriptor && typeof descriptor.value === "function") {
|
|
189
|
+
return {
|
|
190
|
+
...descriptor,
|
|
191
|
+
value: createBoundMethod(
|
|
192
|
+
context,
|
|
193
|
+
prop,
|
|
194
|
+
descriptor.value,
|
|
195
|
+
config,
|
|
196
|
+
currentTarget
|
|
197
|
+
)
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return descriptor;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function unhandled() {
|
|
205
|
+
return unhandledProperty;
|
|
206
|
+
}
|
|
207
|
+
|
|
47
208
|
// src/tagged-error.ts
|
|
48
209
|
import {
|
|
49
210
|
fallbackORPCErrorMessage,
|
|
@@ -178,98 +339,141 @@ function effectErrorMapToErrorMap(errorMap) {
|
|
|
178
339
|
}
|
|
179
340
|
|
|
180
341
|
// src/effect-procedure.ts
|
|
181
|
-
var
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
342
|
+
var procedureVirtualDescriptors = {
|
|
343
|
+
"~effect": { enumerable: true },
|
|
344
|
+
actionable: { enumerable: false },
|
|
345
|
+
callable: { enumerable: false },
|
|
346
|
+
errors: { enumerable: false },
|
|
347
|
+
meta: { enumerable: false },
|
|
348
|
+
route: { enumerable: false },
|
|
349
|
+
use: { enumerable: false }
|
|
186
350
|
};
|
|
187
|
-
var
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
351
|
+
var baseProcedureVirtualKeys = ["~effect"];
|
|
352
|
+
var decoratedProcedureVirtualKeys = [
|
|
353
|
+
...baseProcedureVirtualKeys,
|
|
354
|
+
"errors",
|
|
355
|
+
"meta",
|
|
356
|
+
"route",
|
|
357
|
+
"use",
|
|
358
|
+
"callable",
|
|
359
|
+
"actionable"
|
|
360
|
+
];
|
|
361
|
+
function getOrCreateVirtualMethod(context, prop, factory) {
|
|
362
|
+
const cache = context.methodCache;
|
|
363
|
+
if (cache.has(prop)) {
|
|
364
|
+
return cache.get(prop);
|
|
191
365
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Sets or updates the metadata.
|
|
211
|
-
* The provided metadata is spared-merged with any existing metadata.
|
|
212
|
-
*
|
|
213
|
-
* @see {@link https://orpc.dev/docs/metadata Metadata Docs}
|
|
214
|
-
*/
|
|
215
|
-
meta(meta) {
|
|
216
|
-
return new _EffectDecoratedProcedure({
|
|
217
|
-
...this["~effect"],
|
|
218
|
-
meta: mergeMeta(this["~effect"].meta, meta)
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Sets or updates the route definition.
|
|
223
|
-
* The provided route is spared-merged with any existing route.
|
|
224
|
-
* This option is typically relevant when integrating with OpenAPI.
|
|
225
|
-
*
|
|
226
|
-
* @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
|
|
227
|
-
* @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
|
|
228
|
-
*/
|
|
229
|
-
route(route) {
|
|
230
|
-
return new _EffectDecoratedProcedure({
|
|
231
|
-
...this["~effect"],
|
|
232
|
-
route: mergeRoute(this["~effect"].route, route)
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
use(middleware, mapInput) {
|
|
236
|
-
const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
|
|
237
|
-
return new _EffectDecoratedProcedure({
|
|
238
|
-
...this["~effect"],
|
|
239
|
-
middlewares: addMiddleware(this["~effect"].middlewares, mapped)
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Make this procedure callable (works like a function while still being a procedure).
|
|
244
|
-
*
|
|
245
|
-
* @see {@link https://orpc.dev/docs/client/server-side Server-side Client Docs}
|
|
246
|
-
*/
|
|
247
|
-
callable(...rest) {
|
|
248
|
-
const client = createProcedureClient(this, ...rest);
|
|
249
|
-
return new Proxy(client, {
|
|
250
|
-
get: (target, key) => {
|
|
251
|
-
return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
|
|
252
|
-
},
|
|
253
|
-
has: (target, key) => {
|
|
254
|
-
return Reflect.has(this, key) || Reflect.has(target, key);
|
|
366
|
+
const value = factory();
|
|
367
|
+
cache.set(prop, value);
|
|
368
|
+
return value;
|
|
369
|
+
}
|
|
370
|
+
function getEffectProcedureDef(context) {
|
|
371
|
+
return {
|
|
372
|
+
...context.upstream["~orpc"],
|
|
373
|
+
effectErrorMap: context.state.effectErrorMap,
|
|
374
|
+
runtime: context.state.runtime
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function createEffectProcedureProxy(target, decorated) {
|
|
378
|
+
return createNodeProxy(target, {
|
|
379
|
+
getVirtual(context, prop, receiver) {
|
|
380
|
+
if (prop === "~effect") {
|
|
381
|
+
return getEffectProcedureDef(context);
|
|
255
382
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Make this procedure compatible with server action.
|
|
260
|
-
*
|
|
261
|
-
* @see {@link https://orpc.dev/docs/server-action Server Action Docs}
|
|
262
|
-
*/
|
|
263
|
-
actionable(...rest) {
|
|
264
|
-
const action = createActionableClient(createProcedureClient(this, ...rest));
|
|
265
|
-
return new Proxy(action, {
|
|
266
|
-
get: (target, key) => {
|
|
267
|
-
return Reflect.has(this, key) ? Reflect.get(this, key) : Reflect.get(target, key);
|
|
268
|
-
},
|
|
269
|
-
has: (target, key) => {
|
|
270
|
-
return Reflect.has(this, key) || Reflect.has(target, key);
|
|
383
|
+
if (!decorated) {
|
|
384
|
+
return unhandled();
|
|
271
385
|
}
|
|
386
|
+
const state = context.state;
|
|
387
|
+
switch (prop) {
|
|
388
|
+
case "errors":
|
|
389
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
390
|
+
return (errors) => {
|
|
391
|
+
const nextEffectErrorMap = {
|
|
392
|
+
...state.effectErrorMap,
|
|
393
|
+
...errors
|
|
394
|
+
};
|
|
395
|
+
return new EffectDecoratedProcedure({
|
|
396
|
+
...getEffectProcedureDef(context),
|
|
397
|
+
effectErrorMap: nextEffectErrorMap,
|
|
398
|
+
errorMap: effectErrorMapToErrorMap(nextEffectErrorMap)
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
case "meta":
|
|
403
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
404
|
+
return (meta) => new EffectDecoratedProcedure({
|
|
405
|
+
...getEffectProcedureDef(context),
|
|
406
|
+
meta: mergeMeta(getEffectProcedureDef(context).meta, meta)
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
case "route":
|
|
410
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
411
|
+
return (route) => new EffectDecoratedProcedure({
|
|
412
|
+
...getEffectProcedureDef(context),
|
|
413
|
+
route: mergeRoute(getEffectProcedureDef(context).route, route)
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
case "use":
|
|
417
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
418
|
+
return (middleware, mapInput) => {
|
|
419
|
+
const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
|
|
420
|
+
return new EffectDecoratedProcedure({
|
|
421
|
+
...getEffectProcedureDef(context),
|
|
422
|
+
middlewares: addMiddleware(
|
|
423
|
+
getEffectProcedureDef(context).middlewares,
|
|
424
|
+
mapped
|
|
425
|
+
)
|
|
426
|
+
});
|
|
427
|
+
};
|
|
428
|
+
});
|
|
429
|
+
case "callable":
|
|
430
|
+
return (...rest) => {
|
|
431
|
+
const client = createProcedureClient(
|
|
432
|
+
receiver,
|
|
433
|
+
...rest
|
|
434
|
+
);
|
|
435
|
+
return composeSurfaceProxy(
|
|
436
|
+
receiver,
|
|
437
|
+
client
|
|
438
|
+
);
|
|
439
|
+
};
|
|
440
|
+
case "actionable":
|
|
441
|
+
return (...rest) => {
|
|
442
|
+
const client = createProcedureClient(
|
|
443
|
+
receiver,
|
|
444
|
+
...rest
|
|
445
|
+
);
|
|
446
|
+
const action = createActionableClient(client);
|
|
447
|
+
return composeSurfaceProxy(
|
|
448
|
+
receiver,
|
|
449
|
+
action
|
|
450
|
+
);
|
|
451
|
+
};
|
|
452
|
+
default:
|
|
453
|
+
return unhandled();
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
virtualDescriptors: procedureVirtualDescriptors,
|
|
457
|
+
virtualKeys: decorated ? decoratedProcedureVirtualKeys : baseProcedureVirtualKeys
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
var EffectProcedure = class _EffectProcedure extends Procedure {
|
|
461
|
+
constructor(def, procedure) {
|
|
462
|
+
super(def);
|
|
463
|
+
attachEffectState(this, procedure ?? new Procedure(def), {
|
|
464
|
+
effectErrorMap: def.effectErrorMap,
|
|
465
|
+
runtime: def.runtime
|
|
272
466
|
});
|
|
467
|
+
if (new.target === _EffectProcedure) {
|
|
468
|
+
return createEffectProcedureProxy(this, false);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
var EffectDecoratedProcedure = class extends EffectProcedure {
|
|
473
|
+
constructor(def, procedure) {
|
|
474
|
+
super(def, procedure);
|
|
475
|
+
assertEffectState(this);
|
|
476
|
+
return createEffectProcedureProxy(this, true);
|
|
273
477
|
}
|
|
274
478
|
};
|
|
275
479
|
|
|
@@ -277,44 +481,44 @@ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends EffectPro
|
|
|
277
481
|
function enhanceEffectRouter(router, options) {
|
|
278
482
|
if (isLazy(router)) {
|
|
279
483
|
const laziedMeta = getLazyMeta(router);
|
|
280
|
-
const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta
|
|
484
|
+
const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta.prefix) : options.prefix;
|
|
281
485
|
const enhanced2 = lazy(
|
|
282
486
|
async () => {
|
|
283
487
|
const { default: unlaziedRouter } = await unlazy(router);
|
|
284
|
-
const
|
|
285
|
-
return unlazy(
|
|
488
|
+
const wrappedRouter = enhanceEffectRouter(unlaziedRouter, options);
|
|
489
|
+
return unlazy(wrappedRouter);
|
|
286
490
|
},
|
|
287
491
|
{
|
|
288
492
|
...laziedMeta,
|
|
289
493
|
prefix: enhancedPrefix
|
|
290
494
|
}
|
|
291
495
|
);
|
|
292
|
-
|
|
293
|
-
return accessible;
|
|
496
|
+
return createAccessibleLazyRouter(enhanced2);
|
|
294
497
|
}
|
|
295
498
|
if (isProcedure(router)) {
|
|
296
|
-
const
|
|
499
|
+
const source = unwrapEffectUpstream(router);
|
|
500
|
+
const sourceEffectErrorMap = getEffectErrorMap(router);
|
|
501
|
+
const middlewares = mergeMiddlewares(
|
|
297
502
|
options.middlewares,
|
|
298
|
-
|
|
503
|
+
source["~orpc"].middlewares,
|
|
299
504
|
{ dedupeLeading: options.dedupeLeadingMiddlewares }
|
|
300
505
|
);
|
|
301
|
-
const newMiddlewareAdded =
|
|
506
|
+
const newMiddlewareAdded = middlewares.length - source["~orpc"].middlewares.length;
|
|
302
507
|
const effectErrorMap = {
|
|
303
508
|
...options.errorMap,
|
|
304
|
-
...
|
|
509
|
+
...sourceEffectErrorMap
|
|
305
510
|
};
|
|
306
511
|
const errorMap = effectErrorMapToErrorMap(effectErrorMap);
|
|
307
|
-
|
|
308
|
-
...
|
|
309
|
-
route: enhanceRoute(
|
|
512
|
+
return new EffectProcedure({
|
|
513
|
+
...source["~orpc"],
|
|
514
|
+
route: enhanceRoute(source["~orpc"].route, options),
|
|
310
515
|
effectErrorMap,
|
|
311
516
|
errorMap,
|
|
312
|
-
middlewares
|
|
313
|
-
inputValidationIndex:
|
|
314
|
-
outputValidationIndex:
|
|
517
|
+
middlewares,
|
|
518
|
+
inputValidationIndex: source["~orpc"].inputValidationIndex + newMiddlewareAdded,
|
|
519
|
+
outputValidationIndex: source["~orpc"].outputValidationIndex + newMiddlewareAdded,
|
|
315
520
|
runtime: options.runtime
|
|
316
521
|
});
|
|
317
|
-
return enhanced2;
|
|
318
522
|
}
|
|
319
523
|
const enhanced = {};
|
|
320
524
|
for (const key in router) {
|
|
@@ -323,7 +527,220 @@ function enhanceEffectRouter(router, options) {
|
|
|
323
527
|
return enhanced;
|
|
324
528
|
}
|
|
325
529
|
|
|
530
|
+
// src/effect-runtime.ts
|
|
531
|
+
import { ORPCError as ORPCError2 } from "@orpc/contract";
|
|
532
|
+
import { Cause as Cause2, Effect, Exit, FiberRefs } from "effect";
|
|
533
|
+
function toORPCErrorFromCause(cause) {
|
|
534
|
+
return Cause2.match(cause, {
|
|
535
|
+
onDie(defect) {
|
|
536
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
537
|
+
cause: defect
|
|
538
|
+
});
|
|
539
|
+
},
|
|
540
|
+
onFail(error) {
|
|
541
|
+
if (isORPCTaggedError(error)) {
|
|
542
|
+
return error.toORPCError();
|
|
543
|
+
}
|
|
544
|
+
if (error instanceof ORPCError2) {
|
|
545
|
+
return error;
|
|
546
|
+
}
|
|
547
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
548
|
+
cause: error
|
|
549
|
+
});
|
|
550
|
+
},
|
|
551
|
+
onInterrupt(fiberId) {
|
|
552
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
553
|
+
cause: new Error(`${fiberId} Interrupted`)
|
|
554
|
+
});
|
|
555
|
+
},
|
|
556
|
+
onSequential(left) {
|
|
557
|
+
return left;
|
|
558
|
+
},
|
|
559
|
+
onEmpty: new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
560
|
+
cause: new Error("Unknown error")
|
|
561
|
+
}),
|
|
562
|
+
onParallel(left) {
|
|
563
|
+
return left;
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
function createEffectProcedureHandler(options) {
|
|
568
|
+
const {
|
|
569
|
+
runtime,
|
|
570
|
+
effectErrorMap,
|
|
571
|
+
effectFn,
|
|
572
|
+
spanConfig,
|
|
573
|
+
defaultCaptureStackTrace
|
|
574
|
+
} = options;
|
|
575
|
+
return async (opts) => {
|
|
576
|
+
const effectOpts = {
|
|
577
|
+
context: opts.context,
|
|
578
|
+
input: opts.input,
|
|
579
|
+
path: opts.path,
|
|
580
|
+
procedure: opts.procedure,
|
|
581
|
+
signal: opts.signal,
|
|
582
|
+
lastEventId: opts.lastEventId,
|
|
583
|
+
errors: createEffectErrorConstructorMap(effectErrorMap)
|
|
584
|
+
};
|
|
585
|
+
const spanName = spanConfig?.name ?? opts.path.join(".");
|
|
586
|
+
const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
|
|
587
|
+
const resolver = Effect.fnUntraced(effectFn);
|
|
588
|
+
const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {
|
|
589
|
+
captureStackTrace
|
|
590
|
+
});
|
|
591
|
+
const parentFiberRefs = getCurrentFiberRefs();
|
|
592
|
+
const effectWithRefs = parentFiberRefs ? Effect.fiberIdWith(
|
|
593
|
+
(fiberId) => Effect.flatMap(
|
|
594
|
+
Effect.getFiberRefs,
|
|
595
|
+
(fiberRefs) => Effect.setFiberRefs(
|
|
596
|
+
FiberRefs.joinAs(fiberRefs, fiberId, parentFiberRefs)
|
|
597
|
+
).pipe(Effect.andThen(tracedEffect))
|
|
598
|
+
)
|
|
599
|
+
) : tracedEffect;
|
|
600
|
+
const exit = await runtime.runPromiseExit(effectWithRefs, {
|
|
601
|
+
signal: opts.signal
|
|
602
|
+
});
|
|
603
|
+
if (Exit.isFailure(exit)) {
|
|
604
|
+
throw toORPCErrorFromCause(exit.cause);
|
|
605
|
+
}
|
|
606
|
+
return exit.value;
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
326
610
|
// src/effect-builder.ts
|
|
611
|
+
var builderVirtualDescriptors = {
|
|
612
|
+
"~effect": { enumerable: true },
|
|
613
|
+
effect: { enumerable: false },
|
|
614
|
+
errors: { enumerable: false },
|
|
615
|
+
handler: { enumerable: false },
|
|
616
|
+
lazy: { enumerable: false },
|
|
617
|
+
router: { enumerable: false },
|
|
618
|
+
traced: { enumerable: false }
|
|
619
|
+
};
|
|
620
|
+
var builderVirtualKeys = [
|
|
621
|
+
"~effect",
|
|
622
|
+
"errors",
|
|
623
|
+
"effect",
|
|
624
|
+
"traced",
|
|
625
|
+
"handler",
|
|
626
|
+
"router",
|
|
627
|
+
"lazy"
|
|
628
|
+
];
|
|
629
|
+
function isBuilderLike(value) {
|
|
630
|
+
return typeof value === "object" && value !== null && "~orpc" in value;
|
|
631
|
+
}
|
|
632
|
+
function getOrCreateVirtualMethod2(context, prop, factory) {
|
|
633
|
+
const cache = context.methodCache;
|
|
634
|
+
if (cache.has(prop)) {
|
|
635
|
+
return cache.get(prop);
|
|
636
|
+
}
|
|
637
|
+
const value = factory();
|
|
638
|
+
cache.set(prop, value);
|
|
639
|
+
return value;
|
|
640
|
+
}
|
|
641
|
+
function getEffectBuilderDef(context) {
|
|
642
|
+
return {
|
|
643
|
+
...context.upstream["~orpc"],
|
|
644
|
+
effectErrorMap: context.state.effectErrorMap,
|
|
645
|
+
runtime: context.state.runtime,
|
|
646
|
+
spanConfig: context.state.spanConfig
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
function wrapBuilderLike(builder, state) {
|
|
650
|
+
return new EffectBuilder(
|
|
651
|
+
{
|
|
652
|
+
...builder["~orpc"],
|
|
653
|
+
effectErrorMap: state.effectErrorMap,
|
|
654
|
+
runtime: state.runtime,
|
|
655
|
+
spanConfig: state.spanConfig
|
|
656
|
+
},
|
|
657
|
+
unwrapEffectUpstream(builder)
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
function createEffectBuilderProxy(target) {
|
|
661
|
+
return createNodeProxy(target, {
|
|
662
|
+
getVirtual(context, prop) {
|
|
663
|
+
const effectDef = getEffectBuilderDef(context);
|
|
664
|
+
if (prop === "~effect") {
|
|
665
|
+
return getEffectBuilderDef(context);
|
|
666
|
+
}
|
|
667
|
+
const { upstream: source, state } = context;
|
|
668
|
+
switch (prop) {
|
|
669
|
+
case "errors":
|
|
670
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
671
|
+
return (errors) => {
|
|
672
|
+
const nextEffectErrorMap = {
|
|
673
|
+
...state.effectErrorMap,
|
|
674
|
+
...errors
|
|
675
|
+
};
|
|
676
|
+
const nextBuilder = Reflect.apply(
|
|
677
|
+
Reflect.get(source, "errors", source),
|
|
678
|
+
source,
|
|
679
|
+
[effectErrorMapToErrorMap(errors)]
|
|
680
|
+
);
|
|
681
|
+
return wrapBuilderLike(nextBuilder, {
|
|
682
|
+
...state,
|
|
683
|
+
effectErrorMap: nextEffectErrorMap
|
|
684
|
+
});
|
|
685
|
+
};
|
|
686
|
+
});
|
|
687
|
+
case "effect":
|
|
688
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
689
|
+
return (effectFn) => {
|
|
690
|
+
const defaultCaptureStackTrace = addSpanStackTrace();
|
|
691
|
+
return new EffectDecoratedProcedure({
|
|
692
|
+
...effectDef,
|
|
693
|
+
handler: async (opts) => {
|
|
694
|
+
return createEffectProcedureHandler({
|
|
695
|
+
defaultCaptureStackTrace,
|
|
696
|
+
effectErrorMap: state.effectErrorMap,
|
|
697
|
+
effectFn,
|
|
698
|
+
runtime: state.runtime,
|
|
699
|
+
spanConfig: state.spanConfig
|
|
700
|
+
})(opts);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
});
|
|
705
|
+
case "traced":
|
|
706
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
707
|
+
return (spanName) => wrapBuilderLike(source, {
|
|
708
|
+
...state,
|
|
709
|
+
spanConfig: {
|
|
710
|
+
captureStackTrace: addSpanStackTrace(),
|
|
711
|
+
name: spanName
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
case "handler":
|
|
716
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
717
|
+
return (handler) => new EffectDecoratedProcedure({
|
|
718
|
+
...effectDef,
|
|
719
|
+
handler
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
case "router":
|
|
723
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
724
|
+
return (router) => enhanceEffectRouter(router, effectDef);
|
|
725
|
+
});
|
|
726
|
+
case "lazy":
|
|
727
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
728
|
+
return (loader) => enhanceEffectRouter(lazy2(loader), effectDef);
|
|
729
|
+
});
|
|
730
|
+
default:
|
|
731
|
+
return unhandled();
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
virtualDescriptors: builderVirtualDescriptors,
|
|
735
|
+
virtualKeys: builderVirtualKeys,
|
|
736
|
+
wrapResult(context, _prop, result) {
|
|
737
|
+
if (!isBuilderLike(result)) {
|
|
738
|
+
return result;
|
|
739
|
+
}
|
|
740
|
+
return wrapBuilderLike(result, context.state);
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
}
|
|
327
744
|
function addSpanStackTrace() {
|
|
328
745
|
const ErrorConstructor = Error;
|
|
329
746
|
const limit = ErrorConstructor.stackTraceLimit;
|
|
@@ -344,381 +761,292 @@ function addSpanStackTrace() {
|
|
|
344
761
|
}
|
|
345
762
|
};
|
|
346
763
|
}
|
|
347
|
-
var EffectBuilder = class
|
|
348
|
-
constructor(def) {
|
|
764
|
+
var EffectBuilder = class {
|
|
765
|
+
constructor(def, builder) {
|
|
349
766
|
const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
|
|
350
|
-
this
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
* Sets or overrides the config.
|
|
355
|
-
*
|
|
356
|
-
* @see {@link https://orpc.dev/docs/client/server-side#middlewares-order Middlewares Order Docs}
|
|
357
|
-
* @see {@link https://orpc.dev/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
|
|
358
|
-
*/
|
|
359
|
-
$config(config) {
|
|
360
|
-
const inputValidationCount = this["~effect"].inputValidationIndex - fallbackConfig(
|
|
361
|
-
"initialInputValidationIndex",
|
|
362
|
-
this["~effect"].config.initialInputValidationIndex
|
|
363
|
-
);
|
|
364
|
-
const outputValidationCount = this["~effect"].outputValidationIndex - fallbackConfig(
|
|
365
|
-
"initialOutputValidationIndex",
|
|
366
|
-
this["~effect"].config.initialOutputValidationIndex
|
|
367
|
-
);
|
|
368
|
-
return new _EffectBuilder({
|
|
369
|
-
...this["~effect"],
|
|
370
|
-
config,
|
|
371
|
-
dedupeLeadingMiddlewares: fallbackConfig(
|
|
372
|
-
"dedupeLeadingMiddlewares",
|
|
373
|
-
config.dedupeLeadingMiddlewares
|
|
374
|
-
),
|
|
375
|
-
inputValidationIndex: fallbackConfig(
|
|
376
|
-
"initialInputValidationIndex",
|
|
377
|
-
config.initialInputValidationIndex
|
|
378
|
-
) + inputValidationCount,
|
|
379
|
-
outputValidationIndex: fallbackConfig(
|
|
380
|
-
"initialOutputValidationIndex",
|
|
381
|
-
config.initialOutputValidationIndex
|
|
382
|
-
) + outputValidationCount
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Set or override the initial context.
|
|
387
|
-
*
|
|
388
|
-
* @see {@link https://orpc.dev/docs/context Context Docs}
|
|
389
|
-
*/
|
|
390
|
-
$context() {
|
|
391
|
-
return new _EffectBuilder({
|
|
392
|
-
...this["~effect"],
|
|
393
|
-
middlewares: [],
|
|
394
|
-
inputValidationIndex: fallbackConfig(
|
|
395
|
-
"initialInputValidationIndex",
|
|
396
|
-
this["~effect"].config.initialInputValidationIndex
|
|
397
|
-
),
|
|
398
|
-
outputValidationIndex: fallbackConfig(
|
|
399
|
-
"initialOutputValidationIndex",
|
|
400
|
-
this["~effect"].config.initialOutputValidationIndex
|
|
401
|
-
)
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Sets or overrides the initial meta.
|
|
406
|
-
*
|
|
407
|
-
* @see {@link https://orpc.dev/docs/metadata Metadata Docs}
|
|
408
|
-
*/
|
|
409
|
-
$meta(initialMeta) {
|
|
410
|
-
return new _EffectBuilder({
|
|
411
|
-
...this["~effect"],
|
|
412
|
-
meta: initialMeta
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Sets or overrides the initial route.
|
|
417
|
-
* This option is typically relevant when integrating with OpenAPI.
|
|
418
|
-
*
|
|
419
|
-
* @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
|
|
420
|
-
* @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
|
|
421
|
-
*/
|
|
422
|
-
$route(initialRoute) {
|
|
423
|
-
return new _EffectBuilder({
|
|
424
|
-
...this["~effect"],
|
|
425
|
-
route: initialRoute
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Sets or overrides the initial input schema.
|
|
430
|
-
*
|
|
431
|
-
* @see {@link https://orpc.dev/docs/procedure#initial-configuration Initial Procedure Configuration Docs}
|
|
432
|
-
*/
|
|
433
|
-
$input(initialInputSchema) {
|
|
434
|
-
return new _EffectBuilder({
|
|
435
|
-
...this["~effect"],
|
|
436
|
-
inputSchema: initialInputSchema
|
|
767
|
+
attachEffectState(this, builder ?? new Builder(orpcDef), {
|
|
768
|
+
effectErrorMap,
|
|
769
|
+
runtime,
|
|
770
|
+
spanConfig
|
|
437
771
|
});
|
|
772
|
+
return createEffectBuilderProxy(this);
|
|
438
773
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
774
|
+
};
|
|
775
|
+
function makeEffectORPC(runtime, builder) {
|
|
776
|
+
const resolvedBuilder = builder ?? emptyBuilder();
|
|
777
|
+
const effectErrorMap = getEffectErrorMap(resolvedBuilder);
|
|
778
|
+
return new EffectBuilder(
|
|
779
|
+
{
|
|
780
|
+
...resolvedBuilder["~orpc"],
|
|
781
|
+
effectErrorMap,
|
|
782
|
+
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
783
|
+
runtime
|
|
784
|
+
},
|
|
785
|
+
unwrapEffectUpstream(resolvedBuilder)
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
function emptyBuilder() {
|
|
789
|
+
return new Builder({
|
|
790
|
+
config: {},
|
|
791
|
+
dedupeLeadingMiddlewares: true,
|
|
792
|
+
errorMap: {},
|
|
793
|
+
inputValidationIndex: fallbackConfig("initialInputValidationIndex"),
|
|
794
|
+
meta: {},
|
|
795
|
+
middlewares: [],
|
|
796
|
+
outputValidationIndex: fallbackConfig("initialOutputValidationIndex"),
|
|
797
|
+
route: {}
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// src/eoc.ts
|
|
802
|
+
import { isContractProcedure, oc } from "@orpc/contract";
|
|
803
|
+
var effectContractSymbol = /* @__PURE__ */ Symbol.for(
|
|
804
|
+
"@orpc/effect/contract"
|
|
805
|
+
);
|
|
806
|
+
function isWrappableContractBuilder(value) {
|
|
807
|
+
return typeof value === "object" && value !== null && "~orpc" in value;
|
|
808
|
+
}
|
|
809
|
+
function mergeEffectErrorMaps(left, right) {
|
|
810
|
+
if (!left) {
|
|
811
|
+
return right;
|
|
470
812
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return new _EffectBuilder({
|
|
474
|
-
...this["~effect"],
|
|
475
|
-
middlewares: addMiddleware2(this["~effect"].middlewares, mapped)
|
|
476
|
-
});
|
|
813
|
+
if (!right) {
|
|
814
|
+
return left;
|
|
477
815
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
return
|
|
486
|
-
...this["~effect"],
|
|
487
|
-
meta: mergeMeta2(this["~effect"].meta, meta)
|
|
488
|
-
});
|
|
816
|
+
return {
|
|
817
|
+
...left,
|
|
818
|
+
...right
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function setEffectContractErrorMap(value, effectErrorMap) {
|
|
822
|
+
if (!effectErrorMap) {
|
|
823
|
+
return;
|
|
489
824
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
return new _EffectBuilder({
|
|
500
|
-
...this["~effect"],
|
|
501
|
-
route: mergeRoute2(this["~effect"].route, route)
|
|
502
|
-
});
|
|
825
|
+
Object.defineProperty(value, effectContractSymbol, {
|
|
826
|
+
value: { errorMap: effectErrorMap },
|
|
827
|
+
enumerable: false,
|
|
828
|
+
configurable: true
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
function getEffectContractErrorMap(value) {
|
|
832
|
+
if (typeof value !== "object" || value === null) {
|
|
833
|
+
return void 0;
|
|
503
834
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
}
|
|
835
|
+
return value[effectContractSymbol]?.errorMap;
|
|
836
|
+
}
|
|
837
|
+
function applyEffectContractErrorMapToRouter(router, source, inheritedEffectErrorMap) {
|
|
838
|
+
const routerRecord = router;
|
|
839
|
+
const sourceRecord = source;
|
|
840
|
+
for (const key of Object.keys(routerRecord)) {
|
|
841
|
+
const routerValue = routerRecord[key];
|
|
842
|
+
const sourceValue = sourceRecord && typeof sourceRecord === "object" ? sourceRecord[key] : void 0;
|
|
843
|
+
if (!routerValue) {
|
|
844
|
+
continue;
|
|
845
|
+
}
|
|
846
|
+
if (isContractProcedure(routerValue)) {
|
|
847
|
+
const sourceEffectErrorMap = getEffectContractErrorMap(sourceValue);
|
|
848
|
+
setEffectContractErrorMap(
|
|
849
|
+
routerValue,
|
|
850
|
+
mergeEffectErrorMaps(inheritedEffectErrorMap, sourceEffectErrorMap)
|
|
851
|
+
);
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
if (typeof routerValue === "object") {
|
|
855
|
+
applyEffectContractErrorMapToRouter(
|
|
856
|
+
routerValue,
|
|
857
|
+
sourceValue,
|
|
858
|
+
inheritedEffectErrorMap
|
|
859
|
+
);
|
|
860
|
+
}
|
|
523
861
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
output(schema) {
|
|
530
|
-
return new _EffectBuilder({
|
|
531
|
-
...this["~effect"],
|
|
532
|
-
outputSchema: schema,
|
|
533
|
-
outputValidationIndex: fallbackConfig(
|
|
534
|
-
"initialOutputValidationIndex",
|
|
535
|
-
this["~effect"].config.initialOutputValidationIndex
|
|
536
|
-
) + this["~effect"].middlewares.length
|
|
537
|
-
});
|
|
862
|
+
}
|
|
863
|
+
function wrapEffectContractBuilder(builder, inheritedEffectErrorMap) {
|
|
864
|
+
const currentEffectErrorMap = inheritedEffectErrorMap ?? getEffectContractErrorMap(builder);
|
|
865
|
+
if (typeof builder === "object" && builder !== null) {
|
|
866
|
+
setEffectContractErrorMap(builder, currentEffectErrorMap);
|
|
538
867
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
*
|
|
544
|
-
* @param spanName - The name of the span for telemetry (e.g., 'users.getUser')
|
|
545
|
-
* @returns An EffectBuilder with span tracing configured
|
|
546
|
-
*
|
|
547
|
-
* @example
|
|
548
|
-
* ```ts
|
|
549
|
-
* const getUser = effectOs
|
|
550
|
-
* .input(z.object({ id: z.string() }))
|
|
551
|
-
* .traced('users.getUser')
|
|
552
|
-
* .effect(function* ({ input }) {
|
|
553
|
-
* const userService = yield* UserService
|
|
554
|
-
* return yield* userService.findById(input.id)
|
|
555
|
-
* })
|
|
556
|
-
* ```
|
|
557
|
-
*/
|
|
558
|
-
traced(spanName) {
|
|
559
|
-
return new _EffectBuilder({
|
|
560
|
-
...this["~effect"],
|
|
561
|
-
spanConfig: {
|
|
562
|
-
name: spanName,
|
|
563
|
-
captureStackTrace: addSpanStackTrace()
|
|
868
|
+
const proxy = new Proxy(builder, {
|
|
869
|
+
get(target, prop, receiver) {
|
|
870
|
+
if (prop === effectContractSymbol) {
|
|
871
|
+
return currentEffectErrorMap ? { errorMap: currentEffectErrorMap } : void 0;
|
|
564
872
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
*
|
|
578
|
-
* @see {@link https://orpc.dev/docs/procedure Procedure Docs}
|
|
579
|
-
*/
|
|
580
|
-
effect(effectFn) {
|
|
581
|
-
const { runtime, spanConfig } = this["~effect"];
|
|
582
|
-
const defaultCaptureStackTrace = addSpanStackTrace();
|
|
583
|
-
return new EffectDecoratedProcedure({
|
|
584
|
-
...this["~effect"],
|
|
585
|
-
handler: async (opts) => {
|
|
586
|
-
const effectOpts = {
|
|
587
|
-
context: opts.context,
|
|
588
|
-
input: opts.input,
|
|
589
|
-
path: opts.path,
|
|
590
|
-
procedure: opts.procedure,
|
|
591
|
-
signal: opts.signal,
|
|
592
|
-
lastEventId: opts.lastEventId,
|
|
593
|
-
errors: createEffectErrorConstructorMap(
|
|
594
|
-
this["~effect"].effectErrorMap
|
|
595
|
-
)
|
|
873
|
+
if (prop === "errors") {
|
|
874
|
+
return (errors) => {
|
|
875
|
+
const nextEffectErrorMap = mergeEffectErrorMaps(
|
|
876
|
+
currentEffectErrorMap,
|
|
877
|
+
errors
|
|
878
|
+
);
|
|
879
|
+
return wrapEffectContractBuilder(
|
|
880
|
+
Reflect.apply(Reflect.get(target, prop, receiver), target, [
|
|
881
|
+
effectErrorMapToErrorMap(errors)
|
|
882
|
+
]),
|
|
883
|
+
nextEffectErrorMap
|
|
884
|
+
);
|
|
596
885
|
};
|
|
597
|
-
const spanName = spanConfig?.name ?? opts.path.join(".");
|
|
598
|
-
const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
|
|
599
|
-
const resolver = Effect.fnUntraced(effectFn);
|
|
600
|
-
const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {
|
|
601
|
-
captureStackTrace
|
|
602
|
-
});
|
|
603
|
-
const parentFiberRefs = getCurrentFiberRefs();
|
|
604
|
-
const effectWithRefs = parentFiberRefs ? Effect.fiberIdWith(
|
|
605
|
-
(fiberId) => Effect.flatMap(
|
|
606
|
-
Effect.getFiberRefs,
|
|
607
|
-
(fiberRefs) => Effect.setFiberRefs(
|
|
608
|
-
FiberRefs.joinAs(fiberRefs, fiberId, parentFiberRefs)
|
|
609
|
-
).pipe(Effect.andThen(tracedEffect))
|
|
610
|
-
)
|
|
611
|
-
) : tracedEffect;
|
|
612
|
-
const exit = await runtime.runPromiseExit(effectWithRefs, {
|
|
613
|
-
signal: opts.signal
|
|
614
|
-
});
|
|
615
|
-
if (Exit.isFailure(exit)) {
|
|
616
|
-
throw Cause2.match(exit.cause, {
|
|
617
|
-
onDie(defect) {
|
|
618
|
-
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
619
|
-
cause: defect
|
|
620
|
-
});
|
|
621
|
-
},
|
|
622
|
-
onFail(error) {
|
|
623
|
-
if (isORPCTaggedError(error)) {
|
|
624
|
-
return error.toORPCError();
|
|
625
|
-
}
|
|
626
|
-
if (error instanceof ORPCError2) {
|
|
627
|
-
return error;
|
|
628
|
-
}
|
|
629
|
-
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
630
|
-
cause: error
|
|
631
|
-
});
|
|
632
|
-
},
|
|
633
|
-
onInterrupt(fiberId) {
|
|
634
|
-
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
635
|
-
cause: new Error(`${fiberId} Interrupted`)
|
|
636
|
-
});
|
|
637
|
-
},
|
|
638
|
-
onSequential(left) {
|
|
639
|
-
return left;
|
|
640
|
-
},
|
|
641
|
-
onEmpty: new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
642
|
-
cause: new Error("Unknown error")
|
|
643
|
-
}),
|
|
644
|
-
onParallel(left) {
|
|
645
|
-
return left;
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
|
-
}
|
|
649
|
-
return exit.value;
|
|
650
886
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
...this["~effect"],
|
|
676
|
-
tags: mergeTags(this["~effect"].tags, tags)
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Applies all of the previously defined options to the specified router.
|
|
681
|
-
*
|
|
682
|
-
* @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
|
|
683
|
-
*/
|
|
684
|
-
router(router) {
|
|
685
|
-
return enhanceEffectRouter(router, {
|
|
686
|
-
...this["~effect"]
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
/**
|
|
690
|
-
* Create a lazy router
|
|
691
|
-
* And applies all of the previously defined options to the specified router.
|
|
692
|
-
*
|
|
693
|
-
* @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
|
|
694
|
-
*/
|
|
695
|
-
lazy(loader) {
|
|
696
|
-
return enhanceEffectRouter(lazy2(loader), {
|
|
697
|
-
...this["~effect"]
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
function makeEffectORPC(runtime, builder) {
|
|
702
|
-
const resolvedBuilder = builder ?? emptyBuilder();
|
|
703
|
-
return new EffectBuilder({
|
|
704
|
-
...resolvedBuilder["~orpc"],
|
|
705
|
-
errorMap: effectErrorMapToErrorMap(resolvedBuilder["~orpc"].errorMap),
|
|
706
|
-
effectErrorMap: resolvedBuilder["~orpc"].errorMap,
|
|
707
|
-
runtime
|
|
887
|
+
if (prop === "router") {
|
|
888
|
+
return (router) => {
|
|
889
|
+
const result = Reflect.apply(
|
|
890
|
+
Reflect.get(target, prop, receiver),
|
|
891
|
+
target,
|
|
892
|
+
[router]
|
|
893
|
+
);
|
|
894
|
+
applyEffectContractErrorMapToRouter(
|
|
895
|
+
result,
|
|
896
|
+
router,
|
|
897
|
+
currentEffectErrorMap
|
|
898
|
+
);
|
|
899
|
+
return result;
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
const value = Reflect.get(target, prop, receiver);
|
|
903
|
+
if (typeof value !== "function") {
|
|
904
|
+
return value;
|
|
905
|
+
}
|
|
906
|
+
return (...args) => {
|
|
907
|
+
const result = Reflect.apply(value, target, args);
|
|
908
|
+
return isWrappableContractBuilder(result) ? wrapEffectContractBuilder(result, currentEffectErrorMap) : result;
|
|
909
|
+
};
|
|
910
|
+
}
|
|
708
911
|
});
|
|
912
|
+
setEffectContractErrorMap(proxy, currentEffectErrorMap);
|
|
913
|
+
return proxy;
|
|
709
914
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
915
|
+
var eoc = wrapEffectContractBuilder(
|
|
916
|
+
oc,
|
|
917
|
+
{}
|
|
918
|
+
);
|
|
919
|
+
|
|
920
|
+
// src/contract.ts
|
|
921
|
+
var CONTRACT_HIDDEN_METHODS = /* @__PURE__ */ new Set([
|
|
922
|
+
"$config",
|
|
923
|
+
"$context",
|
|
924
|
+
"$input",
|
|
925
|
+
"$meta",
|
|
926
|
+
"$route",
|
|
927
|
+
"errors",
|
|
928
|
+
"input",
|
|
929
|
+
"lazy",
|
|
930
|
+
"meta",
|
|
931
|
+
"middleware",
|
|
932
|
+
"output",
|
|
933
|
+
"prefix",
|
|
934
|
+
"route",
|
|
935
|
+
"router",
|
|
936
|
+
"tag"
|
|
937
|
+
]);
|
|
938
|
+
function makeEnhanceOptions(runtime) {
|
|
939
|
+
return {
|
|
718
940
|
middlewares: [],
|
|
719
|
-
|
|
941
|
+
errorMap: {},
|
|
942
|
+
dedupeLeadingMiddlewares: true,
|
|
943
|
+
runtime
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
function wrapContractNode(contract, target, runtime) {
|
|
947
|
+
const cache = /* @__PURE__ */ new Map();
|
|
948
|
+
return new Proxy(target, {
|
|
949
|
+
get(currentTarget, prop, receiver) {
|
|
950
|
+
if (cache.has(prop)) {
|
|
951
|
+
return cache.get(prop);
|
|
952
|
+
}
|
|
953
|
+
if (isContractProcedure2(contract)) {
|
|
954
|
+
if (prop === "effect") {
|
|
955
|
+
const effect = (effectFn) => {
|
|
956
|
+
const effectErrorMap = getEffectContractErrorMap(contract) ?? currentTarget["~orpc"].errorMap;
|
|
957
|
+
return new EffectDecoratedProcedure({
|
|
958
|
+
...currentTarget["~orpc"],
|
|
959
|
+
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
960
|
+
effectErrorMap,
|
|
961
|
+
runtime,
|
|
962
|
+
handler: createEffectProcedureHandler({
|
|
963
|
+
runtime,
|
|
964
|
+
effectErrorMap,
|
|
965
|
+
effectFn,
|
|
966
|
+
defaultCaptureStackTrace: addSpanStackTrace()
|
|
967
|
+
})
|
|
968
|
+
});
|
|
969
|
+
};
|
|
970
|
+
cache.set(prop, effect);
|
|
971
|
+
return effect;
|
|
972
|
+
}
|
|
973
|
+
if (prop === "use") {
|
|
974
|
+
const use = (...args) => wrapContractNode(
|
|
975
|
+
contract,
|
|
976
|
+
Reflect.apply(
|
|
977
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
978
|
+
currentTarget,
|
|
979
|
+
args
|
|
980
|
+
),
|
|
981
|
+
runtime
|
|
982
|
+
);
|
|
983
|
+
cache.set(prop, use);
|
|
984
|
+
return use;
|
|
985
|
+
}
|
|
986
|
+
if (CONTRACT_HIDDEN_METHODS.has(String(prop))) {
|
|
987
|
+
return void 0;
|
|
988
|
+
}
|
|
989
|
+
} else {
|
|
990
|
+
if (prop === "$context" || prop === "$config" || prop === "use") {
|
|
991
|
+
const wrappedMethod = (...args) => wrapContractNode(
|
|
992
|
+
contract,
|
|
993
|
+
Reflect.apply(
|
|
994
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
995
|
+
currentTarget,
|
|
996
|
+
args
|
|
997
|
+
),
|
|
998
|
+
runtime
|
|
999
|
+
);
|
|
1000
|
+
cache.set(prop, wrappedMethod);
|
|
1001
|
+
return wrappedMethod;
|
|
1002
|
+
}
|
|
1003
|
+
if (prop === "router" || prop === "lazy") {
|
|
1004
|
+
const wrappedMethod = (...args) => enhanceEffectRouter(
|
|
1005
|
+
Reflect.apply(
|
|
1006
|
+
Reflect.get(currentTarget, prop, currentTarget),
|
|
1007
|
+
currentTarget,
|
|
1008
|
+
args
|
|
1009
|
+
),
|
|
1010
|
+
makeEnhanceOptions(runtime)
|
|
1011
|
+
);
|
|
1012
|
+
cache.set(prop, wrappedMethod);
|
|
1013
|
+
return wrappedMethod;
|
|
1014
|
+
}
|
|
1015
|
+
if (typeof prop === "string" && prop in contract) {
|
|
1016
|
+
const child = wrapContractNode(
|
|
1017
|
+
contract[prop],
|
|
1018
|
+
Reflect.get(currentTarget, prop, receiver),
|
|
1019
|
+
runtime
|
|
1020
|
+
);
|
|
1021
|
+
cache.set(prop, child);
|
|
1022
|
+
return child;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
const value = Reflect.get(currentTarget, prop, receiver);
|
|
1026
|
+
return typeof value === "function" ? value.bind(currentTarget) : value;
|
|
1027
|
+
},
|
|
1028
|
+
has(currentTarget, prop) {
|
|
1029
|
+
if (isContractProcedure2(contract)) {
|
|
1030
|
+
if (prop === "effect") {
|
|
1031
|
+
return true;
|
|
1032
|
+
}
|
|
1033
|
+
if (CONTRACT_HIDDEN_METHODS.has(String(prop))) {
|
|
1034
|
+
return false;
|
|
1035
|
+
}
|
|
1036
|
+
} else if (typeof prop === "string" && prop in contract) {
|
|
1037
|
+
return true;
|
|
1038
|
+
}
|
|
1039
|
+
return Reflect.has(currentTarget, prop);
|
|
1040
|
+
}
|
|
720
1041
|
});
|
|
721
1042
|
}
|
|
1043
|
+
function implementEffect(contract, runtime) {
|
|
1044
|
+
return wrapContractNode(
|
|
1045
|
+
contract,
|
|
1046
|
+
implement(contract),
|
|
1047
|
+
runtime
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
722
1050
|
export {
|
|
723
1051
|
EffectBuilder,
|
|
724
1052
|
EffectDecoratedProcedure,
|
|
@@ -727,6 +1055,8 @@ export {
|
|
|
727
1055
|
addSpanStackTrace,
|
|
728
1056
|
createEffectErrorConstructorMap,
|
|
729
1057
|
effectErrorMapToErrorMap,
|
|
1058
|
+
eoc,
|
|
1059
|
+
implementEffect,
|
|
730
1060
|
isORPCTaggedError,
|
|
731
1061
|
isORPCTaggedErrorClass,
|
|
732
1062
|
makeEffectORPC,
|