@trpc/server 11.0.0-next.324 → 11.0.0-next.326

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 (91) hide show
  1. package/adapters/next-app-dir/index.d.ts +1 -0
  2. package/adapters/next-app-dir/index.js +1 -0
  3. package/dist/adapters/aws-lambda/index.js +1 -0
  4. package/dist/adapters/aws-lambda/index.mjs +1 -0
  5. package/dist/adapters/aws-lambda/utils.js +1 -0
  6. package/dist/adapters/aws-lambda/utils.mjs +1 -0
  7. package/dist/adapters/fastify/fastifyRequestHandler.js +1 -0
  8. package/dist/adapters/fastify/fastifyRequestHandler.mjs +1 -0
  9. package/dist/adapters/fetch/fetchRequestHandler.js +1 -0
  10. package/dist/adapters/fetch/fetchRequestHandler.mjs +1 -0
  11. package/dist/adapters/next-app-dir/formDataToObject.d.ts +2 -0
  12. package/dist/adapters/next-app-dir/formDataToObject.d.ts.map +1 -0
  13. package/dist/adapters/next-app-dir/formDataToObject.js +34 -0
  14. package/dist/adapters/next-app-dir/formDataToObject.mjs +32 -0
  15. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts +24 -0
  16. package/dist/adapters/next-app-dir/nextAppDirCaller.d.ts.map +1 -0
  17. package/dist/adapters/next-app-dir/nextAppDirCaller.js +86 -0
  18. package/dist/adapters/next-app-dir/nextAppDirCaller.mjs +84 -0
  19. package/dist/adapters/next-app-dir/notFound.d.ts +7 -0
  20. package/dist/adapters/next-app-dir/notFound.d.ts.map +1 -0
  21. package/dist/adapters/next-app-dir/notFound.js +16 -0
  22. package/dist/adapters/next-app-dir/notFound.mjs +14 -0
  23. package/dist/adapters/next-app-dir/redirect.d.ts +18 -0
  24. package/dist/adapters/next-app-dir/redirect.d.ts.map +1 -0
  25. package/dist/adapters/next-app-dir/redirect.js +34 -0
  26. package/dist/adapters/next-app-dir/redirect.mjs +31 -0
  27. package/dist/adapters/next-app-dir/rethrowNextErrors.d.ts +6 -0
  28. package/dist/adapters/next-app-dir/rethrowNextErrors.d.ts.map +1 -0
  29. package/dist/adapters/next-app-dir/rethrowNextErrors.js +23 -0
  30. package/dist/adapters/next-app-dir/rethrowNextErrors.mjs +21 -0
  31. package/dist/adapters/next-app-dir.d.ts +4 -0
  32. package/dist/adapters/next-app-dir.d.ts.map +1 -0
  33. package/dist/adapters/next-app-dir.js +11 -0
  34. package/dist/adapters/next-app-dir.mjs +3 -0
  35. package/dist/adapters/next.js +1 -0
  36. package/dist/adapters/next.mjs +1 -0
  37. package/dist/adapters/node-http/content-type/json/getPostBody.js +1 -0
  38. package/dist/adapters/node-http/content-type/json/getPostBody.mjs +1 -0
  39. package/dist/adapters/node-http/content-type/json/index.js +1 -0
  40. package/dist/adapters/node-http/content-type/json/index.mjs +1 -0
  41. package/dist/adapters/node-http/nodeHTTPRequestHandler.js +1 -0
  42. package/dist/adapters/node-http/nodeHTTPRequestHandler.mjs +1 -0
  43. package/dist/adapters/standalone.js +1 -0
  44. package/dist/adapters/standalone.mjs +1 -0
  45. package/dist/adapters/ws.js +1 -0
  46. package/dist/adapters/ws.mjs +1 -0
  47. package/dist/bundle-analysis.json +158 -73
  48. package/dist/http.js +1 -0
  49. package/dist/http.mjs +1 -0
  50. package/dist/index.js +1 -0
  51. package/dist/index.mjs +1 -0
  52. package/dist/rpc.js +1 -0
  53. package/dist/rpc.mjs +1 -0
  54. package/dist/shared.js +1 -0
  55. package/dist/shared.mjs +1 -0
  56. package/dist/unstable-core-do-not-import/clientish/inference.d.ts +3 -3
  57. package/dist/unstable-core-do-not-import/clientish/inference.d.ts.map +1 -1
  58. package/dist/unstable-core-do-not-import/error/getErrorShape.js +1 -0
  59. package/dist/unstable-core-do-not-import/error/getErrorShape.mjs +1 -0
  60. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.js +1 -0
  61. package/dist/unstable-core-do-not-import/http/getHTTPStatusCode.mjs +1 -0
  62. package/dist/unstable-core-do-not-import/initTRPC.d.ts.map +1 -1
  63. package/dist/unstable-core-do-not-import/initTRPC.js +2 -4
  64. package/dist/unstable-core-do-not-import/initTRPC.mjs +2 -4
  65. package/dist/unstable-core-do-not-import/procedure.d.ts +8 -7
  66. package/dist/unstable-core-do-not-import/procedure.d.ts.map +1 -1
  67. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts +9 -21
  68. package/dist/unstable-core-do-not-import/procedureBuilder.d.ts.map +1 -1
  69. package/dist/unstable-core-do-not-import/procedureBuilder.js +5 -6
  70. package/dist/unstable-core-do-not-import/procedureBuilder.mjs +6 -7
  71. package/dist/unstable-core-do-not-import/router.d.ts +3 -3
  72. package/dist/unstable-core-do-not-import/router.d.ts.map +1 -1
  73. package/dist/unstable-core-do-not-import/utils.d.ts +5 -0
  74. package/dist/unstable-core-do-not-import/utils.d.ts.map +1 -1
  75. package/dist/unstable-core-do-not-import/utils.js +9 -0
  76. package/dist/unstable-core-do-not-import/utils.mjs +9 -1
  77. package/dist/unstable-core-do-not-import.js +1 -0
  78. package/dist/unstable-core-do-not-import.mjs +1 -1
  79. package/package.json +8 -3
  80. package/src/adapters/next-app-dir/formDataToObject.ts +36 -0
  81. package/src/adapters/next-app-dir/nextAppDirCaller.ts +129 -0
  82. package/src/adapters/next-app-dir/notFound.ts +12 -0
  83. package/src/adapters/next-app-dir/redirect.ts +30 -0
  84. package/src/adapters/next-app-dir/rethrowNextErrors.ts +25 -0
  85. package/src/adapters/next-app-dir.ts +3 -0
  86. package/src/unstable-core-do-not-import/clientish/inference.ts +9 -5
  87. package/src/unstable-core-do-not-import/initTRPC.ts +2 -6
  88. package/src/unstable-core-do-not-import/procedure.ts +10 -17
  89. package/src/unstable-core-do-not-import/procedureBuilder.ts +34 -49
  90. package/src/unstable-core-do-not-import/router.ts +4 -3
  91. package/src/unstable-core-do-not-import/utils.ts +12 -0
@@ -0,0 +1,129 @@
1
+ import { getTRPCErrorFromUnknown, TRPCError } from '../../@trpc/server';
2
+ // FIXME: fix lint rule, this is ok
3
+ // eslint-disable-next-line no-restricted-imports
4
+ import type { ErrorHandlerOptions } from '../../unstable-core-do-not-import/procedure';
5
+ // FIXME: fix lint rule, this is ok
6
+ // eslint-disable-next-line no-restricted-imports
7
+ import type { CallerOverride } from '../../unstable-core-do-not-import/procedureBuilder';
8
+ // FIXME: fix lint rule, this is ok
9
+ // eslint-disable-next-line no-restricted-imports
10
+ import type {
11
+ MaybePromise,
12
+ Simplify,
13
+ } from '../../unstable-core-do-not-import/types';
14
+ import { formDataToObject } from './formDataToObject';
15
+ import { TRPCRedirectError } from './redirect';
16
+ import { rethrowNextErrors } from './rethrowNextErrors';
17
+
18
+ type ContextCallback<TContext> = object extends TContext
19
+ ? {
20
+ createContext?: () => MaybePromise<TContext>;
21
+ }
22
+ : {
23
+ createContext: () => MaybePromise<TContext>;
24
+ };
25
+
26
+ /**
27
+ * Create a caller that works with Next.js React Server Components & Server Actions
28
+ */
29
+ export function nextAppDirCaller<TContext>(
30
+ config: Simplify<
31
+ {
32
+ /**
33
+ * Transform form data to a `Record` before passing it to the procedure
34
+ * @default true
35
+ */
36
+ normalizeFormData?: boolean;
37
+ /**
38
+ * Called when an error occurs in the handler
39
+ */
40
+ onError?: (opts: ErrorHandlerOptions<TContext>) => void;
41
+ } & ContextCallback<TContext>
42
+ >,
43
+ ): CallerOverride<TContext> {
44
+ const {
45
+ normalizeFormData = true,
46
+
47
+ // rethrowNextErrors = true
48
+ } = config;
49
+ const createContext = async (): Promise<TContext> => {
50
+ return config?.createContext?.() ?? ({} as TContext);
51
+ };
52
+ return async (opts) => {
53
+ const ctx: TContext = await createContext().catch((cause) => {
54
+ const error = new TRPCError({
55
+ code: 'INTERNAL_SERVER_ERROR',
56
+ message: 'Failed to create context',
57
+ cause,
58
+ });
59
+
60
+ throw error;
61
+ });
62
+
63
+ const handleError = (cause: unknown) => {
64
+ const error = getTRPCErrorFromUnknown(cause);
65
+
66
+ config.onError?.({
67
+ ctx,
68
+ error,
69
+ input: opts.args[0],
70
+ path: '',
71
+ type: opts._def.type,
72
+ });
73
+
74
+ rethrowNextErrors(error);
75
+
76
+ throw error;
77
+ };
78
+ switch (opts._def.type) {
79
+ case 'mutation': {
80
+ /**
81
+ * When you wrap an action with useFormState, it gets an extra argument as its first argument.
82
+ * The submitted form data is therefore its second argument instead of its first as it would usually be.
83
+ * The new first argument that gets added is the current state of the form.
84
+ * @see https://react.dev/reference/react-dom/hooks/useFormState#my-action-can-no-longer-read-the-submitted-form-data
85
+ */
86
+ let input = opts.args.length === 1 ? opts.args[0] : opts.args[1];
87
+ if (normalizeFormData && input instanceof FormData) {
88
+ input = formDataToObject(input);
89
+ }
90
+
91
+ return await opts
92
+ .invoke({
93
+ type: opts._def.type,
94
+ ctx,
95
+ getRawInput: async () => input,
96
+ path: '',
97
+ input,
98
+ })
99
+ .then((data) => {
100
+ if (data instanceof TRPCRedirectError) throw data;
101
+ return data;
102
+ })
103
+ .catch(handleError);
104
+ }
105
+ case 'query': {
106
+ const input = opts.args[0];
107
+ return await opts
108
+ .invoke({
109
+ type: opts._def.type,
110
+ ctx,
111
+ getRawInput: async () => input,
112
+ path: '',
113
+ input,
114
+ })
115
+ .then((data) => {
116
+ if (data instanceof TRPCRedirectError) throw data;
117
+ return data;
118
+ })
119
+ .catch(handleError);
120
+ }
121
+ default: {
122
+ throw new TRPCError({
123
+ code: 'NOT_IMPLEMENTED',
124
+ message: `Not implemented for type ${opts._def.type}`,
125
+ });
126
+ }
127
+ }
128
+ };
129
+ }
@@ -0,0 +1,12 @@
1
+ import type { notFound as __notFound } from 'next/navigation';
2
+ import { TRPCError } from '../../@trpc/server';
3
+
4
+ /**
5
+ * Like `next/navigation`'s `notFound()` but throws a `TRPCError` that later will be handled by Next.js
6
+ * @public
7
+ */
8
+ export const notFound: typeof __notFound = () => {
9
+ throw new TRPCError({
10
+ code: 'NOT_FOUND',
11
+ });
12
+ };
@@ -0,0 +1,30 @@
1
+ import type { RedirectType } from 'next/navigation';
2
+ import { TRPCError } from '../../@trpc/server';
3
+
4
+ /**
5
+ * @internal
6
+ */
7
+ export class TRPCRedirectError extends TRPCError {
8
+ public readonly args;
9
+ constructor(url: URL | string, redirectType?: RedirectType) {
10
+ super({
11
+ // TODO(?): This should maybe a custom error code
12
+ code: 'UNPROCESSABLE_CONTENT',
13
+ message: `Redirect error to "${url}" that will be handled by Next.js`,
14
+ });
15
+
16
+ this.args = [url.toString(), redirectType] as const;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Like `next/navigation`'s `redirect()` but throws a `TRPCError` that later will be handled by Next.js
22
+ * This provides better typesafety than the `next/navigation`'s `redirect()` since the action continues
23
+ * to execute on the frontend even if Next's `redirect()` has a return type of `never`.
24
+ * @public
25
+ * @remark You should only use this if you're also using `nextAppDirCaller`.
26
+ */
27
+ export const redirect = (url: URL | string, redirectType?: RedirectType) => {
28
+ // We rethrow this internally so the returntype on the client is undefined.
29
+ return new TRPCRedirectError(url, redirectType) as unknown as undefined;
30
+ };
@@ -0,0 +1,25 @@
1
+ import { isNotFoundError } from 'next/dist/client/components/not-found';
2
+ import { isRedirectError } from 'next/dist/client/components/redirect';
3
+ import {
4
+ notFound as __notFound,
5
+ redirect as __redirect,
6
+ } from 'next/navigation';
7
+ import type { TRPCError } from '../../@trpc/server';
8
+ import { TRPCRedirectError } from './redirect';
9
+
10
+ /**
11
+ * Rethrow errors that should be handled by Next.js
12
+ */
13
+
14
+ export const rethrowNextErrors = (error: TRPCError) => {
15
+ if (error.code === 'NOT_FOUND') {
16
+ __notFound();
17
+ }
18
+ if (error instanceof TRPCRedirectError) {
19
+ __redirect(...error.args);
20
+ }
21
+ const { cause } = error;
22
+ if (isRedirectError(cause) || isNotFoundError(cause)) {
23
+ throw error.cause;
24
+ }
25
+ };
@@ -0,0 +1,3 @@
1
+ export { nextAppDirCaller as experimental_nextAppDirCaller } from './next-app-dir/nextAppDirCaller';
2
+ export { redirect as experimental_redirect } from './next-app-dir/redirect';
3
+ export { notFound as experimental_notFound } from './next-app-dir/notFound';
@@ -1,5 +1,9 @@
1
1
  import type { inferObservableValue } from '../../observable';
2
- import type { AnyProcedure, inferProcedureInput } from '../procedure';
2
+ import type {
3
+ AnyProcedure,
4
+ inferProcedureInput,
5
+ inferProcedureOutput,
6
+ } from '../procedure';
3
7
  import type { AnyRouter, RouterRecord } from '../router';
4
8
  import type {
5
9
  AnyClientTypes,
@@ -16,16 +20,16 @@ export type inferTransformedProcedureOutput<
16
20
  TInferrable extends InferrableClientTypes,
17
21
  TProcedure extends AnyProcedure,
18
22
  > = inferClientTypes<TInferrable>['transformer'] extends false
19
- ? Serialize<TProcedure['_def']['_output_out']>
20
- : TProcedure['_def']['_output_out'];
23
+ ? Serialize<inferProcedureOutput<TProcedure>>
24
+ : inferProcedureOutput<TProcedure>;
21
25
  /** @internal */
22
26
 
23
27
  export type inferTransformedSubscriptionOutput<
24
28
  TInferrable extends InferrableClientTypes,
25
29
  TProcedure extends AnyProcedure,
26
30
  > = inferClientTypes<TInferrable>['transformer'] extends false
27
- ? Serialize<inferObservableValue<TProcedure['_def']['_output_out']>>
28
- : inferObservableValue<TProcedure['_def']['_output_out']>;
31
+ ? Serialize<inferObservableValue<inferProcedureOutput<TProcedure>>>
32
+ : inferObservableValue<inferProcedureOutput<TProcedure>>;
29
33
 
30
34
  export type GetInferenceHelpers<
31
35
  TType extends 'input' | 'output',
@@ -1,4 +1,3 @@
1
- import { createFlatProxy } from './createProxy';
2
1
  import {
3
2
  defaultFormatter,
4
3
  type DefaultErrorShape,
@@ -16,6 +15,7 @@ import {
16
15
  import type { DataTransformerOptions } from './transformer';
17
16
  import { defaultTransformer, getDataTransformer } from './transformer';
18
17
  import type { Unwrap, ValidateShape } from './types';
18
+ import { $typesProxy } from './utils';
19
19
 
20
20
  type inferErrorFormatterShape<TType> = TType extends ErrorFormatter<
21
21
  any,
@@ -95,11 +95,7 @@ class TRPCBuilder<TContext extends object, TMeta extends object> {
95
95
  * These are just types, they can't be used at runtime
96
96
  * @internal
97
97
  */
98
- $types: createFlatProxy((key) => {
99
- throw new Error(
100
- `Tried to access "$types.${key}" which is not available at runtime`,
101
- );
102
- }),
98
+ $types: $typesProxy,
103
99
  };
104
100
 
105
101
  {
@@ -23,7 +23,6 @@ export interface ProcedureOptions {
23
23
  interface BuiltProcedureDef {
24
24
  input: unknown;
25
25
  output: unknown;
26
- experimental_caller?: true;
27
26
  }
28
27
 
29
28
  /**
@@ -35,8 +34,10 @@ export interface Procedure<
35
34
  TDef extends BuiltProcedureDef,
36
35
  > {
37
36
  _def: {
38
- _input_in: TDef['input'];
39
- _output_out: TDef['output'];
37
+ $types: {
38
+ input: TDef['input'];
39
+ output: TDef['output'];
40
+ };
40
41
  procedure: true;
41
42
  type: TType;
42
43
  /**
@@ -44,20 +45,12 @@ export interface Procedure<
44
45
  * Meta is not inferrable on individual procedures, only on the router
45
46
  */
46
47
  meta: unknown;
47
- experimental_caller: TDef['experimental_caller'] extends true
48
- ? true
49
- : false;
48
+ experimental_caller: boolean;
50
49
  };
51
50
  /**
52
51
  * @internal
53
52
  */
54
- (
55
- opts: TDef['experimental_caller'] extends true
56
- ? TDef['input']
57
- : ProcedureCallOptions,
58
- ): Promise<
59
- TDef['experimental_caller'] extends true ? TDef['output'] : unknown
60
- >;
53
+ (opts: ProcedureCallOptions<unknown>): Promise<TDef['output']>;
61
54
  }
62
55
 
63
56
  export interface QueryProcedure<TDef extends BuiltProcedureDef>
@@ -75,15 +68,15 @@ export type AnySubscriptionProcedure = SubscriptionProcedure<any>;
75
68
  export type AnyProcedure = Procedure<ProcedureType, any>;
76
69
 
77
70
  export type inferProcedureInput<TProcedure extends AnyProcedure> =
78
- undefined extends inferProcedureParams<TProcedure>['_input_in']
79
- ? void | inferProcedureParams<TProcedure>['_input_in']
80
- : inferProcedureParams<TProcedure>['_input_in'];
71
+ undefined extends inferProcedureParams<TProcedure>['$types']['input']
72
+ ? void | inferProcedureParams<TProcedure>['$types']['input']
73
+ : inferProcedureParams<TProcedure>['$types']['input'];
81
74
 
82
75
  export type inferProcedureParams<TProcedure> = TProcedure extends AnyProcedure
83
76
  ? TProcedure['_def']
84
77
  : never;
85
78
  export type inferProcedureOutput<TProcedure> =
86
- inferProcedureParams<TProcedure>['_output_out'];
79
+ inferProcedureParams<TProcedure>['$types']['output'];
87
80
 
88
81
  /**
89
82
  * @internal
@@ -30,7 +30,7 @@ import type {
30
30
  Simplify,
31
31
  TypeError,
32
32
  } from './types';
33
- import { mergeWithoutOverrides } from './utils';
33
+ import { $typesProxy, mergeWithoutOverrides } from './utils';
34
34
 
35
35
  type IntersectIfDefined<TType, TWith> = TType extends UnsetMarker
36
36
  ? TWith
@@ -45,9 +45,9 @@ type DefaultValue<TValue, TFallback> = TValue extends UnsetMarker
45
45
  ? TFallback
46
46
  : TValue;
47
47
 
48
- export type CallerOverride = (opts: {
48
+ export type CallerOverride<TContext> = (opts: {
49
49
  args: unknown[];
50
- invoke: (opts: ProcedureCallOptions) => Promise<unknown>;
50
+ invoke: (opts: ProcedureCallOptions<TContext>) => Promise<unknown>;
51
51
  _def: AnyProcedure['_def'];
52
52
  }) => Promise<unknown>;
53
53
  type ProcedureBuilderDef<TMeta> = {
@@ -70,7 +70,7 @@ type ProcedureBuilderDef<TMeta> = {
70
70
  */
71
71
  subscription?: boolean;
72
72
  type?: ProcedureType;
73
- caller?: CallerOverride;
73
+ caller?: CallerOverride<unknown>;
74
74
  };
75
75
 
76
76
  type AnyProcedureBuilderDef = ProcedureBuilderDef<any>;
@@ -301,18 +301,14 @@ export interface ProcedureBuilder<
301
301
  TOutputIn,
302
302
  $Output
303
303
  >,
304
- ): QueryProcedure<
305
- TCaller extends true
306
- ? {
307
- experimental_caller: true;
308
- input: DefaultValue<TInputIn, void>;
309
- output: DefaultValue<TOutputOut, $Output>;
310
- }
311
- : {
312
- input: DefaultValue<TInputIn, void>;
313
- output: DefaultValue<TOutputOut, $Output>;
314
- }
315
- >;
304
+ ): TCaller extends true
305
+ ? (
306
+ input: DefaultValue<TInputIn, void>,
307
+ ) => Promise<DefaultValue<TOutputOut, $Output>>
308
+ : QueryProcedure<{
309
+ input: DefaultValue<TInputIn, void>;
310
+ output: DefaultValue<TOutputOut, $Output>;
311
+ }>;
316
312
 
317
313
  /**
318
314
  * Mutation procedure
@@ -327,18 +323,14 @@ export interface ProcedureBuilder<
327
323
  TOutputIn,
328
324
  $Output
329
325
  >,
330
- ): MutationProcedure<
331
- TCaller extends true
332
- ? {
333
- experimental_caller: true;
334
- input: DefaultValue<TInputIn, void>;
335
- output: DefaultValue<TOutputOut, $Output>;
336
- }
337
- : {
338
- input: DefaultValue<TInputIn, void>;
339
- output: DefaultValue<TOutputOut, $Output>;
340
- }
341
- >;
326
+ ): TCaller extends true
327
+ ? (
328
+ input: DefaultValue<TInputIn, void>,
329
+ ) => Promise<DefaultValue<TOutputOut, $Output>>
330
+ : MutationProcedure<{
331
+ input: DefaultValue<TInputIn, void>;
332
+ output: DefaultValue<TOutputOut, $Output>;
333
+ }>;
342
334
 
343
335
  /**
344
336
  * Subscription procedure
@@ -353,25 +345,19 @@ export interface ProcedureBuilder<
353
345
  TOutputIn,
354
346
  $Output
355
347
  >,
356
- ): SubscriptionProcedure<
357
- TCaller extends true
358
- ? {
359
- experimental_caller: true;
360
- input: DefaultValue<TInputIn, void>;
361
- output: DefaultValue<TOutputOut, inferObservableValue<$Output>>;
362
- }
363
- : {
364
- input: DefaultValue<TInputIn, void>;
365
- output: DefaultValue<TOutputOut, inferObservableValue<$Output>>;
366
- }
367
- >;
348
+ ): TCaller extends true
349
+ ? TypeError<'Not implemented'>
350
+ : SubscriptionProcedure<{
351
+ input: DefaultValue<TInputIn, void>;
352
+ output: DefaultValue<TOutputOut, inferObservableValue<$Output>>;
353
+ }>;
368
354
 
369
355
  /**
370
356
  * Overrides the way a procedure is invoked
371
357
  * Do not use this unless you know what you're doing - this is an experimental API
372
358
  */
373
359
  experimental_caller(
374
- caller: CallerOverride,
360
+ caller: CallerOverride<TContext>,
375
361
  ): ProcedureBuilder<
376
362
  TContext,
377
363
  TMeta,
@@ -510,10 +496,9 @@ function createResolver(
510
496
  const _def: AnyProcedure['_def'] = {
511
497
  ...finalBuilder._def,
512
498
  type: _defIn.type,
513
- experimental_caller: finalBuilder._def.caller ? true : false,
514
- _input_in: null,
515
- _output_out: null,
499
+ experimental_caller: Boolean(finalBuilder._def.caller),
516
500
  meta: finalBuilder._def.meta,
501
+ $types: $typesProxy,
517
502
  };
518
503
 
519
504
  const invoke = createProcedureCaller(finalBuilder._def);
@@ -521,8 +506,8 @@ function createResolver(
521
506
  if (!callerOverride) {
522
507
  return invoke;
523
508
  }
524
- const callerWrapper = (...args: unknown[]) => {
525
- return callerOverride({
509
+ const callerWrapper = async (...args: unknown[]) => {
510
+ return await callerOverride({
526
511
  args,
527
512
  invoke,
528
513
  _def: _def,
@@ -536,8 +521,8 @@ function createResolver(
536
521
  /**
537
522
  * @internal
538
523
  */
539
- export interface ProcedureCallOptions {
540
- ctx: unknown;
524
+ export interface ProcedureCallOptions<TContext> {
525
+ ctx: TContext;
541
526
  getRawInput: GetRawInputFn;
542
527
  input?: unknown;
543
528
  path: string;
@@ -550,7 +535,7 @@ If you want to call this function on the server, see https://trpc.io/docs/v11/se
550
535
  `.trim();
551
536
 
552
537
  function createProcedureCaller(_def: AnyProcedureBuilderDef): AnyProcedure {
553
- async function procedure(opts: ProcedureCallOptions) {
538
+ async function procedure(opts: ProcedureCallOptions<unknown>) {
554
539
  // is direct server-side call
555
540
  if (!opts || !('getRawInput' in opts)) {
556
541
  throw new Error(codeblock);
@@ -6,6 +6,7 @@ import type {
6
6
  AnyProcedure,
7
7
  ErrorHandlerOptions,
8
8
  inferProcedureInput,
9
+ inferProcedureOutput,
9
10
  } from './procedure';
10
11
  import type { ProcedureCallOptions } from './procedureBuilder';
11
12
  import type { AnyRootTypes, RootConfig } from './rootConfig';
@@ -21,8 +22,8 @@ type DecorateProcedure<TProcedure extends AnyProcedure> = (
21
22
  input: inferProcedureInput<TProcedure>,
22
23
  ) => Promise<
23
24
  TProcedure['_def']['type'] extends 'subscription'
24
- ? Observable<TProcedure['_def']['_output_out'], TRPCError>
25
- : TProcedure['_def']['_output_out']
25
+ ? Observable<inferProcedureOutput<TProcedure>, TRPCError>
26
+ : inferProcedureOutput<TProcedure>
26
27
  >;
27
28
 
28
29
  /**
@@ -224,7 +225,7 @@ function isProcedure(
224
225
  * @internal
225
226
  */
226
227
  export function callProcedure(
227
- opts: ProcedureCallOptions & {
228
+ opts: ProcedureCallOptions<unknown> & {
228
229
  procedures: RouterRecord;
229
230
  allowMethodOverride?: boolean;
230
231
  },
@@ -1,3 +1,5 @@
1
+ import { createFlatProxy } from './createProxy';
2
+
1
3
  /**
2
4
  * Ensures there are no duplicate keys when building a procedure.
3
5
  * @internal
@@ -41,3 +43,13 @@ export function omitPrototype<TObj extends Record<string, unknown>>(
41
43
  ): TObj {
42
44
  return Object.assign(Object.create(null), obj);
43
45
  }
46
+
47
+ /**
48
+ * Prevents access to `$types` at runtime
49
+ * @internal
50
+ */
51
+ export const $typesProxy = createFlatProxy<any>((key) => {
52
+ throw new Error(
53
+ `Tried to access "$types.${key}" which is not available at runtime`,
54
+ );
55
+ });