@theokit/http 0.4.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 +172 -0
- package/dist/app.d.ts +67 -0
- package/dist/app.js +11 -0
- package/dist/app.js.map +1 -0
- package/dist/chunk-34KOKJ5M.js +71 -0
- package/dist/chunk-34KOKJ5M.js.map +1 -0
- package/dist/chunk-3PGQVQWG.js +276 -0
- package/dist/chunk-3PGQVQWG.js.map +1 -0
- package/dist/chunk-7QVYU63E.js +7 -0
- package/dist/chunk-7QVYU63E.js.map +1 -0
- package/dist/chunk-HLW7YKZE.js +99 -0
- package/dist/chunk-HLW7YKZE.js.map +1 -0
- package/dist/chunk-LKNI6QEP.js +20 -0
- package/dist/chunk-LKNI6QEP.js.map +1 -0
- package/dist/chunk-LWCNTZN6.js +87 -0
- package/dist/chunk-LWCNTZN6.js.map +1 -0
- package/dist/chunk-SMWUPP2C.js +125 -0
- package/dist/chunk-SMWUPP2C.js.map +1 -0
- package/dist/chunk-TBMGRXH5.js +477 -0
- package/dist/chunk-TBMGRXH5.js.map +1 -0
- package/dist/chunk-U46H4CGF.js +34 -0
- package/dist/chunk-U46H4CGF.js.map +1 -0
- package/dist/exception-filter-chain-BCSQ3MZ2.js +10 -0
- package/dist/exception-filter-chain-BCSQ3MZ2.js.map +1 -0
- package/dist/index.d.ts +1047 -0
- package/dist/index.js +761 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor-chain-6S3PUV7J.js +9 -0
- package/dist/interceptor-chain-6S3PUV7J.js.map +1 -0
- package/dist/middleware-consumer-ljxK1fU_.d.ts +58 -0
- package/dist/runtime-node.d.ts +21 -0
- package/dist/runtime-node.js +12 -0
- package/dist/runtime-node.js.map +1 -0
- package/dist/theokit-plugin.d.ts +65 -0
- package/dist/theokit-plugin.js +432 -0
- package/dist/theokit-plugin.js.map +1 -0
- package/dist/types-CGthbcon.d.ts +19 -0
- package/package.json +58 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TheoApp
|
|
3
|
+
} from "./chunk-TBMGRXH5.js";
|
|
4
|
+
import {
|
|
5
|
+
MiddlewareConsumerImpl,
|
|
6
|
+
middlewareMatchesPath,
|
|
7
|
+
runMiddleware
|
|
8
|
+
} from "./chunk-LWCNTZN6.js";
|
|
9
|
+
import {
|
|
10
|
+
HttpDecoratorsConfigError,
|
|
11
|
+
createExecutionContext,
|
|
12
|
+
joinPath,
|
|
13
|
+
resolveDtoSchema,
|
|
14
|
+
walkControllerMetadata
|
|
15
|
+
} from "./chunk-SMWUPP2C.js";
|
|
16
|
+
import {
|
|
17
|
+
createNodeAdapter
|
|
18
|
+
} from "./chunk-HLW7YKZE.js";
|
|
19
|
+
import {
|
|
20
|
+
runInterceptors
|
|
21
|
+
} from "./chunk-U46H4CGF.js";
|
|
22
|
+
import {
|
|
23
|
+
runExceptionFilters
|
|
24
|
+
} from "./chunk-34KOKJ5M.js";
|
|
25
|
+
import {
|
|
26
|
+
BadGatewayException,
|
|
27
|
+
BadRequestException,
|
|
28
|
+
CATCH_EXCEPTIONS,
|
|
29
|
+
CONTROLLER_PREFIX,
|
|
30
|
+
ConflictException,
|
|
31
|
+
ForbiddenException,
|
|
32
|
+
GatewayTimeoutException,
|
|
33
|
+
GoneException,
|
|
34
|
+
HttpException,
|
|
35
|
+
HttpStatus,
|
|
36
|
+
HttpVersionNotSupportedException,
|
|
37
|
+
ImATeapotException,
|
|
38
|
+
InternalServerErrorException,
|
|
39
|
+
MethodNotAllowedException,
|
|
40
|
+
NotAcceptableException,
|
|
41
|
+
NotFoundException,
|
|
42
|
+
NotImplementedException,
|
|
43
|
+
PayloadTooLargeException,
|
|
44
|
+
PreconditionFailedException,
|
|
45
|
+
ROUTE_HEADERS,
|
|
46
|
+
ROUTE_METHODS,
|
|
47
|
+
ROUTE_PARAMS,
|
|
48
|
+
ROUTE_REDIRECT,
|
|
49
|
+
ROUTE_STATUS,
|
|
50
|
+
RequestTimeoutException,
|
|
51
|
+
ServiceUnavailableException,
|
|
52
|
+
TooManyRequestsException,
|
|
53
|
+
USE_FILTERS,
|
|
54
|
+
USE_GUARDS,
|
|
55
|
+
USE_INTERCEPTORS,
|
|
56
|
+
UnauthorizedException,
|
|
57
|
+
UnprocessableEntityException,
|
|
58
|
+
UnsupportedMediaTypeException,
|
|
59
|
+
getMeta,
|
|
60
|
+
setMeta
|
|
61
|
+
} from "./chunk-3PGQVQWG.js";
|
|
62
|
+
import {
|
|
63
|
+
resolveOrNew
|
|
64
|
+
} from "./chunk-LKNI6QEP.js";
|
|
65
|
+
import {
|
|
66
|
+
__name
|
|
67
|
+
} from "./chunk-7QVYU63E.js";
|
|
68
|
+
|
|
69
|
+
// src/decorators/controller.ts
|
|
70
|
+
function Controller(prefix = "", opts = {}) {
|
|
71
|
+
return (target) => {
|
|
72
|
+
setMeta(CONTROLLER_PREFIX, target, {
|
|
73
|
+
prefix,
|
|
74
|
+
host: opts.host
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
__name(Controller, "Controller");
|
|
79
|
+
|
|
80
|
+
// src/decorators/methods.ts
|
|
81
|
+
function makeVerbDecorator(verb) {
|
|
82
|
+
return function(path = "") {
|
|
83
|
+
return (target, propertyKey) => {
|
|
84
|
+
const existing = getMeta(ROUTE_METHODS, target.constructor) ?? [];
|
|
85
|
+
existing.push({
|
|
86
|
+
verb,
|
|
87
|
+
path,
|
|
88
|
+
propertyKey
|
|
89
|
+
});
|
|
90
|
+
setMeta(ROUTE_METHODS, target.constructor, existing);
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
__name(makeVerbDecorator, "makeVerbDecorator");
|
|
95
|
+
var Get = makeVerbDecorator("GET");
|
|
96
|
+
var Post = makeVerbDecorator("POST");
|
|
97
|
+
var Put = makeVerbDecorator("PUT");
|
|
98
|
+
var Patch = makeVerbDecorator("PATCH");
|
|
99
|
+
var Delete = makeVerbDecorator("DELETE");
|
|
100
|
+
var Options = makeVerbDecorator("OPTIONS");
|
|
101
|
+
var Head = makeVerbDecorator("HEAD");
|
|
102
|
+
var All = makeVerbDecorator("ALL");
|
|
103
|
+
|
|
104
|
+
// src/decorators/params.ts
|
|
105
|
+
function isZodSchema(v) {
|
|
106
|
+
return v !== null && v !== void 0 && typeof v === "object" && typeof v.safeParse === "function";
|
|
107
|
+
}
|
|
108
|
+
__name(isZodSchema, "isZodSchema");
|
|
109
|
+
function makeParamDecorator(source) {
|
|
110
|
+
return function(keyOrSchema) {
|
|
111
|
+
return (target, propertyKey, parameterIndex) => {
|
|
112
|
+
if (propertyKey === void 0) return;
|
|
113
|
+
const map = getMeta(ROUTE_PARAMS, target.constructor) ?? /* @__PURE__ */ new Map();
|
|
114
|
+
const entries = map.get(propertyKey) ?? [];
|
|
115
|
+
const entry = {
|
|
116
|
+
source,
|
|
117
|
+
index: parameterIndex
|
|
118
|
+
};
|
|
119
|
+
if (typeof keyOrSchema === "string") {
|
|
120
|
+
entry.key = keyOrSchema;
|
|
121
|
+
} else if (isZodSchema(keyOrSchema)) {
|
|
122
|
+
entry.schema = keyOrSchema;
|
|
123
|
+
}
|
|
124
|
+
entries.push(entry);
|
|
125
|
+
map.set(propertyKey, entries);
|
|
126
|
+
setMeta(ROUTE_PARAMS, target.constructor, map);
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
__name(makeParamDecorator, "makeParamDecorator");
|
|
131
|
+
var Req = makeParamDecorator("req");
|
|
132
|
+
var Body = makeParamDecorator("body");
|
|
133
|
+
var Param = makeParamDecorator("param");
|
|
134
|
+
var Query = makeParamDecorator("query");
|
|
135
|
+
var Headers = makeParamDecorator("headers");
|
|
136
|
+
var Session = makeParamDecorator("session");
|
|
137
|
+
var Ip = makeParamDecorator("ip");
|
|
138
|
+
var HostParam = makeParamDecorator("host");
|
|
139
|
+
function Res(opts) {
|
|
140
|
+
return (target, propertyKey, parameterIndex) => {
|
|
141
|
+
if (propertyKey === void 0) return;
|
|
142
|
+
const map = getMeta(ROUTE_PARAMS, target.constructor) ?? /* @__PURE__ */ new Map();
|
|
143
|
+
const entries = map.get(propertyKey) ?? [];
|
|
144
|
+
entries.push({
|
|
145
|
+
source: "res",
|
|
146
|
+
index: parameterIndex,
|
|
147
|
+
passthrough: opts?.passthrough
|
|
148
|
+
});
|
|
149
|
+
map.set(propertyKey, entries);
|
|
150
|
+
setMeta(ROUTE_PARAMS, target.constructor, map);
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
__name(Res, "Res");
|
|
154
|
+
|
|
155
|
+
// src/decorators/response.ts
|
|
156
|
+
function HttpCode(status) {
|
|
157
|
+
return (target, propertyKey) => {
|
|
158
|
+
setMeta(ROUTE_STATUS, target.constructor, status, propertyKey);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
__name(HttpCode, "HttpCode");
|
|
162
|
+
function Header(name, value) {
|
|
163
|
+
return (target, propertyKey) => {
|
|
164
|
+
const existing = getMeta(ROUTE_HEADERS, target.constructor, propertyKey) ?? [];
|
|
165
|
+
existing.push([
|
|
166
|
+
name,
|
|
167
|
+
value
|
|
168
|
+
]);
|
|
169
|
+
setMeta(ROUTE_HEADERS, target.constructor, existing, propertyKey);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
__name(Header, "Header");
|
|
173
|
+
function Redirect(url, status = 302) {
|
|
174
|
+
return (target, propertyKey) => {
|
|
175
|
+
setMeta(ROUTE_REDIRECT, target.constructor, {
|
|
176
|
+
url,
|
|
177
|
+
status
|
|
178
|
+
}, propertyKey);
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
__name(Redirect, "Redirect");
|
|
182
|
+
|
|
183
|
+
// src/decorators/middleware.ts
|
|
184
|
+
function UseGuards(...guards) {
|
|
185
|
+
return (target, propertyKey) => {
|
|
186
|
+
const actualTarget = propertyKey ? target.constructor : target;
|
|
187
|
+
const existing = getMeta(USE_GUARDS, actualTarget, propertyKey) ?? [];
|
|
188
|
+
setMeta(USE_GUARDS, actualTarget, [
|
|
189
|
+
...existing,
|
|
190
|
+
...guards
|
|
191
|
+
], propertyKey);
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
__name(UseGuards, "UseGuards");
|
|
195
|
+
function UseInterceptors(...interceptors) {
|
|
196
|
+
return (target, propertyKey) => {
|
|
197
|
+
const actualTarget = propertyKey ? target.constructor : target;
|
|
198
|
+
const existing = getMeta(USE_INTERCEPTORS, actualTarget, propertyKey) ?? [];
|
|
199
|
+
setMeta(USE_INTERCEPTORS, actualTarget, [
|
|
200
|
+
...existing,
|
|
201
|
+
...interceptors
|
|
202
|
+
], propertyKey);
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
__name(UseInterceptors, "UseInterceptors");
|
|
206
|
+
function UseFilters(...filters) {
|
|
207
|
+
return (target, propertyKey) => {
|
|
208
|
+
const actualTarget = propertyKey ? target.constructor : target;
|
|
209
|
+
const existing = getMeta(USE_FILTERS, actualTarget, propertyKey) ?? [];
|
|
210
|
+
setMeta(USE_FILTERS, actualTarget, [
|
|
211
|
+
...existing,
|
|
212
|
+
...filters
|
|
213
|
+
], propertyKey);
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
__name(UseFilters, "UseFilters");
|
|
217
|
+
function Catch(...exceptions) {
|
|
218
|
+
return (target) => {
|
|
219
|
+
setMeta(CATCH_EXCEPTIONS, target, exceptions);
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
__name(Catch, "Catch");
|
|
223
|
+
|
|
224
|
+
// src/decorators/set-metadata.ts
|
|
225
|
+
import "reflect-metadata";
|
|
226
|
+
var decoratorKeyCounter = 0;
|
|
227
|
+
function createDecorator() {
|
|
228
|
+
const key = /* @__PURE__ */ Symbol.for(`theokit:custom:${++decoratorKeyCounter}`);
|
|
229
|
+
const decorator = /* @__PURE__ */ __name((value) => {
|
|
230
|
+
return (target, propertyKey) => {
|
|
231
|
+
const metaTarget = propertyKey !== void 0 ? target.constructor : target;
|
|
232
|
+
Reflect.defineMetadata(key, value, metaTarget, propertyKey);
|
|
233
|
+
};
|
|
234
|
+
}, "decorator");
|
|
235
|
+
decorator.key = key;
|
|
236
|
+
return decorator;
|
|
237
|
+
}
|
|
238
|
+
__name(createDecorator, "createDecorator");
|
|
239
|
+
function SetMetadata(metaKey, value) {
|
|
240
|
+
return (target, propertyKey) => {
|
|
241
|
+
const metaTarget = propertyKey !== void 0 ? target.constructor : target;
|
|
242
|
+
Reflect.defineMetadata(metaKey, value, metaTarget, propertyKey);
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
__name(SetMetadata, "SetMetadata");
|
|
246
|
+
var Reflector = class {
|
|
247
|
+
static {
|
|
248
|
+
__name(this, "Reflector");
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Read metadata set by a typed decorator created via createDecorator<T>().
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* const Roles = createDecorator<string[]>()
|
|
256
|
+
* const reflector = new Reflector()
|
|
257
|
+
* const roles = reflector.get(Roles, handlerFn) // string[] | undefined
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
get(decorator, target, propertyKey) {
|
|
261
|
+
const key = decorator.key;
|
|
262
|
+
if (!key) return void 0;
|
|
263
|
+
if (propertyKey !== void 0) {
|
|
264
|
+
return Reflect.getMetadata(key, target, propertyKey);
|
|
265
|
+
}
|
|
266
|
+
return Reflect.getMetadata(key, target);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Read metadata set by @SetMetadata(key, value).
|
|
270
|
+
*/
|
|
271
|
+
getByKey(key, target, propertyKey) {
|
|
272
|
+
if (propertyKey !== void 0) {
|
|
273
|
+
return Reflect.getMetadata(key, target, propertyKey);
|
|
274
|
+
}
|
|
275
|
+
return Reflect.getMetadata(key, target);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Read metadata checking method-level first, then class-level.
|
|
279
|
+
* Returns the first non-undefined value found.
|
|
280
|
+
*
|
|
281
|
+
* NestJS equivalent: `reflector.getAllAndOverride(ROLES_KEY, [context.getHandler(), context.getClass()])`
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* const Roles = createDecorator<string[]>()
|
|
286
|
+
* // In a guard:
|
|
287
|
+
* const roles = reflector.getAllAndOverride(Roles, context.getClass(), context.getMethodName())
|
|
288
|
+
* // Checks method-level @Roles first, falls back to class-level @Roles
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
getAllAndOverride(decorator, target, propertyKey) {
|
|
292
|
+
if (propertyKey !== void 0) {
|
|
293
|
+
const methodLevel = this.get(decorator, target, propertyKey);
|
|
294
|
+
if (methodLevel !== void 0) return methodLevel;
|
|
295
|
+
}
|
|
296
|
+
return this.get(decorator, target);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Read metadata checking method-level first, then class-level, by raw key.
|
|
300
|
+
* Returns the first non-undefined value found.
|
|
301
|
+
*/
|
|
302
|
+
getAllAndOverrideByKey(key, target, propertyKey) {
|
|
303
|
+
if (propertyKey !== void 0) {
|
|
304
|
+
const methodLevel = this.getByKey(key, target, propertyKey);
|
|
305
|
+
if (methodLevel !== void 0) return methodLevel;
|
|
306
|
+
}
|
|
307
|
+
return this.getByKey(key, target);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Read metadata from both method-level and class-level, merging arrays.
|
|
311
|
+
* Returns all found values as a flat array.
|
|
312
|
+
*
|
|
313
|
+
* NestJS equivalent: `reflector.getAllAndMerge(ROLES_KEY, [context.getHandler(), context.getClass()])`
|
|
314
|
+
*
|
|
315
|
+
* @example
|
|
316
|
+
* ```ts
|
|
317
|
+
* const Tags = createDecorator<string[]>()
|
|
318
|
+
*
|
|
319
|
+
* @Tags(['api'])
|
|
320
|
+
* @Controller('cats')
|
|
321
|
+
* class CatsCtrl {
|
|
322
|
+
* @Tags(['read'])
|
|
323
|
+
* @Get()
|
|
324
|
+
* findAll() {}
|
|
325
|
+
* }
|
|
326
|
+
*
|
|
327
|
+
* reflector.getAllAndMerge(Tags, CatsCtrl, 'findAll')
|
|
328
|
+
* // → ['read', 'api'] (method + class merged)
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
getAllAndMerge(decorator, target, propertyKey) {
|
|
332
|
+
const result = [];
|
|
333
|
+
if (propertyKey !== void 0) {
|
|
334
|
+
const methodLevel = this.get(decorator, target, propertyKey);
|
|
335
|
+
if (methodLevel !== void 0) {
|
|
336
|
+
if (Array.isArray(methodLevel)) result.push(...methodLevel);
|
|
337
|
+
else result.push(methodLevel);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const classLevel = this.get(decorator, target);
|
|
341
|
+
if (classLevel !== void 0) {
|
|
342
|
+
if (Array.isArray(classLevel)) result.push(...classLevel);
|
|
343
|
+
else result.push(classLevel);
|
|
344
|
+
}
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// src/decorators/throttle.ts
|
|
350
|
+
var THROTTLE_KEY = /* @__PURE__ */ Symbol.for("theokit:http-decorators:throttle");
|
|
351
|
+
var SKIP_THROTTLE_KEY = /* @__PURE__ */ Symbol.for("theokit:http-decorators:skip-throttle");
|
|
352
|
+
function Throttle(options) {
|
|
353
|
+
return (target, propertyKey) => {
|
|
354
|
+
const actualTarget = propertyKey !== void 0 ? target.constructor : target;
|
|
355
|
+
setMeta(THROTTLE_KEY, actualTarget, options, propertyKey);
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
__name(Throttle, "Throttle");
|
|
359
|
+
function SkipThrottle(skip = true) {
|
|
360
|
+
return (target, propertyKey) => {
|
|
361
|
+
const actualTarget = propertyKey !== void 0 ? target.constructor : target;
|
|
362
|
+
setMeta(SKIP_THROTTLE_KEY, actualTarget, skip, propertyKey);
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
__name(SkipThrottle, "SkipThrottle");
|
|
366
|
+
function getThrottleOptions(target, propertyKey) {
|
|
367
|
+
return getMeta(THROTTLE_KEY, target, propertyKey);
|
|
368
|
+
}
|
|
369
|
+
__name(getThrottleOptions, "getThrottleOptions");
|
|
370
|
+
function isThrottleSkipped(target, propertyKey) {
|
|
371
|
+
return getMeta(SKIP_THROTTLE_KEY, target, propertyKey) ?? false;
|
|
372
|
+
}
|
|
373
|
+
__name(isThrottleSkipped, "isThrottleSkipped");
|
|
374
|
+
|
|
375
|
+
// src/bridge/register-controllers.ts
|
|
376
|
+
function registerControllers(controllers) {
|
|
377
|
+
const seen = /* @__PURE__ */ new Set();
|
|
378
|
+
const unique = [];
|
|
379
|
+
for (const Ctor of controllers) {
|
|
380
|
+
if (seen.has(Ctor)) {
|
|
381
|
+
console.warn(`[@theokit/http] Controller ${Ctor.name} registered multiple times \u2014 dropping duplicate`);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
seen.add(Ctor);
|
|
385
|
+
unique.push(Ctor);
|
|
386
|
+
}
|
|
387
|
+
return unique.flatMap((Ctor) => {
|
|
388
|
+
const walks = walkControllerMetadata(Ctor);
|
|
389
|
+
return walks.map((w) => ({
|
|
390
|
+
verb: w.verb,
|
|
391
|
+
fullPath: w.fullPath,
|
|
392
|
+
walkResult: w
|
|
393
|
+
}));
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
__name(registerControllers, "registerControllers");
|
|
397
|
+
|
|
398
|
+
// src/bridge/create-server.ts
|
|
399
|
+
import "reflect-metadata";
|
|
400
|
+
function createDecoratorServer(controllersOrOpts) {
|
|
401
|
+
const { controllers, container, configure } = Array.isArray(controllersOrOpts) ? {
|
|
402
|
+
controllers: controllersOrOpts,
|
|
403
|
+
container: void 0,
|
|
404
|
+
configure: void 0
|
|
405
|
+
} : controllersOrOpts;
|
|
406
|
+
const middlewareConsumer = new MiddlewareConsumerImpl(container);
|
|
407
|
+
if (configure) configure(middlewareConsumer);
|
|
408
|
+
const middlewareEntries = middlewareConsumer.getEntries();
|
|
409
|
+
const seen = /* @__PURE__ */ new Set();
|
|
410
|
+
const unique = [];
|
|
411
|
+
for (const Ctor of controllers) {
|
|
412
|
+
if (seen.has(Ctor)) continue;
|
|
413
|
+
seen.add(Ctor);
|
|
414
|
+
unique.push(Ctor);
|
|
415
|
+
}
|
|
416
|
+
const routes = [];
|
|
417
|
+
for (const Ctor of unique) {
|
|
418
|
+
const instance = resolveOrNew(Ctor, container);
|
|
419
|
+
const walks = walkControllerMetadata(Ctor);
|
|
420
|
+
for (const w of walks) {
|
|
421
|
+
routes.push({
|
|
422
|
+
walk: w,
|
|
423
|
+
instance
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
routes.sort((a, b) => {
|
|
428
|
+
const aP = a.walk.fullPath.includes(":");
|
|
429
|
+
const bP = b.walk.fullPath.includes(":");
|
|
430
|
+
if (aP !== bP) return aP ? 1 : -1;
|
|
431
|
+
return 0;
|
|
432
|
+
});
|
|
433
|
+
const adapter = createNodeAdapter();
|
|
434
|
+
const handler = /* @__PURE__ */ __name((request) => handleRequest(routes, request, container, middlewareEntries), "handler");
|
|
435
|
+
return adapter.createServer(handler);
|
|
436
|
+
}
|
|
437
|
+
__name(createDecoratorServer, "createDecoratorServer");
|
|
438
|
+
async function handleRequest(routes, request, container, middlewareEntries = []) {
|
|
439
|
+
const url = new URL(request.url);
|
|
440
|
+
const method = request.method.toUpperCase();
|
|
441
|
+
const pathname = url.pathname;
|
|
442
|
+
const match = findRoute(routes, method, pathname);
|
|
443
|
+
if (!match) {
|
|
444
|
+
return jsonResponse(404, {
|
|
445
|
+
error: {
|
|
446
|
+
code: "NOT_FOUND",
|
|
447
|
+
message: `No route for ${method} ${pathname}`
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
const { walk, instance, params } = match;
|
|
452
|
+
try {
|
|
453
|
+
const mwResponse = await runMiddleware(middlewareEntries, request, pathname);
|
|
454
|
+
if (mwResponse) return mwResponse;
|
|
455
|
+
const ctx = createExecutionContext(request, instance.constructor, walk.propertyKey);
|
|
456
|
+
const guardResponse = await runGuards(walk.guards, ctx, container);
|
|
457
|
+
if (guardResponse) return guardResponse;
|
|
458
|
+
const body = await resolveBody(method, request, walk);
|
|
459
|
+
if (body instanceof Response) return body;
|
|
460
|
+
const args = buildArgs(walk.paramEntries, {
|
|
461
|
+
request,
|
|
462
|
+
body,
|
|
463
|
+
params,
|
|
464
|
+
query: Object.fromEntries(url.searchParams)
|
|
465
|
+
});
|
|
466
|
+
if (walk.redirect) {
|
|
467
|
+
return new Response(null, {
|
|
468
|
+
status: walk.redirect.status,
|
|
469
|
+
headers: {
|
|
470
|
+
location: walk.redirect.url
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
const handlerFn = instance[walk.propertyKey];
|
|
475
|
+
const result = await runInterceptors(walk.interceptors, () => handlerFn.apply(instance, args), request, container);
|
|
476
|
+
return buildResponse(result, walk, method);
|
|
477
|
+
} catch (err) {
|
|
478
|
+
return runExceptionFilters(err, walk.filters, request, container);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
__name(handleRequest, "handleRequest");
|
|
482
|
+
async function runGuards(guards, context, container) {
|
|
483
|
+
for (const GuardCtor of guards) {
|
|
484
|
+
const guard = resolveOrNew(GuardCtor, container);
|
|
485
|
+
const allowed = await guard.canActivate(context);
|
|
486
|
+
if (!allowed) {
|
|
487
|
+
const ex = new ForbiddenException("Forbidden resource");
|
|
488
|
+
return jsonResponse(ex.statusCode, ex.toJSON());
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
__name(runGuards, "runGuards");
|
|
494
|
+
async function resolveBody(method, request, walk) {
|
|
495
|
+
if (![
|
|
496
|
+
"POST",
|
|
497
|
+
"PUT",
|
|
498
|
+
"PATCH"
|
|
499
|
+
].includes(method)) return void 0;
|
|
500
|
+
let body;
|
|
501
|
+
try {
|
|
502
|
+
const text = await request.text();
|
|
503
|
+
body = text ? JSON.parse(text) : void 0;
|
|
504
|
+
} catch {
|
|
505
|
+
body = void 0;
|
|
506
|
+
}
|
|
507
|
+
if (walk.bodySchema && body !== void 0) {
|
|
508
|
+
const result = walk.bodySchema.safeParse(body);
|
|
509
|
+
if (!result.success) {
|
|
510
|
+
return jsonResponse(422, {
|
|
511
|
+
error: {
|
|
512
|
+
code: "VALIDATION_ERROR",
|
|
513
|
+
issues: result.error.issues
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
body = result.data;
|
|
518
|
+
}
|
|
519
|
+
return body;
|
|
520
|
+
}
|
|
521
|
+
__name(resolveBody, "resolveBody");
|
|
522
|
+
function buildResponse(result, walk, method) {
|
|
523
|
+
const status = walk.status ?? (method === "POST" ? 201 : 200);
|
|
524
|
+
const headers = {
|
|
525
|
+
"content-type": "application/json"
|
|
526
|
+
};
|
|
527
|
+
for (const [name, value] of walk.headers) {
|
|
528
|
+
headers[name.toLowerCase()] = value;
|
|
529
|
+
}
|
|
530
|
+
if (result === void 0 || result === null) {
|
|
531
|
+
return new Response(null, {
|
|
532
|
+
status: status === 200 ? 204 : status,
|
|
533
|
+
headers
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
if (typeof result === "string") {
|
|
537
|
+
headers["content-type"] = "text/plain";
|
|
538
|
+
return new Response(result, {
|
|
539
|
+
status,
|
|
540
|
+
headers
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
return new Response(JSON.stringify(result), {
|
|
544
|
+
status,
|
|
545
|
+
headers
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
__name(buildResponse, "buildResponse");
|
|
549
|
+
function jsonResponse(status, body) {
|
|
550
|
+
return new Response(JSON.stringify(body), {
|
|
551
|
+
status,
|
|
552
|
+
headers: {
|
|
553
|
+
"content-type": "application/json"
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
__name(jsonResponse, "jsonResponse");
|
|
558
|
+
function findRoute(routes, method, pathname) {
|
|
559
|
+
for (const { walk, instance } of routes) {
|
|
560
|
+
if (walk.verb !== "ALL" && walk.verb !== method) continue;
|
|
561
|
+
const params = matchPath(walk.fullPath, pathname);
|
|
562
|
+
if (params !== null) return {
|
|
563
|
+
walk,
|
|
564
|
+
instance,
|
|
565
|
+
params
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
__name(findRoute, "findRoute");
|
|
571
|
+
function matchPath(pattern, pathname) {
|
|
572
|
+
const paramNames = [];
|
|
573
|
+
const regexStr = pattern.replace(/:(\w+)/g, (_m, name) => {
|
|
574
|
+
paramNames.push(name);
|
|
575
|
+
return "([^/]+)";
|
|
576
|
+
});
|
|
577
|
+
const match = new RegExp(`^${regexStr}$`).exec(pathname);
|
|
578
|
+
if (!match) return null;
|
|
579
|
+
const params = {};
|
|
580
|
+
paramNames.forEach((name, i) => {
|
|
581
|
+
params[name] = match[i + 1];
|
|
582
|
+
});
|
|
583
|
+
return params;
|
|
584
|
+
}
|
|
585
|
+
__name(matchPath, "matchPath");
|
|
586
|
+
function buildArgs(paramEntries, ctx) {
|
|
587
|
+
if (paramEntries.length === 0) return [];
|
|
588
|
+
const maxIndex = Math.max(...paramEntries.map((p) => p.index));
|
|
589
|
+
const args = Array.from({
|
|
590
|
+
length: maxIndex + 1
|
|
591
|
+
}, () => void 0);
|
|
592
|
+
for (const p of paramEntries) {
|
|
593
|
+
switch (p.source) {
|
|
594
|
+
case "req":
|
|
595
|
+
args[p.index] = ctx.request;
|
|
596
|
+
break;
|
|
597
|
+
case "body":
|
|
598
|
+
args[p.index] = p.key ? ctx.body[p.key] : ctx.body;
|
|
599
|
+
break;
|
|
600
|
+
case "param":
|
|
601
|
+
args[p.index] = p.key ? ctx.params[p.key] : ctx.params;
|
|
602
|
+
break;
|
|
603
|
+
case "query":
|
|
604
|
+
args[p.index] = p.key ? ctx.query[p.key] : ctx.query;
|
|
605
|
+
break;
|
|
606
|
+
case "headers":
|
|
607
|
+
args[p.index] = p.key ? ctx.request.headers.get(p.key.toLowerCase()) : Object.fromEntries(ctx.request.headers.entries());
|
|
608
|
+
break;
|
|
609
|
+
case "ip":
|
|
610
|
+
args[p.index] = ctx.request.headers.get("x-forwarded-for") ?? "127.0.0.1";
|
|
611
|
+
break;
|
|
612
|
+
case "session":
|
|
613
|
+
args[p.index] = void 0;
|
|
614
|
+
break;
|
|
615
|
+
default:
|
|
616
|
+
args[p.index] = void 0;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return args;
|
|
620
|
+
}
|
|
621
|
+
__name(buildArgs, "buildArgs");
|
|
622
|
+
|
|
623
|
+
// src/typed-client.ts
|
|
624
|
+
function createTypedClient(baseUrl, defaultHeaders) {
|
|
625
|
+
async function request(method, path, body, opts) {
|
|
626
|
+
const url = new URL(path, baseUrl);
|
|
627
|
+
if (opts?.query) {
|
|
628
|
+
for (const [k, v] of Object.entries(opts.query)) url.searchParams.set(k, v);
|
|
629
|
+
}
|
|
630
|
+
const headers = {
|
|
631
|
+
...defaultHeaders,
|
|
632
|
+
...opts?.headers
|
|
633
|
+
};
|
|
634
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
635
|
+
const res = await fetch(url.toString(), {
|
|
636
|
+
method,
|
|
637
|
+
headers,
|
|
638
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
639
|
+
});
|
|
640
|
+
if (!res.ok) {
|
|
641
|
+
const error = await res.json().catch(() => ({
|
|
642
|
+
message: res.statusText
|
|
643
|
+
}));
|
|
644
|
+
throw new TypedClientError(res.status, error);
|
|
645
|
+
}
|
|
646
|
+
if (res.status === 204) return void 0;
|
|
647
|
+
return res.json();
|
|
648
|
+
}
|
|
649
|
+
__name(request, "request");
|
|
650
|
+
return {
|
|
651
|
+
get: /* @__PURE__ */ __name((path, opts) => request("GET", path, void 0, opts), "get"),
|
|
652
|
+
post: /* @__PURE__ */ __name((path, body, opts) => request("POST", path, body, opts), "post"),
|
|
653
|
+
put: /* @__PURE__ */ __name((path, body, opts) => request("PUT", path, body, opts), "put"),
|
|
654
|
+
delete: /* @__PURE__ */ __name((path, opts) => request("DELETE", path, void 0, opts), "delete")
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
__name(createTypedClient, "createTypedClient");
|
|
658
|
+
var TypedClientError = class extends Error {
|
|
659
|
+
static {
|
|
660
|
+
__name(this, "TypedClientError");
|
|
661
|
+
}
|
|
662
|
+
status;
|
|
663
|
+
body;
|
|
664
|
+
constructor(status, body) {
|
|
665
|
+
super(`HTTP ${status}: ${JSON.stringify(body)}`), this.status = status, this.body = body;
|
|
666
|
+
this.name = "TypedClientError";
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
// src/contract.ts
|
|
671
|
+
function contract(routes) {
|
|
672
|
+
return routes;
|
|
673
|
+
}
|
|
674
|
+
__name(contract, "contract");
|
|
675
|
+
export {
|
|
676
|
+
All,
|
|
677
|
+
BadGatewayException,
|
|
678
|
+
BadRequestException,
|
|
679
|
+
Body,
|
|
680
|
+
CATCH_EXCEPTIONS,
|
|
681
|
+
CONTROLLER_PREFIX,
|
|
682
|
+
Catch,
|
|
683
|
+
ConflictException,
|
|
684
|
+
Controller,
|
|
685
|
+
Delete,
|
|
686
|
+
ForbiddenException,
|
|
687
|
+
GatewayTimeoutException,
|
|
688
|
+
Get,
|
|
689
|
+
GoneException,
|
|
690
|
+
Head,
|
|
691
|
+
Header,
|
|
692
|
+
Headers,
|
|
693
|
+
HostParam,
|
|
694
|
+
HttpCode,
|
|
695
|
+
HttpDecoratorsConfigError,
|
|
696
|
+
HttpException,
|
|
697
|
+
HttpStatus,
|
|
698
|
+
HttpVersionNotSupportedException,
|
|
699
|
+
ImATeapotException,
|
|
700
|
+
InternalServerErrorException,
|
|
701
|
+
Ip,
|
|
702
|
+
MethodNotAllowedException,
|
|
703
|
+
MiddlewareConsumerImpl,
|
|
704
|
+
NotAcceptableException,
|
|
705
|
+
NotFoundException,
|
|
706
|
+
NotImplementedException,
|
|
707
|
+
Options,
|
|
708
|
+
Param,
|
|
709
|
+
Patch,
|
|
710
|
+
PayloadTooLargeException,
|
|
711
|
+
Post,
|
|
712
|
+
PreconditionFailedException,
|
|
713
|
+
Put,
|
|
714
|
+
Query,
|
|
715
|
+
ROUTE_HEADERS,
|
|
716
|
+
ROUTE_METHODS,
|
|
717
|
+
ROUTE_PARAMS,
|
|
718
|
+
ROUTE_REDIRECT,
|
|
719
|
+
ROUTE_STATUS,
|
|
720
|
+
Redirect,
|
|
721
|
+
Reflector,
|
|
722
|
+
Req,
|
|
723
|
+
RequestTimeoutException,
|
|
724
|
+
Res,
|
|
725
|
+
ServiceUnavailableException,
|
|
726
|
+
Session,
|
|
727
|
+
SetMetadata,
|
|
728
|
+
SkipThrottle,
|
|
729
|
+
TheoApp,
|
|
730
|
+
Throttle,
|
|
731
|
+
TooManyRequestsException,
|
|
732
|
+
TypedClientError,
|
|
733
|
+
USE_FILTERS,
|
|
734
|
+
USE_GUARDS,
|
|
735
|
+
USE_INTERCEPTORS,
|
|
736
|
+
UnauthorizedException,
|
|
737
|
+
UnprocessableEntityException,
|
|
738
|
+
UnsupportedMediaTypeException,
|
|
739
|
+
UseFilters,
|
|
740
|
+
UseGuards,
|
|
741
|
+
UseInterceptors,
|
|
742
|
+
contract,
|
|
743
|
+
createDecorator,
|
|
744
|
+
createDecoratorServer,
|
|
745
|
+
createExecutionContext,
|
|
746
|
+
createTypedClient,
|
|
747
|
+
getMeta,
|
|
748
|
+
getThrottleOptions,
|
|
749
|
+
isThrottleSkipped,
|
|
750
|
+
joinPath,
|
|
751
|
+
middlewareMatchesPath,
|
|
752
|
+
registerControllers,
|
|
753
|
+
resolveDtoSchema,
|
|
754
|
+
resolveOrNew,
|
|
755
|
+
runExceptionFilters,
|
|
756
|
+
runInterceptors,
|
|
757
|
+
runMiddleware,
|
|
758
|
+
setMeta,
|
|
759
|
+
walkControllerMetadata
|
|
760
|
+
};
|
|
761
|
+
//# sourceMappingURL=index.js.map
|