@orpc/contract 1.14.6 → 2.0.0-beta.2

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.
@@ -1,81 +1,90 @@
1
1
  import { ORPCError } from '@orpc/client';
2
- import { get } from '@orpc/shared';
3
- import { i as isContractProcedure, V as ValidationError, v as validateORPCError } from '../shared/contract.D_dZrO__.mjs';
2
+ import { toArray } from '@orpc/shared';
3
+ import { g as getProcedureContractOrThrow, V as ValidationError, e as reconcileORPCError } from '../shared/contract.CW-2wl1i.mjs';
4
4
 
5
- class RequestValidationPluginError extends Error {
6
- }
7
- class RequestValidationPlugin {
8
- constructor(contract) {
5
+ class RequestValidationLinkPlugin {
6
+ constructor(contract, options = {}) {
9
7
  this.contract = contract;
8
+ this.forwardValidatedInput = options.forwardValidatedInput ?? false;
10
9
  }
10
+ name = "~request-validation";
11
+ forwardValidatedInput;
11
12
  init(options) {
12
- options.interceptors ??= [];
13
- options.interceptors.push(async ({ next, path, input }) => {
14
- const procedure = get(this.contract, path);
15
- if (!isContractProcedure(procedure)) {
16
- throw new RequestValidationPluginError(`No valid procedure found at path "${path.join(".")}", this may happen when the contract router is not properly configured.`);
17
- }
18
- const inputSchema = procedure["~orpc"].inputSchema;
19
- if (inputSchema) {
20
- const result = await inputSchema["~standard"].validate(input);
21
- if (result.issues) {
22
- throw new ORPCError("BAD_REQUEST", {
23
- message: "Input validation failed",
24
- data: {
25
- issues: result.issues
26
- },
27
- cause: new ValidationError({
28
- message: "Input validation failed",
29
- issues: result.issues,
30
- data: input
31
- })
32
- });
13
+ return {
14
+ ...options,
15
+ interceptors: [...toArray(options.interceptors), async ({ next, ...interceptorOptions }) => {
16
+ const procedure = getProcedureContractOrThrow(this.contract, interceptorOptions.path);
17
+ let currentInput = interceptorOptions.input;
18
+ if (procedure["~orpc"].inputSchemas) {
19
+ for (const schema of procedure["~orpc"].inputSchemas) {
20
+ const result = await schema["~standard"].validate(currentInput);
21
+ if (result.issues) {
22
+ throw new ORPCError("BAD_REQUEST", {
23
+ message: "Input validation failed",
24
+ data: {
25
+ issues: result.issues
26
+ },
27
+ cause: new ValidationError({
28
+ message: "Input validation failed",
29
+ issues: result.issues,
30
+ invalidData: currentInput
31
+ })
32
+ });
33
+ }
34
+ currentInput = result.value;
35
+ }
33
36
  }
34
- }
35
- return await next();
36
- });
37
+ return this.forwardValidatedInput ? next({ ...interceptorOptions, input: currentInput }) : next();
38
+ }]
39
+ };
37
40
  }
38
41
  }
39
42
 
40
- class ResponseValidationPlugin {
43
+ class ResponseValidationLinkPlugin {
41
44
  constructor(contract) {
42
45
  this.contract = contract;
43
46
  }
44
- /**
45
- * run before (validate after) retry plugin, because validation failed can't be retried
46
- * run before (validate after) durable iterator plugin, because we expect durable iterator to validation (if user use it)
47
- */
48
- order = 12e5;
47
+ name = "~response-validation";
49
48
  init(options) {
50
- options.interceptors ??= [];
51
- options.interceptors.push(async ({ next, path }) => {
52
- const procedure = get(this.contract, path);
53
- if (!isContractProcedure(procedure)) {
54
- throw new Error(`[ResponseValidationPlugin] no valid procedure found at path "${path.join(".")}", this may happen when the contract router is not properly configured.`);
55
- }
56
- try {
57
- const output = await next();
58
- const outputSchema = procedure["~orpc"].outputSchema;
59
- if (!outputSchema) {
49
+ return {
50
+ ...options,
51
+ interceptors: [
52
+ async ({ next, path }) => {
53
+ const procedure = getProcedureContractOrThrow(this.contract, path);
54
+ try {
55
+ return await next();
56
+ } catch (error) {
57
+ if (error instanceof ORPCError) {
58
+ throw await reconcileORPCError(procedure["~orpc"].errorMap, error);
59
+ }
60
+ throw error;
61
+ }
62
+ },
63
+ ...toArray(options.interceptors),
64
+ async ({ next, path }) => {
65
+ const procedure = getProcedureContractOrThrow(this.contract, path);
66
+ const outputSchemas = toArray(procedure["~orpc"].outputSchemas);
67
+ let output = await next();
68
+ for (let i = outputSchemas.length - 1; i >= 0; i--) {
69
+ const schema = outputSchemas[i];
70
+ const result = await schema["~standard"].validate(output);
71
+ if (result.issues) {
72
+ throw new ORPCError("INTERNAL_SERVER_ERROR", {
73
+ message: "Output validation failed",
74
+ cause: new ValidationError({
75
+ message: "Output validation failed",
76
+ issues: result.issues,
77
+ invalidData: output
78
+ })
79
+ });
80
+ }
81
+ output = result.value;
82
+ }
60
83
  return output;
61
84
  }
62
- const result = await outputSchema["~standard"].validate(output);
63
- if (result.issues) {
64
- throw new ValidationError({
65
- message: "Server response output does not match expected schema",
66
- issues: result.issues,
67
- data: output
68
- });
69
- }
70
- return result.value;
71
- } catch (e) {
72
- if (e instanceof ORPCError) {
73
- throw await validateORPCError(procedure["~orpc"].errorMap, e);
74
- }
75
- throw e;
76
- }
77
- });
85
+ ]
86
+ };
78
87
  }
79
88
  }
80
89
 
81
- export { RequestValidationPlugin, RequestValidationPluginError, ResponseValidationPlugin };
90
+ export { RequestValidationLinkPlugin, ResponseValidationLinkPlugin };
@@ -0,0 +1,180 @@
1
+ import { toArray, getConstructor, isTypescriptObject } from '@orpc/shared';
2
+ import { cloneORPCError } from '@orpc/client';
3
+
4
+ function mergeErrorMap(errorMap1, errorMap2) {
5
+ return { ...errorMap1, ...errorMap2 };
6
+ }
7
+ async function reconcileORPCError(map, error) {
8
+ const config = map[error.code];
9
+ if (!config) {
10
+ if (!error.defined) {
11
+ return error;
12
+ }
13
+ const cloned2 = cloneORPCError(error);
14
+ cloned2.defined = false;
15
+ cloned2.inferable = false;
16
+ return cloned2;
17
+ }
18
+ if (!config.data) {
19
+ if (error.defined && error.inferable) {
20
+ return error;
21
+ }
22
+ const cloned2 = cloneORPCError(error);
23
+ cloned2.defined = true;
24
+ cloned2.inferable = true;
25
+ return cloned2;
26
+ }
27
+ const validated = await config.data["~standard"].validate(error.data);
28
+ if (validated.issues) {
29
+ if (!error.defined) {
30
+ return error;
31
+ }
32
+ const cloned2 = cloneORPCError(error);
33
+ cloned2.defined = false;
34
+ cloned2.inferable = false;
35
+ return cloned2;
36
+ }
37
+ if (error.data === validated.value && error.defined && error.inferable) {
38
+ return error;
39
+ }
40
+ const cloned = cloneORPCError(error);
41
+ cloned.data = validated.value;
42
+ cloned.defined = true;
43
+ cloned.inferable = true;
44
+ return cloned;
45
+ }
46
+
47
+ function resolveMetaPlugins(baseMeta, existingPlugins, incomingPlugins) {
48
+ existingPlugins = toArray(existingPlugins);
49
+ incomingPlugins = toArray(incomingPlugins);
50
+ let meta = baseMeta;
51
+ for (const plugin of incomingPlugins) {
52
+ if (plugin.init) {
53
+ meta = plugin.init(meta);
54
+ }
55
+ }
56
+ const plugins = [...existingPlugins, ...incomingPlugins];
57
+ for (const plugin of plugins) {
58
+ if (plugin.apply) {
59
+ meta = plugin.apply(meta);
60
+ }
61
+ }
62
+ return [meta, plugins];
63
+ }
64
+ function defineMeta(name, merge) {
65
+ const metaPlugin = (value) => ({
66
+ name,
67
+ init: (meta) => {
68
+ const current = meta[name];
69
+ return {
70
+ ...meta,
71
+ [name]: merge(value, current)
72
+ };
73
+ }
74
+ });
75
+ const getMeta = (procedureOrLazy) => procedureOrLazy["~orpc"].meta[name];
76
+ return [metaPlugin, getMeta];
77
+ }
78
+
79
+ class ProcedureContract {
80
+ "~orpc";
81
+ constructor(def) {
82
+ this["~orpc"] = def;
83
+ }
84
+ /**
85
+ * Checks if the given instance satisfies the {@see ProcedureContract} class/interface.
86
+ */
87
+ static [Symbol.hasInstance](instance) {
88
+ if (this !== ProcedureContract) {
89
+ return Function.prototype[Symbol.hasInstance].call(this, instance);
90
+ }
91
+ const constructor = getConstructor(instance);
92
+ if (constructor === ProcedureContract) {
93
+ return true;
94
+ }
95
+ return isTypescriptObject(instance) && isTypescriptObject(instance["~orpc"]) && isTypescriptObject(instance["~orpc"].errorMap) && isTypescriptObject(instance["~orpc"].meta) && (instance["~orpc"].inputSchemas === void 0 || Array.isArray(instance["~orpc"].inputSchemas)) && (instance["~orpc"].outputSchemas === void 0 || Array.isArray(instance["~orpc"].outputSchemas));
96
+ }
97
+ }
98
+
99
+ function augmentContractRouter(router, options) {
100
+ if (router instanceof ProcedureContract) {
101
+ const [meta, metaPlugins] = resolveMetaPlugins(
102
+ options.meta,
103
+ options.metaPlugins,
104
+ router["~orpc"].metaPlugins
105
+ );
106
+ const enhanced2 = new ProcedureContract({
107
+ ...router["~orpc"],
108
+ errorMap: mergeErrorMap(options.errorMap, router["~orpc"].errorMap),
109
+ meta,
110
+ metaPlugins
111
+ });
112
+ return enhanced2;
113
+ }
114
+ if (!isTypescriptObject(router)) {
115
+ return router;
116
+ }
117
+ const enhanced = {};
118
+ for (const key in router) {
119
+ enhanced[key] = augmentContractRouter(router[key], options);
120
+ }
121
+ return enhanced;
122
+ }
123
+ function getRouterContract(router, path) {
124
+ let current = router;
125
+ for (let i = 0; i < path.length; i++) {
126
+ const segment = path[i];
127
+ if (!isTypescriptObject(current)) {
128
+ return void 0;
129
+ }
130
+ if (current instanceof ProcedureContract) {
131
+ return void 0;
132
+ }
133
+ current = current[segment];
134
+ }
135
+ if (!isTypescriptObject(current)) {
136
+ return void 0;
137
+ }
138
+ return current;
139
+ }
140
+ function getProcedureContractOrThrow(router, path) {
141
+ const procedure = getRouterContract(router, path);
142
+ if (!(procedure instanceof ProcedureContract)) {
143
+ throw new TypeError(`No valid procedure found at path "${path.join(".")}", this may happen when the router contract is not properly configured.`);
144
+ }
145
+ return procedure;
146
+ }
147
+ function minifyRouterContract(router) {
148
+ if (router instanceof ProcedureContract) {
149
+ const procedure = {
150
+ "~orpc": {
151
+ errorMap: {},
152
+ meta: router["~orpc"].meta
153
+ }
154
+ };
155
+ return procedure;
156
+ }
157
+ if (!isTypescriptObject(router)) {
158
+ return router;
159
+ }
160
+ const json = {};
161
+ for (const key in router) {
162
+ json[key] = minifyRouterContract(router[key]);
163
+ }
164
+ return json;
165
+ }
166
+
167
+ class ValidationError extends Error {
168
+ /**
169
+ * This array is readonly because the upstream Standard Schema returns readonly issues.
170
+ */
171
+ issues;
172
+ invalidData;
173
+ constructor(options) {
174
+ super(options.message, options);
175
+ this.issues = options.issues;
176
+ this.invalidData = options.invalidData;
177
+ }
178
+ }
179
+
180
+ export { ProcedureContract as P, ValidationError as V, augmentContractRouter as a, getRouterContract as b, minifyRouterContract as c, defineMeta as d, reconcileORPCError as e, getProcedureContractOrThrow as g, mergeErrorMap as m, resolveMetaPlugins as r };
@@ -0,0 +1,126 @@
1
+ import { ThrowableError } from '@orpc/shared';
2
+ import { ORPCErrorCode, ORPCError } from '@orpc/client';
3
+ import { StandardSchemaV1 } from '@standard-schema/spec';
4
+
5
+ /**
6
+ * TOutput default = TInput for better readability (shorter) in-case both TInput, TOutput is equal
7
+ */
8
+ type Schema<TInput, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;
9
+ type AnySchema = Schema<any>;
10
+ type SchemaIssue = StandardSchemaV1.Issue;
11
+ type InferSchemaInput<T extends AnySchema> = T extends StandardSchemaV1<infer UInput, any> ? UInput : never;
12
+ type InferSchemaOutput<T extends AnySchema> = T extends StandardSchemaV1<any, infer UOutput> ? UOutput : never;
13
+ type MergedSchema<T extends AnySchema, U extends AnySchema> = T extends Schema<infer TInput, infer TOutput> ? U extends Schema<infer UInput, infer UOutput> ? Schema<TInput & UInput, TOutput & UOutput> : never : never;
14
+
15
+ interface ErrorMapItem<TDataSchema extends AnySchema> {
16
+ message?: string;
17
+ data?: TDataSchema;
18
+ }
19
+ type ErrorMap = {
20
+ [key in ORPCErrorCode]?: ErrorMapItem<AnySchema>;
21
+ };
22
+ type ORPCErrorFromErrorMap<TErrorMap extends ErrorMap> = {
23
+ [K in keyof TErrorMap]: K extends string ? TErrorMap[K] extends ErrorMapItem<infer TDataSchema extends Schema<unknown>> ? ORPCError<K, InferSchemaOutput<TDataSchema>> : never : never;
24
+ }[keyof TErrorMap];
25
+ interface ValidationErrorOptions extends ErrorOptions {
26
+ message: string;
27
+ issues: readonly SchemaIssue[];
28
+ invalidData: unknown;
29
+ }
30
+ declare class ValidationError extends Error {
31
+ /**
32
+ * This array is readonly because the upstream Standard Schema returns readonly issues.
33
+ */
34
+ issues: readonly SchemaIssue[];
35
+ invalidData: unknown;
36
+ constructor(options: ValidationErrorOptions);
37
+ }
38
+
39
+ interface Meta {
40
+ [key: PropertyKey]: unknown;
41
+ }
42
+ interface MetaPluginDefinition<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
43
+ __TInputSchema?: {
44
+ type: TInputSchema;
45
+ };
46
+ __TOutputSchema?: {
47
+ type: TOutputSchema;
48
+ };
49
+ __TErrorMap?: {
50
+ type: TErrorMap;
51
+ };
52
+ }
53
+ interface MetaPlugin<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
54
+ /** This only for types, so it should be optional */
55
+ '~orpc'?: MetaPluginDefinition<TInputSchema, TOutputSchema, TErrorMap> | undefined;
56
+ /** Unique name of the plugin, used for identification. */
57
+ 'name': string;
58
+ /**
59
+ * Runs once when this plugin is first added to the builder.
60
+ * Use this to set up initial metadata values.
61
+ */
62
+ 'init'?: (meta: Meta) => Meta;
63
+ /**
64
+ * Runs every time metadata is updated.
65
+ * This is called for all plugins in the chain whenever a new plugin is added.
66
+ */
67
+ 'apply'?: (meta: Meta) => Meta;
68
+ }
69
+ type AnyMetaPlugin = MetaPlugin<any, any, any>;
70
+ declare const HIDDEN_META_PLUGINS_SYMBOL: unique symbol;
71
+ declare function getHiddenMetaPlugins(container: unknown): AnyMetaPlugin[] | undefined;
72
+ declare function setHiddenMetaPlugins<T extends object>(container: T, metaPlugins: AnyMetaPlugin[]): void;
73
+
74
+ interface ProcedureContractDefinition<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
75
+ __TInputSchema?: {
76
+ type: TInputSchema;
77
+ };
78
+ __TOutputSchema?: {
79
+ type: TOutputSchema;
80
+ };
81
+ /**
82
+ * Non-serializable should be optional
83
+ */
84
+ inputSchemas?: AnySchema[] | undefined;
85
+ outputSchemas?: AnySchema[] | undefined;
86
+ metaPlugins?: AnyMetaPlugin[] | undefined;
87
+ errorMap: TErrorMap;
88
+ meta: Meta;
89
+ }
90
+ declare class ProcedureContract<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
91
+ '~orpc': ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>;
92
+ constructor(def: ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>);
93
+ /**
94
+ * Checks if the given instance satisfies the {@see ProcedureContract} class/interface.
95
+ */
96
+ static [Symbol.hasInstance](instance: unknown): boolean;
97
+ }
98
+ type AnyProcedureContract = ProcedureContract<any, any, any>;
99
+
100
+ type RouterContract = AnyProcedureContract | {
101
+ [k: string]: RouterContract;
102
+ };
103
+ type InferRouterContractInputs<T extends RouterContract> = T extends ProcedureContract<infer UInputSchema, any, any> ? InferSchemaInput<UInputSchema> : {
104
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractInputs<T[K]> : never;
105
+ };
106
+ type InferRouterContractOutputs<T extends RouterContract> = T extends ProcedureContract<any, infer UOutputSchema, any> ? InferSchemaOutput<UOutputSchema> : {
107
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractOutputs<T[K]> : never;
108
+ };
109
+ type InferRouterContractErrorMap<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? UErrorMap : {
110
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractErrorMap<T[K]> : never;
111
+ }[keyof T];
112
+ /**
113
+ * Infer the union of throwable errors for entire router-contract.
114
+ */
115
+ type InferRouterContractError<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? ORPCErrorFromErrorMap<UErrorMap> | ThrowableError : {
116
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractError<T[K]> : never;
117
+ }[keyof T];
118
+ /**
119
+ * Infer throwable errors for each procedure-contract, preserving the router-contract shape.
120
+ */
121
+ type InferRouterContractErrors<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? ORPCErrorFromErrorMap<UErrorMap> | ThrowableError : {
122
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractErrors<T[K]> : never;
123
+ };
124
+
125
+ export { HIDDEN_META_PLUGINS_SYMBOL as H, ProcedureContract as P, ValidationError as V, getHiddenMetaPlugins as p, setHiddenMetaPlugins as s };
126
+ export type { AnySchema as A, ErrorMap as E, InferSchemaInput as I, MetaPlugin as M, ORPCErrorFromErrorMap as O, RouterContract as R, Schema as S, MergedSchema as a, Meta as b, AnyMetaPlugin as c, AnyProcedureContract as d, InferSchemaOutput as e, SchemaIssue as f, ErrorMapItem as g, InferRouterContractError as h, InferRouterContractErrorMap as i, InferRouterContractErrors as j, InferRouterContractInputs as k, InferRouterContractOutputs as l, MetaPluginDefinition as m, ProcedureContractDefinition as n, ValidationErrorOptions as o };
@@ -0,0 +1,126 @@
1
+ import { ThrowableError } from '@orpc/shared';
2
+ import { ORPCErrorCode, ORPCError } from '@orpc/client';
3
+ import { StandardSchemaV1 } from '@standard-schema/spec';
4
+
5
+ /**
6
+ * TOutput default = TInput for better readability (shorter) in-case both TInput, TOutput is equal
7
+ */
8
+ type Schema<TInput, TOutput = TInput> = StandardSchemaV1<TInput, TOutput>;
9
+ type AnySchema = Schema<any>;
10
+ type SchemaIssue = StandardSchemaV1.Issue;
11
+ type InferSchemaInput<T extends AnySchema> = T extends StandardSchemaV1<infer UInput, any> ? UInput : never;
12
+ type InferSchemaOutput<T extends AnySchema> = T extends StandardSchemaV1<any, infer UOutput> ? UOutput : never;
13
+ type MergedSchema<T extends AnySchema, U extends AnySchema> = T extends Schema<infer TInput, infer TOutput> ? U extends Schema<infer UInput, infer UOutput> ? Schema<TInput & UInput, TOutput & UOutput> : never : never;
14
+
15
+ interface ErrorMapItem<TDataSchema extends AnySchema> {
16
+ message?: string;
17
+ data?: TDataSchema;
18
+ }
19
+ type ErrorMap = {
20
+ [key in ORPCErrorCode]?: ErrorMapItem<AnySchema>;
21
+ };
22
+ type ORPCErrorFromErrorMap<TErrorMap extends ErrorMap> = {
23
+ [K in keyof TErrorMap]: K extends string ? TErrorMap[K] extends ErrorMapItem<infer TDataSchema extends Schema<unknown>> ? ORPCError<K, InferSchemaOutput<TDataSchema>> : never : never;
24
+ }[keyof TErrorMap];
25
+ interface ValidationErrorOptions extends ErrorOptions {
26
+ message: string;
27
+ issues: readonly SchemaIssue[];
28
+ invalidData: unknown;
29
+ }
30
+ declare class ValidationError extends Error {
31
+ /**
32
+ * This array is readonly because the upstream Standard Schema returns readonly issues.
33
+ */
34
+ issues: readonly SchemaIssue[];
35
+ invalidData: unknown;
36
+ constructor(options: ValidationErrorOptions);
37
+ }
38
+
39
+ interface Meta {
40
+ [key: PropertyKey]: unknown;
41
+ }
42
+ interface MetaPluginDefinition<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
43
+ __TInputSchema?: {
44
+ type: TInputSchema;
45
+ };
46
+ __TOutputSchema?: {
47
+ type: TOutputSchema;
48
+ };
49
+ __TErrorMap?: {
50
+ type: TErrorMap;
51
+ };
52
+ }
53
+ interface MetaPlugin<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
54
+ /** This only for types, so it should be optional */
55
+ '~orpc'?: MetaPluginDefinition<TInputSchema, TOutputSchema, TErrorMap> | undefined;
56
+ /** Unique name of the plugin, used for identification. */
57
+ 'name': string;
58
+ /**
59
+ * Runs once when this plugin is first added to the builder.
60
+ * Use this to set up initial metadata values.
61
+ */
62
+ 'init'?: (meta: Meta) => Meta;
63
+ /**
64
+ * Runs every time metadata is updated.
65
+ * This is called for all plugins in the chain whenever a new plugin is added.
66
+ */
67
+ 'apply'?: (meta: Meta) => Meta;
68
+ }
69
+ type AnyMetaPlugin = MetaPlugin<any, any, any>;
70
+ declare const HIDDEN_META_PLUGINS_SYMBOL: unique symbol;
71
+ declare function getHiddenMetaPlugins(container: unknown): AnyMetaPlugin[] | undefined;
72
+ declare function setHiddenMetaPlugins<T extends object>(container: T, metaPlugins: AnyMetaPlugin[]): void;
73
+
74
+ interface ProcedureContractDefinition<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
75
+ __TInputSchema?: {
76
+ type: TInputSchema;
77
+ };
78
+ __TOutputSchema?: {
79
+ type: TOutputSchema;
80
+ };
81
+ /**
82
+ * Non-serializable should be optional
83
+ */
84
+ inputSchemas?: AnySchema[] | undefined;
85
+ outputSchemas?: AnySchema[] | undefined;
86
+ metaPlugins?: AnyMetaPlugin[] | undefined;
87
+ errorMap: TErrorMap;
88
+ meta: Meta;
89
+ }
90
+ declare class ProcedureContract<TInputSchema extends AnySchema, TOutputSchema extends AnySchema, TErrorMap extends ErrorMap> {
91
+ '~orpc': ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>;
92
+ constructor(def: ProcedureContractDefinition<TInputSchema, TOutputSchema, TErrorMap>);
93
+ /**
94
+ * Checks if the given instance satisfies the {@see ProcedureContract} class/interface.
95
+ */
96
+ static [Symbol.hasInstance](instance: unknown): boolean;
97
+ }
98
+ type AnyProcedureContract = ProcedureContract<any, any, any>;
99
+
100
+ type RouterContract = AnyProcedureContract | {
101
+ [k: string]: RouterContract;
102
+ };
103
+ type InferRouterContractInputs<T extends RouterContract> = T extends ProcedureContract<infer UInputSchema, any, any> ? InferSchemaInput<UInputSchema> : {
104
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractInputs<T[K]> : never;
105
+ };
106
+ type InferRouterContractOutputs<T extends RouterContract> = T extends ProcedureContract<any, infer UOutputSchema, any> ? InferSchemaOutput<UOutputSchema> : {
107
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractOutputs<T[K]> : never;
108
+ };
109
+ type InferRouterContractErrorMap<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? UErrorMap : {
110
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractErrorMap<T[K]> : never;
111
+ }[keyof T];
112
+ /**
113
+ * Infer the union of throwable errors for entire router-contract.
114
+ */
115
+ type InferRouterContractError<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? ORPCErrorFromErrorMap<UErrorMap> | ThrowableError : {
116
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractError<T[K]> : never;
117
+ }[keyof T];
118
+ /**
119
+ * Infer throwable errors for each procedure-contract, preserving the router-contract shape.
120
+ */
121
+ type InferRouterContractErrors<T extends RouterContract> = T extends ProcedureContract<any, any, infer UErrorMap> ? ORPCErrorFromErrorMap<UErrorMap> | ThrowableError : {
122
+ [K in keyof T]: T[K] extends RouterContract ? InferRouterContractErrors<T[K]> : never;
123
+ };
124
+
125
+ export { HIDDEN_META_PLUGINS_SYMBOL as H, ProcedureContract as P, ValidationError as V, getHiddenMetaPlugins as p, setHiddenMetaPlugins as s };
126
+ export type { AnySchema as A, ErrorMap as E, InferSchemaInput as I, MetaPlugin as M, ORPCErrorFromErrorMap as O, RouterContract as R, Schema as S, MergedSchema as a, Meta as b, AnyMetaPlugin as c, AnyProcedureContract as d, InferSchemaOutput as e, SchemaIssue as f, ErrorMapItem as g, InferRouterContractError as h, InferRouterContractErrorMap as i, InferRouterContractErrors as j, InferRouterContractInputs as k, InferRouterContractOutputs as l, MetaPluginDefinition as m, ProcedureContractDefinition as n, ValidationErrorOptions as o };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/contract",
3
3
  "type": "module",
4
- "version": "1.14.6",
4
+ "version": "2.0.0-beta.2",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.dev",
7
7
  "repository": {
@@ -14,6 +14,7 @@
14
14
  ],
15
15
  "sideEffects": false,
16
16
  "exports": {
17
+ "./package.json": "./package.json",
17
18
  ".": {
18
19
  "types": "./dist/index.d.mts",
19
20
  "import": "./dist/index.mjs",
@@ -30,18 +31,16 @@
30
31
  ],
31
32
  "dependencies": {
32
33
  "@standard-schema/spec": "^1.1.0",
33
- "openapi-types": "^12.1.3",
34
- "@orpc/shared": "1.14.6",
35
- "@orpc/client": "1.14.6"
34
+ "@orpc/client": "2.0.0-beta.2",
35
+ "@orpc/shared": "2.0.0-beta.2"
36
36
  },
37
37
  "devDependencies": {
38
- "arktype": "2.2.0",
38
+ "arktype": "^2.1.29",
39
39
  "valibot": "^1.2.0",
40
- "zod": "^4.3.6"
40
+ "zod": "^4.4.3"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "unbuild",
44
- "build:watch": "pnpm run build --watch",
45
44
  "type:check": "tsc -b"
46
45
  }
47
46
  }
@@ -1,53 +0,0 @@
1
- import { fallbackORPCErrorStatus, ORPCError, isORPCErrorStatus } from '@orpc/client';
2
-
3
- class ValidationError extends Error {
4
- issues;
5
- data;
6
- constructor(options) {
7
- super(options.message, options);
8
- this.issues = options.issues;
9
- this.data = options.data;
10
- }
11
- }
12
- function mergeErrorMap(errorMap1, errorMap2) {
13
- return { ...errorMap1, ...errorMap2 };
14
- }
15
- async function validateORPCError(map, error) {
16
- const { code, status, message, data, cause, defined } = error;
17
- const config = map?.[error.code];
18
- if (!config || fallbackORPCErrorStatus(error.code, config.status) !== error.status) {
19
- return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error;
20
- }
21
- if (!config.data) {
22
- return defined ? error : new ORPCError(code, { defined: true, status, message, data, cause });
23
- }
24
- const validated = await config.data["~standard"].validate(error.data);
25
- if (validated.issues) {
26
- return defined ? new ORPCError(code, { defined: false, status, message, data, cause }) : error;
27
- }
28
- return new ORPCError(code, { defined: true, status, message, data: validated.value, cause });
29
- }
30
-
31
- class ContractProcedure {
32
- /**
33
- * This property holds the defined options for the contract procedure.
34
- */
35
- "~orpc";
36
- constructor(def) {
37
- if (def.route?.successStatus && isORPCErrorStatus(def.route.successStatus)) {
38
- throw new Error("[ContractProcedure] Invalid successStatus.");
39
- }
40
- if (Object.values(def.errorMap).some((val) => val && val.status && !isORPCErrorStatus(val.status))) {
41
- throw new Error("[ContractProcedure] Invalid error status code.");
42
- }
43
- this["~orpc"] = def;
44
- }
45
- }
46
- function isContractProcedure(item) {
47
- if (item instanceof ContractProcedure) {
48
- return true;
49
- }
50
- return (typeof item === "object" || typeof item === "function") && item !== null && "~orpc" in item && typeof item["~orpc"] === "object" && item["~orpc"] !== null && "errorMap" in item["~orpc"] && "route" in item["~orpc"] && "meta" in item["~orpc"];
51
- }
52
-
53
- export { ContractProcedure as C, ValidationError as V, isContractProcedure as i, mergeErrorMap as m, validateORPCError as v };