@synchjs/ewb 1.0.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.
Files changed (41) hide show
  1. package/README.md +292 -0
  2. package/dist/Components/ServeMemoryStore.d.ts +14 -0
  3. package/dist/Components/ServeMemoryStore.d.ts.map +1 -0
  4. package/dist/Components/ServeMemoryStore.js +77 -0
  5. package/dist/Components/Server.d.ts +48 -0
  6. package/dist/Components/Server.d.ts.map +1 -0
  7. package/dist/Components/Server.js +441 -0
  8. package/dist/Decorations/Authorized.d.ts +8 -0
  9. package/dist/Decorations/Authorized.d.ts.map +1 -0
  10. package/dist/Decorations/Authorized.js +20 -0
  11. package/dist/Decorations/Controller.d.ts +8 -0
  12. package/dist/Decorations/Controller.d.ts.map +1 -0
  13. package/dist/Decorations/Controller.js +21 -0
  14. package/dist/Decorations/Metadata.d.ts +30 -0
  15. package/dist/Decorations/Metadata.d.ts.map +1 -0
  16. package/dist/Decorations/Metadata.js +32 -0
  17. package/dist/Decorations/Methods.d.ts +8 -0
  18. package/dist/Decorations/Methods.d.ts.map +1 -0
  19. package/dist/Decorations/Methods.js +52 -0
  20. package/dist/Decorations/Middleware.d.ts +5 -0
  21. package/dist/Decorations/Middleware.d.ts.map +1 -0
  22. package/dist/Decorations/Middleware.js +19 -0
  23. package/dist/Decorations/Security.d.ts +9 -0
  24. package/dist/Decorations/Security.d.ts.map +1 -0
  25. package/dist/Decorations/Security.js +24 -0
  26. package/dist/Decorations/Serve.d.ts +2 -0
  27. package/dist/Decorations/Serve.d.ts.map +1 -0
  28. package/dist/Decorations/Serve.js +31 -0
  29. package/dist/Decorations/Tailwind.d.ts +7 -0
  30. package/dist/Decorations/Tailwind.d.ts.map +1 -0
  31. package/dist/Decorations/Tailwind.js +8 -0
  32. package/dist/Decorations/index.d.ts +9 -0
  33. package/dist/Decorations/index.d.ts.map +1 -0
  34. package/dist/Decorations/index.js +8 -0
  35. package/dist/globals.d.ts +6 -0
  36. package/dist/globals.d.ts.map +1 -0
  37. package/dist/globals.js +0 -0
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +5 -0
  41. package/package.json +51 -0
@@ -0,0 +1,441 @@
1
+ import express from "express";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import swaggerUi from "swagger-ui-express";
5
+ const swaggerJsdoc = require("swagger-jsdoc");
6
+ import helmet from "helmet";
7
+ import cors from "cors";
8
+ import rateLimit from "express-rate-limit";
9
+ import Ajv from "ajv";
10
+ import addFormats from "ajv-formats";
11
+ import { MetadataStorage } from "../Decorations";
12
+ import * as jwt from "jsonwebtoken";
13
+ import { AUTH_METADATA_KEY, PUBLIC_METADATA_KEY, } from "../Decorations/Authorized";
14
+ import { SECURITY_METADATA_KEY, } from "../Decorations/Security";
15
+ import { TAILWIND_METADATA_KEY, } from "../Decorations/Tailwind";
16
+ import { ServeMemoryStore } from "./ServeMemoryStore";
17
+ import boxen from "boxen";
18
+ import pc from "picocolors";
19
+ export class Server {
20
+ _app;
21
+ _port;
22
+ _controllersDir;
23
+ _id;
24
+ _enableSwagger;
25
+ _swaggerPath;
26
+ _enableLogging;
27
+ _securitySchemes;
28
+ _ajv;
29
+ _securityHandlers;
30
+ _container;
31
+ _serverInstance;
32
+ // Stats
33
+ _controllerCount = 0;
34
+ _routeCount = 0;
35
+ _tailwindEnabled = false;
36
+ constructor(options) {
37
+ this._port = options.port;
38
+ this._app = express();
39
+ this._id = options.id;
40
+ this._enableSwagger = options.enableSwagger || false;
41
+ this._swaggerPath = options.swaggerPath || "/api-docs";
42
+ this._enableLogging =
43
+ options.logging === undefined ? true : options.logging;
44
+ this._controllersDir = options.controllersDir || "controllers";
45
+ this._securityHandlers = options.securityHandlers || {};
46
+ this._securitySchemes = options.securitySchemes;
47
+ this._container = options.container;
48
+ // Initialize AJV
49
+ this._ajv = new Ajv({ allErrors: true, strict: false });
50
+ addFormats(this._ajv);
51
+ // Security Middleware
52
+ this._app.use(helmet(options.helmetOptions));
53
+ this._app.use(cors(options.corsOptions));
54
+ this._app.use(rateLimit(options.rateLimitOptions || {
55
+ windowMs: 15 * 60 * 1000,
56
+ max: 100,
57
+ }));
58
+ this._app.use(express.json());
59
+ global.servers.set(this._id, this._app);
60
+ }
61
+ log(message) {
62
+ if (this._enableLogging) {
63
+ console.log(message);
64
+ }
65
+ }
66
+ async init() {
67
+ await this.loadControllers();
68
+ if (this._enableSwagger) {
69
+ this.setupSwagger();
70
+ }
71
+ // Serve Static Assets from Memory Store
72
+ this._app.use((req, res, next) => {
73
+ if (req.method !== "GET" && req.method !== "HEAD")
74
+ return next();
75
+ const asset = ServeMemoryStore.instance.getAsset(req.path);
76
+ if (asset) {
77
+ res.type(asset.type).send(Buffer.from(asset.content));
78
+ return;
79
+ }
80
+ next();
81
+ });
82
+ // Global Error Handler
83
+ this._app.use((err, req, res, next) => {
84
+ console.error(`[${this._id}] Error:`, err);
85
+ res.status(err.status || 500).json({
86
+ error: "Internal Server Error",
87
+ message: "An unexpected error occurred",
88
+ });
89
+ });
90
+ this._serverInstance = this._app.listen(this._port, () => {
91
+ if (this._enableLogging) {
92
+ this.printStartupMessage();
93
+ }
94
+ });
95
+ }
96
+ printStartupMessage() {
97
+ const pad = (str) => str.padEnd(15);
98
+ const lines = [
99
+ pc.green(`Server '${this._id}' is running!`),
100
+ "",
101
+ `${pc.bold(pad("Port:"))}${this._port}`,
102
+ `${pc.bold(pad("PID:"))}${process.pid}`,
103
+ `${pc.bold(pad("Controllers:"))}${this._controllerCount}`,
104
+ `${pc.bold(pad("Routes:"))}${this._routeCount}`,
105
+ `${pc.bold(pad("Tailwind:"))}${this._tailwindEnabled ? pc.blue("Enabled") : pc.dim("Disabled")}`,
106
+ ];
107
+ if (this._enableSwagger) {
108
+ lines.push(`${pc.bold(pad("Swagger:"))}http://localhost:${this._port}${this._swaggerPath}`);
109
+ }
110
+ console.log(boxen(lines.join("\n"), {
111
+ padding: 1,
112
+ margin: 1,
113
+ borderStyle: "round",
114
+ borderColor: "green",
115
+ title: "Server Status",
116
+ titleAlignment: "center",
117
+ }));
118
+ }
119
+ close() {
120
+ if (this._serverInstance) {
121
+ this._serverInstance.close(() => {
122
+ this.log(`Server '${this._id}' stopped.`);
123
+ });
124
+ }
125
+ global.servers.delete(this._id);
126
+ }
127
+ async loadControllers() {
128
+ const absoluteControllersPath = path.resolve(process.cwd(), this._controllersDir);
129
+ if (!fs.existsSync(absoluteControllersPath)) {
130
+ console.warn(`Controllers directory not found: ${absoluteControllersPath}`);
131
+ return;
132
+ }
133
+ const files = fs
134
+ .readdirSync(absoluteControllersPath)
135
+ .filter((file) => file.endsWith(".ts") || file.endsWith(".js"));
136
+ for (const file of files) {
137
+ const filePath = path.join(absoluteControllersPath, file);
138
+ await import(filePath);
139
+ }
140
+ const controllers = MetadataStorage.instance.getControllers();
141
+ for (const controller of controllers) {
142
+ if (controller.serverIds && !controller.serverIds.includes(this._id)) {
143
+ continue;
144
+ }
145
+ this._controllerCount++;
146
+ // Check for Tailwind metadata
147
+ const tailwindOptions = Reflect.getMetadata(TAILWIND_METADATA_KEY, controller.target);
148
+ if (tailwindOptions?.enable) {
149
+ this._tailwindEnabled = true;
150
+ }
151
+ const instance = this._container?.get
152
+ ? this._container.get(controller.target)
153
+ : new controller.target();
154
+ // Check class level auth
155
+ const classAuthInfo = Reflect.getMetadata(AUTH_METADATA_KEY, controller.target);
156
+ for (const route of controller.routes) {
157
+ const fullPath = (controller.path + "/" + route.path).replace(/\/+/g, "/");
158
+ const middlewares = [];
159
+ // Check method level metadata
160
+ const methodAuthInfo = Reflect.getMetadata(AUTH_METADATA_KEY, controller.target.prototype, route.handlerName);
161
+ const isPublic = Reflect.getMetadata(PUBLIC_METADATA_KEY, controller.target.prototype, route.handlerName);
162
+ // Determine if auth is required and which secret to use
163
+ let authSecret;
164
+ if (isPublic) {
165
+ authSecret = undefined;
166
+ }
167
+ else if (methodAuthInfo) {
168
+ authSecret = methodAuthInfo.secret || process.env.JWT_SECRET;
169
+ }
170
+ else if (classAuthInfo) {
171
+ authSecret = classAuthInfo.secret || process.env.JWT_SECRET;
172
+ }
173
+ // 1. Auth Middleware (New Decorator Logic)
174
+ if (authSecret) {
175
+ middlewares.push(this.createJwtMiddleware(authSecret));
176
+ // Inject Swagger security definition automatically
177
+ if (!route.swagger) {
178
+ route.swagger = {
179
+ responses: {
180
+ 200: {
181
+ description: "Default response",
182
+ },
183
+ },
184
+ };
185
+ }
186
+ if (!route.swagger.security) {
187
+ route.swagger.security = [];
188
+ }
189
+ // specific check to avoid duplicating if user manually added it
190
+ const hasBearer = route.swagger.security.some((s) => "bearerAuth" in s);
191
+ if (!hasBearer) {
192
+ route.swagger.security.push({ bearerAuth: [] });
193
+ }
194
+ }
195
+ // 2. Generic Security Middleware (@Security, @OAuth, etc)
196
+ const classGenericSecurity = Reflect.getMetadata(SECURITY_METADATA_KEY, controller.target) || [];
197
+ const methodGenericSecurity = Reflect.getMetadata(SECURITY_METADATA_KEY, controller.target.prototype, route.handlerName) || [];
198
+ let genericRequirements = [];
199
+ if (isPublic) {
200
+ // If public, we might want to skip class generic security too?
201
+ // Usually yes.
202
+ genericRequirements = [...methodGenericSecurity];
203
+ }
204
+ else {
205
+ genericRequirements = [
206
+ ...classGenericSecurity,
207
+ ...methodGenericSecurity,
208
+ ];
209
+ }
210
+ // Add to Swagger
211
+ if (genericRequirements.length > 0) {
212
+ if (!route.swagger) {
213
+ route.swagger = {
214
+ responses: {
215
+ 200: { description: "Default response" },
216
+ },
217
+ };
218
+ }
219
+ if (!route.swagger.security) {
220
+ route.swagger.security = [];
221
+ }
222
+ route.swagger.security.push(...genericRequirements);
223
+ }
224
+ // 3. Auth Middleware (Old logic - support existing manual config + generic)
225
+ const manualRequirements = [
226
+ ...(route.swagger?.security || []),
227
+ ...(controller.security || []),
228
+ ];
229
+ // We already pushed genericRequirements to route.swagger.security, so manualRequirements includes them?
230
+ // Wait, route.swagger.security is updated above.
231
+ // So manualRequirements now has everything including bearerAuth (pushed above) and generic (pushed above).
232
+ // BUT, controller.security (from @Controller options) might duplicate classGenericSecurity?
233
+ // Let's rely on route.swagger.security + controller.security.
234
+ // And we should filter out duplicates if necessary, but Swagger UI handles it usually (OR logic between items in array).
235
+ // Actually, genericRequirements are added to route.swagger.security.
236
+ // So we can just use route.swagger.security.
237
+ // However, controller.security is separate.
238
+ const allSecurityRequirements = [
239
+ ...(route.swagger?.security || []),
240
+ ...(controller.security || []),
241
+ ];
242
+ // Filter out bearerAuth if handled by createJwtMiddleware (to avoid double check if handler is missing)
243
+ // createJwtMiddleware handles 'bearerAuth'.
244
+ // createAuthMiddleware handles everything else via securityHandlers.
245
+ // If we have 'bearerAuth' in requirements, createAuthMiddleware will look for a handler for 'bearerAuth'.
246
+ // If user didn't provide one, it warns.
247
+ // We should probably allow 'bearerAuth' in createAuthMiddleware IF user provided a handler.
248
+ // But we added createJwtMiddleware explicitly.
249
+ // So we should filter 'bearerAuth' out of requirements passed to createAuthMiddleware UNLESS user provided a handler for it?
250
+ // Or just let it run. If user provides handler, it runs twice?
251
+ // createJwtMiddleware is added if `authSecret` is true (from @BearerAuth).
252
+ // If `bearerAuth` is in swagger because of @BearerAuth, we risk running twice if user adds handler.
253
+ // But `@BearerAuth` logic uses `createJwtMiddleware`.
254
+ // The `genericRequirements` logic adds to swagger.
255
+ // Let's assume standard usage: use @BearerAuth OR @Security("bearerAuth"). Not both.
256
+ if (allSecurityRequirements.length > 0) {
257
+ middlewares.push(this.createAuthMiddleware(allSecurityRequirements));
258
+ }
259
+ // 4. Validation Middleware
260
+ // 2. Validation Middleware
261
+ if (route.swagger?.requestBody &&
262
+ route.swagger.requestBody.content?.["application/json"]
263
+ ?.schema) {
264
+ const schema = route.swagger.requestBody.content["application/json"].schema;
265
+ middlewares.push(this.createValidationMiddleware(schema));
266
+ }
267
+ // 3. Custom Middlewares
268
+ // Controller Level
269
+ if (controller.middlewares) {
270
+ middlewares.push(...controller.middlewares);
271
+ }
272
+ // Route Level
273
+ if (route.middlewares) {
274
+ middlewares.push(...route.middlewares);
275
+ }
276
+ // 3. Route Handler
277
+ const handler = (req, res, next) => {
278
+ try {
279
+ const result = instance[route.handlerName](req, res, next);
280
+ const handleResult = (val) => {
281
+ if (val !== undefined && !res.headersSent) {
282
+ if (typeof val === "string") {
283
+ res.send(val);
284
+ }
285
+ else if (typeof val === "object") {
286
+ res.json(val);
287
+ }
288
+ }
289
+ };
290
+ if (result instanceof Promise) {
291
+ result.then(handleResult).catch(next);
292
+ }
293
+ else {
294
+ handleResult(result);
295
+ }
296
+ }
297
+ catch (error) {
298
+ next(error);
299
+ }
300
+ };
301
+ this._app[route.method](fullPath, ...middlewares, handler);
302
+ this._routeCount++;
303
+ }
304
+ }
305
+ }
306
+ createJwtMiddleware(secret) {
307
+ return (req, res, next) => {
308
+ const authHeader = req.headers.authorization;
309
+ if (!authHeader || !authHeader.startsWith("Bearer ")) {
310
+ return res
311
+ .status(401)
312
+ .json({ error: "Unauthorized: Missing Bearer token" });
313
+ }
314
+ const token = authHeader.split(" ")[1];
315
+ try {
316
+ const decoded = jwt.verify(token, secret);
317
+ req.user = decoded; // Attach user to request
318
+ next();
319
+ }
320
+ catch (err) {
321
+ return res.status(403).json({ error: "Forbidden: Invalid token" });
322
+ }
323
+ };
324
+ }
325
+ createAuthMiddleware(requirements) {
326
+ return (req, res, next) => {
327
+ if (requirements.length === 0)
328
+ return next();
329
+ let requirementIndex = 0;
330
+ const checkRequirement = (index) => {
331
+ if (index >= requirements.length) {
332
+ // All requirements failed
333
+ return res.status(401).json({ error: "Unauthorized" });
334
+ }
335
+ const requirement = requirements[index];
336
+ const schemes = Object.keys(requirement);
337
+ if (schemes.length === 0) {
338
+ // Empty requirement means public access is allowed
339
+ return next();
340
+ }
341
+ const checkScheme = (schemeIndex) => {
342
+ if (schemeIndex >= schemes.length) {
343
+ // All schemes in this requirement passed
344
+ return next();
345
+ }
346
+ const scheme = schemes[schemeIndex];
347
+ const handler = this._securityHandlers[scheme];
348
+ if (!handler) {
349
+ console.warn(`[${this._id}] Security handler for '${scheme}' not configured.`);
350
+ // If handler is missing, this scheme fails. Ideally, we should treat it as an error.
351
+ // But since this is one of potentially many AND schemes, failure here means this requirement fails.
352
+ // Move to next requirement.
353
+ return checkRequirement(index + 1);
354
+ }
355
+ handler(req, res, (err) => {
356
+ if (err) {
357
+ // This scheme failed, so the whole requirement fails.
358
+ // Move to the next requirement (OR logic).
359
+ return checkRequirement(index + 1);
360
+ }
361
+ // This scheme passed, move to the next scheme in the same requirement (AND logic).
362
+ checkScheme(schemeIndex + 1);
363
+ });
364
+ };
365
+ checkScheme(0);
366
+ };
367
+ checkRequirement(0);
368
+ };
369
+ }
370
+ createValidationMiddleware(schema) {
371
+ const validate = this._ajv.compile(schema);
372
+ return (req, res, next) => {
373
+ const valid = validate(req.body);
374
+ if (!valid) {
375
+ return res.status(400).json({
376
+ error: "Validation Error",
377
+ details: validate.errors,
378
+ });
379
+ }
380
+ next();
381
+ };
382
+ }
383
+ setupSwagger() {
384
+ const controllers = MetadataStorage.instance
385
+ .getControllers()
386
+ .filter((c) => !c.serverIds || c.serverIds.includes(this._id));
387
+ const paths = {};
388
+ for (const controller of controllers) {
389
+ for (const route of controller.routes) {
390
+ const fullPath = (controller.path + "/" + route.path)
391
+ .replace(/\/+/g, "/")
392
+ .replace(/:([^/]+)/g, "{$1}");
393
+ if (!paths[fullPath]) {
394
+ paths[fullPath] = {};
395
+ }
396
+ const operation = route.swagger
397
+ ? { ...route.swagger }
398
+ : {
399
+ responses: {
400
+ 200: {
401
+ description: "Default response",
402
+ },
403
+ },
404
+ };
405
+ if (controller.tags) {
406
+ operation.tags = [...(operation.tags || []), ...controller.tags];
407
+ }
408
+ if (controller.security) {
409
+ operation.security = [
410
+ ...(operation.security || []),
411
+ ...controller.security,
412
+ ];
413
+ }
414
+ paths[fullPath][route.method] = operation;
415
+ }
416
+ }
417
+ const options = {
418
+ definition: {
419
+ openapi: "3.0.0",
420
+ info: {
421
+ title: `Server ${this._id} API`,
422
+ version: "1.0.0",
423
+ },
424
+ paths: paths,
425
+ components: {
426
+ securitySchemes: {
427
+ bearerAuth: {
428
+ type: "http",
429
+ scheme: "bearer",
430
+ bearerFormat: "JWT",
431
+ },
432
+ ...this._securitySchemes,
433
+ },
434
+ },
435
+ },
436
+ apis: [],
437
+ };
438
+ const specs = swaggerJsdoc(options);
439
+ this._app.use(this._swaggerPath, swaggerUi.serve, swaggerUi.setup(specs));
440
+ }
441
+ }
@@ -0,0 +1,8 @@
1
+ export declare const AUTH_METADATA_KEY = "auth:info";
2
+ export declare const PUBLIC_METADATA_KEY = "auth:public";
3
+ export interface AuthInfo {
4
+ secret?: string;
5
+ }
6
+ export declare function BearerAuth(secret?: string): MethodDecorator & ClassDecorator;
7
+ export declare function Public(): MethodDecorator;
8
+ //# sourceMappingURL=Authorized.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Authorized.d.ts","sourceRoot":"","sources":["../../src/Decorations/Authorized.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAC7C,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,cAAc,CAmB5E;AAED,wBAAgB,MAAM,IAAI,eAAe,CAQxC"}
@@ -0,0 +1,20 @@
1
+ // Key to store auth metadata
2
+ export const AUTH_METADATA_KEY = "auth:info";
3
+ export const PUBLIC_METADATA_KEY = "auth:public";
4
+ export function BearerAuth(secret) {
5
+ return function (target, propertyKey, descriptor) {
6
+ // If used on a method
7
+ if (propertyKey) {
8
+ Reflect.defineMetadata(AUTH_METADATA_KEY, { secret }, target, propertyKey);
9
+ }
10
+ else {
11
+ // If used on a class
12
+ Reflect.defineMetadata(AUTH_METADATA_KEY, { secret }, target);
13
+ }
14
+ };
15
+ }
16
+ export function Public() {
17
+ return function (target, propertyKey, descriptor) {
18
+ Reflect.defineMetadata(PUBLIC_METADATA_KEY, true, target, propertyKey);
19
+ };
20
+ }
@@ -0,0 +1,8 @@
1
+ import { OpenAPIV3 } from "openapi-types";
2
+ export interface ControllerOptions {
3
+ serverIds?: string[];
4
+ tags?: string[];
5
+ security?: OpenAPIV3.SecurityRequirementObject[];
6
+ }
7
+ export declare function Controller(path: string, options?: ControllerOptions): (target: Function) => void;
8
+ //# sourceMappingURL=Controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Controller.d.ts","sourceRoot":"","sources":["../../src/Decorations/Controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG1C,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,SAAS,CAAC,yBAAyB,EAAE,CAAC;CAClD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,IACjD,QAAQ,QAAQ,UAyBlC"}
@@ -0,0 +1,21 @@
1
+ import { MetadataStorage } from "./Metadata";
2
+ export function Controller(path, options) {
3
+ return function (target) {
4
+ const routes = MetadataStorage.instance.getRoutes(target);
5
+ const controllerMiddlewares = Reflect.getMetadata("middlewares", target) || [];
6
+ // Inject middleware into routes
7
+ routes.forEach((route) => {
8
+ route.middlewares =
9
+ Reflect.getMetadata("middlewares", target.prototype, route.handlerName) || [];
10
+ });
11
+ MetadataStorage.instance.addController({
12
+ target: target,
13
+ path: path,
14
+ serverIds: options?.serverIds,
15
+ tags: options?.tags,
16
+ security: options?.security,
17
+ middlewares: controllerMiddlewares,
18
+ routes: routes,
19
+ });
20
+ };
21
+ }
@@ -0,0 +1,30 @@
1
+ import "reflect-metadata";
2
+ import type { RequestHandler } from "express";
3
+ import { OpenAPIV3 } from "openapi-types";
4
+ export interface RouteDefinition {
5
+ method: "get" | "post" | "put" | "delete" | "patch";
6
+ path: string;
7
+ handlerName: string;
8
+ swagger?: OpenAPIV3.OperationObject;
9
+ middlewares?: RequestHandler[];
10
+ }
11
+ export interface ControllerDefinition {
12
+ target: any;
13
+ path: string;
14
+ serverIds?: string[];
15
+ routes: RouteDefinition[];
16
+ tags?: string[];
17
+ security?: OpenAPIV3.SecurityRequirementObject[];
18
+ middlewares?: RequestHandler[];
19
+ }
20
+ export declare class MetadataStorage {
21
+ private static _instance;
22
+ private _controllers;
23
+ private constructor();
24
+ static get instance(): MetadataStorage;
25
+ addController(controller: ControllerDefinition): void;
26
+ getControllers(): ControllerDefinition[];
27
+ addRoute(target: any, route: RouteDefinition): void;
28
+ getRoutes(target: any): RouteDefinition[];
29
+ }
30
+ //# sourceMappingURL=Metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Metadata.d.ts","sourceRoot":"","sources":["../../src/Decorations/Metadata.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC;IACpC,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,SAAS,CAAC,yBAAyB,EAAE,CAAC;IACjD,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAChC;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAkB;IAC1C,OAAO,CAAC,YAAY,CAA8B;IAElD,OAAO;IAEP,WAAkB,QAAQ,IAAI,eAAe,CAK5C;IAEM,aAAa,CAAC,UAAU,EAAE,oBAAoB;IAI9C,cAAc,IAAI,oBAAoB,EAAE;IAIxC,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe;IAc5C,SAAS,CAAC,MAAM,EAAE,GAAG,GAAG,eAAe,EAAE;CAGjD"}
@@ -0,0 +1,32 @@
1
+ import "reflect-metadata";
2
+ export class MetadataStorage {
3
+ static _instance;
4
+ _controllers = [];
5
+ constructor() { }
6
+ static get instance() {
7
+ if (!MetadataStorage._instance) {
8
+ MetadataStorage._instance = new MetadataStorage();
9
+ }
10
+ return MetadataStorage._instance;
11
+ }
12
+ addController(controller) {
13
+ this._controllers.push(controller);
14
+ }
15
+ getControllers() {
16
+ return this._controllers;
17
+ }
18
+ addRoute(target, route) {
19
+ const existingController = this._controllers.find((c) => c.target === target);
20
+ if (existingController) {
21
+ existingController.routes.push(route);
22
+ }
23
+ else {
24
+ const routes = Reflect.getMetadata("routes", target) || [];
25
+ routes.push(route);
26
+ Reflect.defineMetadata("routes", routes, target);
27
+ }
28
+ }
29
+ getRoutes(target) {
30
+ return Reflect.getMetadata("routes", target) || [];
31
+ }
32
+ }
@@ -0,0 +1,8 @@
1
+ import "reflect-metadata";
2
+ import { OpenAPIV3 } from "openapi-types";
3
+ export declare function Get(path: string, swagger?: OpenAPIV3.OperationObject): MethodDecorator;
4
+ export declare function Post(path: string, swagger?: OpenAPIV3.OperationObject): MethodDecorator;
5
+ export declare function Put(path: string, swagger?: OpenAPIV3.OperationObject): MethodDecorator;
6
+ export declare function Delete(path: string, swagger?: OpenAPIV3.OperationObject): MethodDecorator;
7
+ export declare function Patch(path: string, swagger?: OpenAPIV3.OperationObject): MethodDecorator;
8
+ //# sourceMappingURL=Methods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Methods.d.ts","sourceRoot":"","sources":["../../src/Decorations/Methods.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,GAClC,eAAe,CAajB;AAED,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,GAClC,eAAe,CAajB;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,GAClC,eAAe,CAajB;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,GAClC,eAAe,CAajB;AAED,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,SAAS,CAAC,eAAe,GAClC,eAAe,CAajB"}
@@ -0,0 +1,52 @@
1
+ import "reflect-metadata";
2
+ import { MetadataStorage } from "./Metadata";
3
+ export function Get(path, swagger) {
4
+ return function (target, propertyKey, descriptor) {
5
+ MetadataStorage.instance.addRoute(target.constructor, {
6
+ method: "get",
7
+ path,
8
+ handlerName: propertyKey,
9
+ swagger,
10
+ });
11
+ };
12
+ }
13
+ export function Post(path, swagger) {
14
+ return function (target, propertyKey, descriptor) {
15
+ MetadataStorage.instance.addRoute(target.constructor, {
16
+ method: "post",
17
+ path,
18
+ handlerName: propertyKey,
19
+ swagger,
20
+ });
21
+ };
22
+ }
23
+ export function Put(path, swagger) {
24
+ return function (target, propertyKey, descriptor) {
25
+ MetadataStorage.instance.addRoute(target.constructor, {
26
+ method: "put",
27
+ path,
28
+ handlerName: propertyKey,
29
+ swagger,
30
+ });
31
+ };
32
+ }
33
+ export function Delete(path, swagger) {
34
+ return function (target, propertyKey, descriptor) {
35
+ MetadataStorage.instance.addRoute(target.constructor, {
36
+ method: "delete",
37
+ path,
38
+ handlerName: propertyKey,
39
+ swagger,
40
+ });
41
+ };
42
+ }
43
+ export function Patch(path, swagger) {
44
+ return function (target, propertyKey, descriptor) {
45
+ MetadataStorage.instance.addRoute(target.constructor, {
46
+ method: "patch",
47
+ path,
48
+ handlerName: propertyKey,
49
+ swagger,
50
+ });
51
+ };
52
+ }
@@ -0,0 +1,5 @@
1
+ import "reflect-metadata";
2
+ import type { RequestHandler } from "express";
3
+ export declare function Use(...middlewares: RequestHandler[]): (target: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => void;
4
+ export declare function Middleware(...middlewares: RequestHandler[]): (target: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) => void;
5
+ //# sourceMappingURL=Middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Middleware.d.ts","sourceRoot":"","sources":["../../src/Decorations/Middleware.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,GAAG,CAAC,GAAG,WAAW,EAAE,cAAc,EAAE,IAEhD,QAAQ,GAAG,EACX,cAAc,MAAM,GAAG,MAAM,EAC7B,aAAa,kBAAkB,UAuBlC;AACD,wBAAgB,UAAU,CAAC,GAAG,WAAW,EAAE,cAAc,EAAE,YA1B/C,GAAG,gBACG,MAAM,GAAG,MAAM,eAChB,kBAAkB,UA0BlC"}