effect-orpc 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -105
- package/dist/{chunk-VOWRLWZZ.js → chunk-IJP6L2XR.js} +6 -2
- package/dist/chunk-IJP6L2XR.js.map +1 -0
- package/dist/index.js +770 -282
- package/dist/index.js.map +1 -1
- package/dist/node.js +4 -3
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/src/contract.ts +46 -11
- package/src/effect-builder.ts +295 -33
- package/src/effect-enhance-router.ts +3 -3
- package/src/effect-procedure.ts +205 -11
- package/src/effect-runtime.ts +445 -23
- package/src/extension/create-node-proxy.ts +17 -1
- package/src/extension/state.ts +16 -20
- package/src/fiber-context-bridge.ts +13 -0
- package/src/index.ts +1 -0
- package/src/node.ts +2 -1
- package/src/runtime-source.ts +76 -0
- package/src/tagged-error.ts +1 -10
- package/src/tests/contract.test.ts +21 -0
- package/src/tests/effect-builder.proxy.test.ts +4 -4
- package/src/tests/effect-builder.test.ts +544 -7
- package/src/tests/effect-error-map.test.ts +10 -10
- package/src/tests/effect-procedure.test.ts +9 -6
- package/src/tests/node-side-effect.test.ts +80 -0
- package/src/tests/parity.effect-builder.test.ts +10 -3
- package/src/tests/parity.effect-procedure.test.ts +24 -8
- package/src/tests/shared.ts +1 -25
- package/src/types/effect-builder-surface.ts +117 -1
- package/src/types/effect-procedure-surface.ts +98 -1
- package/src/types/index.ts +291 -5
- package/src/types/variants.ts +351 -18
- package/dist/chunk-VOWRLWZZ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getCurrentFiberRefs
|
|
3
|
-
|
|
2
|
+
getCurrentFiberRefs,
|
|
3
|
+
runWithFiberRefs
|
|
4
|
+
} from "./chunk-IJP6L2XR.js";
|
|
4
5
|
|
|
5
6
|
// src/contract.ts
|
|
6
7
|
import { isContractProcedure as isContractProcedure2 } from "@orpc/contract";
|
|
@@ -8,6 +9,7 @@ import { implement } from "@orpc/server";
|
|
|
8
9
|
|
|
9
10
|
// src/effect-builder.ts
|
|
10
11
|
import { Builder, fallbackConfig, lazy as lazy2 } from "@orpc/server";
|
|
12
|
+
import { Layer as Layer3 } from "effect";
|
|
11
13
|
|
|
12
14
|
// src/effect-enhance-router.ts
|
|
13
15
|
import {
|
|
@@ -27,12 +29,420 @@ import {
|
|
|
27
29
|
// src/effect-procedure.ts
|
|
28
30
|
import { mergeMeta, mergeRoute } from "@orpc/contract";
|
|
29
31
|
import {
|
|
32
|
+
Procedure,
|
|
30
33
|
addMiddleware,
|
|
31
34
|
createActionableClient,
|
|
32
35
|
createProcedureClient,
|
|
33
|
-
decorateMiddleware
|
|
34
|
-
Procedure
|
|
36
|
+
decorateMiddleware
|
|
35
37
|
} from "@orpc/server";
|
|
38
|
+
import { Layer } from "effect";
|
|
39
|
+
|
|
40
|
+
// src/effect-runtime.ts
|
|
41
|
+
import { ORPCError as ORPCError2 } from "@orpc/contract";
|
|
42
|
+
import { Cause as Cause2, Effect, Exit, Option } from "effect";
|
|
43
|
+
|
|
44
|
+
// src/tagged-error.ts
|
|
45
|
+
import {
|
|
46
|
+
fallbackORPCErrorMessage,
|
|
47
|
+
fallbackORPCErrorStatus,
|
|
48
|
+
isORPCErrorStatus,
|
|
49
|
+
ORPCError
|
|
50
|
+
} from "@orpc/client";
|
|
51
|
+
import { resolveMaybeOptionalOptions } from "@orpc/shared";
|
|
52
|
+
import "effect/Cause";
|
|
53
|
+
import * as Data from "effect/Data";
|
|
54
|
+
var ORPCErrorSymbol = /* @__PURE__ */ Symbol.for(
|
|
55
|
+
"@orpc/effect/ORPCTaggedError"
|
|
56
|
+
);
|
|
57
|
+
function isORPCTaggedErrorClass(value) {
|
|
58
|
+
return typeof value === "function" && "_tag" in value && "code" in value && typeof value._tag === "string" && typeof value.code === "string";
|
|
59
|
+
}
|
|
60
|
+
function isORPCTaggedError(value) {
|
|
61
|
+
return typeof value === "object" && value !== null && ORPCErrorSymbol in value;
|
|
62
|
+
}
|
|
63
|
+
function toConstantCase(str) {
|
|
64
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
|
|
65
|
+
}
|
|
66
|
+
function ORPCTaggedError(tag, props) {
|
|
67
|
+
const code = props?.code ?? toConstantCase(tag);
|
|
68
|
+
class ORPCTaggedErrorBase extends Data.TaggedError(tag) {
|
|
69
|
+
status;
|
|
70
|
+
defined;
|
|
71
|
+
data;
|
|
72
|
+
code = code;
|
|
73
|
+
schema = props?.schema;
|
|
74
|
+
[ORPCErrorSymbol];
|
|
75
|
+
constructor(...rest) {
|
|
76
|
+
super();
|
|
77
|
+
const opts = resolveMaybeOptionalOptions(rest);
|
|
78
|
+
const status = opts.status ?? props?.status;
|
|
79
|
+
if (status !== void 0 && !isORPCErrorStatus(status)) {
|
|
80
|
+
throw new globalThis.Error(
|
|
81
|
+
"[ORPCTaggedError] Invalid error status code."
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
this.status = fallbackORPCErrorStatus(code, status);
|
|
85
|
+
this.defined = opts.defined ?? true;
|
|
86
|
+
this.data = opts.data;
|
|
87
|
+
this.message = fallbackORPCErrorMessage(
|
|
88
|
+
this.code,
|
|
89
|
+
opts.message ?? props?.message
|
|
90
|
+
);
|
|
91
|
+
this.cause = opts.cause;
|
|
92
|
+
this[ORPCErrorSymbol] = new ORPCError(
|
|
93
|
+
this.code,
|
|
94
|
+
{
|
|
95
|
+
status: this.status,
|
|
96
|
+
message: this.message,
|
|
97
|
+
data: this.data,
|
|
98
|
+
defined: this.defined,
|
|
99
|
+
cause: this.cause
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Converts this error to a plain ORPCError.
|
|
105
|
+
* Useful when you need to return from an oRPC handler.
|
|
106
|
+
*/
|
|
107
|
+
toORPCError() {
|
|
108
|
+
return this[ORPCErrorSymbol];
|
|
109
|
+
}
|
|
110
|
+
toJSON() {
|
|
111
|
+
return {
|
|
112
|
+
_tag: this._tag,
|
|
113
|
+
defined: this[ORPCErrorSymbol].defined,
|
|
114
|
+
code: this[ORPCErrorSymbol].code,
|
|
115
|
+
status: this[ORPCErrorSymbol].status,
|
|
116
|
+
message: this[ORPCErrorSymbol].message,
|
|
117
|
+
data: this[ORPCErrorSymbol].data
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return Object.assign(ORPCTaggedErrorBase, {
|
|
122
|
+
_tag: tag,
|
|
123
|
+
code
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function toORPCError(error) {
|
|
127
|
+
return error[ORPCErrorSymbol];
|
|
128
|
+
}
|
|
129
|
+
function createEffectErrorConstructorMap(errors) {
|
|
130
|
+
const target = errors ?? {};
|
|
131
|
+
const proxy = new Proxy(target, {
|
|
132
|
+
get(proxyTarget, code) {
|
|
133
|
+
if (typeof code !== "string") {
|
|
134
|
+
return Reflect.get(proxyTarget, code);
|
|
135
|
+
}
|
|
136
|
+
const config = target[code];
|
|
137
|
+
if (isORPCTaggedErrorClass(config)) {
|
|
138
|
+
return (...opts) => new config(...opts);
|
|
139
|
+
}
|
|
140
|
+
return (...rest) => {
|
|
141
|
+
const options = resolveMaybeOptionalOptions(rest);
|
|
142
|
+
return new ORPCError(code, {
|
|
143
|
+
defined: Boolean(config),
|
|
144
|
+
status: config?.status,
|
|
145
|
+
message: options.message ?? config?.message,
|
|
146
|
+
data: options.data,
|
|
147
|
+
cause: options.cause
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
return proxy;
|
|
153
|
+
}
|
|
154
|
+
function effectErrorMapToErrorMap(errorMap) {
|
|
155
|
+
const result = {};
|
|
156
|
+
if (!errorMap) {
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
for (const [code, ClassOrErrorItem] of Object.entries(errorMap)) {
|
|
160
|
+
if (!ClassOrErrorItem) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (isORPCTaggedErrorClass(ClassOrErrorItem)) {
|
|
164
|
+
const classInstance = new ClassOrErrorItem();
|
|
165
|
+
result[classInstance.code] = {
|
|
166
|
+
status: classInstance.status,
|
|
167
|
+
message: classInstance.message,
|
|
168
|
+
data: classInstance.schema
|
|
169
|
+
};
|
|
170
|
+
} else {
|
|
171
|
+
result[code] = ClassOrErrorItem;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/effect-runtime.ts
|
|
178
|
+
function toORPCErrorFromCause(cause) {
|
|
179
|
+
return Cause2.match(cause, {
|
|
180
|
+
onDie(defect) {
|
|
181
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
182
|
+
cause: defect
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
onFail(error) {
|
|
186
|
+
if (isORPCTaggedError(error)) {
|
|
187
|
+
return error.toORPCError();
|
|
188
|
+
}
|
|
189
|
+
if (error instanceof ORPCError2) {
|
|
190
|
+
return error;
|
|
191
|
+
}
|
|
192
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
193
|
+
cause: error
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
onInterrupt(fiberId) {
|
|
197
|
+
return new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
198
|
+
cause: new Error(`${fiberId} Interrupted`)
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
onSequential(left) {
|
|
202
|
+
return left;
|
|
203
|
+
},
|
|
204
|
+
onEmpty: new ORPCError2("INTERNAL_SERVER_ERROR", {
|
|
205
|
+
cause: new Error("Unknown error")
|
|
206
|
+
}),
|
|
207
|
+
onParallel(left) {
|
|
208
|
+
return left;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function createEffectProcedureHandler(options) {
|
|
213
|
+
const {
|
|
214
|
+
runner,
|
|
215
|
+
effectErrorMap,
|
|
216
|
+
effectFn,
|
|
217
|
+
effectSteps = [],
|
|
218
|
+
spanConfig,
|
|
219
|
+
defaultCaptureStackTrace
|
|
220
|
+
} = options;
|
|
221
|
+
return async (opts) => {
|
|
222
|
+
const effectOpts = {
|
|
223
|
+
context: opts.context,
|
|
224
|
+
input: opts.input,
|
|
225
|
+
path: opts.path,
|
|
226
|
+
procedure: opts.procedure,
|
|
227
|
+
signal: opts.signal,
|
|
228
|
+
lastEventId: opts.lastEventId,
|
|
229
|
+
errors: createEffectErrorConstructorMap(effectErrorMap)
|
|
230
|
+
};
|
|
231
|
+
const spanName = spanConfig?.name ?? opts.path.join(".");
|
|
232
|
+
const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
|
|
233
|
+
const resolver = Effect.fnUntraced(effectFn);
|
|
234
|
+
const handlerEffect = resolver(effectOpts);
|
|
235
|
+
const tracedEffect = Effect.withSpan(
|
|
236
|
+
runEffectPipeline({
|
|
237
|
+
baseOptions: effectOpts,
|
|
238
|
+
effectErrorMap,
|
|
239
|
+
final: (context) => Effect.map(
|
|
240
|
+
context === effectOpts.context ? handlerEffect : resolver({ ...effectOpts, context }),
|
|
241
|
+
(output) => ({ output, context: {} })
|
|
242
|
+
),
|
|
243
|
+
input: opts.input,
|
|
244
|
+
steps: effectSteps
|
|
245
|
+
}),
|
|
246
|
+
spanName,
|
|
247
|
+
{ captureStackTrace }
|
|
248
|
+
);
|
|
249
|
+
const exit = await runner.runPromiseExit(tracedEffect, {
|
|
250
|
+
signal: opts.signal
|
|
251
|
+
});
|
|
252
|
+
if (Exit.isFailure(exit)) {
|
|
253
|
+
throw toORPCErrorFromCause(exit.cause);
|
|
254
|
+
}
|
|
255
|
+
return exit.value.output;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function createEffectPipelineMiddleware(options) {
|
|
259
|
+
const { runner, effectErrorMap, steps } = options;
|
|
260
|
+
return async (opts, input) => {
|
|
261
|
+
const baseOptions = makeEffectOptions(opts, input, effectErrorMap);
|
|
262
|
+
const effect = runEffectPipeline({
|
|
263
|
+
baseOptions,
|
|
264
|
+
effectErrorMap,
|
|
265
|
+
final: (context) => withCurrentFiberContext(
|
|
266
|
+
() => opts.next(
|
|
267
|
+
context === opts.context ? void 0 : { context }
|
|
268
|
+
)
|
|
269
|
+
),
|
|
270
|
+
input,
|
|
271
|
+
steps
|
|
272
|
+
});
|
|
273
|
+
const exit = await runner.runPromiseExit(effect, {
|
|
274
|
+
signal: opts.signal
|
|
275
|
+
});
|
|
276
|
+
if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
|
|
277
|
+
return exit.value;
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function createEffectProviderMiddleware(options) {
|
|
281
|
+
const { runner, effectErrorMap, tag, provider } = options;
|
|
282
|
+
return async (opts, input) => {
|
|
283
|
+
const effectOpts = makeEffectOptions(opts, input, effectErrorMap);
|
|
284
|
+
const effect = Effect.flatMap(
|
|
285
|
+
provider(effectOpts),
|
|
286
|
+
(service) => Effect.provideService(
|
|
287
|
+
withCurrentFiberContext(() => opts.next()),
|
|
288
|
+
tag,
|
|
289
|
+
service
|
|
290
|
+
)
|
|
291
|
+
);
|
|
292
|
+
const exit = await runner.runPromiseExit(effect, {
|
|
293
|
+
signal: opts.signal
|
|
294
|
+
});
|
|
295
|
+
if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
|
|
296
|
+
return exit.value;
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
function createEffectOptionalProviderMiddleware(options) {
|
|
300
|
+
const { runner, effectErrorMap, tag, provider } = options;
|
|
301
|
+
return async (opts, input) => {
|
|
302
|
+
const effectOpts = makeEffectOptions(opts, input, effectErrorMap);
|
|
303
|
+
const effect = Effect.flatMap(
|
|
304
|
+
provider(effectOpts),
|
|
305
|
+
(service) => Option.match(service, {
|
|
306
|
+
onNone: () => withCurrentFiberContext(() => opts.next()),
|
|
307
|
+
onSome: (value) => Effect.provideService(
|
|
308
|
+
withCurrentFiberContext(() => opts.next()),
|
|
309
|
+
tag,
|
|
310
|
+
value
|
|
311
|
+
)
|
|
312
|
+
})
|
|
313
|
+
);
|
|
314
|
+
const exit = await runner.runPromiseExit(effect, {
|
|
315
|
+
signal: opts.signal
|
|
316
|
+
});
|
|
317
|
+
if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
|
|
318
|
+
return exit.value;
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function isEffectMiddleware(value) {
|
|
322
|
+
return typeof value === "function" && value.constructor?.name === "GeneratorFunction";
|
|
323
|
+
}
|
|
324
|
+
function makeEffectOptions(opts, input, effectErrorMap) {
|
|
325
|
+
return {
|
|
326
|
+
context: opts.context,
|
|
327
|
+
input,
|
|
328
|
+
path: opts.path,
|
|
329
|
+
procedure: opts.procedure,
|
|
330
|
+
signal: opts.signal,
|
|
331
|
+
lastEventId: opts.lastEventId,
|
|
332
|
+
errors: createEffectErrorConstructorMap(effectErrorMap)
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function runEffectPipeline(options) {
|
|
336
|
+
const run = (index, context) => {
|
|
337
|
+
const step = options.steps[index];
|
|
338
|
+
if (!step) return options.final(context);
|
|
339
|
+
const stepOptions = { ...options.baseOptions, context };
|
|
340
|
+
if (step._tag === "provide") {
|
|
341
|
+
return Effect.flatMap(
|
|
342
|
+
step.provider(stepOptions),
|
|
343
|
+
(service) => Effect.provideService(run(index + 1, context), step.tag, service)
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
if (step._tag === "provideOptional") {
|
|
347
|
+
return Effect.flatMap(
|
|
348
|
+
step.provider(stepOptions),
|
|
349
|
+
(service) => Option.match(service, {
|
|
350
|
+
onNone: () => run(index + 1, context),
|
|
351
|
+
onSome: (value) => Effect.provideService(run(index + 1, context), step.tag, value)
|
|
352
|
+
})
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
if (step._tag === "provideLayer") {
|
|
356
|
+
return Effect.provide(run(index + 1, context), step.layer);
|
|
357
|
+
}
|
|
358
|
+
const nextTracker = createMiddlewareNextTracker();
|
|
359
|
+
const effectOptions = {
|
|
360
|
+
context,
|
|
361
|
+
path: stepOptions.path,
|
|
362
|
+
procedure: stepOptions.procedure,
|
|
363
|
+
signal: stepOptions.signal,
|
|
364
|
+
lastEventId: stepOptions.lastEventId,
|
|
365
|
+
errors: createEffectErrorConstructorMap(options.effectErrorMap),
|
|
366
|
+
next: nextTracker.wrapNext(
|
|
367
|
+
(...rest) => {
|
|
368
|
+
const nextContext = rest[0]?.context ?? {};
|
|
369
|
+
return Effect.map(
|
|
370
|
+
run(index + 1, { ...context, ...nextContext }),
|
|
371
|
+
(result) => ({
|
|
372
|
+
output: result.output,
|
|
373
|
+
context: nextContext
|
|
374
|
+
})
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
};
|
|
379
|
+
const effectOutput = makeEffectMiddlewareOutput((output) => ({ output, context: {} }));
|
|
380
|
+
const middlewareEffect = Effect.fnUntraced(step.middleware)(
|
|
381
|
+
effectOptions,
|
|
382
|
+
options.input,
|
|
383
|
+
effectOutput
|
|
384
|
+
);
|
|
385
|
+
return Effect.flatMap(
|
|
386
|
+
middlewareEffect,
|
|
387
|
+
(result) => resolveEffectMiddlewareContinuation({
|
|
388
|
+
autoNext: () => effectOptions.next(),
|
|
389
|
+
nextInvoked: nextTracker.nextInvoked,
|
|
390
|
+
nextResult: nextTracker.nextResult,
|
|
391
|
+
result
|
|
392
|
+
})
|
|
393
|
+
);
|
|
394
|
+
};
|
|
395
|
+
return run(0, options.baseOptions.context);
|
|
396
|
+
}
|
|
397
|
+
function createMiddlewareNextTracker() {
|
|
398
|
+
let nextInvoked = false;
|
|
399
|
+
let nextResult;
|
|
400
|
+
return {
|
|
401
|
+
get nextInvoked() {
|
|
402
|
+
return nextInvoked;
|
|
403
|
+
},
|
|
404
|
+
get nextResult() {
|
|
405
|
+
return nextResult;
|
|
406
|
+
},
|
|
407
|
+
wrapNext(nextFn) {
|
|
408
|
+
return ((...args) => {
|
|
409
|
+
nextInvoked = true;
|
|
410
|
+
return Effect.map(nextFn(...args), (result) => {
|
|
411
|
+
nextResult = result;
|
|
412
|
+
return result;
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function resolveEffectMiddlewareContinuation(options) {
|
|
419
|
+
const { result, nextInvoked, nextResult, autoNext } = options;
|
|
420
|
+
if (result !== void 0) {
|
|
421
|
+
return Effect.succeed(result);
|
|
422
|
+
}
|
|
423
|
+
if (nextInvoked) {
|
|
424
|
+
if (nextResult === void 0) {
|
|
425
|
+
return Effect.die(
|
|
426
|
+
new Error(
|
|
427
|
+
"Effect middleware invoked next() but did not return its result"
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
return Effect.succeed(nextResult);
|
|
432
|
+
}
|
|
433
|
+
return autoNext();
|
|
434
|
+
}
|
|
435
|
+
function makeEffectMiddlewareOutput(output) {
|
|
436
|
+
return (value) => withCurrentFiberContext(() => output(value));
|
|
437
|
+
}
|
|
438
|
+
function withCurrentFiberContext(fn) {
|
|
439
|
+
return Effect.flatMap(
|
|
440
|
+
Effect.getFiberRefs,
|
|
441
|
+
(fiberRefs) => Effect.promise(
|
|
442
|
+
() => runWithFiberRefs(fiberRefs, () => Promise.resolve(fn()))
|
|
443
|
+
)
|
|
444
|
+
);
|
|
445
|
+
}
|
|
36
446
|
|
|
37
447
|
// src/extension/compose-surfaces.ts
|
|
38
448
|
function composeSurfaceProxy(surface, target) {
|
|
@@ -98,7 +508,8 @@ function createBoundMethod(context, prop, value, config, receiver) {
|
|
|
98
508
|
return cache.get(prop);
|
|
99
509
|
}
|
|
100
510
|
const wrapped = (...args) => {
|
|
101
|
-
const
|
|
511
|
+
const nextArgs = config.wrapArgs?.(context, prop, args, receiver) ?? args;
|
|
512
|
+
const result = Reflect.apply(value, context.upstream, nextArgs);
|
|
102
513
|
return config.wrapResult?.(context, prop, result, receiver) ?? result;
|
|
103
514
|
};
|
|
104
515
|
cache.set(prop, wrapped);
|
|
@@ -158,184 +569,51 @@ function createNodeProxy(target, config) {
|
|
|
158
569
|
for (const key of Reflect.ownKeys(context.upstream)) {
|
|
159
570
|
keys.add(key);
|
|
160
571
|
}
|
|
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
|
-
|
|
208
|
-
// src/tagged-error.ts
|
|
209
|
-
import {
|
|
210
|
-
fallbackORPCErrorMessage,
|
|
211
|
-
fallbackORPCErrorStatus,
|
|
212
|
-
isORPCErrorStatus,
|
|
213
|
-
ORPCError
|
|
214
|
-
} from "@orpc/client";
|
|
215
|
-
import { resolveMaybeOptionalOptions } from "@orpc/shared";
|
|
216
|
-
import "effect/Cause";
|
|
217
|
-
import * as Data from "effect/Data";
|
|
218
|
-
var ORPCErrorSymbol = /* @__PURE__ */ Symbol.for(
|
|
219
|
-
"@orpc/effect/ORPCTaggedError"
|
|
220
|
-
);
|
|
221
|
-
function isORPCTaggedErrorClass(value) {
|
|
222
|
-
return typeof value === "function" && "_tag" in value && "code" in value && typeof value._tag === "string" && typeof value.code === "string";
|
|
223
|
-
}
|
|
224
|
-
function isORPCTaggedError(value) {
|
|
225
|
-
return typeof value === "object" && value !== null && ORPCErrorSymbol in value;
|
|
226
|
-
}
|
|
227
|
-
function toConstantCase(str) {
|
|
228
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
|
|
229
|
-
}
|
|
230
|
-
function ORPCTaggedError(tag, props) {
|
|
231
|
-
const code = props?.code ?? toConstantCase(tag);
|
|
232
|
-
class ORPCTaggedErrorBase extends Data.TaggedError(tag) {
|
|
233
|
-
status;
|
|
234
|
-
defined;
|
|
235
|
-
data;
|
|
236
|
-
code = code;
|
|
237
|
-
schema = props?.schema;
|
|
238
|
-
[ORPCErrorSymbol];
|
|
239
|
-
constructor(...rest) {
|
|
240
|
-
super();
|
|
241
|
-
const opts = resolveMaybeOptionalOptions(rest);
|
|
242
|
-
const status = opts.status ?? props?.status;
|
|
243
|
-
if (status !== void 0 && !isORPCErrorStatus(status)) {
|
|
244
|
-
throw new globalThis.Error(
|
|
245
|
-
"[ORPCTaggedError] Invalid error status code."
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
this.status = fallbackORPCErrorStatus(code, status);
|
|
249
|
-
this.defined = opts.defined ?? true;
|
|
250
|
-
this.data = opts.data;
|
|
251
|
-
this.message = fallbackORPCErrorMessage(
|
|
252
|
-
this.code,
|
|
253
|
-
opts.message ?? props?.message
|
|
572
|
+
for (const key of virtualKeys) {
|
|
573
|
+
keys.add(key);
|
|
574
|
+
}
|
|
575
|
+
return [...keys];
|
|
576
|
+
},
|
|
577
|
+
getOwnPropertyDescriptor(currentTarget, prop) {
|
|
578
|
+
const context = createNodeProxyContext(
|
|
579
|
+
currentTarget
|
|
254
580
|
);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
581
|
+
if (virtualKeys.has(prop)) {
|
|
582
|
+
const value = config.getVirtual?.(context, prop, currentTarget);
|
|
583
|
+
if (value !== void 0 && value !== unhandledProperty) {
|
|
584
|
+
return {
|
|
585
|
+
configurable: true,
|
|
586
|
+
enumerable: config.virtualDescriptors?.[prop]?.enumerable ?? false,
|
|
587
|
+
value,
|
|
588
|
+
writable: false
|
|
589
|
+
};
|
|
264
590
|
}
|
|
591
|
+
}
|
|
592
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(
|
|
593
|
+
context.upstream,
|
|
594
|
+
prop
|
|
265
595
|
);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
* Converts this error to a plain ORPCError.
|
|
269
|
-
* Useful when you need to return from an oRPC handler.
|
|
270
|
-
*/
|
|
271
|
-
toORPCError() {
|
|
272
|
-
return this[ORPCErrorSymbol];
|
|
273
|
-
}
|
|
274
|
-
toJSON() {
|
|
275
|
-
return {
|
|
276
|
-
_tag: this._tag,
|
|
277
|
-
defined: this[ORPCErrorSymbol].defined,
|
|
278
|
-
code: this[ORPCErrorSymbol].code,
|
|
279
|
-
status: this[ORPCErrorSymbol].status,
|
|
280
|
-
message: this[ORPCErrorSymbol].message,
|
|
281
|
-
data: this[ORPCErrorSymbol].data
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
return Object.assign(ORPCTaggedErrorBase, {
|
|
286
|
-
_tag: tag,
|
|
287
|
-
code
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
function toORPCError(error) {
|
|
291
|
-
return error[ORPCErrorSymbol];
|
|
292
|
-
}
|
|
293
|
-
function createEffectErrorConstructorMap(errors) {
|
|
294
|
-
const target = errors ?? {};
|
|
295
|
-
const proxy = new Proxy(target, {
|
|
296
|
-
get(proxyTarget, code) {
|
|
297
|
-
if (typeof code !== "string") {
|
|
298
|
-
return Reflect.get(proxyTarget, code);
|
|
596
|
+
if (descriptor === void 0) {
|
|
597
|
+
return Reflect.getOwnPropertyDescriptor(currentTarget, prop);
|
|
299
598
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
599
|
+
if ("value" in descriptor && typeof descriptor.value === "function") {
|
|
600
|
+
return {
|
|
601
|
+
...descriptor,
|
|
602
|
+
value: createBoundMethod(
|
|
603
|
+
context,
|
|
604
|
+
prop,
|
|
605
|
+
descriptor.value,
|
|
606
|
+
config,
|
|
607
|
+
currentTarget
|
|
608
|
+
)
|
|
609
|
+
};
|
|
303
610
|
}
|
|
304
|
-
return
|
|
305
|
-
const options = resolveMaybeOptionalOptions(rest);
|
|
306
|
-
return new ORPCError(code, {
|
|
307
|
-
defined: Boolean(config),
|
|
308
|
-
status: config?.status,
|
|
309
|
-
message: options.message ?? config?.message,
|
|
310
|
-
data: options.data,
|
|
311
|
-
cause: options.cause
|
|
312
|
-
});
|
|
313
|
-
};
|
|
611
|
+
return descriptor;
|
|
314
612
|
}
|
|
315
613
|
});
|
|
316
|
-
return proxy;
|
|
317
614
|
}
|
|
318
|
-
function
|
|
319
|
-
|
|
320
|
-
if (!errorMap) {
|
|
321
|
-
return result;
|
|
322
|
-
}
|
|
323
|
-
for (const [code, ClassOrErrorItem] of Object.entries(errorMap)) {
|
|
324
|
-
if (!ClassOrErrorItem) {
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
if (isORPCTaggedErrorClass(ClassOrErrorItem)) {
|
|
328
|
-
const classInstance = new ClassOrErrorItem();
|
|
329
|
-
result[classInstance.code] = {
|
|
330
|
-
status: classInstance.status,
|
|
331
|
-
message: classInstance.message,
|
|
332
|
-
data: classInstance.schema
|
|
333
|
-
};
|
|
334
|
-
} else {
|
|
335
|
-
result[code] = ClassOrErrorItem;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return result;
|
|
615
|
+
function unhandled() {
|
|
616
|
+
return unhandledProperty;
|
|
339
617
|
}
|
|
340
618
|
|
|
341
619
|
// src/effect-procedure.ts
|
|
@@ -345,6 +623,8 @@ var procedureVirtualDescriptors = {
|
|
|
345
623
|
callable: { enumerable: false },
|
|
346
624
|
errors: { enumerable: false },
|
|
347
625
|
meta: { enumerable: false },
|
|
626
|
+
provide: { enumerable: false },
|
|
627
|
+
provideOptional: { enumerable: false },
|
|
348
628
|
route: { enumerable: false },
|
|
349
629
|
use: { enumerable: false }
|
|
350
630
|
};
|
|
@@ -353,6 +633,8 @@ var decoratedProcedureVirtualKeys = [
|
|
|
353
633
|
...baseProcedureVirtualKeys,
|
|
354
634
|
"errors",
|
|
355
635
|
"meta",
|
|
636
|
+
"provide",
|
|
637
|
+
"provideOptional",
|
|
356
638
|
"route",
|
|
357
639
|
"use",
|
|
358
640
|
"callable",
|
|
@@ -370,10 +652,52 @@ function getOrCreateVirtualMethod(context, prop, factory) {
|
|
|
370
652
|
function getEffectProcedureDef(context) {
|
|
371
653
|
return {
|
|
372
654
|
...context.upstream["~orpc"],
|
|
655
|
+
effectSteps: context.state.effectSteps,
|
|
656
|
+
effectHandler: context.state.effectHandler,
|
|
373
657
|
effectErrorMap: context.state.effectErrorMap,
|
|
374
|
-
|
|
658
|
+
runner: context.state.runner
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
function makeEffectProcedureHandler(def) {
|
|
662
|
+
if (!def.effectHandler) {
|
|
663
|
+
return def.handler;
|
|
664
|
+
}
|
|
665
|
+
return createEffectProcedureHandler({
|
|
666
|
+
defaultCaptureStackTrace: def.effectHandler.defaultCaptureStackTrace,
|
|
667
|
+
effectErrorMap: def.effectErrorMap,
|
|
668
|
+
effectFn: def.effectHandler.effectFn,
|
|
669
|
+
effectSteps: def.effectSteps,
|
|
670
|
+
runner: def.runner,
|
|
671
|
+
spanConfig: def.effectHandler.spanConfig
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
function withRebuiltEffectHandler(def) {
|
|
675
|
+
return {
|
|
676
|
+
...def,
|
|
677
|
+
handler: makeEffectProcedureHandler(def)
|
|
375
678
|
};
|
|
376
679
|
}
|
|
680
|
+
function appendEffectStep(def, step) {
|
|
681
|
+
return withRebuiltEffectHandler({
|
|
682
|
+
...def,
|
|
683
|
+
effectSteps: [...def.effectSteps ?? [], step]
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
function flushEffectSteps(def) {
|
|
687
|
+
if (!def.effectSteps?.length) {
|
|
688
|
+
return def;
|
|
689
|
+
}
|
|
690
|
+
const middleware = createEffectPipelineMiddleware({
|
|
691
|
+
effectErrorMap: def.effectErrorMap,
|
|
692
|
+
runner: def.runner,
|
|
693
|
+
steps: def.effectSteps
|
|
694
|
+
});
|
|
695
|
+
return withRebuiltEffectHandler({
|
|
696
|
+
...def,
|
|
697
|
+
effectSteps: void 0,
|
|
698
|
+
middlewares: addMiddleware(def.middlewares, middleware)
|
|
699
|
+
});
|
|
700
|
+
}
|
|
377
701
|
function createEffectProcedureProxy(target, decorated) {
|
|
378
702
|
return createNodeProxy(target, {
|
|
379
703
|
getVirtual(context, prop, receiver) {
|
|
@@ -413,16 +737,99 @@ function createEffectProcedureProxy(target, decorated) {
|
|
|
413
737
|
route: mergeRoute(getEffectProcedureDef(context).route, route)
|
|
414
738
|
});
|
|
415
739
|
});
|
|
740
|
+
case "provide":
|
|
741
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
742
|
+
return (tagOrLayer, provider) => {
|
|
743
|
+
const def = getEffectProcedureDef(context);
|
|
744
|
+
if (Layer.isLayer(tagOrLayer)) {
|
|
745
|
+
const step = {
|
|
746
|
+
_tag: "provideLayer",
|
|
747
|
+
layer: tagOrLayer
|
|
748
|
+
};
|
|
749
|
+
if (def.effectHandler) {
|
|
750
|
+
return new EffectDecoratedProcedure(
|
|
751
|
+
appendEffectStep(def, step)
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
return new EffectDecoratedProcedure({
|
|
755
|
+
...def,
|
|
756
|
+
middlewares: addMiddleware(
|
|
757
|
+
def.middlewares,
|
|
758
|
+
createEffectPipelineMiddleware({
|
|
759
|
+
effectErrorMap: state.effectErrorMap,
|
|
760
|
+
runner: state.runner,
|
|
761
|
+
steps: [step]
|
|
762
|
+
})
|
|
763
|
+
)
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
if (def.effectHandler) {
|
|
767
|
+
return new EffectDecoratedProcedure(
|
|
768
|
+
appendEffectStep(def, {
|
|
769
|
+
_tag: "provide",
|
|
770
|
+
provider,
|
|
771
|
+
tag: tagOrLayer
|
|
772
|
+
})
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
return new EffectDecoratedProcedure({
|
|
776
|
+
...def,
|
|
777
|
+
middlewares: addMiddleware(
|
|
778
|
+
def.middlewares,
|
|
779
|
+
createEffectProviderMiddleware({
|
|
780
|
+
effectErrorMap: state.effectErrorMap,
|
|
781
|
+
provider,
|
|
782
|
+
runner: state.runner,
|
|
783
|
+
tag: tagOrLayer
|
|
784
|
+
})
|
|
785
|
+
)
|
|
786
|
+
});
|
|
787
|
+
};
|
|
788
|
+
});
|
|
789
|
+
case "provideOptional":
|
|
790
|
+
return getOrCreateVirtualMethod(context, prop, () => {
|
|
791
|
+
return (tag, provider) => {
|
|
792
|
+
const def = getEffectProcedureDef(context);
|
|
793
|
+
if (def.effectHandler) {
|
|
794
|
+
return new EffectDecoratedProcedure(
|
|
795
|
+
appendEffectStep(def, {
|
|
796
|
+
_tag: "provideOptional",
|
|
797
|
+
provider,
|
|
798
|
+
tag
|
|
799
|
+
})
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
return new EffectDecoratedProcedure({
|
|
803
|
+
...def,
|
|
804
|
+
middlewares: addMiddleware(
|
|
805
|
+
def.middlewares,
|
|
806
|
+
createEffectOptionalProviderMiddleware({
|
|
807
|
+
effectErrorMap: state.effectErrorMap,
|
|
808
|
+
provider,
|
|
809
|
+
runner: state.runner,
|
|
810
|
+
tag
|
|
811
|
+
})
|
|
812
|
+
)
|
|
813
|
+
});
|
|
814
|
+
};
|
|
815
|
+
});
|
|
416
816
|
case "use":
|
|
417
817
|
return getOrCreateVirtualMethod(context, prop, () => {
|
|
418
818
|
return (middleware, mapInput) => {
|
|
819
|
+
const def = getEffectProcedureDef(context);
|
|
820
|
+
if (!mapInput && isEffectMiddleware(middleware)) {
|
|
821
|
+
return new EffectDecoratedProcedure(
|
|
822
|
+
appendEffectStep(def, {
|
|
823
|
+
_tag: "middleware",
|
|
824
|
+
middleware
|
|
825
|
+
})
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
const flushedDef = flushEffectSteps(def);
|
|
419
829
|
const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
|
|
420
830
|
return new EffectDecoratedProcedure({
|
|
421
|
-
...
|
|
422
|
-
middlewares: addMiddleware(
|
|
423
|
-
getEffectProcedureDef(context).middlewares,
|
|
424
|
-
mapped
|
|
425
|
-
)
|
|
831
|
+
...flushedDef,
|
|
832
|
+
middlewares: addMiddleware(flushedDef.middlewares, mapped)
|
|
426
833
|
});
|
|
427
834
|
};
|
|
428
835
|
});
|
|
@@ -459,10 +866,13 @@ function createEffectProcedureProxy(target, decorated) {
|
|
|
459
866
|
}
|
|
460
867
|
var EffectProcedure = class _EffectProcedure extends Procedure {
|
|
461
868
|
constructor(def, procedure) {
|
|
462
|
-
|
|
463
|
-
|
|
869
|
+
const { effectSteps, effectHandler, ...procedureDef } = def;
|
|
870
|
+
super(procedureDef);
|
|
871
|
+
attachEffectState(this, procedure ?? new Procedure(procedureDef), {
|
|
872
|
+
effectSteps,
|
|
873
|
+
effectHandler,
|
|
464
874
|
effectErrorMap: def.effectErrorMap,
|
|
465
|
-
|
|
875
|
+
runner: def.runner
|
|
466
876
|
});
|
|
467
877
|
if (new.target === _EffectProcedure) {
|
|
468
878
|
return createEffectProcedureProxy(this, false);
|
|
@@ -517,7 +927,7 @@ function enhanceEffectRouter(router, options) {
|
|
|
517
927
|
middlewares,
|
|
518
928
|
inputValidationIndex: source["~orpc"].inputValidationIndex + newMiddlewareAdded,
|
|
519
929
|
outputValidationIndex: source["~orpc"].outputValidationIndex + newMiddlewareAdded,
|
|
520
|
-
|
|
930
|
+
runner: options.runner
|
|
521
931
|
});
|
|
522
932
|
}
|
|
523
933
|
const enhanced = {};
|
|
@@ -527,85 +937,44 @@ function enhanceEffectRouter(router, options) {
|
|
|
527
937
|
return enhanced;
|
|
528
938
|
}
|
|
529
939
|
|
|
530
|
-
// src/
|
|
531
|
-
import {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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)
|
|
940
|
+
// src/runtime-source.ts
|
|
941
|
+
import { Effect as Effect2, FiberRefs, ManagedRuntime } from "effect";
|
|
942
|
+
function makeEffectRuntimeRunner(source) {
|
|
943
|
+
if (source === void 0) {
|
|
944
|
+
return {
|
|
945
|
+
runPromiseExit: (effect, options) => Effect2.runPromiseExit(withParentFiberRefs(effect), {
|
|
946
|
+
signal: options?.signal
|
|
947
|
+
})
|
|
584
948
|
};
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
)
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
signal: opts.signal
|
|
602
|
-
});
|
|
603
|
-
if (Exit.isFailure(exit)) {
|
|
604
|
-
throw toORPCErrorFromCause(exit.cause);
|
|
605
|
-
}
|
|
606
|
-
return exit.value;
|
|
949
|
+
}
|
|
950
|
+
if (ManagedRuntime.isManagedRuntime(source)) {
|
|
951
|
+
const runtime = source;
|
|
952
|
+
return {
|
|
953
|
+
runtime,
|
|
954
|
+
runPromiseExit: (effect, options) => runtime.runPromiseExit(withParentFiberRefs(effect), {
|
|
955
|
+
signal: options?.signal
|
|
956
|
+
})
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
const layer = source;
|
|
960
|
+
return {
|
|
961
|
+
runPromiseExit: (effect, options) => Effect2.runPromiseExit(
|
|
962
|
+
withParentFiberRefs(Effect2.provide(effect, layer)),
|
|
963
|
+
{ signal: options?.signal }
|
|
964
|
+
)
|
|
607
965
|
};
|
|
608
966
|
}
|
|
967
|
+
function withParentFiberRefs(effect) {
|
|
968
|
+
const parentFiberRefs = getCurrentFiberRefs();
|
|
969
|
+
return parentFiberRefs ? Effect2.fiberIdWith(
|
|
970
|
+
(fiberId) => Effect2.flatMap(
|
|
971
|
+
Effect2.getFiberRefs,
|
|
972
|
+
(fiberRefs) => Effect2.setFiberRefs(
|
|
973
|
+
FiberRefs.joinAs(fiberRefs, fiberId, parentFiberRefs)
|
|
974
|
+
).pipe(Effect2.andThen(effect))
|
|
975
|
+
)
|
|
976
|
+
) : effect;
|
|
977
|
+
}
|
|
609
978
|
|
|
610
979
|
// src/effect-builder.ts
|
|
611
980
|
var builderVirtualDescriptors = {
|
|
@@ -614,6 +983,9 @@ var builderVirtualDescriptors = {
|
|
|
614
983
|
errors: { enumerable: false },
|
|
615
984
|
handler: { enumerable: false },
|
|
616
985
|
lazy: { enumerable: false },
|
|
986
|
+
middleware: { enumerable: false },
|
|
987
|
+
provide: { enumerable: false },
|
|
988
|
+
provideOptional: { enumerable: false },
|
|
617
989
|
router: { enumerable: false },
|
|
618
990
|
traced: { enumerable: false }
|
|
619
991
|
};
|
|
@@ -621,6 +993,9 @@ var builderVirtualKeys = [
|
|
|
621
993
|
"~effect",
|
|
622
994
|
"errors",
|
|
623
995
|
"effect",
|
|
996
|
+
"middleware",
|
|
997
|
+
"provide",
|
|
998
|
+
"provideOptional",
|
|
624
999
|
"traced",
|
|
625
1000
|
"handler",
|
|
626
1001
|
"router",
|
|
@@ -642,8 +1017,10 @@ function getEffectBuilderDef(context) {
|
|
|
642
1017
|
return {
|
|
643
1018
|
...context.upstream["~orpc"],
|
|
644
1019
|
effectErrorMap: context.state.effectErrorMap,
|
|
645
|
-
|
|
646
|
-
spanConfig: context.state.spanConfig
|
|
1020
|
+
runner: context.state.runner,
|
|
1021
|
+
spanConfig: context.state.spanConfig,
|
|
1022
|
+
effectSteps: context.state.effectSteps,
|
|
1023
|
+
effectHandler: context.state.effectHandler
|
|
647
1024
|
};
|
|
648
1025
|
}
|
|
649
1026
|
function wrapBuilderLike(builder, state) {
|
|
@@ -651,12 +1028,39 @@ function wrapBuilderLike(builder, state) {
|
|
|
651
1028
|
{
|
|
652
1029
|
...builder["~orpc"],
|
|
653
1030
|
effectErrorMap: state.effectErrorMap,
|
|
654
|
-
|
|
655
|
-
spanConfig: state.spanConfig
|
|
1031
|
+
runner: state.runner,
|
|
1032
|
+
spanConfig: state.spanConfig,
|
|
1033
|
+
effectSteps: state.effectSteps,
|
|
1034
|
+
effectHandler: state.effectHandler
|
|
656
1035
|
},
|
|
657
1036
|
unwrapEffectUpstream(builder)
|
|
658
1037
|
);
|
|
659
1038
|
}
|
|
1039
|
+
function appendEffectStep2(state, step) {
|
|
1040
|
+
return {
|
|
1041
|
+
...state,
|
|
1042
|
+
effectSteps: [...state.effectSteps ?? [], step]
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
function flushEffectSteps2(builder, state) {
|
|
1046
|
+
if (!state.effectSteps?.length) {
|
|
1047
|
+
return { builder, state };
|
|
1048
|
+
}
|
|
1049
|
+
const middleware = createEffectPipelineMiddleware({
|
|
1050
|
+
effectErrorMap: state.effectErrorMap,
|
|
1051
|
+
runner: state.runner,
|
|
1052
|
+
steps: state.effectSteps
|
|
1053
|
+
});
|
|
1054
|
+
return {
|
|
1055
|
+
builder: Reflect.apply(Reflect.get(builder, "use", builder), builder, [
|
|
1056
|
+
middleware
|
|
1057
|
+
]),
|
|
1058
|
+
state: {
|
|
1059
|
+
...state,
|
|
1060
|
+
effectSteps: void 0
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
660
1064
|
function createEffectBuilderProxy(target) {
|
|
661
1065
|
return createNodeProxy(target, {
|
|
662
1066
|
getVirtual(context, prop) {
|
|
@@ -688,20 +1092,98 @@ function createEffectBuilderProxy(target) {
|
|
|
688
1092
|
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
689
1093
|
return (effectFn) => {
|
|
690
1094
|
const defaultCaptureStackTrace = addSpanStackTrace();
|
|
1095
|
+
const effectHandler = {
|
|
1096
|
+
defaultCaptureStackTrace,
|
|
1097
|
+
effectFn,
|
|
1098
|
+
spanConfig: state.spanConfig
|
|
1099
|
+
};
|
|
691
1100
|
return new EffectDecoratedProcedure({
|
|
692
1101
|
...effectDef,
|
|
1102
|
+
effectHandler,
|
|
693
1103
|
handler: async (opts) => {
|
|
694
1104
|
return createEffectProcedureHandler({
|
|
695
1105
|
defaultCaptureStackTrace,
|
|
696
1106
|
effectErrorMap: state.effectErrorMap,
|
|
697
1107
|
effectFn,
|
|
698
|
-
|
|
1108
|
+
effectSteps: state.effectSteps,
|
|
1109
|
+
runner: state.runner,
|
|
699
1110
|
spanConfig: state.spanConfig
|
|
700
1111
|
})(opts);
|
|
701
1112
|
}
|
|
702
1113
|
});
|
|
703
1114
|
};
|
|
704
1115
|
});
|
|
1116
|
+
case "middleware":
|
|
1117
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
1118
|
+
return (middleware) => {
|
|
1119
|
+
if (isEffectMiddleware(middleware)) {
|
|
1120
|
+
const effectMiddleware = createEffectPipelineMiddleware({
|
|
1121
|
+
effectErrorMap: state.effectErrorMap,
|
|
1122
|
+
runner: state.runner,
|
|
1123
|
+
steps: [
|
|
1124
|
+
...state.effectSteps ?? [],
|
|
1125
|
+
{ _tag: "middleware", middleware }
|
|
1126
|
+
]
|
|
1127
|
+
});
|
|
1128
|
+
return Reflect.apply(
|
|
1129
|
+
Reflect.get(source, "middleware", source),
|
|
1130
|
+
source,
|
|
1131
|
+
[effectMiddleware]
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
return Reflect.apply(
|
|
1135
|
+
Reflect.get(source, "middleware", source),
|
|
1136
|
+
source,
|
|
1137
|
+
[middleware]
|
|
1138
|
+
);
|
|
1139
|
+
};
|
|
1140
|
+
});
|
|
1141
|
+
case "provide":
|
|
1142
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
1143
|
+
return (tagOrLayer, provider) => {
|
|
1144
|
+
return wrapBuilderLike(
|
|
1145
|
+
source,
|
|
1146
|
+
appendEffectStep2(
|
|
1147
|
+
state,
|
|
1148
|
+
Layer3.isLayer(tagOrLayer) ? { _tag: "provideLayer", layer: tagOrLayer } : { _tag: "provide", provider, tag: tagOrLayer }
|
|
1149
|
+
)
|
|
1150
|
+
);
|
|
1151
|
+
};
|
|
1152
|
+
});
|
|
1153
|
+
case "provideOptional":
|
|
1154
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
1155
|
+
return (tag, provider) => {
|
|
1156
|
+
return wrapBuilderLike(
|
|
1157
|
+
source,
|
|
1158
|
+
appendEffectStep2(state, {
|
|
1159
|
+
_tag: "provideOptional",
|
|
1160
|
+
provider,
|
|
1161
|
+
tag
|
|
1162
|
+
})
|
|
1163
|
+
);
|
|
1164
|
+
};
|
|
1165
|
+
});
|
|
1166
|
+
case "use":
|
|
1167
|
+
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
1168
|
+
return (middleware, ...rest) => {
|
|
1169
|
+
if (isEffectMiddleware(middleware) && rest.length === 0) {
|
|
1170
|
+
return wrapBuilderLike(
|
|
1171
|
+
source,
|
|
1172
|
+
appendEffectStep2(state, {
|
|
1173
|
+
_tag: "middleware",
|
|
1174
|
+
middleware
|
|
1175
|
+
})
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
const flushed = flushEffectSteps2(source, state);
|
|
1179
|
+
const nextBuilder = Reflect.apply(
|
|
1180
|
+
Reflect.get(flushed.builder, "use", flushed.builder),
|
|
1181
|
+
flushed.builder,
|
|
1182
|
+
[middleware, ...rest]
|
|
1183
|
+
);
|
|
1184
|
+
return wrapBuilderLike(nextBuilder, flushed.state);
|
|
1185
|
+
};
|
|
1186
|
+
});
|
|
705
1187
|
case "traced":
|
|
706
1188
|
return getOrCreateVirtualMethod2(context, prop, () => {
|
|
707
1189
|
return (spanName) => wrapBuilderLike(source, {
|
|
@@ -763,24 +1245,28 @@ function addSpanStackTrace() {
|
|
|
763
1245
|
}
|
|
764
1246
|
var EffectBuilder = class {
|
|
765
1247
|
constructor(def, builder) {
|
|
766
|
-
const {
|
|
1248
|
+
const { runner, spanConfig, effectErrorMap, effectSteps, ...orpcDef } = def;
|
|
767
1249
|
attachEffectState(this, builder ?? new Builder(orpcDef), {
|
|
1250
|
+
effectSteps,
|
|
1251
|
+
effectHandler: def.effectHandler,
|
|
768
1252
|
effectErrorMap,
|
|
769
|
-
|
|
1253
|
+
runner,
|
|
770
1254
|
spanConfig
|
|
771
1255
|
});
|
|
772
1256
|
return createEffectBuilderProxy(this);
|
|
773
1257
|
}
|
|
774
1258
|
};
|
|
775
|
-
function makeEffectORPC(
|
|
776
|
-
const
|
|
1259
|
+
function makeEffectORPC(source, builder) {
|
|
1260
|
+
const sourceIsBuilder = source !== void 0 && isBuilderLike(source);
|
|
1261
|
+
const resolvedBuilder = sourceIsBuilder ? source : builder ?? emptyBuilder();
|
|
777
1262
|
const effectErrorMap = getEffectErrorMap(resolvedBuilder);
|
|
1263
|
+
const runner = sourceIsBuilder || source === void 0 ? makeEffectRuntimeRunner() : makeEffectRuntimeRunner(source);
|
|
778
1264
|
return new EffectBuilder(
|
|
779
1265
|
{
|
|
780
1266
|
...resolvedBuilder["~orpc"],
|
|
781
1267
|
effectErrorMap,
|
|
782
1268
|
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
783
|
-
|
|
1269
|
+
runner
|
|
784
1270
|
},
|
|
785
1271
|
unwrapEffectUpstream(resolvedBuilder)
|
|
786
1272
|
);
|
|
@@ -797,6 +1283,7 @@ function emptyBuilder() {
|
|
|
797
1283
|
route: {}
|
|
798
1284
|
});
|
|
799
1285
|
}
|
|
1286
|
+
var eos = makeEffectORPC();
|
|
800
1287
|
|
|
801
1288
|
// src/eoc.ts
|
|
802
1289
|
import { isContractProcedure, oc } from "@orpc/contract";
|
|
@@ -935,15 +1422,15 @@ var CONTRACT_HIDDEN_METHODS = /* @__PURE__ */ new Set([
|
|
|
935
1422
|
"router",
|
|
936
1423
|
"tag"
|
|
937
1424
|
]);
|
|
938
|
-
function makeEnhanceOptions(
|
|
1425
|
+
function makeEnhanceOptions(runner) {
|
|
939
1426
|
return {
|
|
940
1427
|
middlewares: [],
|
|
941
1428
|
errorMap: {},
|
|
942
1429
|
dedupeLeadingMiddlewares: true,
|
|
943
|
-
|
|
1430
|
+
runner
|
|
944
1431
|
};
|
|
945
1432
|
}
|
|
946
|
-
function wrapContractNode(contract, target,
|
|
1433
|
+
function wrapContractNode(contract, target, runner) {
|
|
947
1434
|
const cache = /* @__PURE__ */ new Map();
|
|
948
1435
|
return new Proxy(target, {
|
|
949
1436
|
get(currentTarget, prop, receiver) {
|
|
@@ -958,9 +1445,9 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
958
1445
|
...currentTarget["~orpc"],
|
|
959
1446
|
errorMap: effectErrorMapToErrorMap(effectErrorMap),
|
|
960
1447
|
effectErrorMap,
|
|
961
|
-
|
|
1448
|
+
runner,
|
|
962
1449
|
handler: createEffectProcedureHandler({
|
|
963
|
-
|
|
1450
|
+
runner,
|
|
964
1451
|
effectErrorMap,
|
|
965
1452
|
effectFn,
|
|
966
1453
|
defaultCaptureStackTrace: addSpanStackTrace()
|
|
@@ -978,7 +1465,7 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
978
1465
|
currentTarget,
|
|
979
1466
|
args
|
|
980
1467
|
),
|
|
981
|
-
|
|
1468
|
+
runner
|
|
982
1469
|
);
|
|
983
1470
|
cache.set(prop, use);
|
|
984
1471
|
return use;
|
|
@@ -995,7 +1482,7 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
995
1482
|
currentTarget,
|
|
996
1483
|
args
|
|
997
1484
|
),
|
|
998
|
-
|
|
1485
|
+
runner
|
|
999
1486
|
);
|
|
1000
1487
|
cache.set(prop, wrappedMethod);
|
|
1001
1488
|
return wrappedMethod;
|
|
@@ -1007,7 +1494,7 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
1007
1494
|
currentTarget,
|
|
1008
1495
|
args
|
|
1009
1496
|
),
|
|
1010
|
-
makeEnhanceOptions(
|
|
1497
|
+
makeEnhanceOptions(runner)
|
|
1011
1498
|
);
|
|
1012
1499
|
cache.set(prop, wrappedMethod);
|
|
1013
1500
|
return wrappedMethod;
|
|
@@ -1016,7 +1503,7 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
1016
1503
|
const child = wrapContractNode(
|
|
1017
1504
|
contract[prop],
|
|
1018
1505
|
Reflect.get(currentTarget, prop, receiver),
|
|
1019
|
-
|
|
1506
|
+
runner
|
|
1020
1507
|
);
|
|
1021
1508
|
cache.set(prop, child);
|
|
1022
1509
|
return child;
|
|
@@ -1040,11 +1527,11 @@ function wrapContractNode(contract, target, runtime) {
|
|
|
1040
1527
|
}
|
|
1041
1528
|
});
|
|
1042
1529
|
}
|
|
1043
|
-
function implementEffect(contract,
|
|
1530
|
+
function implementEffect(contract, source) {
|
|
1044
1531
|
return wrapContractNode(
|
|
1045
1532
|
contract,
|
|
1046
1533
|
implement(contract),
|
|
1047
|
-
|
|
1534
|
+
makeEffectRuntimeRunner(source)
|
|
1048
1535
|
);
|
|
1049
1536
|
}
|
|
1050
1537
|
export {
|
|
@@ -1056,6 +1543,7 @@ export {
|
|
|
1056
1543
|
createEffectErrorConstructorMap,
|
|
1057
1544
|
effectErrorMapToErrorMap,
|
|
1058
1545
|
eoc,
|
|
1546
|
+
eos,
|
|
1059
1547
|
implementEffect,
|
|
1060
1548
|
isORPCTaggedError,
|
|
1061
1549
|
isORPCTaggedErrorClass,
|