@longzai-intelligence-transport/http-adapter-nestjs 0.1.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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @longzai-intelligence-transport/http-adapter-nestjs
2
+
3
+ NestJS Swagger 集成适配器,提供路由装饰器和 Zod 到 OpenAPI 的转换工具。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ bun add @longzai-intelligence-transport/http-adapter-nestjs
9
+ ```
10
+
11
+ ## 功能特性
12
+
13
+ - **路由装饰器** - `@ApiRoute` 装饰器,自动生成 Swagger 文档
14
+ - **认证装饰器** - `@RequireAuth` 和 `@PublicRoute` 装饰器
15
+ - **Zod 转 OpenAPI** - 将 Zod Schema 转换为 OpenAPI Schema
16
+ - **类型提取** - 从 Zod Schema 提取类型描述
17
+
18
+ ## 依赖
19
+
20
+ - `@nestjs/common` - NestJS 核心模块(peer dependency)
21
+ - `@nestjs/swagger` - Swagger 集成模块(peer dependency)
22
+ - `zod` - Schema 验证(peer dependency)
23
+ - `@longzai-intelligence-transport/http-core` - 核心模块
24
+
25
+ ## 使用示例
26
+
27
+ ```typescript
28
+ import {
29
+ ApiRoute,
30
+ RequireAuth,
31
+ zodToOpenApi,
32
+ } from '@longzai-intelligence-transport/http-adapter-nestjs';
33
+ import { Controller, Get } from '@nestjs/common';
34
+
35
+ @Controller('users')
36
+ @RequireAuth()
37
+ export class UserController {
38
+ @Get(':id')
39
+ @ApiRoute({
40
+ summary: '获取用户信息',
41
+ response: UserSchema,
42
+ })
43
+ async getUser() {
44
+ // ...
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## 导出模块
50
+
51
+ ### 装饰器
52
+
53
+ - `ApiRoute` - 路由装饰器,自动生成 Swagger 文档
54
+ - `RequireAuth` - 标记需要认证的路由
55
+ - `PublicRoute` - 标记公开路由
56
+ - `ROUTE_DEFINITION_KEY` - 路由定义元数据键
57
+
58
+ ### 工具函数
59
+
60
+ - `zodToOpenApi` - 将 Zod Schema 转换为 OpenAPI Schema
61
+ - `extractZodDescriptions` - 提取 Zod Schema 字段描述
62
+ - `getTypeName` - 获取类型名称
63
+ - `getDef` - 获取 Zod 定义
64
+
65
+ ### 类型
66
+
67
+ - `OpenApiSchema` - OpenAPI Schema 类型
68
+ - `RouteDefinition` - 路由定义类型(从 core 重新导出)
69
+ - `HttpMethod` - HTTP 方法类型(从 core 重新导出)
70
+
71
+ ## 许可证
72
+
73
+ UNLICENSED
@@ -0,0 +1,429 @@
1
+ import { ApiResponse, HttpMethod, HttpMethod as HttpMethod$1, InferRouteBody, InferRouteFullResponse, InferRouteParams, InferRouteQuery, InferRouteResponse, InferRouteResponse as InferRouteResponse$1, InferRouteReturn, RouteDefinition, RouteDefinition as RouteDefinition$1, RouteGroup, RouteGroup as RouteGroup$1, createTypedEmpty, createTypedResponse } from "@longzai-intelligence-transport/http-core";
2
+ import { ZodType, core } from "zod";
3
+
4
+ //#region src/decorators/api-route.decorator.d.ts
5
+ /**
6
+ * 任意路由定义类型
7
+ *
8
+ * 用于装饰器内部,放宽泛型约束以便统一处理
9
+ */
10
+ type AnyRouteDefinition = RouteDefinition$1<HttpMethod$1, string, ZodType | undefined, ZodType | undefined, ZodType | undefined, ZodType>;
11
+ /**
12
+ * 路由元数据 Key
13
+ *
14
+ * 用于在反射元数据中存储路由定义信息的键名
15
+ */
16
+ declare const ROUTE_DEFINITION_KEY = "route_definition";
17
+ /**
18
+ * 错误响应配置项
19
+ */
20
+ type ErrorResponseBody = {
21
+ /**
22
+ * HTTP 状态码
23
+ */
24
+ status: number;
25
+ /**
26
+ * 错误描述文本
27
+ */
28
+ description: string;
29
+ };
30
+ /**
31
+ * API 路由装饰器可选项
32
+ */
33
+ type ApiRouteOptions$1 = {
34
+ /**
35
+ * 是否需要认证,默认为 true
36
+ */
37
+ requireAuth?: boolean;
38
+ /**
39
+ * 成功响应的描述文本,默认为"成功"
40
+ */
41
+ successDescription?: string;
42
+ /**
43
+ * 错误响应配置数组
44
+ */
45
+ errorResponses?: Array<ErrorResponseBody>;
46
+ };
47
+ /**
48
+ * 根据路由定义自动生成 Swagger 文档的装饰器
49
+ *
50
+ * 集成路由定义与 NestJS Swagger,自动添加认证标记、API 操作描述、
51
+ * 响应模式、路径参数、查询参数和请求体。
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * @ApiRoute(userRoutes.getProfile, { requireAuth: true })
56
+ * async getProfile() { ... }
57
+ * ```;
58
+ *
59
+ * @typeParam T - 路由定义类型
60
+ * @param route - 路由定义对象,包含请求和响应的 Zod schema
61
+ * @param options - 可选配置项
62
+ * @param options.requireAuth - 是否需要认证,默认为 true
63
+ * @param options.successDescription - 成功响应的描述文本,默认为"成功"
64
+ * @param options.errorResponses - 错误响应配置数组
65
+ * @returns 组合装饰器
66
+ */
67
+ declare function ApiRoute<T extends AnyRouteDefinition>(route: T, options?: ApiRouteOptions$1): <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
68
+ /**
69
+ * 标记路由需要认证
70
+ *
71
+ * 便捷装饰器,用于显式声明接口需要 Bearer Token 认证。等同于直接使用 @ApiBearerAuth()。
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * @RequireAuth()
76
+ * async protectedEndpoint() { ... }
77
+ * ```;
78
+ *
79
+ * @returns Bearer Auth 装饰器
80
+ */
81
+ declare function RequireAuth(): ClassDecorator & MethodDecorator;
82
+ /**
83
+ * 标记路由为公开接口
84
+ *
85
+ * 空装饰器,用于显式声明接口不需要认证。实际的公开访问控制需要在全局 Guard 中配合 SkipAuth 装饰器实现。
86
+ *
87
+ * @remarks
88
+ * 此装饰器本身不实现任何功能,仅作为代码可读性的标记。
89
+ * 如需跳过认证,请配合使用 @SetMetadata('isPublic', true) 或自定义装饰器。
90
+ * @example
91
+ * ```typescript
92
+ * @PublicRoute()
93
+ * async publicEndpoint() { ... }
94
+ * ```;
95
+ *
96
+ * @returns 空组合装饰器
97
+ */
98
+ declare function PublicRoute(): <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
99
+ //#endregion
100
+ //#region src/decorators/typed-controller.decorator.d.ts
101
+ /**
102
+ * 可用于 TypedController 的路由类型
103
+ *
104
+ * 包含 prefix 和可选的 tags、auth 属性
105
+ */
106
+ type TypedControllerRoute = {
107
+ /**
108
+ * 路径前缀
109
+ */
110
+ readonly prefix: string;
111
+ /**
112
+ * 认证策略
113
+ */
114
+ readonly auth?: string;
115
+ /**
116
+ * API 标签
117
+ */
118
+ readonly tags?: string[];
119
+ };
120
+ /**
121
+ * 带有路由定义的路由分组
122
+ *
123
+ * 扩展 RouteGroup,额外包含 routes 属性用于存放路由定义集合
124
+ *
125
+ * @typeParam TPrefix - 路径前缀类型
126
+ */
127
+ type RouteGroupWithRoutes<TPrefix extends string> = RouteGroup$1<TPrefix> & {
128
+ /**
129
+ * 路由定义集合
130
+ */
131
+ readonly routes: unknown;
132
+ };
133
+ /**
134
+ * TypedController 可接受的输入类型
135
+ *
136
+ * 支持路由分组、带路由定义的路由分组,以及手动构造的路由类型
137
+ *
138
+ * @typeParam TPrefix - 路径前缀类型
139
+ */
140
+ type TypedControllerInput<TPrefix extends string> = RouteGroup$1<TPrefix> | RouteGroupWithRoutes<TPrefix> | TypedControllerRoute;
141
+ /**
142
+ * 从路由分组自动生成 Controller 和 Swagger 文档标签的装饰器
143
+ *
144
+ * 集成路由分组与 NestJS Controller,自动提取分组的 prefix 设置 @Controller(),
145
+ * 提取 tags 设置 @ApiTags(),替代手动组合 @Controller() + @ApiTags() 的写法。
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // 使用 RouteGroup
150
+ * @TypedController(clientApi)
151
+ * export class ActivityController {}
152
+ *
153
+ * // 使用带 routes 的路由分组
154
+ * @TypedController(authRoutes)
155
+ * export class AuthController {}
156
+ * ```;
157
+ *
158
+ * @typeParam TPrefix - 路径前缀类型
159
+ * @param route - 路由分组或路由模块对象,包含 prefix 和可选的 tags
160
+ * @returns 组合的类装饰器
161
+ */
162
+ declare function TypedController<TPrefix extends string>(route: TypedControllerInput<TPrefix>): ClassDecorator;
163
+ //#endregion
164
+ //#region src/decorators/create-typed-handler.decorator.d.ts
165
+ /**
166
+ * Handler 路由类型
167
+ *
168
+ * 包含 prefix 和可选的 tags、auth 属性
169
+ */
170
+ type TypedHandlerRoute = {
171
+ /**
172
+ * 路径前缀
173
+ */
174
+ readonly prefix: string;
175
+ /**
176
+ * 认证策略
177
+ */
178
+ readonly auth?: string;
179
+ /**
180
+ * API 标签
181
+ */
182
+ readonly tags?: string[];
183
+ };
184
+ /**
185
+ * Handler 装饰器工厂返回类型
186
+ *
187
+ * 无参类装饰器工厂函数
188
+ */
189
+ type TypedHandlerDecoratorFactory = () => ClassDecorator;
190
+ /**
191
+ * Handler 模式的类装饰器工厂
192
+ *
193
+ * 绑定路由后返回类装饰器,语义上用于 handler 模式(一个类对应一个路由操作)。
194
+ * 从路由定义自动提取 prefix 和 tags,组合 @Controller() + @ApiTags()。
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * const { TypedHandler } = defineHandler(clientRoutes.activities.list);
199
+ *
200
+ * @TypedHandler()
201
+ * export class ListActivitiesHandler {
202
+ * @TypedHandle()
203
+ * async handle() {}
204
+ * }
205
+ * ```;
206
+ *
207
+ * @param route - 路由定义或路由分组对象
208
+ * @returns 类装饰器工厂函数
209
+ */
210
+ declare function createTypedHandler(route: RouteDefinition$1 | RouteGroup$1<string> | TypedHandlerRoute): TypedHandlerDecoratorFactory;
211
+ //#endregion
212
+ //#region src/decorators/typed-route.decorator.d.ts
213
+ /**
214
+ * ApiRoute 的可选项类型
215
+ */
216
+ type ApiRouteOptions = Parameters<typeof ApiRoute>[1];
217
+ /**
218
+ * 从路由定义自动生成 NestJS 方法装饰器和 Swagger 文档的装饰器
219
+ *
220
+ * 集成路由定义与 NestJS HTTP 方法装饰器,自动提取 method 设置对应的方法装饰器,
221
+ * 优先使用 basePath(分组路由的相对路径),复用 ApiRoute 生成 Swagger 文档。
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * @TypedController(clientRoutes.activities)
226
+ * export class ActivityController {
227
+ * @TypedRoute(clientRoutes.activities.detail)
228
+ * async getDetail() {}
229
+ * }
230
+ * ```;
231
+ *
232
+ * @typeParam T - 路由定义类型
233
+ * @param route - 路由定义对象
234
+ * @param options - 可选配置项,透传给 ApiRoute
235
+ * @returns 组合的方法装饰器
236
+ */
237
+ declare function TypedRoute<T extends AnyRouteDefinition>(route: T, options?: ApiRouteOptions): MethodDecorator;
238
+ //#endregion
239
+ //#region src/utils/zod-to-openapi.types.d.ts
240
+ /**
241
+ * OpenAPI Schema 定义
242
+ *
243
+ * 描述 OpenAPI 3.0 规范中的 Schema 对象结构
244
+ */
245
+ type OpenApiSchema = {
246
+ /**
247
+ * 数据类型
248
+ */
249
+ type?: string;
250
+ /**
251
+ * 对象属性
252
+ */
253
+ properties?: Record<string, OpenApiSchema>;
254
+ /**
255
+ * 数组项 Schema
256
+ */
257
+ items?: OpenApiSchema;
258
+ /**
259
+ * 枚举值
260
+ */
261
+ enum?: (string | number | boolean)[];
262
+ /**
263
+ * 格式修饰符
264
+ */
265
+ format?: string;
266
+ /**
267
+ * 最小值
268
+ */
269
+ minimum?: number;
270
+ /**
271
+ * 最大值
272
+ */
273
+ maximum?: number;
274
+ /**
275
+ * 最小长度
276
+ */
277
+ minLength?: number;
278
+ /**
279
+ * 最大长度
280
+ */
281
+ maxLength?: number;
282
+ /**
283
+ * 最小项数
284
+ */
285
+ minItems?: number;
286
+ /**
287
+ * 最大项数
288
+ */
289
+ maxItems?: number;
290
+ /**
291
+ * 必需字段列表
292
+ */
293
+ required?: string[];
294
+ /**
295
+ * 默认值
296
+ */
297
+ default?: unknown;
298
+ /**
299
+ * 描述文本
300
+ */
301
+ description?: string;
302
+ /**
303
+ * 额外属性 Schema
304
+ */
305
+ additionalProperties?: OpenApiSchema | boolean;
306
+ /**
307
+ * 是否可空
308
+ */
309
+ nullable?: boolean;
310
+ /**
311
+ * 联合类型(oneOf)
312
+ */
313
+ oneOf?: OpenApiSchema[];
314
+ /**
315
+ * 联合类型(anyOf)
316
+ */
317
+ anyOf?: OpenApiSchema[];
318
+ /**
319
+ * 交叉类型(allOf)
320
+ */
321
+ allOf?: OpenApiSchema[];
322
+ };
323
+ //#endregion
324
+ //#region src/utils/zod-to-openapi.converter.d.ts
325
+ /**
326
+ * 将 Zod Schema 转换为 OpenAPI Schema
327
+ *
328
+ * 用于生成 Swagger 文档。这是一个简化实现,支持常用的 Zod 类型。
329
+ *
330
+ * @remarks
331
+ * 为什么使用自定义实现而不是第三方库:
332
+ * 1. 项目使用 Zod v4,而大多数第三方库(如 zod-openapi)主要支持 Zod v3
333
+ * 2. 自定义实现可以更好地控制输出格式,满足项目特定需求
334
+ * 3. 避免引入额外依赖,减少包大小
335
+ * 当前支持的 Zod 类型:
336
+ * - 基础类型:string, number, boolean, date
337
+ * - 复合类型:array, object, record
338
+ * - 修饰类型:optional, nullable, default
339
+ * - 字面量类型:enum, literal
340
+ * - 联合类型:union, intersection
341
+ *
342
+ * @param schema - Zod Schema 对象(支持 core.$ZodType 及其子类型 ZodType)
343
+ * @returns OpenAPI Schema 对象
344
+ */
345
+ declare function zodToOpenApi(schema: core.$ZodType): OpenApiSchema;
346
+ /**
347
+ * 从 Zod Schema 提取字段描述
348
+ *
349
+ * 遍历 ZodObject 的 shape,提取每个字段的 description 属性
350
+ *
351
+ * @param schema - Zod Schema 对象(支持 core.$ZodType 及其子类型 ZodType)
352
+ * @returns 字段名到描述文本的映射
353
+ */
354
+ declare function extractZodDescriptions(schema: core.$ZodType): Record<string, string>;
355
+ //#endregion
356
+ //#region src/utils/zod-to-openapi.utils.d.ts
357
+ /**
358
+ * 获取 Zod 类型的类型名称
359
+ *
360
+ * Zod v4 使用 def.type 作为类型标识
361
+ *
362
+ * @param def - Zod 定义对象
363
+ * @returns 类型名称字符串
364
+ */
365
+ declare function getTypeName(def: core.$ZodTypeDef): string | undefined;
366
+ /**
367
+ * 获取 Zod Schema 的定义对象
368
+ *
369
+ * Zod v4 使用 _zod.def 作为内部结构
370
+ *
371
+ * @param schema - Zod Schema 对象(支持 core.$ZodType 及其子类型)
372
+ * @returns 定义对象
373
+ */
374
+ declare function getDef(schema: core.$ZodType): core.$ZodTypeDef;
375
+ //#endregion
376
+ //#region src/utils/handler.utils.d.ts
377
+ /**
378
+ * defineHandler 返回值类型
379
+ *
380
+ * @typeParam R - 路由定义类型
381
+ */
382
+ type HandlerBindings<R extends RouteDefinition$1> = {
383
+ /**
384
+ * Handler 类装饰器工厂函数
385
+ */
386
+ readonly TypedHandler: () => ClassDecorator;
387
+ /**
388
+ * 路由方法装饰器
389
+ */
390
+ readonly TypedHandle: () => MethodDecorator;
391
+ /**
392
+ * 类型安全响应函数
393
+ */
394
+ readonly typedResponse: (data: InferRouteResponse$1<R>) => ApiResponse<InferRouteResponse$1<R>>;
395
+ /**
396
+ * 类型安全空响应函数
397
+ */
398
+ readonly typedEmpty: () => ApiResponse<void>;
399
+ };
400
+ /**
401
+ * 一次性合成 Handler 所需的全部绑定
402
+ *
403
+ * 输入路由定义,返回类装饰器、方法装饰器和响应函数。
404
+ * 路由类型通过独立的 route 变量配合 InferRouteParams / InferRouteReturn 等类型工具使用。
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const route = api.client.order.routes.detail;
409
+ * const { TypedHandler, TypedHandle, typedResponse } = defineHandler(route);
410
+ *
411
+ * @TypedHandler()
412
+ * export class DetailHandler {
413
+ * @TypedHandle()
414
+ * async handle(
415
+ * @Param('id') id: InferRouteParams<typeof route>['id'],
416
+ * ): InferRouteReturn<typeof route> {
417
+ * const data = await this.orderService.findById(id);
418
+ * return typedResponse(data);
419
+ * }
420
+ * }
421
+ * ```;
422
+ *
423
+ * @typeParam R - 路由定义类型
424
+ * @param route - 路由定义
425
+ * @returns Handler 绑定对象
426
+ */
427
+ declare function defineHandler<R extends RouteDefinition$1>(route: R): HandlerBindings<R>;
428
+ //#endregion
429
+ export { type AnyRouteDefinition, ApiRoute, type HandlerBindings, type HttpMethod, type InferRouteBody, type InferRouteFullResponse, type InferRouteParams, type InferRouteQuery, type InferRouteResponse, type InferRouteReturn, type OpenApiSchema, PublicRoute, ROUTE_DEFINITION_KEY, RequireAuth, type RouteDefinition, type RouteGroup, TypedController, TypedRoute, createTypedEmpty, createTypedHandler, createTypedResponse, defineHandler, extractZodDescriptions, getDef, getTypeName, zodToOpenApi };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{Controller as e,Delete as t,Get as n,Patch as r,Post as i,Put as a,applyDecorators as o}from"@nestjs/common";import{ApiBearerAuth as s,ApiBody as c,ApiOperation as l,ApiParam as u,ApiQuery as d,ApiResponse as f,ApiTags as p}from"@nestjs/swagger";import{createTypedEmpty as m,createTypedEmpty as h,createTypedResponse as g,createTypedResponse as ee}from"@longzai-intelligence-transport/http-core";function _(e){return e.type}function v(e){return e._zod.def}function y(e,t){return t===`array`}function b(e,t){return t===`object`}function x(e,t){return t===`record`}function S(e,t){return t===`optional`||t===`nullable`}function C(e,t){return t==="default"}function w(e,t){return t===`enum`}function T(e,t){return t===`literal`}function E(e,t){return t===`union`}function D(e,t){return t===`intersection`}function O(e,t){return{type:`array`,items:e.element?t(e.element):{type:`object`}}}function k(e,t){let n={},r=[],i=e.shape;if(i)for(let[e,a]of Object.entries(i)){n[e]=t(a);let i=_(v(a));i!==`optional`&&i!==`nullable`&&r.push(e)}let a={type:`object`,properties:n};return r.length>0&&(a.required=r),a}function A(e,t){return{type:`object`,additionalProperties:e.valueType?t(e.valueType):!0}}function j(e,t){return{...e.innerType?t(e.innerType):{type:`object`},nullable:!0}}function M(e,t){let n=e.defaultValue;return{...e.innerType?t(e.innerType):{type:`object`},default:typeof n==`function`?n():n}}function N(e){return{type:`string`,enum:e.entries?Object.values(e.entries):[]}}function P(e){let t=e.values?.[0];return typeof t==`string`?{type:`string`,enum:[t]}:typeof t==`number`?{type:`number`,enum:[t]}:typeof t==`boolean`?{type:`boolean`,enum:[t]}:{type:`string`}}function F(e,t){return{oneOf:e.options?.map(e=>t(e))??[]}}function I(e,t){let n=[];return e.left&&n.push(t(e.left)),e.right&&n.push(t(e.right)),{allOf:n}}const te={string:{type:`string`},number:{type:`number`},int:{type:`number`},boolean:{type:`boolean`},date:{type:`string`,format:`date-time`}};function L(e){let t=v(e),n=_(t);return n?te[n]||(y(t,n)?O(t,L):b(t,n)?k(t,L):x(t,n)?A(t,L):S(t,n)?j(t,L):C(t,n)?M(t,L):w(t,n)?N(t):T(t,n)?P(t):E(t,n)?F(t,L):D(t,n)?I(t,L):{type:`object`}):{type:`object`}}function R(e){let t={},n=v(e),r=_(n);if(r&&b(n,r)&&n.shape)for(let[e,r]of Object.entries(n.shape)){let n=`description`in r&&typeof r.description==`string`?r.description:void 0;n&&(t[e]=n)}return t}const z=`route_definition`;function B(e,t){t!==!1&&e.push(s())}function V(e,t,n){let r=L(t);e.push(f({status:200,description:n??`成功`,schema:r}))}function H(e,t){if(t)for(let n of t)e.push(f({status:n.status,description:n.description,schema:{type:`object`,properties:{code:{type:`string`},message:{type:`string`},data:{type:`object`,nullable:!0}}}}))}function U(e,t){if(!t)return;let n=L(t);if(n.properties)for(let[t,r]of Object.entries(n.properties))e.push(u({name:t,schema:r,required:!0}))}function W(e,t){if(!t)return;let n=L(t);if(n.properties){let t=n.required||[];for(let[r,i]of Object.entries(n.properties))e.push(d({name:r,schema:i,required:t.includes(r)}))}}function G(e,t){t&&e.push(c({schema:L(t)}))}function K(e,t){let n=[];return B(n,t?.requireAuth),n.push(l({summary:e.summary,tags:e.tags})),V(n,e.response,t?.successDescription),H(n,t?.errorResponses),U(n,e.params),W(n,e.query),G(n,e.body),o(...n)}function q(){return s()}function J(){return o()}function Y(t){let n=[];return n.push(e(t.prefix)),t.tags&&t.tags.length>0&&n.push(p(...t.tags)),o(...n)}function X(e){if(e.basePath){let t=e.basePath.startsWith(`/`)?e.basePath:`/${e.basePath}`;return(e.path.endsWith(t)?e.path.slice(0,-t.length):e.path)||`/`}let t=e.path.lastIndexOf(`/`);return t>0?e.path.slice(0,t):e.path}function Z(e){return`prefix`in e&&typeof e.prefix==`string`}function Q(t){return()=>{let n=[],r=Z(t)?t.prefix:X(t);return n.push(e(r)),t.tags&&t.tags.length>0&&n.push(p(...t.tags)),o(...n)}}function ne(e){switch(e){case`GET`:return n;case`POST`:return i;case`PUT`:return a;case`PATCH`:return r;case`DELETE`:return t}}function $(e,t){return o(ne(e.method)(e.basePath??e.path),K(e,t))}function re(e){return{TypedHandler:Q(e),TypedHandle:()=>$(e),typedResponse:ee(e),typedEmpty:h(e)}}export{K as ApiRoute,J as PublicRoute,z as ROUTE_DEFINITION_KEY,q as RequireAuth,Y as TypedController,$ as TypedRoute,m as createTypedEmpty,Q as createTypedHandler,g as createTypedResponse,re as defineHandler,R as extractZodDescriptions,v as getDef,_ as getTypeName,L as zodToOpenApi};
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@longzai-intelligence-transport/http-adapter-nestjs",
3
+ "version": "0.1.0",
4
+ "keywords": [
5
+ "adapter",
6
+ "decorator",
7
+ "http",
8
+ "nestjs",
9
+ "swagger",
10
+ "utils"
11
+ ],
12
+ "license": "UNLICENSED",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "tsgo --build tsconfig/build.json && resolve-aliases -p tsconfig/build.json",
27
+ "build:prod": "NODE_ENV=production tsdown",
28
+ "prepublishOnly": "bun run build:prod",
29
+ "typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
30
+ "typecheck:app": "tsgo --noEmit -p tsconfig/app.json",
31
+ "typecheck:node": "tsgo --noEmit -p tsconfig/node.json",
32
+ "typecheck:test": "tsgo --noEmit -p tsconfig/test.json",
33
+ "lint": "oxlint && oxfmt --check",
34
+ "lint:fix": "oxlint --fix && oxfmt",
35
+ "test": "bun test",
36
+ "test:watch": "bun test --watch",
37
+ "test:coverage": "bun test --coverage",
38
+ "clean": "rimraf dist out .cache"
39
+ },
40
+ "dependencies": {
41
+ "@longzai-intelligence-transport/http-core": "0.1.0"
42
+ },
43
+ "devDependencies": {
44
+ "@nestjs/common": "^11.1.26",
45
+ "@nestjs/swagger": "^11.4.4",
46
+ "zod": "^4.4.3"
47
+ },
48
+ "peerDependencies": {
49
+ "@nestjs/common": "^11.0.0",
50
+ "@nestjs/swagger": "^11.0.0",
51
+ "zod": "^4.4.3"
52
+ }
53
+ }