@ifecodes/backend-template 1.1.8 → 1.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.
Files changed (93) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +423 -365
  3. package/bin/cli.js +1276 -836
  4. package/bin/lib/microservice-config.js +155 -150
  5. package/bin/lib/prompts.js +277 -241
  6. package/bin/lib/readme-generator.js +364 -335
  7. package/bin/lib/service-setup.js +901 -679
  8. package/package.json +64 -55
  9. package/template/base/js/.env.example +5 -5
  10. package/template/base/js/.eslintrc.json +10 -13
  11. package/template/base/js/.husky/pre-commit +1 -7
  12. package/template/base/js/.prettierrc +7 -7
  13. package/template/base/js/eslint.config.js +33 -31
  14. package/template/base/js/package.json +29 -28
  15. package/template/base/js/src/app.js +20 -15
  16. package/template/base/js/src/config/env.js +32 -2
  17. package/template/base/js/src/config/index.js +2 -2
  18. package/template/base/js/src/docs/index.js +5 -0
  19. package/template/base/js/src/docs/route-registry.js +63 -0
  20. package/template/base/js/src/middlewares/error-handler.middleware.js +22 -0
  21. package/template/base/js/src/middlewares/index.js +9 -3
  22. package/template/base/js/src/middlewares/method-not-allowed.middleware.js +8 -2
  23. package/template/base/js/src/middlewares/not-found.middleware.js +4 -1
  24. package/template/base/js/src/middlewares/observability.middleware.js +24 -0
  25. package/template/base/js/src/middlewares/root.middleware.js +7 -5
  26. package/template/base/js/src/middlewares/validation.middleware.js +39 -0
  27. package/template/base/js/src/modules/index.js +8 -8
  28. package/template/base/js/src/modules/v1/health/health.controller.auth.js +29 -0
  29. package/template/base/js/src/modules/v1/health/health.controller.js +4 -4
  30. package/template/base/js/src/modules/v1/health/health.route.js +70 -5
  31. package/template/base/js/src/modules/v1/health/index.js +1 -1
  32. package/template/base/js/src/modules/v1/index.js +3 -3
  33. package/template/base/js/src/routes.js +13 -6
  34. package/template/base/js/src/server.js +18 -18
  35. package/template/base/js/src/utils/http-error.js +27 -6
  36. package/template/base/js/src/utils/index.js +28 -22
  37. package/template/base/js/src/utils/logger.js +57 -67
  38. package/template/base/ts/.eslintrc.json +13 -17
  39. package/template/base/ts/.prettierrc +7 -7
  40. package/template/base/ts/eslint.config.js +33 -33
  41. package/template/base/ts/package.json +41 -39
  42. package/template/base/ts/src/app.ts +20 -15
  43. package/template/base/ts/src/config/db.ts +4 -4
  44. package/template/base/ts/src/config/env.ts +40 -10
  45. package/template/base/ts/src/config/index.ts +2 -2
  46. package/template/base/ts/src/docs/index.ts +3 -0
  47. package/template/base/ts/src/docs/route-registry.ts +98 -0
  48. package/template/base/ts/src/middlewares/error-handler.middleware.ts +26 -0
  49. package/template/base/ts/src/middlewares/index.ts +6 -3
  50. package/template/base/ts/src/middlewares/method-not-allowed.middleware.ts +23 -16
  51. package/template/base/ts/src/middlewares/not-found.middleware.ts +10 -8
  52. package/template/base/ts/src/middlewares/observability.middleware.ts +25 -0
  53. package/template/base/ts/src/middlewares/root.middleware.ts +16 -14
  54. package/template/base/ts/src/middlewares/validation.middleware.ts +46 -0
  55. package/template/base/ts/src/modules/index.ts +8 -8
  56. package/template/base/ts/src/modules/v1/health/health.controller.auth.ts +26 -0
  57. package/template/base/ts/src/modules/v1/health/health.controller.ts +18 -18
  58. package/template/base/ts/src/modules/v1/health/health.route.ts +68 -9
  59. package/template/base/ts/src/modules/v1/health/index.ts +1 -1
  60. package/template/base/ts/src/modules/v1/index.ts +8 -8
  61. package/template/base/ts/src/routes.ts +23 -15
  62. package/template/base/ts/src/server.ts +19 -19
  63. package/template/base/ts/src/utils/http-error.ts +63 -45
  64. package/template/base/ts/src/utils/index.ts +14 -11
  65. package/template/base/ts/src/utils/logger.ts +58 -68
  66. package/template/base/ts/tsconfig.json +21 -22
  67. package/template/features/auth/argon2/inject.js +50 -50
  68. package/template/features/auth/base/health-openapi.ts +62 -0
  69. package/template/features/auth/base/inject.js +174 -172
  70. package/template/features/auth/bcrypt/inject.js +40 -40
  71. package/template/features/auth/models/user.model.js +24 -24
  72. package/template/features/auth/models/user.model.ts +1 -1
  73. package/template/features/auth/modules/auth.controller.js +21 -21
  74. package/template/features/auth/modules/auth.controller.ts +28 -20
  75. package/template/features/auth/modules/auth.routes.js +89 -10
  76. package/template/features/auth/modules/auth.routes.ts +86 -11
  77. package/template/features/auth/modules/auth.service.js +29 -29
  78. package/template/features/auth/modules/auth.service.ts +38 -38
  79. package/template/features/auth/modules/index.js +1 -1
  80. package/template/features/auth/utils/hash.ts +20 -20
  81. package/template/features/auth/utils/jwt.js +12 -12
  82. package/template/features/cors/inject.js +14 -13
  83. package/template/features/helmet/inject.js +7 -6
  84. package/template/features/morgan/inject.js +8 -7
  85. package/template/features/rate-limit/inject.js +7 -6
  86. package/template/gateway/js/app.js +42 -42
  87. package/template/gateway/js/inject.js +33 -31
  88. package/template/gateway/js/server.js +19 -19
  89. package/template/gateway/ts/app.ts +43 -43
  90. package/template/gateway/ts/inject.js +33 -33
  91. package/template/gateway/ts/server.ts +19 -19
  92. package/template/microservice/docker/docker-compose.yml +5 -5
  93. package/template/microservice/nodocker/pm2.config.js +3 -3
@@ -1,15 +1,20 @@
1
- import express from "express";
2
- import router from "./routes";
3
- /*__IMPORTS__*/
4
-
5
- const app = express();
6
-
7
- // Parse JSON request bodies
8
- app.use(express.json());
9
-
10
- /*__MIDDLEWARE__*/
11
-
12
- // Connect routes
13
- app.use(router);
14
-
15
- export default app;
1
+ import express from "express";
2
+ import router from "./routes";
3
+ import { errorHandler, observabilityMiddleware } from "@/middlewares";
4
+ /*__IMPORTS__*/
5
+
6
+ const app = express();
7
+
8
+ // Parse JSON request bodies
9
+ app.use(express.json());
10
+
11
+ app.use(observabilityMiddleware);
12
+
13
+ /*__MIDDLEWARE__*/
14
+
15
+ // Connect routes
16
+ app.use(router);
17
+
18
+ app.use(errorHandler);
19
+
20
+ export default app;
@@ -1,4 +1,4 @@
1
- // MongoDB connection will be added here when authentication is enabled
2
- export const connectDB = async () => {
3
- // Database connection placeholder
4
- };
1
+ // MongoDB connection will be added here when authentication is enabled
2
+ export const connectDB = async () => {
3
+ // Database connection placeholder
4
+ };
@@ -1,10 +1,40 @@
1
- import dotenv from "dotenv";
2
- dotenv.config();
3
-
4
- export const ENV = {
5
- PORT: process.env.PORT!,
6
- /*__ALLOWED_ORIGIN__*/
7
- NODE_ENV: process.env.NODE_ENV!,
8
- /*__MONGO_URI__*/
9
- /*__JWT_SECRET__*/
10
- };
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
3
+
4
+ const colors = {
5
+ reset: "\x1b[0m",
6
+ red: "\x1b[31m",
7
+ bold: "\x1b[1m",
8
+ };
9
+
10
+ function format(tag: string, color: string) {
11
+ return `${color}${colors.bold}[${tag}]${colors.reset}`;
12
+ }
13
+
14
+ const validateEnv = (env: Record<string, string | undefined>) => {
15
+ const missing = Object.entries(env)
16
+ .filter(([, value]) => value === undefined || value === "")
17
+ .map(([key]) => key);
18
+
19
+ if (missing.length > 0) {
20
+ console.error(
21
+ format("env", colors.red),
22
+ `Missing required environment variables: ${missing.join(", ")}`,
23
+ );
24
+ console.error(
25
+ format("env", colors.red),
26
+ "Please update your .env file and restart the server.",
27
+ );
28
+ process.exit(1);
29
+ }
30
+ };
31
+
32
+ export const ENV = {
33
+ PORT: process.env.PORT!,
34
+ /*__ALLOWED_ORIGIN__*/
35
+ NODE_ENV: process.env.NODE_ENV!,
36
+ /*__MONGO_URI__*/
37
+ /*__JWT_SECRET__*/
38
+ };
39
+
40
+ validateEnv(ENV);
@@ -1,2 +1,2 @@
1
- export { connectDB } from "./db";
2
- export { ENV } from "./env";
1
+ export { connectDB } from "./db";
2
+ export { ENV } from "./env";
@@ -0,0 +1,3 @@
1
+ import { routeRegistry } from "./route-registry";
2
+
3
+ export { routeRegistry };
@@ -0,0 +1,98 @@
1
+ import { RequestHandler } from "express";
2
+
3
+ export interface RouteDoc {
4
+ tags?: string[];
5
+ summary: string;
6
+ description?: string;
7
+ parameters?: Array<{
8
+ name: string;
9
+ in: "query" | "path" | "header" | "cookie";
10
+ required?: boolean;
11
+ schema: Record<string, unknown>;
12
+ description?: string;
13
+ }>;
14
+ requestBody?: {
15
+ required?: boolean;
16
+ content: {
17
+ "application/json": {
18
+ schema: Record<string, unknown>;
19
+ };
20
+ };
21
+ };
22
+ responses: Record<
23
+ number | string,
24
+ {
25
+ description: string;
26
+ content?: {
27
+ "application/json": {
28
+ schema?: Record<string, unknown>;
29
+ };
30
+ };
31
+ }
32
+ >;
33
+ }
34
+
35
+ export interface RouteSchema {
36
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
37
+ path: string;
38
+ handler: RequestHandler | RequestHandler[];
39
+ docs: RouteDoc;
40
+ }
41
+
42
+ class RouteRegistry {
43
+ private routes: RouteSchema[] = [];
44
+
45
+ register(route: RouteSchema): void {
46
+ this.routes.push(route);
47
+ }
48
+
49
+ getRoutes(): RouteSchema[] {
50
+ return this.routes;
51
+ }
52
+
53
+ generateOpenAPI(projectName: string, version = "1.0.0"): Record<string, unknown> {
54
+ const paths: Record<string, unknown> = {};
55
+ const tags = new Set<string>();
56
+
57
+ // Collect all unique tags
58
+ this.routes.forEach((route) => {
59
+ route.docs.tags?.forEach((tag) => tags.add(tag));
60
+ });
61
+
62
+ // Build paths from routes
63
+ this.routes.forEach((route) => {
64
+ if (!paths[route.path]) {
65
+ paths[route.path] = {};
66
+ }
67
+
68
+ const pathItem = paths[route.path] as Record<string, unknown>;
69
+ const method = route.method.toLowerCase();
70
+
71
+ pathItem[method] = {
72
+ tags: route.docs.tags || [],
73
+ summary: route.docs.summary,
74
+ description: route.docs.description,
75
+ parameters: route.docs.parameters || [],
76
+ requestBody: route.docs.requestBody,
77
+ responses: route.docs.responses,
78
+ };
79
+ });
80
+
81
+ return {
82
+ openapi: "3.0.3",
83
+ info: {
84
+ title: `${projectName} API`,
85
+ version,
86
+ description: "Auto-generated from route schemas.",
87
+ },
88
+ servers: [{ url: "http://localhost:4000" }],
89
+ tags: Array.from(tags).map((tag) => ({
90
+ name: tag,
91
+ description: `${tag} endpoints`,
92
+ })),
93
+ paths,
94
+ };
95
+ }
96
+ }
97
+
98
+ export const routeRegistry = new RouteRegistry();
@@ -0,0 +1,26 @@
1
+ import { NextFunction, Request, Response } from "express";
2
+ import { HttpError, logger } from "@/utils";
3
+
4
+ // Centralized error handling middleware
5
+
6
+ export const errorHandler = (
7
+ err: unknown,
8
+ _: Request,
9
+ res: Response,
10
+ __: NextFunction,
11
+ ) => {
12
+ if (err instanceof HttpError) {
13
+ logger.warn("ErrorHandler", `${err.status} ${err.message}`);
14
+ return res.status(err.status).json({
15
+ status: "error",
16
+ message: err.message,
17
+ });
18
+ }
19
+
20
+ logger.error("ErrorHandler", "Unhandled error", err as Error);
21
+
22
+ return res.status(500).json({
23
+ status: "error",
24
+ message: "Internal Server Error",
25
+ });
26
+ };
@@ -1,3 +1,6 @@
1
- export { default as methodNotAllowedHandler } from "./method-not-allowed.middleware";
2
- export { notFound } from "./not-found.middleware";
3
- export { rootHandler } from "./root.middleware";
1
+ export { default as methodNotAllowedHandler } from "./method-not-allowed.middleware";
2
+ export { notFound } from "./not-found.middleware";
3
+ export { rootHandler } from "./root.middleware";
4
+ export { errorHandler } from "./error-handler.middleware";
5
+ export { observabilityMiddleware } from "./observability.middleware";
6
+ export { validateRequest } from "./validation.middleware";
@@ -1,16 +1,23 @@
1
- import { Request, Response, NextFunction } from "express";
2
-
3
- const methodNotAllowed =
4
- (allowedMethods: string[]) => (req: Request, res: Response, next: NextFunction) => {
5
- if (!allowedMethods.includes(req.method)) {
6
- res.set("Allow", allowedMethods.join(", "));
7
- return res.status(405).json({
8
- status: "error",
9
- message: `Method ${req.method} not allowed for ${req.originalUrl}`,
10
- allowed: allowedMethods,
11
- });
12
- }
13
- next();
14
- };
15
-
16
- export default methodNotAllowed;
1
+ import { Request, Response, NextFunction } from "express";
2
+ import { logger } from "@/utils";
3
+
4
+ // Middleware to handle 405 Method Not Allowed for unsupported HTTP methods on defined routes
5
+
6
+ const methodNotAllowed =
7
+ (allowedMethods: string[]) => (req: Request, res: Response, next: NextFunction) => {
8
+ if (!allowedMethods.includes(req.method)) {
9
+ logger.warn(
10
+ "MethodNotAllowed",
11
+ `${req.method} ${req.originalUrl} | allowed: ${allowedMethods.join(", ")}`,
12
+ );
13
+ res.set("Allow", allowedMethods.join(", "));
14
+ return res.status(405).json({
15
+ status: "error",
16
+ message: `Method ${req.method} not allowed for ${req.originalUrl}`,
17
+ allowed: allowedMethods,
18
+ });
19
+ }
20
+ next();
21
+ };
22
+
23
+ export default methodNotAllowed;
@@ -1,8 +1,10 @@
1
- import { Request, Response } from "express";
2
-
3
- export const notFound = (req: Request, res: Response) => {
4
- res.status(404).json({
5
- status: "error",
6
- message: `Route ${req.originalUrl} not found`,
7
- });
8
- };
1
+ import { Request, Response } from "express";
2
+ import { logger } from "@/utils";
3
+
4
+ export const notFound = (req: Request, res: Response) => {
5
+ logger.warn("NotFound", `${req.method} ${req.originalUrl}`);
6
+ res.status(404).json({
7
+ status: "error",
8
+ message: `Route ${req.originalUrl} not found`,
9
+ });
10
+ };
@@ -0,0 +1,25 @@
1
+ import { randomUUID } from "crypto";
2
+ import { NextFunction, Request, Response } from "express";
3
+ import { logger } from "@/utils";
4
+
5
+ export const observabilityMiddleware = (
6
+ req: Request,
7
+ res: Response,
8
+ next: NextFunction,
9
+ ) => {
10
+ const requestId = req.get("X-Request-Id") || randomUUID();
11
+ const startedAt = Date.now();
12
+
13
+ res.locals.requestId = requestId;
14
+ res.setHeader("X-Request-Id", requestId);
15
+
16
+ res.on("finish", () => {
17
+ const duration = Date.now() - startedAt;
18
+ logger.info(
19
+ "HTTP",
20
+ `${requestId} ${req.method} ${req.originalUrl} -> ${res.statusCode} (${duration}ms)`,
21
+ );
22
+ });
23
+
24
+ next();
25
+ };
@@ -1,14 +1,16 @@
1
- import { Request, Response } from "express";
2
-
3
- export const rootHandler = (_req: Request, res: Response) => {
4
- res.json({
5
- name: "/*__PROJECT_NAME__*/",
6
- type: "/*__PROJECT_TYPE__*/",
7
- version: "1.0.0",
8
- status: "running",
9
- endpoints: {
10
- health: "/api/v1/health",
11
- /*__AUTH_ENDPOINT__*/
12
- },
13
- });
14
- };
1
+ import { Request, Response } from "express";
2
+
3
+ export const rootHandler = (_req: Request, res: Response) => {
4
+ res.json({
5
+ name: "/*__PROJECT_NAME__*/",
6
+ type: "/*__PROJECT_TYPE__*/",
7
+ version: "1.0.0",
8
+ status: "running",
9
+ endpoints: {
10
+ root: "/",
11
+ health: "/api/v1/health",
12
+ docs: "/api-docs",
13
+ /*__AUTH_ENDPOINT__*/
14
+ },
15
+ });
16
+ };
@@ -0,0 +1,46 @@
1
+ import { NextFunction, Request, Response } from "express";
2
+ import { BadRequestError } from "@/utils";
3
+
4
+ type RequestSchemas = {
5
+ body?: { parse: (value: unknown) => unknown };
6
+ query?: { parse: (value: unknown) => unknown };
7
+ params?: { parse: (value: unknown) => unknown };
8
+ };
9
+
10
+ const isValidationError = (error: unknown): error is { issues: Array<{ path?: Array<string | number>; message: string }> } => {
11
+ return (
12
+ typeof error === "object" &&
13
+ error !== null &&
14
+ "issues" in error &&
15
+ Array.isArray((error as { issues?: unknown }).issues)
16
+ );
17
+ };
18
+
19
+ export const validateRequest = (schemas: RequestSchemas) => {
20
+ return (req: Request, _: Response, next: NextFunction) => {
21
+ try {
22
+ if (schemas.body) {
23
+ req.body = schemas.body.parse(req.body);
24
+ }
25
+
26
+ if (schemas.query) {
27
+ req.query = schemas.query.parse(req.query) as Request["query"];
28
+ }
29
+
30
+ if (schemas.params) {
31
+ req.params = schemas.params.parse(req.params) as Request["params"];
32
+ }
33
+
34
+ next();
35
+ } catch (error: unknown) {
36
+ if (isValidationError(error)) {
37
+ const issues = error.issues
38
+ .map((issue) => `${issue.path?.join(".") || "request"}: ${issue.message}`)
39
+ .join("; ");
40
+ return next(new BadRequestError(`Request validation failed - ${issues}`));
41
+ }
42
+
43
+ return next(error);
44
+ }
45
+ };
46
+ };
@@ -1,8 +1,8 @@
1
- import { Router } from "express";
2
- import V1Routes from "./v1";
3
-
4
- const router = Router();
5
-
6
- router.use("/v1", V1Routes);
7
-
8
- export default router;
1
+ import { Router } from "express";
2
+ import V1Routes from "./v1";
3
+
4
+ const router = Router();
5
+
6
+ router.use("/v1", V1Routes);
7
+
8
+ export default router;
@@ -0,0 +1,26 @@
1
+ import { Request, Response } from "express";
2
+ import mongoose from "mongoose";
3
+ import { logger } from "@/utils";
4
+
5
+ export const healthCheck = async (_: Request, res: Response) => {
6
+ const mongoState = mongoose.connection.readyState;
7
+
8
+ const healthy = mongoState === 1;
9
+
10
+ const failed: string[] = [];
11
+ if (mongoState !== 1) failed.push("mongodb");
12
+
13
+ return res.status(healthy ? 200 : 503).json({
14
+ status: healthy ? "healthy" : "unhealthy",
15
+ uptime: process.uptime(),
16
+ timestamp: new Date().toISOString(),
17
+ services: {
18
+ mongodb: mongoState === 1 ? "connected" : "disconnected",
19
+ memory: {
20
+ rss: process.memoryUsage().rss,
21
+ heapUsed: process.memoryUsage().heapUsed,
22
+ },
23
+ },
24
+ failed,
25
+ });
26
+ };
@@ -1,18 +1,18 @@
1
- import { Request, Response } from "express";
2
- import { logger } from "@/utils";
3
-
4
- export const healthCheck = async (_: Request, res: Response) => {
5
- logger.info("Health", "healthy");
6
-
7
- return res.status(200).json({
8
- status: "healthy",
9
- uptime: process.uptime(),
10
- timestamp: new Date().toISOString(),
11
- services: {
12
- memory: {
13
- rss: process.memoryUsage().rss,
14
- heapUsed: process.memoryUsage().heapUsed,
15
- },
16
- },
17
- });
18
- };
1
+ import { Request, Response } from "express";
2
+ import { logger } from "@/utils";
3
+
4
+ export const healthCheck = async (_: Request, res: Response) => {
5
+ logger.info("Health", "healthy");
6
+
7
+ return res.status(200).json({
8
+ status: "healthy",
9
+ uptime: process.uptime(),
10
+ timestamp: new Date().toISOString(),
11
+ services: {
12
+ memory: {
13
+ rss: process.memoryUsage().rss,
14
+ heapUsed: process.memoryUsage().heapUsed,
15
+ },
16
+ },
17
+ });
18
+ };
@@ -1,9 +1,68 @@
1
- import { Router } from "express";
2
- import { healthCheck } from "./health.controller";
3
- import { methodNotAllowedHandler } from "@/middlewares";
4
-
5
- const router = Router();
6
- router.use(methodNotAllowedHandler(["GET"]));
7
- router.get("/", healthCheck);
8
-
9
- export default router;
1
+ import { Router } from "express";
2
+ import { healthCheck } from "./health.controller";
3
+ import { methodNotAllowedHandler, validateRequest } from "@/middlewares";
4
+ import { z } from "zod";
5
+ import { routeRegistry } from "@/docs";
6
+
7
+ const router = Router();
8
+ const healthQuerySchema = z
9
+ .object({
10
+ verbose: z.coerce.boolean().optional(),
11
+ })
12
+ .strict();
13
+
14
+ // Register route schema with auto-generated docs
15
+ routeRegistry.register({
16
+ method: "GET",
17
+ path: "/api/v1/health",
18
+ handler: healthCheck,
19
+ docs: {
20
+ tags: ["Health"],
21
+ summary: "Health check endpoint",
22
+ description:
23
+ "Returns API health status and runtime metrics including uptime and memory usage.",
24
+ parameters: [
25
+ {
26
+ name: "verbose",
27
+ in: "query",
28
+ required: false,
29
+ schema: { type: "boolean" },
30
+ description: "Optional verbose mode for detailed diagnostics.",
31
+ },
32
+ ],
33
+ responses: {
34
+ "200": {
35
+ description: "Healthy response with system metrics",
36
+ content: {
37
+ "application/json": {
38
+ schema: {
39
+ type: "object",
40
+ properties: {
41
+ status: { type: "string", example: "healthy" },
42
+ uptime: { type: "number", example: 123.45 },
43
+ timestamp: { type: "string", example: "2024-01-01T00:00:00.000Z" },
44
+ services: {
45
+ type: "object",
46
+ properties: {
47
+ memory: {
48
+ type: "object",
49
+ properties: {
50
+ rss: { type: "number" },
51
+ heapUsed: { type: "number" },
52
+ },
53
+ },
54
+ },
55
+ },
56
+ },
57
+ },
58
+ },
59
+ },
60
+ },
61
+ },
62
+ },
63
+ });
64
+
65
+ router.use(methodNotAllowedHandler(["GET"]));
66
+ router.get("/", validateRequest({ query: healthQuerySchema }), healthCheck);
67
+
68
+ export default router;
@@ -1 +1 @@
1
- export { default as healthRoutes } from "./health.route";
1
+ export { default as healthRoutes } from "./health.route";
@@ -1,8 +1,8 @@
1
- import { Router } from "express";
2
- import { healthRoutes } from "./health";
3
-
4
- const router = Router();
5
-
6
- router.use("/health", healthRoutes);
7
-
8
- export default router;
1
+ import { Router } from "express";
2
+ import { healthRoutes } from "./health";
3
+
4
+ const router = Router();
5
+
6
+ router.use("/health", healthRoutes);
7
+
8
+ export default router;
@@ -1,15 +1,23 @@
1
- import { Router } from "express";
2
- import modulesRouter from "./modules";
3
- import { notFound, rootHandler } from "./middlewares";
4
-
5
- const router = Router();
6
-
7
- // Root endpoint
8
- router.get("/", rootHandler);
9
-
10
- router.use("/api", modulesRouter);
11
-
12
- // 404 handler - must be last
13
- router.use(notFound);
14
-
15
- export default router;
1
+ import { NextFunction, Request, Response, Router } from "express";
2
+ import modulesRouter from "./modules";
3
+ import { notFound, rootHandler } from "./middlewares";
4
+ import swaggerUi from "swagger-ui-express";
5
+ import { routeRegistry } from "./docs";
6
+
7
+ const router = Router();
8
+
9
+ // Root endpoint
10
+ router.get("/", rootHandler);
11
+
12
+ // Swagger UI with auto-generated spec
13
+ router.use("/api-docs", swaggerUi.serve, (_req: Request, res: Response, next: NextFunction) => {
14
+ const spec = routeRegistry.generateOpenAPI("/*__PROJECT_NAME__*/", "1.0.0");
15
+ swaggerUi.setup(spec)(_req, res, next);
16
+ });
17
+
18
+ router.use("/api", modulesRouter);
19
+
20
+ // 404 handler - must be last
21
+ router.use(notFound);
22
+
23
+ export default router;
@@ -1,19 +1,19 @@
1
- import app from "./app";
2
- import { ENV } from "./config";
3
- import { logger } from "@/utils";
4
- /*__DB_IMPORT__*/
5
-
6
- const PORT = ENV.PORT || 3000;
7
-
8
- const startServer = async () => {
9
- /*__DB_CONNECT__*/
10
-
11
- app.listen(PORT, () => {
12
- logger.info("Server", `Server is running on port ${PORT}`);
13
- });
14
- };
15
-
16
- startServer().catch((error) => {
17
- logger.error("Server", "Failed to start server", error as Error);
18
- process.exit(1);
19
- });
1
+ import app from "./app";
2
+ import { ENV } from "./config";
3
+ import { logger } from "@/utils";
4
+ /*__DB_IMPORT__*/
5
+
6
+ const PORT = ENV.PORT || 3000;
7
+
8
+ const startServer = async () => {
9
+ /*__DB_CONNECT__*/
10
+
11
+ app.listen(PORT, () => {
12
+ logger.info("Server", `Server is running on port ${PORT}`);
13
+ });
14
+ };
15
+
16
+ startServer().catch((error) => {
17
+ logger.error("Server", "Failed to start server", error as Error);
18
+ process.exit(1);
19
+ });