@shivaedev/effect-trpc 0.1.1 → 0.3.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +24 -7
  3. package/dist/adapter.d.ts +15 -3
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +1 -1
  6. package/dist/adapter.js.map +1 -1
  7. package/dist/index.d.ts +3 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/internal/context-bridge.d.ts +4 -1
  12. package/dist/internal/context-bridge.d.ts.map +1 -1
  13. package/dist/internal/context-bridge.js +8 -1
  14. package/dist/internal/context-bridge.js.map +1 -1
  15. package/dist/internal/procedure-types.d.ts +2 -1
  16. package/dist/internal/procedure-types.d.ts.map +1 -1
  17. package/dist/internal/runtime.d.ts +5 -2
  18. package/dist/internal/runtime.d.ts.map +1 -1
  19. package/dist/internal/runtime.js +48 -16
  20. package/dist/internal/runtime.js.map +1 -1
  21. package/dist/internal/subscription-handler.d.ts +14 -0
  22. package/dist/internal/subscription-handler.d.ts.map +1 -0
  23. package/dist/internal/subscription-handler.js +18 -0
  24. package/dist/internal/subscription-handler.js.map +1 -0
  25. package/dist/internal/vitest-trpc.d.ts +2 -1
  26. package/dist/internal/vitest-trpc.d.ts.map +1 -1
  27. package/dist/internal/vitest-trpc.js +8 -3
  28. package/dist/internal/vitest-trpc.js.map +1 -1
  29. package/dist/procedure.d.ts +10 -3
  30. package/dist/procedure.d.ts.map +1 -1
  31. package/dist/procedure.js +16 -3
  32. package/dist/procedure.js.map +1 -1
  33. package/dist/request-signal.d.ts +4 -0
  34. package/dist/request-signal.d.ts.map +1 -0
  35. package/dist/request-signal.js +4 -0
  36. package/dist/request-signal.js.map +1 -0
  37. package/dist/testing/types.d.ts +19 -9
  38. package/dist/testing/types.d.ts.map +1 -1
  39. package/dist/testing/vitest.d.ts +2 -1
  40. package/dist/testing/vitest.d.ts.map +1 -1
  41. package/dist/testing/vitest.js +29 -22
  42. package/dist/testing/vitest.js.map +1 -1
  43. package/dist/testing.d.ts +2 -2
  44. package/dist/testing.d.ts.map +1 -1
  45. package/dist/testing.js +1 -1
  46. package/dist/testing.js.map +1 -1
  47. package/dist/types.d.ts +3 -2
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/adapter.ts +29 -4
  51. package/src/index.ts +3 -0
  52. package/src/internal/context-bridge.ts +14 -1
  53. package/src/internal/procedure-types.ts +9 -1
  54. package/src/internal/runtime.ts +72 -38
  55. package/src/internal/subscription-handler.ts +61 -0
  56. package/src/internal/vitest-trpc.ts +34 -17
  57. package/src/procedure.ts +58 -0
  58. package/src/request-signal.ts +7 -0
  59. package/src/testing/types.ts +61 -14
  60. package/src/testing/vitest.ts +72 -26
  61. package/src/testing.ts +7 -1
  62. package/src/types.ts +7 -2
@@ -4,7 +4,9 @@ import * as TestClock from "effect/testing/TestClock";
4
4
  import * as TestConsole from "effect/testing/TestConsole";
5
5
  import { makeEffectCallerFactory } from "../testing/caller.js";
6
6
  import type {
7
- TrpcTest,
7
+ TrpcHarnessTest,
8
+ TrpcHarnessTester,
9
+ TrpcHarnessTestRuntimeOptions,
8
10
  TrpcTester,
9
11
  TrpcTestRuntimeOptions,
10
12
  } from "../testing/types.js";
@@ -69,22 +71,24 @@ const runEffectTest = <A, E>(
69
71
  { signal: context.signal },
70
72
  );
71
73
 
72
- export const makeTrpcTester = <
74
+ export const makeTrpcHarnessTester = <
73
75
  Options,
74
76
  Caller extends object,
77
+ Harness,
75
78
  Provided,
76
79
  LayerError,
77
80
  >(
78
81
  fixtureIt: FixtureTestApi<Provided>,
79
- options: TrpcTestRuntimeOptions<Options, Caller, Provided, LayerError>,
80
- ): TrpcTester<Options, Caller, Provided> => {
82
+ options: TrpcHarnessTestRuntimeOptions<
83
+ Options,
84
+ Caller,
85
+ Harness,
86
+ Provided,
87
+ LayerError
88
+ >,
89
+ ): TrpcHarnessTester<Harness, Provided> => {
81
90
  const run = <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
82
- body: (
83
- trpc: ReturnType<
84
- typeof makeEffectCallerFactory<Options, Caller, Provided>
85
- >,
86
- context: TestContext,
87
- ) => Generator<Eff, A, never>,
91
+ body: (harness: Harness, context: TestContext) => Generator<Eff, A, never>,
88
92
  context: TestContext,
89
93
  ): Effect.Effect<A, unknown, Scope.Scope> => {
90
94
  const program = Effect.gen(function* () {
@@ -94,7 +98,8 @@ export const makeTrpcTester = <
94
98
  options.createCaller,
95
99
  services,
96
100
  );
97
- return yield* Effect.gen(() => body(trpc, context));
101
+ const harness = yield* options.makeHarness(trpc, context);
102
+ return yield* Effect.gen(() => body(harness, context));
98
103
  });
99
104
  // The body constraint proves every yielded service is part of Provided.
100
105
  // TypeScript cannot reduce that generic generator requirement here.
@@ -106,7 +111,7 @@ export const makeTrpcTester = <
106
111
  };
107
112
 
108
113
  const register =
109
- (current: FixtureTestApi<Provided>): TrpcTest<Options, Caller, Provided> =>
114
+ (current: FixtureTestApi<Provided>): TrpcHarnessTest<Harness, Provided> =>
110
115
  (name, body, testOptions) =>
111
116
  current(
112
117
  name,
@@ -138,7 +143,7 @@ export const makeTrpcTester = <
138
143
 
139
144
  const make = (
140
145
  current: FixtureTestApi<Provided>,
141
- ): TrpcTester<Options, Caller, Provided> => {
146
+ ): TrpcHarnessTester<Harness, Provided> => {
142
147
  const test = register(current);
143
148
  return Object.assign(test, {
144
149
  skip: register(current.skip),
@@ -151,9 +156,7 @@ export const makeTrpcTester = <
151
156
  name: string,
152
157
  body: (
153
158
  item: Item,
154
- trpc: ReturnType<
155
- typeof makeEffectCallerFactory<Options, Caller, Provided>
156
- >,
159
+ harness: Harness,
157
160
  context: TestContext,
158
161
  ) => Generator<Eff, A, never>,
159
162
  testOptions?: number | TestOptions,
@@ -187,7 +190,7 @@ export const makeTrpcTester = <
187
190
  });
188
191
  return runEffectTest(
189
192
  run(
190
- (trpc, testContext) => body(item, trpc, testContext),
193
+ (harness, testContext) => body(item, harness, testContext),
191
194
  context,
192
195
  ),
193
196
  context,
@@ -200,3 +203,17 @@ export const makeTrpcTester = <
200
203
 
201
204
  return make(fixtureIt);
202
205
  };
206
+
207
+ export const makeTrpcTester = <
208
+ Options,
209
+ Caller extends object,
210
+ Provided,
211
+ LayerError,
212
+ >(
213
+ fixtureIt: FixtureTestApi<Provided>,
214
+ options: TrpcTestRuntimeOptions<Options, Caller, Provided, LayerError>,
215
+ ): TrpcTester<Options, Caller, Provided> =>
216
+ makeTrpcHarnessTester(fixtureIt, {
217
+ ...options,
218
+ makeHarness: (trpc) => Effect.succeed(trpc),
219
+ }) as TrpcTester<Options, Caller, Provided>;
package/src/procedure.ts CHANGED
@@ -2,17 +2,20 @@ import type {
2
2
  TRPCMutationProcedure,
3
3
  TRPCProcedureBuilder,
4
4
  TRPCQueryProcedure,
5
+ TRPCSubscriptionProcedure,
5
6
  } from "@trpc/server";
6
7
  import { Schema } from "effect";
7
8
  import { makeProcedureHandler } from "./internal/procedure-handler.js";
8
9
  import type {
9
10
  DefaultValue,
10
11
  EffectProcedureResolver,
12
+ EffectSubscriptionResolver,
11
13
  IntersectIfDefined,
12
14
  ResolverContext,
13
15
  } from "./internal/procedure-types.js";
14
16
  import type { RuntimeBridge } from "./internal/runtime.js";
15
17
  import { captureStackTrace } from "./internal/stack-trace.js";
18
+ import { makeSubscriptionHandler } from "./internal/subscription-handler.js";
16
19
  import type { EffectProcedureRequestServices } from "./request-services.js";
17
20
 
18
21
  type Builder<
@@ -72,6 +75,8 @@ export class EffectProcedureBuilder<
72
75
  LayerError
73
76
  >,
74
77
  private readonly runtime: RuntimeBridge<RuntimeRequirements>,
78
+ private readonly subscriptionBuilder = builder,
79
+ private readonly subscriptionOutput?: Schema.ConstraintDecoder<unknown>,
75
80
  ) {}
76
81
 
77
82
  input<SchemaValue extends Schema.ConstraintDecoder<unknown>>(
@@ -89,6 +94,9 @@ export class EffectProcedureBuilder<
89
94
  RuntimeRequirements
90
95
  > {
91
96
  const next = this.builder.input(Schema.toStandardSchemaV1(schema) as never);
97
+ const subscriptionNext = this.subscriptionBuilder.input(
98
+ Schema.toStandardSchemaV1(schema) as never,
99
+ );
92
100
  return new EffectProcedureBuilder(
93
101
  next as unknown as Builder<
94
102
  Context,
@@ -101,6 +109,16 @@ export class EffectProcedureBuilder<
101
109
  >,
102
110
  this.requestServices,
103
111
  this.runtime,
112
+ subscriptionNext as unknown as Builder<
113
+ Context,
114
+ Meta,
115
+ ContextOverrides,
116
+ IntersectIfDefined<InputIn, SchemaValue["Encoded"]>,
117
+ IntersectIfDefined<InputOut, SchemaValue["Type"]>,
118
+ OutputIn,
119
+ OutputOut
120
+ >,
121
+ this.subscriptionOutput,
104
122
  );
105
123
  }
106
124
 
@@ -131,6 +149,16 @@ export class EffectProcedureBuilder<
131
149
  >,
132
150
  this.requestServices,
133
151
  this.runtime,
152
+ this.subscriptionBuilder as unknown as Builder<
153
+ Context,
154
+ Meta,
155
+ ContextOverrides,
156
+ InputIn,
157
+ InputOut,
158
+ IntersectIfDefined<OutputIn, SchemaValue["Encoded"]>,
159
+ IntersectIfDefined<OutputOut, SchemaValue["Type"]>
160
+ >,
161
+ schema,
134
162
  );
135
163
  }
136
164
 
@@ -170,6 +198,36 @@ export class EffectProcedureBuilder<
170
198
  }>;
171
199
  }
172
200
 
201
+ subscription<Output>(
202
+ resolver: EffectSubscriptionResolver<
203
+ DefaultValue<InputOut, undefined>,
204
+ ProvidedServices | NoInfer<RuntimeRequirements>,
205
+ DefaultValue<OutputIn, Output>
206
+ >,
207
+ ): TRPCSubscriptionProcedure<{
208
+ input: DefaultValue<InputIn, void>;
209
+ output: AsyncIterable<DefaultValue<OutputOut, Output>, void, unknown>;
210
+ meta: Meta;
211
+ }> {
212
+ const handler = makeSubscriptionHandler(
213
+ this.runtime,
214
+ resolver,
215
+ this.requestServices,
216
+ {
217
+ captureStackTrace: captureStackTrace(),
218
+ type: "subscription",
219
+ },
220
+ this.subscriptionOutput,
221
+ ) as never;
222
+ return this.subscriptionBuilder.subscription(
223
+ handler,
224
+ ) as TRPCSubscriptionProcedure<{
225
+ input: DefaultValue<InputIn, void>;
226
+ output: AsyncIterable<DefaultValue<OutputOut, Output>, void, unknown>;
227
+ meta: Meta;
228
+ }>;
229
+ }
230
+
173
231
  private dispatch<Output>(
174
232
  type: "mutation" | "query",
175
233
  resolver: EffectProcedureResolver<
@@ -0,0 +1,7 @@
1
+ import { Context } from "effect";
2
+
3
+ /** The transport cancellation signal for the current tRPC procedure. */
4
+ export const RequestSignal = Context.Reference<AbortSignal | undefined>(
5
+ "@shivaedev/effect-trpc/RequestSignal",
6
+ { defaultValue: () => undefined },
7
+ );
@@ -3,45 +3,57 @@ import type { Effect, Layer } from "effect";
3
3
  import type { EffectTRPCAdapter } from "../adapter.js";
4
4
  import type { EffectCallerFactory } from "./caller.js";
5
5
 
6
- export type TrpcTest<Options, Caller, Provided> = <
6
+ export type TrpcHarnessTest<Harness, Provided> = <
7
7
  A,
8
8
  Eff extends Effect.Effect<unknown, unknown, Provided>,
9
9
  >(
10
10
  name: string,
11
- body: (
12
- trpc: EffectCallerFactory<Options, Caller>,
13
- context: TestContext,
14
- ) => Generator<Eff, A, never>,
11
+ body: (harness: Harness, context: TestContext) => Generator<Eff, A, never>,
15
12
  options?: number | TestOptions,
16
13
  ) => void;
17
14
 
18
- export interface TrpcTester<Options, Caller, Provided>
19
- extends TrpcTest<Options, Caller, Provided> {
20
- readonly skip: TrpcTest<Options, Caller, Provided>;
21
- readonly skipIf: (condition: unknown) => TrpcTest<Options, Caller, Provided>;
22
- readonly runIf: (condition: unknown) => TrpcTest<Options, Caller, Provided>;
23
- readonly only: TrpcTest<Options, Caller, Provided>;
15
+ export interface TrpcHarnessTester<Harness, Provided>
16
+ extends TrpcHarnessTest<Harness, Provided> {
17
+ readonly skip: TrpcHarnessTest<Harness, Provided>;
18
+ readonly skipIf: (condition: unknown) => TrpcHarnessTest<Harness, Provided>;
19
+ readonly runIf: (condition: unknown) => TrpcHarnessTest<Harness, Provided>;
20
+ readonly only: TrpcHarnessTest<Harness, Provided>;
24
21
  readonly each: <Item>(
25
22
  cases: ReadonlyArray<Item>,
26
23
  ) => <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
27
24
  name: string,
28
25
  body: (
29
26
  item: Item,
30
- trpc: EffectCallerFactory<Options, Caller>,
27
+ harness: Harness,
31
28
  context: TestContext,
32
29
  ) => Generator<Eff, A, never>,
33
30
  options?: number | TestOptions,
34
31
  ) => void;
35
- readonly fails: TrpcTest<Options, Caller, Provided>;
32
+ readonly fails: TrpcHarnessTest<Harness, Provided>;
36
33
  }
37
34
 
35
+ export type TrpcTest<Options, Caller, Provided> = TrpcHarnessTest<
36
+ EffectCallerFactory<Options, Caller>,
37
+ Provided
38
+ >;
39
+
40
+ export type TrpcTester<Options, Caller, Provided> = TrpcHarnessTester<
41
+ EffectCallerFactory<Options, Caller>,
42
+ Provided
43
+ >;
44
+
38
45
  export type TrpcIt<Options, Caller, Provided> = Vitest.Methods & {
39
46
  readonly effectTRPC: TrpcTester<Options, Caller, Provided>;
40
47
  };
41
48
 
42
- export interface TrpcTestRuntimeOptions<
49
+ export type TrpcHarnessIt<Harness, Provided> = Vitest.Methods & {
50
+ readonly effectTRPC: TrpcHarnessTester<Harness, Provided>;
51
+ };
52
+
53
+ export interface TrpcHarnessTestRuntimeOptions<
43
54
  Options,
44
55
  Caller extends object,
56
+ Harness,
45
57
  Provided,
46
58
  LayerError,
47
59
  > {
@@ -51,8 +63,28 @@ export interface TrpcTestRuntimeOptions<
51
63
  ) => Effect.Effect<A, unknown, Provided>;
52
64
  readonly createCaller: (options?: Options) => Caller;
53
65
  readonly layer: Layer.Layer<Provided, LayerError>;
66
+ readonly makeHarness: (
67
+ trpc: EffectCallerFactory<Options, Caller>,
68
+ context: TestContext,
69
+ ) => Effect.Effect<Harness, unknown, Provided>;
54
70
  }
55
71
 
72
+ export type TrpcTestRuntimeOptions<
73
+ Options,
74
+ Caller extends object,
75
+ Provided,
76
+ LayerError,
77
+ > = Omit<
78
+ TrpcHarnessTestRuntimeOptions<
79
+ Options,
80
+ Caller,
81
+ EffectCallerFactory<Options, Caller>,
82
+ Provided,
83
+ LayerError
84
+ >,
85
+ "makeHarness"
86
+ >;
87
+
56
88
  export interface MakeTrpcItOptions<
57
89
  CreateCaller extends (...arguments_: never[]) => object,
58
90
  // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
@@ -66,6 +98,21 @@ export interface MakeTrpcItOptions<
66
98
  readonly layer: TestLayer;
67
99
  }
68
100
 
101
+ export interface MakeTrpcHarnessItOptions<
102
+ CreateCaller extends (...arguments_: never[]) => object,
103
+ // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
104
+ TestLayer extends Layer.Layer<any, any, never>,
105
+ Harness,
106
+ > extends MakeTrpcItOptions<CreateCaller, TestLayer> {
107
+ readonly makeHarness: (
108
+ trpc: EffectCallerFactory<
109
+ CallerOptions<CreateCaller>,
110
+ CallerResult<CreateCaller>
111
+ >,
112
+ context: TestContext,
113
+ ) => Effect.Effect<Harness, unknown, Layer.Success<TestLayer>>;
114
+ }
115
+
69
116
  export type CallerOptions<CreateCaller> = CreateCaller extends (
70
117
  ...arguments_: infer Arguments
71
118
  ) => object
@@ -1,17 +1,54 @@
1
- import { it as effectIt } from "@effect/vitest";
1
+ import { it as effectIt, type Vitest } from "@effect/vitest";
2
2
  import { Effect, Exit, Layer, Scope } from "effect";
3
3
  import {
4
4
  type FixtureTestApi,
5
5
  fixtureName,
6
+ makeTrpcHarnessTester,
6
7
  makeTrpcTester,
7
8
  } from "../internal/vitest-trpc.js";
8
9
  import type {
9
10
  CallerOptions,
10
11
  CallerResult,
12
+ MakeTrpcHarnessItOptions,
11
13
  MakeTrpcItOptions,
14
+ TrpcHarnessIt,
12
15
  TrpcIt,
13
16
  } from "./types.js";
14
17
 
18
+ const makeFixtureIt = <Provided, LayerError>(
19
+ layer: Layer.Layer<Provided, LayerError>,
20
+ ): FixtureTestApi<Provided> =>
21
+ effectIt.extend(
22
+ fixtureName,
23
+ { scope: "worker" },
24
+ // biome-ignore lint/correctness/noEmptyPattern: Vitest fixtures require a destructured context parameter.
25
+ async ({}, { onCleanup }) => {
26
+ const scope = Effect.runSync(Scope.make());
27
+ onCleanup(() => Effect.runPromise(Scope.close(scope, Exit.void)));
28
+
29
+ try {
30
+ return await Effect.runPromise(Layer.buildWithScope(layer, scope));
31
+ } catch (error) {
32
+ await Effect.runPromise(Scope.close(scope, Exit.void));
33
+ throw error;
34
+ }
35
+ },
36
+ ) as unknown as FixtureTestApi<Provided>;
37
+
38
+ const withEffectTRPC = <Tester>(
39
+ tester: Tester,
40
+ ): Vitest.Methods & {
41
+ readonly effectTRPC: Tester;
42
+ } =>
43
+ new Proxy(effectIt, {
44
+ get(target, property, receiver) {
45
+ if (property === "effectTRPC") {
46
+ return tester;
47
+ }
48
+ return Reflect.get(target, property, receiver);
49
+ },
50
+ }) as Vitest.Methods & { readonly effectTRPC: Tester };
51
+
15
52
  export const makeTrpcIt = <
16
53
  CreateCaller extends (...arguments_: never[]) => object,
17
54
  // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
@@ -27,23 +64,8 @@ export const makeTrpcIt = <
27
64
  type Caller = CallerResult<CreateCaller>;
28
65
  type Provided = Layer.Success<TestLayer>;
29
66
 
30
- const fixtureIt = effectIt.extend(
31
- fixtureName,
32
- { scope: "worker" },
33
- // biome-ignore lint/correctness/noEmptyPattern: Vitest fixtures require a destructured context parameter.
34
- async ({}, { onCleanup }) => {
35
- const scope = Effect.runSync(Scope.make());
36
- onCleanup(() => Effect.runPromise(Scope.close(scope, Exit.void)));
37
-
38
- try {
39
- return await Effect.runPromise(
40
- Layer.buildWithScope(options.layer, scope),
41
- );
42
- } catch (error) {
43
- await Effect.runPromise(Scope.close(scope, Exit.void));
44
- throw error;
45
- }
46
- },
67
+ const fixtureIt = makeFixtureIt<Provided, Layer.Error<TestLayer>>(
68
+ options.layer,
47
69
  );
48
70
 
49
71
  const effectTRPC = makeTrpcTester(
@@ -53,12 +75,36 @@ export const makeTrpcIt = <
53
75
  >[1],
54
76
  );
55
77
 
56
- return new Proxy(effectIt, {
57
- get(target, property, receiver) {
58
- if (property === "effectTRPC") {
59
- return effectTRPC;
60
- }
61
- return Reflect.get(target, property, receiver);
62
- },
63
- }) as TrpcIt<Options, Caller, Provided>;
78
+ return withEffectTRPC(effectTRPC) as TrpcIt<Options, Caller, Provided>;
79
+ };
80
+
81
+ export const makeTrpcHarnessIt = <
82
+ CreateCaller extends (...arguments_: never[]) => object,
83
+ // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
84
+ TestLayer extends Layer.Layer<any, any, never>,
85
+ Harness,
86
+ >(
87
+ options: MakeTrpcHarnessItOptions<CreateCaller, TestLayer, Harness>,
88
+ ): TrpcHarnessIt<Harness, Layer.Success<TestLayer>> => {
89
+ type Options = CallerOptions<CreateCaller>;
90
+ type Caller = CallerResult<CreateCaller>;
91
+ type Provided = Layer.Success<TestLayer>;
92
+
93
+ const fixtureIt = makeFixtureIt<Provided, Layer.Error<TestLayer>>(
94
+ options.layer,
95
+ );
96
+ const effectTRPC = makeTrpcHarnessTester(
97
+ fixtureIt,
98
+ options as unknown as Parameters<
99
+ typeof makeTrpcHarnessTester<
100
+ Options,
101
+ Caller,
102
+ Harness,
103
+ Provided,
104
+ Layer.Error<TestLayer>
105
+ >
106
+ >[1],
107
+ );
108
+
109
+ return withEffectTRPC(effectTRPC);
64
110
  };
package/src/testing.ts CHANGED
@@ -5,9 +5,15 @@ export {
5
5
  makeEffectCallerFactory,
6
6
  } from "./testing/caller.js";
7
7
  export type {
8
+ CallerOptions,
9
+ CallerResult,
10
+ MakeTrpcHarnessItOptions,
8
11
  MakeTrpcItOptions,
12
+ TrpcHarnessIt,
13
+ TrpcHarnessTest,
14
+ TrpcHarnessTester,
9
15
  TrpcIt,
10
16
  TrpcTest,
11
17
  TrpcTester,
12
18
  } from "./testing/types.js";
13
- export { makeTrpcIt } from "./testing/vitest.js";
19
+ export { makeTrpcHarnessIt, makeTrpcIt } from "./testing/vitest.js";
package/src/types.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { TRPCError } from "@trpc/server";
2
- import type { Effect } from "effect";
2
+ import type { Effect, Stream } from "effect";
3
3
 
4
- export type ProcedureKind = "mutation" | "query";
4
+ export type ProcedureKind = "mutation" | "query" | "subscription";
5
5
 
6
6
  export interface ProcedureInfo {
7
7
  readonly captureStackTrace: () => string | undefined;
@@ -22,3 +22,8 @@ export type EffectTRPCInstrument = <A, E, R>(
22
22
  effect: Effect.Effect<A, E, R>,
23
23
  procedure: ProcedureInfo,
24
24
  ) => Effect.Effect<A, E, R>;
25
+
26
+ export type EffectTRPCStreamInstrument = <A, E, R>(
27
+ stream: Stream.Stream<A, E, R>,
28
+ procedure: ProcedureInfo,
29
+ ) => Stream.Stream<A, E, R>;