effect-orpc 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,18 +1,35 @@
1
1
  // src/effect-builder.ts
2
2
  import {
3
- mergeErrorMap,
4
3
  mergeMeta as mergeMeta2,
4
+ mergePrefix as mergePrefix2,
5
5
  mergeRoute as mergeRoute2,
6
+ mergeTags,
6
7
  ORPCError as ORPCError2
7
8
  } from "@orpc/contract";
8
9
  import {
9
10
  addMiddleware as addMiddleware2,
10
11
  Builder,
11
12
  decorateMiddleware as decorateMiddleware2,
12
- fallbackConfig
13
+ fallbackConfig,
14
+ lazy as lazy2
13
15
  } from "@orpc/server";
14
16
  import { Cause, Effect, Exit } from "effect";
15
17
 
18
+ // src/effect-enhance-router.ts
19
+ import {
20
+ enhanceRoute,
21
+ mergePrefix
22
+ } from "@orpc/contract";
23
+ import {
24
+ createAccessibleLazyRouter,
25
+ getLazyMeta,
26
+ isLazy,
27
+ isProcedure,
28
+ lazy,
29
+ mergeMiddlewares,
30
+ unlazy
31
+ } from "@orpc/server";
32
+
16
33
  // src/effect-procedure.ts
17
34
  import { mergeMeta, mergeRoute } from "@orpc/contract";
18
35
  import {
@@ -44,7 +61,7 @@ function isORPCTaggedError(value) {
44
61
  function toConstantCase(str) {
45
62
  return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
46
63
  }
47
- function ORPCTaggedError() {
64
+ function ORPCTaggedError(schema) {
48
65
  const factory = (tag, codeOrOptions, defaultOptions) => {
49
66
  const isCodeProvided = typeof codeOrOptions === "string";
50
67
  const code = isCodeProvided ? codeOrOptions : toConstantCase(tag);
@@ -53,6 +70,7 @@ function ORPCTaggedError() {
53
70
  const defaultMessage = options?.message;
54
71
  const BaseTaggedError = Data.TaggedError(tag);
55
72
  class ORPCTaggedErrorBase extends BaseTaggedError {
73
+ static schema = schema;
56
74
  static _tag = tag;
57
75
  static code = code;
58
76
  [ORPCErrorSymbol];
@@ -67,18 +85,19 @@ function ORPCTaggedError() {
67
85
  }
68
86
  const finalStatus = fallbackORPCErrorStatus(code, status);
69
87
  const finalMessage = fallbackORPCErrorMessage(code, inputMessage);
88
+ const data = opts.data;
70
89
  super({
71
90
  message: finalMessage,
72
91
  cause: opts.cause,
73
92
  code,
74
93
  status: finalStatus,
75
- data: opts.data,
94
+ data,
76
95
  defined: opts.defined ?? true
77
96
  });
78
97
  this[ORPCErrorSymbol] = new ORPCError(code, {
79
98
  status: finalStatus,
80
99
  message: finalMessage,
81
- data: opts.data,
100
+ data,
82
101
  defined: this.defined,
83
102
  cause: opts.cause
84
103
  });
@@ -117,7 +136,7 @@ function createEffectErrorConstructorMap(errors) {
117
136
  }
118
137
  const config = target[code];
119
138
  if (isORPCTaggedErrorClass(config)) {
120
- return config;
139
+ return (...opts) => new config(...opts);
121
140
  }
122
141
  return (...rest) => {
123
142
  const options = resolveMaybeOptionalOptions(rest);
@@ -143,11 +162,11 @@ function effectErrorMapToErrorMap(errorMap) {
143
162
  continue;
144
163
  }
145
164
  if (isORPCTaggedErrorClass(ClassOrErrorItem)) {
146
- const error = new ClassOrErrorItem().toORPCError();
147
- result[code] = {
148
- status: error.status,
149
- message: error.message,
150
- data: error.data
165
+ const classInstance = new ClassOrErrorItem();
166
+ result[classInstance.code] = {
167
+ status: classInstance.status,
168
+ message: classInstance.message,
169
+ data: classInstance.schema
151
170
  };
152
171
  } else {
153
172
  result[code] = ClassOrErrorItem;
@@ -157,9 +176,16 @@ function effectErrorMapToErrorMap(errorMap) {
157
176
  }
158
177
 
159
178
  // src/effect-procedure.ts
160
- var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends Procedure {
179
+ var EffectProcedure = class extends Procedure {
180
+ constructor(def) {
181
+ super(def);
182
+ this["~effect"] = def;
183
+ }
184
+ };
185
+ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends EffectProcedure {
161
186
  constructor(def) {
162
187
  super(def);
188
+ this["~effect"] = def;
163
189
  }
164
190
  /**
165
191
  * Adds type-safe custom errors.
@@ -168,9 +194,12 @@ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends Procedure
168
194
  * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
169
195
  */
170
196
  errors(errors) {
171
- const newEffectErrorMap = { ...this["~orpc"].effectErrorMap, ...errors };
197
+ const newEffectErrorMap = {
198
+ ...this["~effect"].effectErrorMap,
199
+ ...errors
200
+ };
172
201
  return new _EffectDecoratedProcedure({
173
- ...this["~orpc"],
202
+ ...this["~effect"],
174
203
  effectErrorMap: newEffectErrorMap,
175
204
  errorMap: effectErrorMapToErrorMap(newEffectErrorMap)
176
205
  });
@@ -183,8 +212,8 @@ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends Procedure
183
212
  */
184
213
  meta(meta) {
185
214
  return new _EffectDecoratedProcedure({
186
- ...this["~orpc"],
187
- meta: mergeMeta(this["~orpc"].meta, meta)
215
+ ...this["~effect"],
216
+ meta: mergeMeta(this["~effect"].meta, meta)
188
217
  });
189
218
  }
190
219
  /**
@@ -197,15 +226,15 @@ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends Procedure
197
226
  */
198
227
  route(route) {
199
228
  return new _EffectDecoratedProcedure({
200
- ...this["~orpc"],
201
- route: mergeRoute(this["~orpc"].route, route)
229
+ ...this["~effect"],
230
+ route: mergeRoute(this["~effect"].route, route)
202
231
  });
203
232
  }
204
233
  use(middleware, mapInput) {
205
234
  const mapped = mapInput ? decorateMiddleware(middleware).mapInput(mapInput) : middleware;
206
235
  return new _EffectDecoratedProcedure({
207
- ...this["~orpc"],
208
- middlewares: addMiddleware(this["~orpc"].middlewares, mapped)
236
+ ...this["~effect"],
237
+ middlewares: addMiddleware(this["~effect"].middlewares, mapped)
209
238
  });
210
239
  }
211
240
  /**
@@ -242,6 +271,56 @@ var EffectDecoratedProcedure = class _EffectDecoratedProcedure extends Procedure
242
271
  }
243
272
  };
244
273
 
274
+ // src/effect-enhance-router.ts
275
+ function enhanceEffectRouter(router, options) {
276
+ if (isLazy(router)) {
277
+ const laziedMeta = getLazyMeta(router);
278
+ const enhancedPrefix = laziedMeta?.prefix ? mergePrefix(options.prefix, laziedMeta?.prefix) : options.prefix;
279
+ const enhanced2 = lazy(
280
+ async () => {
281
+ const { default: unlaziedRouter } = await unlazy(router);
282
+ const enhanced3 = enhanceEffectRouter(unlaziedRouter, options);
283
+ return unlazy(enhanced3);
284
+ },
285
+ {
286
+ ...laziedMeta,
287
+ prefix: enhancedPrefix
288
+ }
289
+ );
290
+ const accessible = createAccessibleLazyRouter(enhanced2);
291
+ return accessible;
292
+ }
293
+ if (isProcedure(router)) {
294
+ const newMiddlewares = mergeMiddlewares(
295
+ options.middlewares,
296
+ router["~orpc"].middlewares,
297
+ { dedupeLeading: options.dedupeLeadingMiddlewares }
298
+ );
299
+ const newMiddlewareAdded = newMiddlewares.length - router["~orpc"].middlewares.length;
300
+ const effectErrorMap = {
301
+ ...options.errorMap,
302
+ ...router["~orpc"].errorMap
303
+ };
304
+ const errorMap = effectErrorMapToErrorMap(effectErrorMap);
305
+ const enhanced2 = new EffectProcedure({
306
+ ...router["~orpc"],
307
+ route: enhanceRoute(router["~orpc"].route, options),
308
+ effectErrorMap,
309
+ errorMap,
310
+ middlewares: newMiddlewares,
311
+ inputValidationIndex: router["~orpc"].inputValidationIndex + newMiddlewareAdded,
312
+ outputValidationIndex: router["~orpc"].outputValidationIndex + newMiddlewareAdded,
313
+ runtime: options.runtime
314
+ });
315
+ return enhanced2;
316
+ }
317
+ const enhanced = {};
318
+ for (const key in router) {
319
+ enhanced[key] = enhanceEffectRouter(router[key], options);
320
+ }
321
+ return enhanced;
322
+ }
323
+
245
324
  // src/effect-builder.ts
246
325
  function addSpanStackTrace() {
247
326
  const ErrorConstructor = Error;
@@ -264,9 +343,96 @@ function addSpanStackTrace() {
264
343
  };
265
344
  }
266
345
  var EffectBuilder = class _EffectBuilder {
267
- "~orpc";
268
346
  constructor(def) {
269
- this["~orpc"] = def;
347
+ const { runtime, spanConfig, effectErrorMap, ...orpcDef } = def;
348
+ this["~orpc"] = orpcDef;
349
+ this["~effect"] = { runtime, spanConfig, effectErrorMap, ...orpcDef };
350
+ }
351
+ /**
352
+ * Sets or overrides the config.
353
+ *
354
+ * @see {@link https://orpc.dev/docs/client/server-side#middlewares-order Middlewares Order Docs}
355
+ * @see {@link https://orpc.dev/docs/best-practices/dedupe-middleware#configuration Dedupe Middleware Docs}
356
+ */
357
+ $config(config) {
358
+ const inputValidationCount = this["~effect"].inputValidationIndex - fallbackConfig(
359
+ "initialInputValidationIndex",
360
+ this["~effect"].config.initialInputValidationIndex
361
+ );
362
+ const outputValidationCount = this["~effect"].outputValidationIndex - fallbackConfig(
363
+ "initialOutputValidationIndex",
364
+ this["~effect"].config.initialOutputValidationIndex
365
+ );
366
+ return new _EffectBuilder({
367
+ ...this["~effect"],
368
+ config,
369
+ dedupeLeadingMiddlewares: fallbackConfig(
370
+ "dedupeLeadingMiddlewares",
371
+ config.dedupeLeadingMiddlewares
372
+ ),
373
+ inputValidationIndex: fallbackConfig(
374
+ "initialInputValidationIndex",
375
+ config.initialInputValidationIndex
376
+ ) + inputValidationCount,
377
+ outputValidationIndex: fallbackConfig(
378
+ "initialOutputValidationIndex",
379
+ config.initialOutputValidationIndex
380
+ ) + outputValidationCount
381
+ });
382
+ }
383
+ /**
384
+ * Set or override the initial context.
385
+ *
386
+ * @see {@link https://orpc.dev/docs/context Context Docs}
387
+ */
388
+ $context() {
389
+ return new _EffectBuilder({
390
+ ...this["~effect"],
391
+ middlewares: [],
392
+ inputValidationIndex: fallbackConfig(
393
+ "initialInputValidationIndex",
394
+ this["~effect"].config.initialInputValidationIndex
395
+ ),
396
+ outputValidationIndex: fallbackConfig(
397
+ "initialOutputValidationIndex",
398
+ this["~effect"].config.initialOutputValidationIndex
399
+ )
400
+ });
401
+ }
402
+ /**
403
+ * Sets or overrides the initial meta.
404
+ *
405
+ * @see {@link https://orpc.dev/docs/metadata Metadata Docs}
406
+ */
407
+ $meta(initialMeta) {
408
+ return new _EffectBuilder({
409
+ ...this["~effect"],
410
+ meta: initialMeta
411
+ });
412
+ }
413
+ /**
414
+ * Sets or overrides the initial route.
415
+ * This option is typically relevant when integrating with OpenAPI.
416
+ *
417
+ * @see {@link https://orpc.dev/docs/openapi/routing OpenAPI Routing Docs}
418
+ * @see {@link https://orpc.dev/docs/openapi/input-output-structure OpenAPI Input/Output Structure Docs}
419
+ */
420
+ $route(initialRoute) {
421
+ return new _EffectBuilder({
422
+ ...this["~effect"],
423
+ route: initialRoute
424
+ });
425
+ }
426
+ /**
427
+ * Sets or overrides the initial input schema.
428
+ *
429
+ * @see {@link https://orpc.dev/docs/procedure#initial-configuration Initial Procedure Configuration Docs}
430
+ */
431
+ $input(initialInputSchema) {
432
+ return new _EffectBuilder({
433
+ ...this["~effect"],
434
+ inputSchema: initialInputSchema
435
+ });
270
436
  }
271
437
  /**
272
438
  * Adds type-safe custom errors.
@@ -290,23 +456,21 @@ var EffectBuilder = class _EffectBuilder {
290
456
  * @see {@link https://orpc.dev/docs/error-handling#type%E2%80%90safe-error-handling Type-Safe Error Handling Docs}
291
457
  */
292
458
  errors(errors) {
459
+ const newEffectErrorMap = {
460
+ ...this["~effect"].effectErrorMap,
461
+ ...errors
462
+ };
293
463
  return new _EffectBuilder({
294
- ...this["~orpc"],
295
- errorMap: mergeErrorMap(
296
- this["~orpc"].errorMap,
297
- effectErrorMapToErrorMap(errors)
298
- ),
299
- effectErrorMap: {
300
- ...this["~orpc"].effectErrorMap,
301
- ...errors
302
- }
464
+ ...this["~effect"],
465
+ errorMap: effectErrorMapToErrorMap(newEffectErrorMap),
466
+ effectErrorMap: newEffectErrorMap
303
467
  });
304
468
  }
305
469
  use(middleware, mapInput) {
306
470
  const mapped = mapInput ? decorateMiddleware2(middleware).mapInput(mapInput) : middleware;
307
471
  return new _EffectBuilder({
308
- ...this["~orpc"],
309
- middlewares: addMiddleware2(this["~orpc"].middlewares, mapped)
472
+ ...this["~effect"],
473
+ middlewares: addMiddleware2(this["~effect"].middlewares, mapped)
310
474
  });
311
475
  }
312
476
  /**
@@ -317,8 +481,8 @@ var EffectBuilder = class _EffectBuilder {
317
481
  */
318
482
  meta(meta) {
319
483
  return new _EffectBuilder({
320
- ...this["~orpc"],
321
- meta: mergeMeta2(this["~orpc"].meta, meta)
484
+ ...this["~effect"],
485
+ meta: mergeMeta2(this["~effect"].meta, meta)
322
486
  });
323
487
  }
324
488
  /**
@@ -331,8 +495,8 @@ var EffectBuilder = class _EffectBuilder {
331
495
  */
332
496
  route(route) {
333
497
  return new _EffectBuilder({
334
- ...this["~orpc"],
335
- route: mergeRoute2(this["~orpc"].route, route)
498
+ ...this["~effect"],
499
+ route: mergeRoute2(this["~effect"].route, route)
336
500
  });
337
501
  }
338
502
  /**
@@ -342,12 +506,17 @@ var EffectBuilder = class _EffectBuilder {
342
506
  */
343
507
  input(schema) {
344
508
  return new _EffectBuilder({
345
- ...this["~orpc"],
509
+ ...this["~effect"],
346
510
  inputSchema: schema,
347
511
  inputValidationIndex: fallbackConfig(
348
512
  "initialInputValidationIndex",
349
- this["~orpc"].config.initialInputValidationIndex
350
- ) + this["~orpc"].middlewares.length
513
+ this["~effect"].config.initialInputValidationIndex
514
+ ) + this["~effect"].middlewares.length
515
+ // we cast to any because EffectProcedureBuilderWithInput is expecting
516
+ // use() input type to be defined, and EffectBuilder types its use() input
517
+ // to unknown to allow any middleware to be passed
518
+ // ---
519
+ // note: the original implentation of the builder also uses any for the same reason
351
520
  });
352
521
  }
353
522
  /**
@@ -357,12 +526,12 @@ var EffectBuilder = class _EffectBuilder {
357
526
  */
358
527
  output(schema) {
359
528
  return new _EffectBuilder({
360
- ...this["~orpc"],
529
+ ...this["~effect"],
361
530
  outputSchema: schema,
362
531
  outputValidationIndex: fallbackConfig(
363
532
  "initialOutputValidationIndex",
364
- this["~orpc"].config.initialOutputValidationIndex
365
- ) + this["~orpc"].middlewares.length
533
+ this["~effect"].config.initialOutputValidationIndex
534
+ ) + this["~effect"].middlewares.length
366
535
  });
367
536
  }
368
537
  /**
@@ -386,13 +555,19 @@ var EffectBuilder = class _EffectBuilder {
386
555
  */
387
556
  traced(spanName) {
388
557
  return new _EffectBuilder({
389
- ...this["~orpc"],
558
+ ...this["~effect"],
390
559
  spanConfig: {
391
560
  name: spanName,
392
561
  captureStackTrace: addSpanStackTrace()
393
562
  }
394
563
  });
395
564
  }
565
+ handler(handler) {
566
+ return new EffectDecoratedProcedure({
567
+ ...this["~effect"],
568
+ handler
569
+ });
570
+ }
396
571
  /**
397
572
  * Defines the handler of the procedure using an Effect.
398
573
  * The Effect is executed using the ManagedRuntime provided during builder creation.
@@ -401,10 +576,10 @@ var EffectBuilder = class _EffectBuilder {
401
576
  * @see {@link https://orpc.dev/docs/procedure Procedure Docs}
402
577
  */
403
578
  effect(effectFn) {
404
- const { runtime, spanConfig } = this["~orpc"];
579
+ const { runtime, spanConfig } = this["~effect"];
405
580
  const defaultCaptureStackTrace = addSpanStackTrace();
406
581
  return new EffectDecoratedProcedure({
407
- ...this["~orpc"],
582
+ ...this["~effect"],
408
583
  handler: async (opts) => {
409
584
  const effectOpts = {
410
585
  context: opts.context,
@@ -413,12 +588,14 @@ var EffectBuilder = class _EffectBuilder {
413
588
  procedure: opts.procedure,
414
589
  signal: opts.signal,
415
590
  lastEventId: opts.lastEventId,
416
- errors: createEffectErrorConstructorMap(this["~orpc"].effectErrorMap)
591
+ errors: createEffectErrorConstructorMap(
592
+ this["~effect"].effectErrorMap
593
+ )
417
594
  };
418
- const baseEffect = effectFn(effectOpts);
419
595
  const spanName = spanConfig?.name ?? opts.path.join(".");
420
596
  const captureStackTrace = spanConfig?.captureStackTrace ?? defaultCaptureStackTrace;
421
- const tracedEffect = Effect.withSpan(baseEffect, spanName, {
597
+ const resolver = Effect.fnUntraced(effectFn);
598
+ const tracedEffect = Effect.withSpan(resolver(effectOpts), spanName, {
422
599
  captureStackTrace
423
600
  });
424
601
  const exit = await runtime.runPromiseExit(tracedEffect, {
@@ -462,11 +639,59 @@ var EffectBuilder = class _EffectBuilder {
462
639
  }
463
640
  });
464
641
  }
642
+ /**
643
+ * Prefixes all procedures in the router.
644
+ * The provided prefix is post-appended to any existing router prefix.
645
+ *
646
+ * @note This option does not affect procedures that do not define a path in their route definition.
647
+ *
648
+ * @see {@link https://orpc.dev/docs/openapi/routing#route-prefixes OpenAPI Route Prefixes Docs}
649
+ */
650
+ prefix(prefix) {
651
+ return new _EffectBuilder({
652
+ ...this["~effect"],
653
+ prefix: mergePrefix2(this["~effect"].prefix, prefix)
654
+ });
655
+ }
656
+ /**
657
+ * Adds tags to all procedures in the router.
658
+ * This helpful when you want to group procedures together in the OpenAPI specification.
659
+ *
660
+ * @see {@link https://orpc.dev/docs/openapi/openapi-specification#operation-metadata OpenAPI Operation Metadata Docs}
661
+ */
662
+ tag(...tags) {
663
+ return new _EffectBuilder({
664
+ ...this["~effect"],
665
+ tags: mergeTags(this["~effect"].tags, tags)
666
+ });
667
+ }
668
+ /**
669
+ * Applies all of the previously defined options to the specified router.
670
+ *
671
+ * @see {@link https://orpc.dev/docs/router#extending-router Extending Router Docs}
672
+ */
673
+ router(router) {
674
+ return enhanceEffectRouter(router, {
675
+ ...this["~effect"]
676
+ });
677
+ }
678
+ /**
679
+ * Create a lazy router
680
+ * And 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
+ lazy(loader) {
685
+ return enhanceEffectRouter(lazy2(loader), {
686
+ ...this["~effect"]
687
+ });
688
+ }
465
689
  };
466
690
  function makeEffectORPC(runtime, builder) {
467
691
  const resolvedBuilder = builder ?? emptyBuilder();
468
692
  return new EffectBuilder({
469
693
  ...resolvedBuilder["~orpc"],
694
+ errorMap: effectErrorMapToErrorMap(resolvedBuilder["~orpc"].errorMap),
470
695
  effectErrorMap: resolvedBuilder["~orpc"].errorMap,
471
696
  runtime
472
697
  });