@orpc/contract 1.8.8 → 1.9.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/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ export { HTTPMethod, HTTPPath, ORPCError } from '@orpc/client';
3
3
  import { E as ErrorMap, a as EnhanceRouteOptions, A as AnyContractRouter, C as ContractProcedure, M as MergedErrorMap, b as AnySchema, c as Meta, R as Route, d as ContractRouter, e as ContractProcedureDef, S as Schema, I as InputStructure, O as OutputStructure, f as InferSchemaInput, g as InferSchemaOutput, h as ErrorFromErrorMap, i as SchemaIssue } from './shared/contract.CvRxURhn.mjs';
4
4
  export { o as AnyContractProcedure, k as ErrorMapItem, z as InferContractRouterErrorMap, x as InferContractRouterInputs, B as InferContractRouterMeta, y as InferContractRouterOutputs, l as ORPCErrorFromErrorMap, T as TypeRest, j as ValidationError, V as ValidationErrorOptions, w as enhanceRoute, p as isContractProcedure, m as mergeErrorMap, n as mergeMeta, s as mergePrefix, q as mergeRoute, t as mergeTags, r as prefixRoute, D as type, u as unshiftTagRoute, v as validateORPCError } from './shared/contract.CvRxURhn.mjs';
5
5
  import { AsyncIteratorClass } from '@orpc/shared';
6
- export { Registry, ThrowableError } from '@orpc/shared';
6
+ export { AsyncIteratorClass, Registry, ThrowableError } from '@orpc/shared';
7
7
  export { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
8
8
  import '@standard-schema/spec';
9
9
 
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { HTTPMethod, HTTPPath, ORPCError } from '@orpc/client';
3
3
  import { E as ErrorMap, a as EnhanceRouteOptions, A as AnyContractRouter, C as ContractProcedure, M as MergedErrorMap, b as AnySchema, c as Meta, R as Route, d as ContractRouter, e as ContractProcedureDef, S as Schema, I as InputStructure, O as OutputStructure, f as InferSchemaInput, g as InferSchemaOutput, h as ErrorFromErrorMap, i as SchemaIssue } from './shared/contract.CvRxURhn.js';
4
4
  export { o as AnyContractProcedure, k as ErrorMapItem, z as InferContractRouterErrorMap, x as InferContractRouterInputs, B as InferContractRouterMeta, y as InferContractRouterOutputs, l as ORPCErrorFromErrorMap, T as TypeRest, j as ValidationError, V as ValidationErrorOptions, w as enhanceRoute, p as isContractProcedure, m as mergeErrorMap, n as mergeMeta, s as mergePrefix, q as mergeRoute, t as mergeTags, r as prefixRoute, D as type, u as unshiftTagRoute, v as validateORPCError } from './shared/contract.CvRxURhn.js';
5
5
  import { AsyncIteratorClass } from '@orpc/shared';
6
- export { Registry, ThrowableError } from '@orpc/shared';
6
+ export { AsyncIteratorClass, Registry, ThrowableError } from '@orpc/shared';
7
7
  export { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
8
8
  import '@standard-schema/spec';
9
9
 
package/dist/index.mjs CHANGED
@@ -3,6 +3,7 @@ export { v as validateORPCError } from './shared/contract.D_dZrO__.mjs';
3
3
  import { mapEventIterator, ORPCError } from '@orpc/client';
4
4
  export { ORPCError } from '@orpc/client';
5
5
  import { isAsyncIteratorObject, get, isTypescriptObject, isPropertyKey } from '@orpc/shared';
6
+ export { AsyncIteratorClass } from '@orpc/shared';
6
7
 
7
8
  function mergeMeta(meta1, meta2) {
8
9
  return { ...meta1, ...meta2 };
@@ -5,6 +5,21 @@ import '@orpc/shared';
5
5
  import '@standard-schema/spec';
6
6
  import 'openapi-types';
7
7
 
8
+ declare class RequestValidationPluginError extends Error {
9
+ }
10
+ /**
11
+ * A link plugin that validates client requests against your contract schema,
12
+ * ensuring that data sent to your server matches the expected types defined in your contract.
13
+ *
14
+ * @throws {ORPCError} with code `BAD_REQUEST` (same as server side) if input doesn't match the expected schema
15
+ * @see {@link https://orpc.unnoq.com/docs/plugins/request-validation Request Validation Plugin Docs}
16
+ */
17
+ declare class RequestValidationPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
18
+ private readonly contract;
19
+ constructor(contract: AnyContractRouter);
20
+ init(options: StandardLinkOptions<T>): void;
21
+ }
22
+
8
23
  /**
9
24
  * A link plugin that validates server responses against your contract schema,
10
25
  * ensuring that data returned from your server matches the expected types defined in your contract.
@@ -17,8 +32,12 @@ import 'openapi-types';
17
32
  declare class ResponseValidationPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
18
33
  private readonly contract;
19
34
  constructor(contract: AnyContractRouter);
35
+ /**
36
+ * run before (validate after) retry plugin, because validation failed can't be retried
37
+ * run before (validate after) durable iterator plugin, because we expect durable iterator to validation (if user use it)
38
+ */
20
39
  order: number;
21
40
  init(options: StandardLinkOptions<T>): void;
22
41
  }
23
42
 
24
- export { ResponseValidationPlugin };
43
+ export { RequestValidationPlugin, RequestValidationPluginError, ResponseValidationPlugin };
@@ -5,6 +5,21 @@ import '@orpc/shared';
5
5
  import '@standard-schema/spec';
6
6
  import 'openapi-types';
7
7
 
8
+ declare class RequestValidationPluginError extends Error {
9
+ }
10
+ /**
11
+ * A link plugin that validates client requests against your contract schema,
12
+ * ensuring that data sent to your server matches the expected types defined in your contract.
13
+ *
14
+ * @throws {ORPCError} with code `BAD_REQUEST` (same as server side) if input doesn't match the expected schema
15
+ * @see {@link https://orpc.unnoq.com/docs/plugins/request-validation Request Validation Plugin Docs}
16
+ */
17
+ declare class RequestValidationPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
18
+ private readonly contract;
19
+ constructor(contract: AnyContractRouter);
20
+ init(options: StandardLinkOptions<T>): void;
21
+ }
22
+
8
23
  /**
9
24
  * A link plugin that validates server responses against your contract schema,
10
25
  * ensuring that data returned from your server matches the expected types defined in your contract.
@@ -17,8 +32,12 @@ import 'openapi-types';
17
32
  declare class ResponseValidationPlugin<T extends ClientContext> implements StandardLinkPlugin<T> {
18
33
  private readonly contract;
19
34
  constructor(contract: AnyContractRouter);
35
+ /**
36
+ * run before (validate after) retry plugin, because validation failed can't be retried
37
+ * run before (validate after) durable iterator plugin, because we expect durable iterator to validation (if user use it)
38
+ */
20
39
  order: number;
21
40
  init(options: StandardLinkOptions<T>): void;
22
41
  }
23
42
 
24
- export { ResponseValidationPlugin };
43
+ export { RequestValidationPlugin, RequestValidationPluginError, ResponseValidationPlugin };
@@ -2,12 +2,50 @@ import { ORPCError } from '@orpc/client';
2
2
  import { get } from '@orpc/shared';
3
3
  import { i as isContractProcedure, V as ValidationError, v as validateORPCError } from '../shared/contract.D_dZrO__.mjs';
4
4
 
5
+ class RequestValidationPluginError extends Error {
6
+ }
7
+ class RequestValidationPlugin {
8
+ constructor(contract) {
9
+ this.contract = contract;
10
+ }
11
+ 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
+ });
33
+ }
34
+ }
35
+ return await next();
36
+ });
37
+ }
38
+ }
39
+
5
40
  class ResponseValidationPlugin {
6
41
  constructor(contract) {
7
42
  this.contract = contract;
8
43
  }
9
- order = 15e5;
10
- // make sure run before DurableEventIteratorLinkPlugin
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;
11
49
  init(options) {
12
50
  options.interceptors ??= [];
13
51
  options.interceptors.push(async ({ next, path }) => {
@@ -40,4 +78,4 @@ class ResponseValidationPlugin {
40
78
  }
41
79
  }
42
80
 
43
- export { ResponseValidationPlugin };
81
+ export { RequestValidationPlugin, RequestValidationPluginError, ResponseValidationPlugin };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/contract",
3
3
  "type": "module",
4
- "version": "1.8.8",
4
+ "version": "1.9.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -31,13 +31,13 @@
31
31
  "dependencies": {
32
32
  "@standard-schema/spec": "^1.0.0",
33
33
  "openapi-types": "^12.1.3",
34
- "@orpc/client": "1.8.8",
35
- "@orpc/shared": "1.8.8"
34
+ "@orpc/shared": "1.9.0",
35
+ "@orpc/client": "1.9.0"
36
36
  },
37
37
  "devDependencies": {
38
- "arktype": "2.1.21",
38
+ "arktype": "2.1.22",
39
39
  "valibot": "^1.1.0",
40
- "zod": "^4.1.5"
40
+ "zod": "^4.1.11"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "unbuild",