@orpc/nest 2.0.0-beta.23 → 2.0.0-beta.25

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/README.md CHANGED
@@ -44,6 +44,7 @@ You can read the documentation [here](https://orpc.dev).
44
44
 
45
45
  - [@orpc/publisher](https://www.npmjs.com/package/@orpc/publisher): Pub/Sub with memory, Redis, and Upstash adapters.
46
46
  - [@orpc/ratelimit](https://www.npmjs.com/package/@orpc/ratelimit): Rate limiting with memory, Redis, and Upstash adapters.
47
+ - [@orpc/hibernation](https://www.npmjs.com/package/@orpc/hibernation): Leverage Hibernation APIs like [Cloudflare's Hibernation WebSocket](https://developers.cloudflare.com/durable-objects/best-practices/websockets/#durable-objects-hibernation-websocket-api).
47
48
  - [@orpc/json-schema](https://www.npmjs.com/package/@orpc/json-schema): Smart coercion for OpenAPI requests.
48
49
 
49
50
  **Framework & ecosystem integrations**
@@ -114,6 +115,7 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
114
115
  </tr>
115
116
  <tr>
116
117
  <td align="center"><a href="https://github.com/itigoore01?ref=orpc" target="_blank" rel="noopener" title="shota"><img src="https://avatars.githubusercontent.com/u/11831107?u=c976a6dc7e055eb026304c46c99100ed22b0c8e0&amp;v=4" width="139" alt="shota"/><br />shota</a></td>
118
+ <td align="center"><a href="https://github.com/ellis-driscoll?ref=orpc" target="_blank" rel="noopener" title="Ellis Driscoll"><img src="https://avatars.githubusercontent.com/u/70685966?u=c5f95bc33b5991d9744abe00052542e4a2ed3cb9&amp;v=4" width="139" alt="Ellis Driscoll"/><br />Ellis Driscoll</a></td>
117
119
  </tr>
118
120
  </table>
119
121
 
@@ -139,8 +141,9 @@ Like what we build over at [middleapi](https://github.com/middleapi)? You can he
139
141
  <td align="center"><a href="https://github.com/mr-kelly?ref=orpc" target="_blank" rel="noopener" title="Kelly Peilin Chan"><img src="https://avatars.githubusercontent.com/u/520852?u=6b0f7105f694e7b5cacf410a3f04c7044b469dc8&amp;v=4" width="119" alt="Kelly Peilin Chan"/><br />Kelly Peilin Chan</a></td>
140
142
  </tr>
141
143
  <tr>
144
+ <td align="center"><a href="https://github.com/guyariely?ref=orpc" target="_blank" rel="noopener" title="Guy Ariely"><img src="https://avatars.githubusercontent.com/u/42813496?u=edb6b7f563bf28e160a290832e7da57c0506f8ca&amp;v=4" width="119" alt="Guy Ariely"/><br />Guy Ariely</a></td>
142
145
  <td align="center"><a href="https://github.com/piscis?ref=orpc" target="_blank" rel="noopener" title="Alex"><img src="https://avatars.githubusercontent.com/u/326163?u=b245f368bd940cf51d08c0b6bf55f8257f359437&amp;v=4" width="119" alt="Alex"/><br />Alex</a></td>
143
- <td align="center"><a href="https://github.com/finom?ref=orpc" target="_blank" rel="noopener" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=29e91400dbd4a9c217048a8f59562c4f740498e6&amp;v=4" width="119" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
146
+ <td align="center"><a href="https://github.com/finom?ref=orpc" target="_blank" rel="noopener" title="Andrey Gubanov"><img src="https://avatars.githubusercontent.com/u/1082083?u=c5f2daf7ebece498e85c83367bb37b4e10e2649d&amp;v=4" width="119" alt="Andrey Gubanov"/><br />Andrey Gubanov</a></td>
144
147
  </tr>
145
148
  </table>
146
149
 
package/dist/index.d.mts CHANGED
@@ -10,6 +10,12 @@ import { ToEventStreamOptions } from '@standardserver/node';
10
10
  import { HttpAdapterHost } from '@nestjs/core';
11
11
 
12
12
  declare const ORPC_MODULE_CONFIG_SYMBOL: unique symbol;
13
+ /**
14
+ * A standard lazy request extended with NestJS route parameters,
15
+ * used as the request representation inside the `@orpc/nest` integration.
16
+ *
17
+ * @see {@link https://orpc.dev/docs/integrations/nest#toneststandardlazyrequest-option | Implement oRPC contract with NestJS - toNestStandardLazyRequest option}
18
+ */
13
19
  interface NestStandardLazyRequest extends StandardLazyRequest {
14
20
  /**
15
21
  * Route parameters extracted from the request path.
@@ -36,6 +42,13 @@ type ORPCModuleConfig = OpenAPIHandlerCodecCoreOptions<DefaultInitialContext> &
36
42
  eventStream?: undefined | ToEventStreamOptions;
37
43
  };
38
44
  };
45
+ /**
46
+ * NestJS module that configures the `@orpc/nest` integration via `forRoot`
47
+ * or `forRootAsync`, providing options such as initial context, plugins,
48
+ * and interceptors to `@Implement` handlers.
49
+ *
50
+ * @see {@link https://orpc.dev/docs/integrations/nest#configuration | Implement oRPC contract with NestJS - Configuration}
51
+ */
39
52
  declare class ORPCModule {
40
53
  static forRoot(config: ORPCModuleConfig): DynamicModule;
41
54
  static forRootAsync(options: {
@@ -45,6 +58,17 @@ declare class ORPCModule {
45
58
  }): DynamicModule;
46
59
  }
47
60
 
61
+ /**
62
+ * Decorator that implements an oRPC contract (procedure or router contract)
63
+ * on a NestJS controller method. It registers the corresponding NestJS routes
64
+ * and handles request decoding and response encoding for you.
65
+ *
66
+ * @remarks
67
+ * **Note**: Every procedure contract must define an `openapi.path` meta;
68
+ * use `populateRouterContractOpenAPIPaths` from `@orpc/openapi` to fill in missing paths.
69
+ *
70
+ * @see {@link https://orpc.dev/docs/integrations/nest#implement-your-contract | Implement oRPC contract with NestJS - Implement Your Contract}
71
+ */
48
72
  declare function Implement<T extends RouterContract>(contract: T): <U extends Promisable<ContractedRouter<T, DefaultInitialContext>>>(target: Record<PropertyKey, any>, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => U>) => void;
49
73
  declare class ImplementInterceptor implements NestInterceptor {
50
74
  private readonly config;
package/dist/index.d.ts CHANGED
@@ -10,6 +10,12 @@ import { ToEventStreamOptions } from '@standardserver/node';
10
10
  import { HttpAdapterHost } from '@nestjs/core';
11
11
 
12
12
  declare const ORPC_MODULE_CONFIG_SYMBOL: unique symbol;
13
+ /**
14
+ * A standard lazy request extended with NestJS route parameters,
15
+ * used as the request representation inside the `@orpc/nest` integration.
16
+ *
17
+ * @see {@link https://orpc.dev/docs/integrations/nest#toneststandardlazyrequest-option | Implement oRPC contract with NestJS - toNestStandardLazyRequest option}
18
+ */
13
19
  interface NestStandardLazyRequest extends StandardLazyRequest {
14
20
  /**
15
21
  * Route parameters extracted from the request path.
@@ -36,6 +42,13 @@ type ORPCModuleConfig = OpenAPIHandlerCodecCoreOptions<DefaultInitialContext> &
36
42
  eventStream?: undefined | ToEventStreamOptions;
37
43
  };
38
44
  };
45
+ /**
46
+ * NestJS module that configures the `@orpc/nest` integration via `forRoot`
47
+ * or `forRootAsync`, providing options such as initial context, plugins,
48
+ * and interceptors to `@Implement` handlers.
49
+ *
50
+ * @see {@link https://orpc.dev/docs/integrations/nest#configuration | Implement oRPC contract with NestJS - Configuration}
51
+ */
39
52
  declare class ORPCModule {
40
53
  static forRoot(config: ORPCModuleConfig): DynamicModule;
41
54
  static forRootAsync(options: {
@@ -45,6 +58,17 @@ declare class ORPCModule {
45
58
  }): DynamicModule;
46
59
  }
47
60
 
61
+ /**
62
+ * Decorator that implements an oRPC contract (procedure or router contract)
63
+ * on a NestJS controller method. It registers the corresponding NestJS routes
64
+ * and handles request decoding and response encoding for you.
65
+ *
66
+ * @remarks
67
+ * **Note**: Every procedure contract must define an `openapi.path` meta;
68
+ * use `populateRouterContractOpenAPIPaths` from `@orpc/openapi` to fill in missing paths.
69
+ *
70
+ * @see {@link https://orpc.dev/docs/integrations/nest#implement-your-contract | Implement oRPC contract with NestJS - Implement Your Contract}
71
+ */
48
72
  declare function Implement<T extends RouterContract>(contract: T): <U extends Promisable<ContractedRouter<T, DefaultInitialContext>>>(target: Record<PropertyKey, any>, propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => U>) => void;
49
73
  declare class ImplementInterceptor implements NestInterceptor {
50
74
  private readonly config;
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import { Readable } from 'node:stream';
2
- import { Module, applyDecorators, Options, Delete, Patch, Put, Post, Get, Head, HttpCode, UseInterceptors, StreamableFile, HttpException, Injectable, Inject, Optional } from '@nestjs/common';
2
+ import { Module, applyDecorators, UseInterceptors, StreamableFile, HttpException, Options, Delete, Patch, Put, Post, Get, Head, HttpCode, Injectable, Inject, Optional } from '@nestjs/common';
3
3
  import { HttpAdapterHost } from '@nestjs/core';
4
4
  import { ProcedureContract, getPathMeta } from '@orpc/contract';
5
5
  import { getOpenAPIMeta, DEFAULT_OPENAPI_METHOD, getDynamicPathParams } from '@orpc/openapi';
6
6
  import { OpenAPIHandlerCodecCore } from '@orpc/openapi/standard';
7
- import { DEFAULT_SUCCESS_STATUS, getRouter, unlazy, Procedure } from '@orpc/server';
7
+ import { unlazy, Procedure, DEFAULT_SUCCESS_STATUS, getRouter } from '@orpc/server';
8
8
  import { StandardHandler } from '@orpc/server/standard';
9
- import { mergeHttpPath, value, isAsyncIteratorObject, stringifyJSON } from '@orpc/shared';
9
+ import { value, isAsyncIteratorObject, stringifyJSON, mergeHttpPath } from '@orpc/shared';
10
10
  import { flattenStandardHeader, generateContentDisposition } from '@standardserver/core';
11
11
  import { toStandardLazyRequest, toEventStream } from '@standardserver/node';
12
12
  import { mergeMap } from 'rxjs';
@@ -76,45 +76,66 @@ const MethodDecoratorMap = {
76
76
  };
77
77
  function Implement(contract) {
78
78
  if (contract instanceof ProcedureContract) {
79
- const meta = getOpenAPIMeta(contract);
80
- if (meta?.path === void 0) {
81
- throw new TypeError(`
82
- @Implement decorator requires contract to have a 'openapi.path' meta.
83
- Please define one using '.meta(openapi({ path: '/example' }))'.
84
- Or use "populateRouterContractOpenAPIPaths" from "@orpc/openapi" utility to automatically fill in any missing paths.
85
- `);
86
- }
87
- const method = meta.method ?? DEFAULT_OPENAPI_METHOD;
88
- const path = toNestPattern(meta.prefix ? mergeHttpPath(meta.prefix, meta.path) : meta.path);
89
- const successStatus = meta.successStatus ?? DEFAULT_SUCCESS_STATUS;
90
79
  return (target, propertyKey, descriptor) => {
91
80
  applyDecorators(
92
- MethodDecoratorMap[method](path),
93
- HttpCode(successStatus),
81
+ toNestRouteDecorator(contract),
94
82
  UseInterceptors(ImplementInterceptor)
95
83
  )(target, propertyKey, descriptor);
96
84
  };
97
85
  }
98
86
  return (target, propertyKey, descriptor) => {
99
- for (const key in contract) {
100
- let methodName = `${propertyKey}_${key}`;
101
- let i = 0;
102
- while (methodName in target) {
103
- methodName = `${propertyKey}_${key}_${i++}`;
104
- }
105
- target[methodName] = async function(...args) {
106
- const router = await descriptor.value.apply(this, args);
107
- return getRouter(router, [key]);
108
- };
87
+ UseInterceptors(ImplementInterceptor)(target, propertyKey, descriptor);
88
+ implementRouterContract(contract, target, propertyKey, descriptor);
89
+ };
90
+ }
91
+ function toNestRouteDecorator(contract) {
92
+ const meta = getOpenAPIMeta(contract);
93
+ if (meta?.path === void 0) {
94
+ throw new TypeError(`
95
+ @Implement decorator requires contract to have a 'openapi.path' meta.
96
+ Please define one using '.meta(openapi({ path: '/example' }))'.
97
+ Or use "populateRouterContractOpenAPIPaths" from "@orpc/openapi" utility to automatically fill in any missing paths.
98
+ `);
99
+ }
100
+ const method = meta.method ?? DEFAULT_OPENAPI_METHOD;
101
+ const path = toNestPattern(meta.prefix ? mergeHttpPath(meta.prefix, meta.path) : meta.path);
102
+ const successStatus = meta.successStatus ?? DEFAULT_SUCCESS_STATUS;
103
+ return applyDecorators(
104
+ MethodDecoratorMap[method](path),
105
+ HttpCode(successStatus)
106
+ );
107
+ }
108
+ function implementRouterContract(contract, target, propertyKey, descriptor) {
109
+ for (const key in contract) {
110
+ let methodName = `${propertyKey}_${key}`;
111
+ let i = 0;
112
+ while (methodName in target) {
113
+ methodName = `${propertyKey}_${key}_${i++}`;
114
+ }
115
+ target[methodName] = async function(...args) {
116
+ const router = await descriptor.value.apply(this, args);
117
+ return getRouter(router, [key]);
118
+ };
119
+ Object.setPrototypeOf(target[methodName], descriptor.value);
120
+ queueMicrotask(() => {
109
121
  for (const p of Reflect.getOwnMetadataKeys(target, propertyKey)) {
110
122
  Reflect.defineMetadata(p, Reflect.getOwnMetadata(p, target, propertyKey), target, methodName);
111
123
  }
112
124
  for (const p of Reflect.getOwnMetadataKeys(target.constructor, propertyKey)) {
113
125
  Reflect.defineMetadata(p, Reflect.getOwnMetadata(p, target.constructor, propertyKey), target.constructor, methodName);
114
126
  }
115
- Implement(contract[key])(target, methodName, Object.getOwnPropertyDescriptor(target, methodName));
127
+ });
128
+ const childContract = contract[key];
129
+ const childDescriptor = Object.getOwnPropertyDescriptor(target, methodName);
130
+ if (childContract instanceof ProcedureContract) {
131
+ const routeDecorator = toNestRouteDecorator(childContract);
132
+ queueMicrotask(() => {
133
+ routeDecorator(target, methodName, childDescriptor);
134
+ });
135
+ } else {
136
+ implementRouterContract(childContract, target, methodName, childDescriptor);
116
137
  }
117
- };
138
+ }
118
139
  }
119
140
  let ImplementInterceptor = class {
120
141
  config;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/nest",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.23",
4
+ "version": "2.0.0-beta.25",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.dev",
7
7
  "repository": {
@@ -37,13 +37,13 @@
37
37
  }
38
38
  },
39
39
  "dependencies": {
40
- "@standardserver/core": "^0.6.0",
41
- "@standardserver/node": "^0.6.0",
42
- "@orpc/openapi": "2.0.0-beta.23",
43
- "@orpc/shared": "2.0.0-beta.23",
44
- "@orpc/client": "2.0.0-beta.23",
45
- "@orpc/contract": "2.0.0-beta.23",
46
- "@orpc/server": "2.0.0-beta.23"
40
+ "@standardserver/core": "^0.7.1",
41
+ "@standardserver/node": "^0.7.1",
42
+ "@orpc/client": "2.0.0-beta.25",
43
+ "@orpc/contract": "2.0.0-beta.25",
44
+ "@orpc/openapi": "2.0.0-beta.25",
45
+ "@orpc/server": "2.0.0-beta.25",
46
+ "@orpc/shared": "2.0.0-beta.25"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@fastify/cookie": "^11.0.2",
@@ -54,7 +54,7 @@
54
54
  "@nestjs/testing": "^11.1.27",
55
55
  "@types/express": "^5.0.6",
56
56
  "express": "^5.2.1",
57
- "fastify": "^5.8.5",
57
+ "fastify": "^5.11.0",
58
58
  "rxjs": "^7.8.2"
59
59
  },
60
60
  "scripts": {