@alis-kit/routers 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 (90) hide show
  1. package/README.md +302 -0
  2. package/dist/adapters/BaseAdapter.d.ts +63 -0
  3. package/dist/adapters/BaseAdapter.d.ts.map +1 -0
  4. package/dist/adapters/BaseAdapter.js +17 -0
  5. package/dist/adapters/BaseAdapter.js.map +1 -0
  6. package/dist/adapters/ExpressAdapter.d.ts +44 -0
  7. package/dist/adapters/ExpressAdapter.d.ts.map +1 -0
  8. package/dist/adapters/ExpressAdapter.js +73 -0
  9. package/dist/adapters/ExpressAdapter.js.map +1 -0
  10. package/dist/adapters/FastifyAdapter.d.ts +61 -0
  11. package/dist/adapters/FastifyAdapter.d.ts.map +1 -0
  12. package/dist/adapters/FastifyAdapter.js +132 -0
  13. package/dist/adapters/FastifyAdapter.js.map +1 -0
  14. package/dist/cookie/CookieSetter.d.ts +74 -0
  15. package/dist/cookie/CookieSetter.d.ts.map +1 -0
  16. package/dist/cookie/CookieSetter.js +89 -0
  17. package/dist/cookie/CookieSetter.js.map +1 -0
  18. package/dist/core/Logger.d.ts +36 -0
  19. package/dist/core/Logger.d.ts.map +1 -0
  20. package/dist/core/Logger.js +53 -0
  21. package/dist/core/Logger.js.map +1 -0
  22. package/dist/core/RouteResolver.d.ts +91 -0
  23. package/dist/core/RouteResolver.d.ts.map +1 -0
  24. package/dist/core/RouteResolver.js +279 -0
  25. package/dist/core/RouteResolver.js.map +1 -0
  26. package/dist/core/RouterKit.d.ts +116 -0
  27. package/dist/core/RouterKit.d.ts.map +1 -0
  28. package/dist/core/RouterKit.js +175 -0
  29. package/dist/core/RouterKit.js.map +1 -0
  30. package/dist/decorators/controller/ReqController.d.ts +29 -0
  31. package/dist/decorators/controller/ReqController.d.ts.map +1 -0
  32. package/dist/decorators/controller/ReqController.js +62 -0
  33. package/dist/decorators/controller/ReqController.js.map +1 -0
  34. package/dist/decorators/mapping/index.d.ts +93 -0
  35. package/dist/decorators/mapping/index.d.ts.map +1 -0
  36. package/dist/decorators/mapping/index.js +128 -0
  37. package/dist/decorators/mapping/index.js.map +1 -0
  38. package/dist/decorators/method/index.d.ts +67 -0
  39. package/dist/decorators/method/index.d.ts.map +1 -0
  40. package/dist/decorators/method/index.js +83 -0
  41. package/dist/decorators/method/index.js.map +1 -0
  42. package/dist/decorators/parameter/index.d.ts +155 -0
  43. package/dist/decorators/parameter/index.d.ts.map +1 -0
  44. package/dist/decorators/parameter/index.js +196 -0
  45. package/dist/decorators/parameter/index.js.map +1 -0
  46. package/dist/exceptions/BadRequestException.d.ts +37 -0
  47. package/dist/exceptions/BadRequestException.d.ts.map +1 -0
  48. package/dist/exceptions/BadRequestException.js +37 -0
  49. package/dist/exceptions/BadRequestException.js.map +1 -0
  50. package/dist/exceptions/BaseException.d.ts +29 -0
  51. package/dist/exceptions/BaseException.d.ts.map +1 -0
  52. package/dist/exceptions/BaseException.js +29 -0
  53. package/dist/exceptions/BaseException.js.map +1 -0
  54. package/dist/exceptions/ConflictException.d.ts +28 -0
  55. package/dist/exceptions/ConflictException.d.ts.map +1 -0
  56. package/dist/exceptions/ConflictException.js +28 -0
  57. package/dist/exceptions/ConflictException.js.map +1 -0
  58. package/dist/exceptions/ForbiddenException.d.ts +26 -0
  59. package/dist/exceptions/ForbiddenException.d.ts.map +1 -0
  60. package/dist/exceptions/ForbiddenException.js +26 -0
  61. package/dist/exceptions/ForbiddenException.js.map +1 -0
  62. package/dist/exceptions/NotFoundException.d.ts +28 -0
  63. package/dist/exceptions/NotFoundException.d.ts.map +1 -0
  64. package/dist/exceptions/NotFoundException.js +28 -0
  65. package/dist/exceptions/NotFoundException.js.map +1 -0
  66. package/dist/exceptions/ServerErrorException.d.ts +33 -0
  67. package/dist/exceptions/ServerErrorException.d.ts.map +1 -0
  68. package/dist/exceptions/ServerErrorException.js +33 -0
  69. package/dist/exceptions/ServerErrorException.js.map +1 -0
  70. package/dist/exceptions/UnauthorizedException.d.ts +28 -0
  71. package/dist/exceptions/UnauthorizedException.d.ts.map +1 -0
  72. package/dist/exceptions/UnauthorizedException.js +28 -0
  73. package/dist/exceptions/UnauthorizedException.js.map +1 -0
  74. package/dist/index.d.ts +15 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +21 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/swagger/SwaggerGenerator.d.ts +63 -0
  79. package/dist/swagger/SwaggerGenerator.d.ts.map +1 -0
  80. package/dist/swagger/SwaggerGenerator.js +266 -0
  81. package/dist/swagger/SwaggerGenerator.js.map +1 -0
  82. package/dist/swagger/SwaggerUI.d.ts +30 -0
  83. package/dist/swagger/SwaggerUI.d.ts.map +1 -0
  84. package/dist/swagger/SwaggerUI.js +52 -0
  85. package/dist/swagger/SwaggerUI.js.map +1 -0
  86. package/dist/types/index.d.ts +255 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +31 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/package.json +52 -0
@@ -0,0 +1,279 @@
1
+ import { ZodError } from "zod";
2
+ import { META, getClassMeta, paramMetaStore } from "../types/index.js";
3
+ import { CookieSetter } from "../cookie/CookieSetter.js";
4
+ import { BaseException } from "../exceptions/BaseException.js";
5
+ import { BadRequestException } from "../exceptions/BadRequestException.js";
6
+ import { ServerErrorException } from "../exceptions/ServerErrorException.js";
7
+ import { Logger } from "./Logger.js";
8
+ /**
9
+ * Internal engine yang membaca metadata dari TC39 decorators (`Symbol.metadata`)
10
+ * dan WeakMap (parameter decorators), lalu mendaftarkan route ke framework adapter.
11
+ *
12
+ * Semua logic inti ada di sini: parameter injection, Zod validation,
13
+ * error handling, response envelope, auth middleware, dan logging.
14
+ */
15
+ export class RouteResolver {
16
+ adapter;
17
+ loggerConfig;
18
+ authMiddleware;
19
+ refreshMiddleware;
20
+ responseEnvelope;
21
+ globalPrefix;
22
+ /** Melacak route yang sudah didaftarkan untuk deteksi duplikat */
23
+ registeredRoutes = new Set();
24
+ /** Semua route yang sudah di-resolve — digunakan untuk generate Swagger spec */
25
+ resolvedRoutes = [];
26
+ /**
27
+ * @param adapter - Framework adapter (Express / Fastify)
28
+ * @param loggerConfig - Konfigurasi logger
29
+ * @param authMiddleware - Middleware untuk authentication type "auth"
30
+ * @param refreshMiddleware - Middleware untuk authentication type "refresh"
31
+ * @param responseEnvelope - Mode response wrapping ("wrap" | "raw")
32
+ * @param globalPrefix - Prefix global untuk semua route (contoh: "/api")
33
+ */
34
+ constructor(adapter, loggerConfig, authMiddleware, refreshMiddleware, responseEnvelope = "wrap", globalPrefix = "") {
35
+ this.adapter = adapter;
36
+ this.loggerConfig = loggerConfig;
37
+ this.authMiddleware = authMiddleware;
38
+ this.refreshMiddleware = refreshMiddleware;
39
+ this.responseEnvelope = responseEnvelope;
40
+ this.globalPrefix = globalPrefix;
41
+ }
42
+ /**
43
+ * Resolves and registers all routes from a controller class.
44
+ * Membaca metadata dari `Symbol.metadata` (TC39) dan WeakMap (parameter),
45
+ * lalu mendaftarkan setiap route ke adapter.
46
+ *
47
+ * @param Controller - Controller class yang sudah di-decorate dengan @ReqController
48
+ *
49
+ * @throws Error jika class tidak memiliki @ReqController
50
+ * @throws Error jika ditemukan duplikat route
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const resolver = new RouteResolver(adapter);
55
+ * resolver.resolve(UserController);
56
+ * ```
57
+ */
58
+ resolve(Controller) {
59
+ const controllerMeta = getClassMeta(Controller, META.CONTROLLER);
60
+ if (!controllerMeta) {
61
+ throw new Error(`[RouterKit] Class "${Controller.name}" is not decorated with @ReqController. ` +
62
+ `Add @ReqController("/path") to the class definition.`);
63
+ }
64
+ const routes = getClassMeta(Controller, META.ROUTES) ?? [];
65
+ const controllerInstance = new Controller();
66
+ for (const route of routes) {
67
+ this.registerRoute(Controller, controllerInstance, controllerMeta, route);
68
+ }
69
+ }
70
+ /**
71
+ * Registers a single route: build path, resolve auth, inject params, register to adapter.
72
+ */
73
+ registerRoute(Controller, instance, controllerMeta, route) {
74
+ const fullPath = this.buildFullPath(controllerMeta.basePath, route.path);
75
+ const routeKey = `${route.method.toUpperCase()} ${fullPath}`;
76
+ if (this.registeredRoutes.has(routeKey)) {
77
+ throw new Error(`[RouterKit] Duplicate route detected: ${routeKey}. ` +
78
+ `Each route must have a unique method + path combination.`);
79
+ }
80
+ this.registeredRoutes.add(routeKey);
81
+ const authType = this.resolveAuthType(route.options.authentication, controllerMeta.authentication);
82
+ const authMiddlewares = this.resolveAuthMiddleware(authType);
83
+ const middlewaresKey = META.MIDDLEWARES_PREFIX + route.propertyKey;
84
+ const methodMiddlewares = getClassMeta(Controller, middlewaresKey) ?? [];
85
+ const allMiddlewares = [...authMiddlewares, ...methodMiddlewares];
86
+ const params = paramMetaStore.get(Controller)?.get(route.propertyKey) ?? [];
87
+ const httpStatusKey = META.HTTP_STATUS_PREFIX + route.propertyKey;
88
+ const statusFromDecorator = getClassMeta(Controller, httpStatusKey);
89
+ const statusCode = route.options.status ?? statusFromDecorator ?? 200;
90
+ const swaggerVisible = controllerMeta.swagger !== false && route.options.swagger !== false;
91
+ const resolvedRoute = {
92
+ method: route.method,
93
+ fullPath,
94
+ middlewares: allMiddlewares,
95
+ params,
96
+ handler: instance[route.propertyKey],
97
+ statusCode,
98
+ controllerTag: controllerMeta.tag,
99
+ swagger: swaggerVisible,
100
+ routeOptions: route.options,
101
+ };
102
+ this.resolvedRoutes.push(resolvedRoute);
103
+ const handler = this.createHandler(instance, route.propertyKey, params, statusCode, route.method);
104
+ this.adapter.registerRoute(route.method, fullPath, allMiddlewares, handler);
105
+ }
106
+ /**
107
+ * Builds the full URL path from controller base path + method path + global prefix.
108
+ */
109
+ buildFullPath(basePath, methodPath) {
110
+ const base = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
111
+ const method = methodPath.startsWith("/") ? methodPath : "/" + methodPath;
112
+ const rawPrefix = this.globalPrefix ?? "";
113
+ if (!rawPrefix)
114
+ return base + method;
115
+ const prefix = rawPrefix.startsWith("/") ? rawPrefix : "/" + rawPrefix;
116
+ const normPrefix = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
117
+ return normPrefix + base + method;
118
+ }
119
+ /**
120
+ * Resolves effective auth type: method-level override, else controller-level.
121
+ */
122
+ resolveAuthType(methodAuth, controllerAuth) {
123
+ if (methodAuth !== undefined) {
124
+ return methodAuth;
125
+ }
126
+ return controllerAuth;
127
+ }
128
+ /**
129
+ * Resolves authentication middleware array from auth type.
130
+ * Returns empty array if auth is disabled or middleware not configured.
131
+ */
132
+ resolveAuthMiddleware(authType) {
133
+ if (authType === false)
134
+ return [];
135
+ if (authType === "auth" && this.authMiddleware) {
136
+ return [this.authMiddleware];
137
+ }
138
+ if (authType === "refresh" && this.refreshMiddleware) {
139
+ return [this.refreshMiddleware];
140
+ }
141
+ return [];
142
+ }
143
+ /**
144
+ * Creates the route handler that manages parameter injection, response sending,
145
+ * error handling, and logging.
146
+ */
147
+ createHandler(instance, propertyKey, params, statusCode, routeMethod) {
148
+ const adapter = this.adapter;
149
+ const loggerConfig = this.loggerConfig;
150
+ return async (req, res) => {
151
+ const start = Date.now();
152
+ try {
153
+ const args = this.resolveParams(params, req, res);
154
+ const method = instance[propertyKey];
155
+ const result = await method.apply(instance, args);
156
+ const handlerWroteResponse = result === res ||
157
+ (typeof result === "object" &&
158
+ result !== null &&
159
+ result.__rawReply === true);
160
+ if (handlerWroteResponse) {
161
+ // No-op: response sudah dikirim oleh handler (misal: HTML redirect)
162
+ }
163
+ else {
164
+ const responseBody = this.responseEnvelope === "raw"
165
+ ? (result ?? null)
166
+ : { message: "OK", data: result ?? null };
167
+ adapter.sendResponse(res, statusCode, responseBody);
168
+ }
169
+ if (loggerConfig && (loggerConfig === true || (typeof loggerConfig === 'object' && loggerConfig.enabled !== false))) {
170
+ const duration = Date.now() - start;
171
+ const url = adapter.getUrl(req);
172
+ const handler = typeof loggerConfig === 'object' ? loggerConfig.handler : undefined;
173
+ Logger.logRequest(routeMethod, url, statusCode, duration, undefined, handler);
174
+ }
175
+ }
176
+ catch (error) {
177
+ const status = this.handleError(error, res);
178
+ if (loggerConfig && (loggerConfig === true || (typeof loggerConfig === 'object' && loggerConfig.enabled !== false))) {
179
+ const duration = Date.now() - start;
180
+ const url = adapter.getUrl(req);
181
+ const handler = typeof loggerConfig === 'object' ? loggerConfig.handler : undefined;
182
+ Logger.logRequest(routeMethod, url, status, duration, error, handler);
183
+ }
184
+ }
185
+ };
186
+ }
187
+ /**
188
+ * Resolves parameter values from the request based on param metadata.
189
+ * Parameters are sorted by index to ensure correct order.
190
+ */
191
+ resolveParams(params, req, res) {
192
+ const sorted = [...params].sort((a, b) => a.index - b.index);
193
+ const args = [];
194
+ for (const param of sorted) {
195
+ args[param.index] = this.resolveParam(param, req, res);
196
+ }
197
+ return args;
198
+ }
199
+ /**
200
+ * Resolves a single parameter value from the request.
201
+ * Supports: body, query, param, req, cookie, reply.
202
+ */
203
+ resolveParam(param, req, res) {
204
+ switch (param.type) {
205
+ case "body": {
206
+ const body = this.adapter.getBody(req);
207
+ if (param.schema) {
208
+ return this.validateWithZod(param.schema, body);
209
+ }
210
+ return body;
211
+ }
212
+ case "query": {
213
+ const query = this.adapter.getQuery(req);
214
+ if (param.schema) {
215
+ return this.validateWithZod(param.schema, query);
216
+ }
217
+ return query;
218
+ }
219
+ case "param": {
220
+ const params = this.adapter.getParams(req);
221
+ return param.key ? params[param.key] : undefined;
222
+ }
223
+ case "req":
224
+ return req;
225
+ case "cookie":
226
+ return new CookieSetter(this.adapter, req, res);
227
+ case "reply":
228
+ return res;
229
+ default:
230
+ return undefined;
231
+ }
232
+ }
233
+ /**
234
+ * Validates data against a Zod schema.
235
+ * Throws BadRequestException with field-level errors on validation failure.
236
+ */
237
+ validateWithZod(schema, data) {
238
+ if (!schema)
239
+ return data;
240
+ try {
241
+ return schema.parse(data);
242
+ }
243
+ catch (error) {
244
+ if (error instanceof ZodError) {
245
+ const errors = error.errors.map((e) => ({
246
+ field: e.path.join("."),
247
+ message: e.message,
248
+ }));
249
+ throw new BadRequestException("Validation failed", { errors });
250
+ }
251
+ throw error;
252
+ }
253
+ }
254
+ /**
255
+ * Handles errors thrown during route execution:
256
+ * - BaseException → send with its status code
257
+ * - Unknown errors → wrap as 500 ServerErrorException
258
+ */
259
+ handleError(error, res) {
260
+ if (error instanceof BaseException) {
261
+ this.adapter.sendResponse(res, error.status, {
262
+ statusCode: error.status,
263
+ code: error.code,
264
+ message: error.message,
265
+ details: error.data ?? undefined,
266
+ });
267
+ return error.status;
268
+ }
269
+ const serverError = new ServerErrorException(error instanceof Error ? error.message : "Internal server error");
270
+ this.adapter.sendResponse(res, serverError.status, {
271
+ statusCode: serverError.status,
272
+ code: serverError.code,
273
+ message: serverError.message,
274
+ details: undefined,
275
+ });
276
+ return serverError.status;
277
+ }
278
+ }
279
+ //# sourceMappingURL=RouteResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouteResolver.js","sourceRoot":"","sources":["../../core/RouteResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ import type { RouterKitConfig, Class } from "../types/index.js";
2
+ /**
3
+ * Main entry point for router-api-kit.
4
+ * Static facade for setup, registration, and lifecycle management.
5
+ *
6
+ * ---
7
+ * ### Lifecycle
8
+ * 1. `RouterKit.setup(config)` — inisialisasi adapter dan resolver
9
+ * 2. `RouterKit.register(ControllerA, ControllerB)` — daftarkan controller
10
+ * 3. `RouterKit.handleNotFound()` — (opsional) daftarkan handler 404 global
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import express from "express";
15
+ * import { RouterKit } from "@alis-kit/routers";
16
+ *
17
+ * const app = express();
18
+ * app.use(express.json());
19
+ *
20
+ * RouterKit.setup({
21
+ * framework: "express",
22
+ * app,
23
+ * authMiddleware: verifyAccessToken,
24
+ * swagger: { enabled: true, path: "/api/docs" },
25
+ * logger: true,
26
+ * });
27
+ *
28
+ * RouterKit.register(AuthController, UserController);
29
+ * RouterKit.handleNotFound();
30
+ *
31
+ * app.listen(3000);
32
+ * ```
33
+ */
34
+ export declare class RouterKit {
35
+ private static adapter;
36
+ private static resolver;
37
+ private static config;
38
+ private static isSetup;
39
+ /**
40
+ * Configures RouterKit with framework adapter, authentication,
41
+ * swagger settings, and other global options.
42
+ *
43
+ * Wajib dipanggil **sebelum** `register()`.
44
+ *
45
+ * @param config - Konfigurasi lengkap RouterKit
46
+ *
47
+ * @throws Error jika framework tidak dikenali
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // Express
52
+ * RouterKit.setup({
53
+ * framework: "express",
54
+ * app: expressApp,
55
+ * swagger: { enabled: true, path: "/docs" },
56
+ * logger: true,
57
+ * });
58
+ * ```
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * // Fastify dengan global prefix dan raw envelope
63
+ * RouterKit.setup({
64
+ * framework: "fastify",
65
+ * app: fastifyInstance,
66
+ * responseEnvelope: "raw",
67
+ * globalPrefix: "/api/v1",
68
+ * });
69
+ * ```
70
+ */
71
+ static setup(config: RouterKitConfig): void;
72
+ /**
73
+ * Registers one or more controller classes.
74
+ * Setiap controller harus di-decorate dengan `@ReqController`.
75
+ *
76
+ * Jika Swagger diaktifkan, spec akan digenerate otomatis setelah registrasi.
77
+ *
78
+ * @param controllers - Satu atau lebih controller class
79
+ *
80
+ * @throws Error jika `setup()` belum dipanggil
81
+ * @throws Error jika controller tidak memiliki `@ReqController`
82
+ * @throws Error jika ada duplikat route (method + path sama)
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // Single controller
87
+ * RouterKit.register(UserController);
88
+ *
89
+ * // Multiple sekaligus
90
+ * RouterKit.register(AuthController, UserController, ProductController);
91
+ * ```
92
+ */
93
+ static register(...controllers: Class[]): void;
94
+ /**
95
+ * Registers a global catch-all handler for 404 Not Found errors.
96
+ * Panggil method ini **setelah** semua route sudah didaftarkan.
97
+ *
98
+ * @throws Error jika `setup()` belum dipanggil
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * RouterKit.setup({ framework: "express", app });
103
+ * RouterKit.register(UserController);
104
+ *
105
+ * // Handler 404 harus setelah semua route
106
+ * RouterKit.handleNotFound();
107
+ * ```
108
+ */
109
+ static handleNotFound(): void;
110
+ /**
111
+ * Resets RouterKit state — berguna untuk testing agar state bersih antar test.
112
+ * @internal
113
+ */
114
+ static reset(): void;
115
+ }
116
+ //# sourceMappingURL=RouterKit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterKit.d.ts","sourceRoot":"","sources":["../../core/RouterKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAShE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,OAAO,CAA4B;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA8B;IACrD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAgC;IACrD,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IA6B3C;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,WAAW,EAAE,KAAK,EAAE,GAAG,IAAI;IAmB9C;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,cAAc,IAAI,IAAI;IAyB7B;;;OAGG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;CAMrB"}
@@ -0,0 +1,175 @@
1
+ import { ExpressAdapter } from "../adapters/ExpressAdapter.js";
2
+ import { FastifyAdapter } from "../adapters/FastifyAdapter.js";
3
+ import { RouteResolver } from "./RouteResolver.js";
4
+ import { Logger } from "./Logger.js";
5
+ import { SwaggerGenerator } from "../swagger/SwaggerGenerator.js";
6
+ import { SwaggerUI } from "../swagger/SwaggerUI.js";
7
+ /**
8
+ * Main entry point for router-api-kit.
9
+ * Static facade for setup, registration, and lifecycle management.
10
+ *
11
+ * ---
12
+ * ### Lifecycle
13
+ * 1. `RouterKit.setup(config)` — inisialisasi adapter dan resolver
14
+ * 2. `RouterKit.register(ControllerA, ControllerB)` — daftarkan controller
15
+ * 3. `RouterKit.handleNotFound()` — (opsional) daftarkan handler 404 global
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import express from "express";
20
+ * import { RouterKit } from "@alis-kit/routers";
21
+ *
22
+ * const app = express();
23
+ * app.use(express.json());
24
+ *
25
+ * RouterKit.setup({
26
+ * framework: "express",
27
+ * app,
28
+ * authMiddleware: verifyAccessToken,
29
+ * swagger: { enabled: true, path: "/api/docs" },
30
+ * logger: true,
31
+ * });
32
+ *
33
+ * RouterKit.register(AuthController, UserController);
34
+ * RouterKit.handleNotFound();
35
+ *
36
+ * app.listen(3000);
37
+ * ```
38
+ */
39
+ export class RouterKit {
40
+ static adapter = null;
41
+ static resolver = null;
42
+ static config = null;
43
+ static isSetup = false;
44
+ /**
45
+ * Configures RouterKit with framework adapter, authentication,
46
+ * swagger settings, and other global options.
47
+ *
48
+ * Wajib dipanggil **sebelum** `register()`.
49
+ *
50
+ * @param config - Konfigurasi lengkap RouterKit
51
+ *
52
+ * @throws Error jika framework tidak dikenali
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Express
57
+ * RouterKit.setup({
58
+ * framework: "express",
59
+ * app: expressApp,
60
+ * swagger: { enabled: true, path: "/docs" },
61
+ * logger: true,
62
+ * });
63
+ * ```
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Fastify dengan global prefix dan raw envelope
68
+ * RouterKit.setup({
69
+ * framework: "fastify",
70
+ * app: fastifyInstance,
71
+ * responseEnvelope: "raw",
72
+ * globalPrefix: "/api/v1",
73
+ * });
74
+ * ```
75
+ */
76
+ static setup(config) {
77
+ switch (config.framework) {
78
+ case "express":
79
+ RouterKit.adapter = new ExpressAdapter(config.app);
80
+ break;
81
+ case "fastify":
82
+ RouterKit.adapter = new FastifyAdapter(config.app);
83
+ break;
84
+ default:
85
+ throw new Error(`[RouterKit] Unsupported framework: "${config.framework}". ` +
86
+ `Supported frameworks are "express" and "fastify".`);
87
+ }
88
+ RouterKit.config = config;
89
+ RouterKit.resolver = new RouteResolver(RouterKit.adapter, config.logger, config.authMiddleware, config.refreshMiddleware, config.responseEnvelope ?? "wrap", config.globalPrefix ?? "");
90
+ RouterKit.isSetup = true;
91
+ console.log(`RouterKit initialized with ${config.framework} adapter`);
92
+ }
93
+ /**
94
+ * Registers one or more controller classes.
95
+ * Setiap controller harus di-decorate dengan `@ReqController`.
96
+ *
97
+ * Jika Swagger diaktifkan, spec akan digenerate otomatis setelah registrasi.
98
+ *
99
+ * @param controllers - Satu atau lebih controller class
100
+ *
101
+ * @throws Error jika `setup()` belum dipanggil
102
+ * @throws Error jika controller tidak memiliki `@ReqController`
103
+ * @throws Error jika ada duplikat route (method + path sama)
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * // Single controller
108
+ * RouterKit.register(UserController);
109
+ *
110
+ * // Multiple sekaligus
111
+ * RouterKit.register(AuthController, UserController, ProductController);
112
+ * ```
113
+ */
114
+ static register(...controllers) {
115
+ if (!RouterKit.isSetup || !RouterKit.resolver || !RouterKit.config) {
116
+ throw new Error(`[RouterKit] RouterKit.setup() must be called before RouterKit.register(). ` +
117
+ `Configure the framework and adapter first.`);
118
+ }
119
+ for (const Controller of controllers) {
120
+ RouterKit.resolver.resolve(Controller);
121
+ console.log(`Registered controller: ${Controller.name}`);
122
+ }
123
+ if (RouterKit.config.swagger?.enabled && RouterKit.resolver.resolvedRoutes.length > 0) {
124
+ const spec = SwaggerGenerator.generate(RouterKit.resolver.resolvedRoutes, RouterKit.config.swagger);
125
+ SwaggerUI.serve(RouterKit.config.app, spec, RouterKit.config.swagger);
126
+ }
127
+ }
128
+ /**
129
+ * Registers a global catch-all handler for 404 Not Found errors.
130
+ * Panggil method ini **setelah** semua route sudah didaftarkan.
131
+ *
132
+ * @throws Error jika `setup()` belum dipanggil
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * RouterKit.setup({ framework: "express", app });
137
+ * RouterKit.register(UserController);
138
+ *
139
+ * // Handler 404 harus setelah semua route
140
+ * RouterKit.handleNotFound();
141
+ * ```
142
+ */
143
+ static handleNotFound() {
144
+ if (!RouterKit.isSetup || !RouterKit.adapter) {
145
+ throw new Error(`[RouterKit] RouterKit.setup() must be called first.`);
146
+ }
147
+ RouterKit.adapter.registerNotFoundHandler((_req, res) => {
148
+ const start = Date.now();
149
+ RouterKit.adapter.sendResponse(res, 404, {
150
+ message: "Path not found",
151
+ data: null,
152
+ });
153
+ const config = RouterKit.config;
154
+ if (config?.logger && (config.logger === true || (typeof config.logger === 'object' && config.logger.enabled !== false))) {
155
+ const duration = Date.now() - start;
156
+ const method = RouterKit.adapter.getMethod(_req);
157
+ const url = RouterKit.adapter.getUrl(_req);
158
+ const handler = typeof config.logger === 'object' ? config.logger.handler : undefined;
159
+ Logger.logRequest(method, url, 404, duration, undefined, handler);
160
+ }
161
+ });
162
+ console.log(`Registered global Not Found handler`);
163
+ }
164
+ /**
165
+ * Resets RouterKit state — berguna untuk testing agar state bersih antar test.
166
+ * @internal
167
+ */
168
+ static reset() {
169
+ RouterKit.adapter = null;
170
+ RouterKit.resolver = null;
171
+ RouterKit.config = null;
172
+ RouterKit.isSetup = false;
173
+ }
174
+ }
175
+ //# sourceMappingURL=RouterKit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterKit.js","sourceRoot":"","sources":["../../core/RouterKit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { ControllerOptions } from "../../types/index.js";
2
+ /**
3
+ * Marks a class as a route controller with a base path and optional configuration.
4
+ *
5
+ * Menyimpan metadata controller ke `context.metadata` via TC39 native decorator.
6
+ * Semua route dalam class ini akan mewarisi `authentication` dan `tag` dari sini.
7
+ *
8
+ * @param basePath - Base URL path untuk semua route di controller ini.
9
+ * Akan otomatis diprefiks dengan "/" jika tidak ada.
10
+ * @param options - Opsi tambahan untuk controller.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * @ReqController("/users", { authentication: "auth", tag: "User Management" })
15
+ * class UserController {
16
+ * // semua route inheritance authentication: "auth"
17
+ * }
18
+ * ```
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * @ReqController("/public")
23
+ * class PublicController {
24
+ * // authentication: false (default)
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function ReqController(basePath: string, options?: ControllerOptions): (_value: Function, context: ClassDecoratorContext) => void;
29
+ //# sourceMappingURL=ReqController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReqController.d.ts","sourceRoot":"","sources":["../../../decorators/controller/ReqController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,sBAAsB,CAAC;AAGlF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,IACxD,QAAQ,QAAQ,EAAE,SAAS,qBAAqB,UAalE"}