@ifecodes/backend-template 1.1.9 → 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 (94) hide show
  1. package/README.md +423 -383
  2. package/bin/cli.js +1276 -964
  3. package/bin/lib/microservice-config.js +155 -150
  4. package/bin/lib/prompts.js +277 -241
  5. package/bin/lib/readme-generator.js +364 -329
  6. package/bin/lib/service-setup.js +901 -684
  7. package/package.json +64 -55
  8. package/template/base/js/.eslintrc.json +10 -13
  9. package/template/base/js/.prettierrc +7 -7
  10. package/template/base/js/eslint.config.js +33 -31
  11. package/template/base/js/package.json +29 -28
  12. package/template/base/js/src/app.js +20 -18
  13. package/template/base/js/src/config/db.js +8 -8
  14. package/template/base/js/src/config/env.js +44 -14
  15. package/template/base/js/src/config/index.js +7 -7
  16. package/template/base/js/src/docs/index.js +5 -0
  17. package/template/base/js/src/docs/route-registry.js +63 -0
  18. package/template/base/js/src/middlewares/error-handler.middleware.js +22 -19
  19. package/template/base/js/src/middlewares/index.js +15 -11
  20. package/template/base/js/src/middlewares/method-not-allowed.middleware.js +19 -13
  21. package/template/base/js/src/middlewares/not-found.middleware.js +13 -10
  22. package/template/base/js/src/middlewares/observability.middleware.js +24 -0
  23. package/template/base/js/src/middlewares/root.middleware.js +18 -16
  24. package/template/base/js/src/middlewares/validation.middleware.js +39 -0
  25. package/template/base/js/src/modules/index.js +8 -8
  26. package/template/base/js/src/modules/v1/health/health.controller.auth.js +29 -0
  27. package/template/base/js/src/modules/v1/health/health.controller.js +21 -21
  28. package/template/base/js/src/modules/v1/health/health.route.js +74 -9
  29. package/template/base/js/src/modules/v1/health/index.js +5 -5
  30. package/template/base/js/src/modules/v1/index.js +8 -8
  31. package/template/base/js/src/routes.js +23 -16
  32. package/template/base/js/src/server.js +18 -18
  33. package/template/base/js/src/utils/http-error.js +74 -74
  34. package/template/base/js/src/utils/index.js +28 -28
  35. package/template/base/js/src/utils/logger.js +57 -67
  36. package/template/base/ts/.eslintrc.json +13 -17
  37. package/template/base/ts/.prettierrc +7 -7
  38. package/template/base/ts/eslint.config.js +33 -33
  39. package/template/base/ts/package.json +41 -39
  40. package/template/base/ts/src/app.ts +20 -18
  41. package/template/base/ts/src/config/db.ts +4 -4
  42. package/template/base/ts/src/config/env.ts +40 -10
  43. package/template/base/ts/src/config/index.ts +2 -2
  44. package/template/base/ts/src/docs/index.ts +3 -0
  45. package/template/base/ts/src/docs/route-registry.ts +98 -0
  46. package/template/base/ts/src/middlewares/error-handler.middleware.ts +4 -1
  47. package/template/base/ts/src/middlewares/index.ts +6 -4
  48. package/template/base/ts/src/middlewares/method-not-allowed.middleware.ts +23 -18
  49. package/template/base/ts/src/middlewares/not-found.middleware.ts +10 -8
  50. package/template/base/ts/src/middlewares/observability.middleware.ts +25 -0
  51. package/template/base/ts/src/middlewares/root.middleware.ts +16 -14
  52. package/template/base/ts/src/middlewares/validation.middleware.ts +46 -0
  53. package/template/base/ts/src/modules/index.ts +8 -8
  54. package/template/base/ts/src/modules/v1/health/health.controller.auth.ts +26 -0
  55. package/template/base/ts/src/modules/v1/health/health.controller.ts +18 -18
  56. package/template/base/ts/src/modules/v1/health/health.route.ts +68 -9
  57. package/template/base/ts/src/modules/v1/health/index.ts +1 -1
  58. package/template/base/ts/src/modules/v1/index.ts +8 -8
  59. package/template/base/ts/src/routes.ts +23 -15
  60. package/template/base/ts/src/server.ts +19 -19
  61. package/template/base/ts/src/utils/http-error.ts +63 -63
  62. package/template/base/ts/src/utils/index.ts +14 -14
  63. package/template/base/ts/src/utils/logger.ts +58 -68
  64. package/template/base/ts/tsconfig.json +21 -21
  65. package/template/features/auth/argon2/inject.js +50 -50
  66. package/template/features/auth/base/health-openapi.ts +62 -0
  67. package/template/features/auth/base/inject.js +174 -172
  68. package/template/features/auth/bcrypt/inject.js +40 -40
  69. package/template/features/auth/models/index.ts +1 -1
  70. package/template/features/auth/models/user.model.js +24 -24
  71. package/template/features/auth/models/user.model.ts +28 -28
  72. package/template/features/auth/modules/auth.controller.js +21 -21
  73. package/template/features/auth/modules/auth.controller.ts +28 -20
  74. package/template/features/auth/modules/auth.routes.js +89 -10
  75. package/template/features/auth/modules/auth.routes.ts +86 -11
  76. package/template/features/auth/modules/auth.service.js +29 -29
  77. package/template/features/auth/modules/auth.service.ts +38 -38
  78. package/template/features/auth/modules/index.js +1 -1
  79. package/template/features/auth/modules/index.ts +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/auth/utils/jwt.ts +15 -15
  83. package/template/features/cors/inject.js +14 -13
  84. package/template/features/helmet/inject.js +7 -6
  85. package/template/features/morgan/inject.js +8 -7
  86. package/template/features/rate-limit/inject.js +7 -6
  87. package/template/gateway/js/app.js +42 -42
  88. package/template/gateway/js/inject.js +33 -33
  89. package/template/gateway/js/server.js +19 -19
  90. package/template/gateway/ts/app.ts +43 -43
  91. package/template/gateway/ts/inject.js +33 -33
  92. package/template/gateway/ts/server.ts +19 -19
  93. package/template/microservice/docker/docker-compose.yml +5 -5
  94. package/template/microservice/nodocker/pm2.config.js +3 -3
@@ -1,16 +1,18 @@
1
- const rootHandler = (_, res) => {
2
- res.json({
3
- name: "/*__PROJECT_NAME__*/",
4
- type: "/*__PROJECT_TYPE__*/",
5
- version: "1.0.0",
6
- status: "running",
7
- endpoints: {
8
- health: "/api/v1/health",
9
- /*__AUTH_ENDPOINT__*/
10
- },
11
- });
12
- };
13
-
14
- module.exports = {
15
- rootHandler,
16
- };
1
+ const rootHandler = (_, res) => {
2
+ res.json({
3
+ name: '/*__PROJECT_NAME__*/',
4
+ type: '/*__PROJECT_TYPE__*/',
5
+ version: '1.0.0',
6
+ status: 'running',
7
+ endpoints: {
8
+ root: '/',
9
+ health: '/api/v1/health',
10
+ docs: '/api-docs',
11
+ /*__AUTH_ENDPOINT__*/
12
+ },
13
+ });
14
+ };
15
+
16
+ module.exports = {
17
+ rootHandler,
18
+ };
@@ -0,0 +1,39 @@
1
+ const { ZodError } = require('zod');
2
+ const { BadRequestError } = require('../utils');
3
+
4
+ const validateRequest = (schemas = {}) => {
5
+ return (req, _, next) => {
6
+ try {
7
+ if (schemas.body) {
8
+ req.body = schemas.body.parse(req.body);
9
+ }
10
+
11
+ if (schemas.query) {
12
+ req.query = schemas.query.parse(req.query);
13
+ }
14
+
15
+ if (schemas.params) {
16
+ req.params = schemas.params.parse(req.params);
17
+ }
18
+
19
+ next();
20
+ } catch (error) {
21
+ if (error instanceof ZodError) {
22
+ const issues = error.issues
23
+ .map(
24
+ (issue) => `${issue.path.join('.') || 'request'}: ${issue.message}`
25
+ )
26
+ .join('; ');
27
+ return next(
28
+ new BadRequestError(`Request validation failed - ${issues}`)
29
+ );
30
+ }
31
+
32
+ return next(error);
33
+ }
34
+ };
35
+ };
36
+
37
+ module.exports = {
38
+ validateRequest,
39
+ };
@@ -1,8 +1,8 @@
1
- const { Router } = require("express");
2
- const V1Routes = require("./v1");
3
-
4
- const router = Router();
5
-
6
- router.use("/v1", V1Routes);
7
-
8
- module.exports = router;
1
+ const { Router } = require('express');
2
+ const V1Routes = require('./v1');
3
+
4
+ const router = Router();
5
+
6
+ router.use('/v1', V1Routes);
7
+
8
+ module.exports = router;
@@ -0,0 +1,29 @@
1
+ const mongoose = require('mongoose');
2
+ const { logger } = require('../../../utils');
3
+
4
+ const healthCheck = async (_, res) => {
5
+ const mongoState = mongoose.connection.readyState;
6
+
7
+ const healthy = mongoState === 1;
8
+
9
+ const failed = [];
10
+ if (mongoState !== 1) failed.push('mongodb');
11
+
12
+ return res.status(healthy ? 200 : 503).json({
13
+ status: healthy ? 'healthy' : 'unhealthy',
14
+ uptime: process.uptime(),
15
+ timestamp: new Date().toISOString(),
16
+ services: {
17
+ mongodb: mongoState === 1 ? 'connected' : 'disconnected',
18
+ memory: {
19
+ rss: process.memoryUsage().rss,
20
+ heapUsed: process.memoryUsage().heapUsed,
21
+ },
22
+ },
23
+ failed,
24
+ });
25
+ };
26
+
27
+ module.exports = {
28
+ healthCheck,
29
+ };
@@ -1,21 +1,21 @@
1
- const { logger } = require("../../../utils");
2
-
3
- const healthCheck = async (_, res) => {
4
- logger.info("Health", "healthy");
5
-
6
- return res.status(200).json({
7
- status: "healthy",
8
- uptime: process.uptime(),
9
- timestamp: new Date().toISOString(),
10
- services: {
11
- memory: {
12
- rss: process.memoryUsage().rss,
13
- heapUsed: process.memoryUsage().heapUsed,
14
- },
15
- },
16
- });
17
- };
18
-
19
- module.exports = {
20
- healthCheck
21
- };
1
+ const { logger } = require('../../../utils');
2
+
3
+ const healthCheck = async (_, res) => {
4
+ logger.info('Health', 'healthy');
5
+
6
+ return res.status(200).json({
7
+ status: 'healthy',
8
+ uptime: process.uptime(),
9
+ timestamp: new Date().toISOString(),
10
+ services: {
11
+ memory: {
12
+ rss: process.memoryUsage().rss,
13
+ heapUsed: process.memoryUsage().heapUsed,
14
+ },
15
+ },
16
+ });
17
+ };
18
+
19
+ module.exports = {
20
+ healthCheck,
21
+ };
@@ -1,9 +1,74 @@
1
- const { Router } = require("express");
2
- const { healthCheck } = require("./health.controller");
3
- const { methodNotAllowedHandler } = require("../../../middlewares");
4
-
5
- const router = Router();
6
- router.use(methodNotAllowedHandler(["GET"]));
7
- router.get("/", healthCheck);
8
-
9
- module.exports = router;
1
+ const { Router } = require('express');
2
+ const { healthCheck } = require('./health.controller');
3
+ const { z } = require('zod');
4
+ const {
5
+ methodNotAllowedHandler,
6
+ validateRequest,
7
+ } = require('../../../middlewares');
8
+ const { routeRegistry } = require('../../../docs');
9
+
10
+ const router = Router();
11
+ const healthQuerySchema = z
12
+ .object({
13
+ verbose: z.coerce.boolean().optional(),
14
+ })
15
+ .strict();
16
+
17
+ // Register route schema with auto-generated docs
18
+ routeRegistry.register({
19
+ method: 'GET',
20
+ path: '/api/v1/health',
21
+ handler: healthCheck,
22
+ docs: {
23
+ tags: ['Health'],
24
+ summary: 'Health check endpoint',
25
+ description:
26
+ 'Returns API health status and runtime metrics including uptime and memory usage.',
27
+ parameters: [
28
+ {
29
+ name: 'verbose',
30
+ in: 'query',
31
+ required: false,
32
+ schema: { type: 'boolean' },
33
+ description: 'Optional verbose mode for detailed diagnostics.',
34
+ },
35
+ ],
36
+ responses: {
37
+ 200: {
38
+ description: 'Healthy response with system metrics',
39
+ content: {
40
+ 'application/json': {
41
+ schema: {
42
+ type: 'object',
43
+ properties: {
44
+ status: { type: 'string', example: 'healthy' },
45
+ uptime: { type: 'number', example: 123.45 },
46
+ timestamp: {
47
+ type: 'string',
48
+ example: '2024-01-01T00:00:00.000Z',
49
+ },
50
+ services: {
51
+ type: 'object',
52
+ properties: {
53
+ memory: {
54
+ type: 'object',
55
+ properties: {
56
+ rss: { type: 'number' },
57
+ heapUsed: { type: 'number' },
58
+ },
59
+ },
60
+ },
61
+ },
62
+ },
63
+ },
64
+ },
65
+ },
66
+ },
67
+ },
68
+ },
69
+ });
70
+
71
+ router.use(methodNotAllowedHandler(['GET']));
72
+ router.get('/', healthCheck);
73
+
74
+ module.exports = router;
@@ -1,5 +1,5 @@
1
- const healthRoutes = require("./health.route");
2
-
3
- module.exports = {
4
- healthRoutes,
5
- };
1
+ const healthRoutes = require('./health.route');
2
+
3
+ module.exports = {
4
+ healthRoutes,
5
+ };
@@ -1,8 +1,8 @@
1
- const { Router } = require("express");
2
- const { healthRoutes } = require("./health");
3
-
4
- const router = Router();
5
-
6
- router.use("/health", healthRoutes);
7
-
8
- module.exports = router;
1
+ const { Router } = require('express');
2
+ const { healthRoutes } = require('./health');
3
+
4
+ const router = Router();
5
+
6
+ router.use('/health', healthRoutes);
7
+
8
+ module.exports = router;
@@ -1,16 +1,23 @@
1
- const { Router } = require("express");
2
- const modulesRouter = require("./modules");
3
- const { notFound, rootHandler } = require("./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
- module.exports = router;
16
-
1
+ const { Router } = require('express');
2
+ const modulesRouter = require('./modules');
3
+ const { notFound, rootHandler } = require('./middlewares');
4
+ const swaggerUi = require('swagger-ui-express');
5
+ const { routeRegistry } = require('./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, (_, res, next) => {
14
+ const spec = routeRegistry.generateOpenAPI('/*__PROJECT_NAME__*/', '1.0.0');
15
+ swaggerUi.setup(spec)(_, res, next);
16
+ });
17
+
18
+ router.use('/api', modulesRouter);
19
+
20
+ // 404 handler - must be last
21
+ router.use(notFound);
22
+
23
+ module.exports = router;
@@ -1,18 +1,18 @@
1
- const app = require("./app");
2
- const { ENV/*__DB_IMPORT__*/ } = require("./config");
3
- const { logger } = require("./utils");
4
-
5
- const PORT = ENV.PORT || 3000;
6
-
7
- const startServer = async () => {
8
- /*__DB_CONNECT__*/
9
-
10
- app.listen(PORT, () => {
11
- logger.info("Server", `Server is running on port ${PORT}`);
12
- });
13
- };
14
-
15
- startServer().catch((error) => {
16
- logger.error("Server", "Failed to start server", error);
17
- process.exit(1);
18
- });
1
+ const app = require('./app');
2
+ const { ENV /*__DB_IMPORT__*/ } = require('./config');
3
+ const { logger } = require('./utils');
4
+
5
+ const PORT = ENV.PORT || 3000;
6
+
7
+ const startServer = async () => {
8
+ /*__DB_CONNECT__*/
9
+
10
+ app.listen(PORT, () => {
11
+ logger.info('Server', `Server is running on port ${PORT}`);
12
+ });
13
+ };
14
+
15
+ startServer().catch((error) => {
16
+ logger.error('Server', 'Failed to start server', error);
17
+ process.exit(1);
18
+ });
@@ -1,74 +1,74 @@
1
- class HttpError extends Error {
2
- constructor(status, message) {
3
- super(message);
4
- this.status = status;
5
- Object.setPrototypeOf(this, new.target.prototype);
6
- }
7
- }
8
-
9
- class BadRequestError extends HttpError {
10
- constructor(message = "Bad Request") {
11
- super(400, message);
12
- }
13
- }
14
-
15
- class UnprocessableEntityError extends HttpError {
16
- constructor(message = "Unprocessable Entity") {
17
- super(422, message);
18
- }
19
- }
20
-
21
- class UnauthorizedError extends HttpError {
22
- constructor(message = "Unauthorized") {
23
- super(401, message);
24
- }
25
- }
26
-
27
- class ForbiddenError extends HttpError {
28
- constructor(message = "Forbidden") {
29
- super(403, message);
30
- }
31
- }
32
-
33
- class NotFoundError extends HttpError {
34
- constructor(message = "Not Found") {
35
- super(404, message);
36
- }
37
- }
38
-
39
- class ConflictError extends HttpError {
40
- constructor(message = "Conflict") {
41
- super(409, message);
42
- }
43
- }
44
-
45
- class TooManyRequestsError extends HttpError {
46
- constructor(message = "Too Many Requests") {
47
- super(429, message);
48
- }
49
- }
50
-
51
- class BadGatewayError extends HttpError {
52
- constructor(message = "Bad Gateway") {
53
- super(502, message);
54
- }
55
- }
56
-
57
- class InternalServerError extends HttpError {
58
- constructor(message = "Internal Server Error") {
59
- super(500, message);
60
- }
61
- }
62
-
63
- module.exports = {
64
- HttpError,
65
- BadRequestError,
66
- UnprocessableEntityError,
67
- UnauthorizedError,
68
- ForbiddenError,
69
- NotFoundError,
70
- ConflictError,
71
- TooManyRequestsError,
72
- BadGatewayError,
73
- InternalServerError,
74
- };
1
+ class HttpError extends Error {
2
+ constructor(status, message) {
3
+ super(message);
4
+ this.status = status;
5
+ Object.setPrototypeOf(this, new.target.prototype);
6
+ }
7
+ }
8
+
9
+ class BadRequestError extends HttpError {
10
+ constructor(message = 'Bad Request') {
11
+ super(400, message);
12
+ }
13
+ }
14
+
15
+ class UnprocessableEntityError extends HttpError {
16
+ constructor(message = 'Unprocessable Entity') {
17
+ super(422, message);
18
+ }
19
+ }
20
+
21
+ class UnauthorizedError extends HttpError {
22
+ constructor(message = 'Unauthorized') {
23
+ super(401, message);
24
+ }
25
+ }
26
+
27
+ class ForbiddenError extends HttpError {
28
+ constructor(message = 'Forbidden') {
29
+ super(403, message);
30
+ }
31
+ }
32
+
33
+ class NotFoundError extends HttpError {
34
+ constructor(message = 'Not Found') {
35
+ super(404, message);
36
+ }
37
+ }
38
+
39
+ class ConflictError extends HttpError {
40
+ constructor(message = 'Conflict') {
41
+ super(409, message);
42
+ }
43
+ }
44
+
45
+ class TooManyRequestsError extends HttpError {
46
+ constructor(message = 'Too Many Requests') {
47
+ super(429, message);
48
+ }
49
+ }
50
+
51
+ class BadGatewayError extends HttpError {
52
+ constructor(message = 'Bad Gateway') {
53
+ super(502, message);
54
+ }
55
+ }
56
+
57
+ class InternalServerError extends HttpError {
58
+ constructor(message = 'Internal Server Error') {
59
+ super(500, message);
60
+ }
61
+ }
62
+
63
+ module.exports = {
64
+ HttpError,
65
+ BadRequestError,
66
+ UnprocessableEntityError,
67
+ UnauthorizedError,
68
+ ForbiddenError,
69
+ NotFoundError,
70
+ ConflictError,
71
+ TooManyRequestsError,
72
+ BadGatewayError,
73
+ InternalServerError,
74
+ };
@@ -1,28 +1,28 @@
1
- const {
2
- HttpError,
3
- BadRequestError,
4
- UnprocessableEntityError,
5
- UnauthorizedError,
6
- ForbiddenError,
7
- NotFoundError,
8
- ConflictError,
9
- TooManyRequestsError,
10
- BadGatewayError,
11
- InternalServerError,
12
- } = require('./http-error');
13
-
14
- const logger = require('./logger');
15
-
16
- module.exports = {
17
- HttpError,
18
- BadRequestError,
19
- UnprocessableEntityError,
20
- UnauthorizedError,
21
- ForbiddenError,
22
- NotFoundError,
23
- ConflictError,
24
- TooManyRequestsError,
25
- BadGatewayError,
26
- InternalServerError,
27
- logger,
28
- };
1
+ const {
2
+ HttpError,
3
+ BadRequestError,
4
+ UnprocessableEntityError,
5
+ UnauthorizedError,
6
+ ForbiddenError,
7
+ NotFoundError,
8
+ ConflictError,
9
+ TooManyRequestsError,
10
+ BadGatewayError,
11
+ InternalServerError,
12
+ } = require('./http-error');
13
+
14
+ const logger = require('./logger');
15
+
16
+ module.exports = {
17
+ HttpError,
18
+ BadRequestError,
19
+ UnprocessableEntityError,
20
+ UnauthorizedError,
21
+ ForbiddenError,
22
+ NotFoundError,
23
+ ConflictError,
24
+ TooManyRequestsError,
25
+ BadGatewayError,
26
+ InternalServerError,
27
+ logger,
28
+ };