@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,150 +1,155 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { fileURLToPath } from "url";
4
-
5
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
-
7
- export const generateDockerCompose = (target, allServices, projectname) => {
8
- const dockerCompose = {
9
- services: {},
10
- };
11
-
12
- // Build environment variables map for all services
13
- const allServicePorts = allServices.map((service, index) => {
14
- const isGateway = service === "gateway";
15
- const port = isGateway ? 4000 : 4001 + allServices.filter((s, i) => s !== "gateway" && i < index).length;
16
- const envVarName = `${service.toUpperCase().replace(/-/g, "_")}_PORT`;
17
- return { service, port, envVarName };
18
- });
19
-
20
- for (const serviceName of allServices) {
21
- // Gateway runs on 4000, other services start from 4001
22
- const serviceInfo = allServicePorts.find(s => s.service === serviceName);
23
- const port = serviceInfo.port;
24
- const envVarName = serviceInfo.envVarName;
25
-
26
- // Build environment variables array - include all service ports
27
- const environmentVars = [
28
- `NODE_ENV=\${NODE_ENV:-development}`,
29
- ...allServicePorts.map(s => `${s.envVarName}=\${${s.envVarName}:-${s.port}}`)
30
- ];
31
-
32
- dockerCompose.services[serviceName] = {
33
- build: {
34
- context: `./services/${serviceName}`,
35
- dockerfile: "Dockerfile"
36
- },
37
- image: `${serviceName}:latest`,
38
- container_name: projectname + "_" + serviceName,
39
- ports: [
40
- `\${${envVarName}:-${port}}:\${${envVarName}:-${port}}`,
41
- ],
42
- environment: environmentVars,
43
- volumes: [
44
- `./services/${serviceName}:/app`,
45
- `./shared:/app/shared`,
46
- `/app/node_modules`
47
- ],
48
- };
49
- }
50
-
51
- fs.writeFileSync(
52
- path.join(target, "docker-compose.yml"),
53
- `services:\n` +
54
- Object.entries(dockerCompose.services)
55
- .map(
56
- ([name, config]) =>
57
- ` ${name}:\n` +
58
- ` build:\n` +
59
- ` context: ${config.build.context}\n` +
60
- ` dockerfile: ${config.build.dockerfile}\n` +
61
- ` image: ${config.image}\n` +
62
- ` container_name: ${config.container_name}\n` +
63
- ` ports:\n - "${config.ports[0]}"\n` +
64
- ` environment:\n` +
65
- config.environment.map((e) => ` - ${e}`).join("\n") + "\n" +
66
- ` volumes:\n` +
67
- config.volumes.map((v) => ` - ${v}`).join("\n")
68
- )
69
- .join("\n")
70
- +
71
- "\n\n" +
72
- // Add x-watch section to help file watchers map service src and shared folders
73
- `x-watch:\n` +
74
- allServices
75
- .map(
76
- (name) =>
77
- ` ${name}:\n - ./services/${name}/src\n - ./shared`
78
- )
79
- .join("\n")
80
- );
81
- };
82
-
83
- export const generatePm2Config = (target, allServices) => {
84
- const pm2Config = {
85
- apps: allServices.map((serviceName, index) => {
86
- const isGateway = serviceName === "gateway";
87
- const port = isGateway ? 4000 : 4001 + allServices.filter((s, i) => s !== "gateway" && i < index).length;
88
-
89
- return {
90
- name: serviceName,
91
- script: `./services/${serviceName}/src/server.ts`,
92
- interpreter: "node",
93
- node_args:
94
- "-r ts-node/register/transpile-only -r tsconfig-paths/register",
95
- watch: true,
96
- ignore_watch: ["node_modules", ".git", "logs"],
97
- watch_delay: 1000,
98
- instances: 1,
99
- exec_mode: "fork",
100
- env: {
101
- PORT: port,
102
- TS_NODE_PROJECT: `services/${serviceName}/tsconfig.json`,
103
- },
104
- };
105
- }),
106
- };
107
-
108
- fs.writeFileSync(
109
- path.join(target, "pm2.config.js"),
110
- `module.exports = ${JSON.stringify(pm2Config, null, 2)};\n`
111
- );
112
- };
113
-
114
- export const copyDockerfile = (target, servicesToCreate) => {
115
- const dockerfilePath = path.join(
116
- __dirname,
117
- "../../template/microservice/docker/Dockerfile"
118
- );
119
-
120
- for (const serviceName of servicesToCreate) {
121
- const serviceDockerfile = path.join(
122
- target,
123
- "services",
124
- serviceName,
125
- "Dockerfile"
126
- );
127
- if (!fs.existsSync(serviceDockerfile)) {
128
- fs.copyFileSync(dockerfilePath, serviceDockerfile);
129
- }
130
- }
131
- };
132
-
133
- export const copyDockerignore = (target, servicesToCreate) => {
134
- const dockerignorePath = path.join(
135
- __dirname,
136
- "../../template/microservice/docker/.dockerignore"
137
- );
138
-
139
- for (const serviceName of servicesToCreate) {
140
- const serviceDockerignore = path.join(
141
- target,
142
- "services",
143
- serviceName,
144
- ".dockerignore"
145
- );
146
- if (!fs.existsSync(serviceDockerignore)) {
147
- fs.copyFileSync(dockerignorePath, serviceDockerignore);
148
- }
149
- }
150
- };
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { fileURLToPath } from "url";
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ export const generateDockerCompose = (target, allServices, projectname) => {
8
+ const dockerCompose = {
9
+ services: {},
10
+ };
11
+
12
+ // Build environment variables map for all services
13
+ const allServicePorts = allServices.map((service, index) => {
14
+ const isGateway = service === "gateway";
15
+ const port = isGateway
16
+ ? 4000
17
+ : 4001 +
18
+ allServices.filter((s, i) => s !== "gateway" && i < index).length;
19
+ const envVarName = `${service.toUpperCase().replace(/-/g, "_")}_PORT`;
20
+ return { service, port, envVarName };
21
+ });
22
+
23
+ for (const serviceName of allServices) {
24
+ // Gateway runs on 4000, other services start from 4001
25
+ const serviceInfo = allServicePorts.find((s) => s.service === serviceName);
26
+ const port = serviceInfo.port;
27
+ const envVarName = serviceInfo.envVarName;
28
+
29
+ // Build environment variables array - include all service ports
30
+ const environmentVars = [
31
+ `NODE_ENV=\${NODE_ENV:-development}`,
32
+ ...allServicePorts.map(
33
+ (s) => `${s.envVarName}=\${${s.envVarName}:-${s.port}}`
34
+ ),
35
+ ];
36
+
37
+ dockerCompose.services[serviceName] = {
38
+ build: {
39
+ context: `./services/${serviceName}`,
40
+ dockerfile: "Dockerfile",
41
+ },
42
+ image: `${serviceName}:latest`,
43
+ container_name: projectname + "_" + serviceName,
44
+ ports: [`\${${envVarName}:-${port}}:\${${envVarName}:-${port}}`],
45
+ environment: environmentVars,
46
+ volumes: [
47
+ `./services/${serviceName}:/app`,
48
+ `./shared:/app/shared`,
49
+ `/app/node_modules`,
50
+ ],
51
+ };
52
+ }
53
+
54
+ fs.writeFileSync(
55
+ path.join(target, "docker-compose.yml"),
56
+ `services:\n` +
57
+ Object.entries(dockerCompose.services)
58
+ .map(
59
+ ([name, config]) =>
60
+ ` ${name}:\n` +
61
+ ` build:\n` +
62
+ ` context: ${config.build.context}\n` +
63
+ ` dockerfile: ${config.build.dockerfile}\n` +
64
+ ` image: ${config.image}\n` +
65
+ ` container_name: ${config.container_name}\n` +
66
+ ` ports:\n - "${config.ports[0]}"\n` +
67
+ ` environment:\n` +
68
+ config.environment.map((e) => ` - ${e}`).join("\n") +
69
+ "\n" +
70
+ ` volumes:\n` +
71
+ config.volumes.map((v) => ` - ${v}`).join("\n")
72
+ )
73
+ .join("\n") +
74
+ "\n\n" +
75
+ // Add x-watch section to help file watchers map service src and shared folders
76
+ `x-watch:\n` +
77
+ allServices
78
+ .map(
79
+ (name) => ` ${name}:\n - ./services/${name}/src\n - ./shared`
80
+ )
81
+ .join("\n")
82
+ );
83
+ };
84
+
85
+ export const generatePm2Config = (target, allServices) => {
86
+ const pm2Config = {
87
+ apps: allServices.map((serviceName, index) => {
88
+ const isGateway = serviceName === "gateway";
89
+ const port = isGateway
90
+ ? 4000
91
+ : 4001 +
92
+ allServices.filter((s, i) => s !== "gateway" && i < index).length;
93
+
94
+ return {
95
+ name: serviceName,
96
+ script: `./services/${serviceName}/src/server.ts`,
97
+ interpreter: "node",
98
+ node_args:
99
+ "-r ts-node/register/transpile-only -r tsconfig-paths/register",
100
+ watch: true,
101
+ ignore_watch: ["node_modules", ".git", "logs"],
102
+ watch_delay: 1000,
103
+ instances: 1,
104
+ exec_mode: "fork",
105
+ env: {
106
+ PORT: port,
107
+ TS_NODE_PROJECT: `services/${serviceName}/tsconfig.json`,
108
+ },
109
+ };
110
+ }),
111
+ };
112
+
113
+ fs.writeFileSync(
114
+ path.join(target, "pm2.config.js"),
115
+ `module.exports = ${JSON.stringify(pm2Config, null, 2)};\n`
116
+ );
117
+ };
118
+
119
+ export const copyDockerfile = (target, servicesToCreate) => {
120
+ const dockerfilePath = path.join(
121
+ __dirname,
122
+ "../../template/microservice/docker/Dockerfile"
123
+ );
124
+
125
+ for (const serviceName of servicesToCreate) {
126
+ const serviceDockerfile = path.join(
127
+ target,
128
+ "services",
129
+ serviceName,
130
+ "Dockerfile"
131
+ );
132
+ if (!fs.existsSync(serviceDockerfile)) {
133
+ fs.copyFileSync(dockerfilePath, serviceDockerfile);
134
+ }
135
+ }
136
+ };
137
+
138
+ export const copyDockerignore = (target, servicesToCreate) => {
139
+ const dockerignorePath = path.join(
140
+ __dirname,
141
+ "../../template/microservice/docker/.dockerignore"
142
+ );
143
+
144
+ for (const serviceName of servicesToCreate) {
145
+ const serviceDockerignore = path.join(
146
+ target,
147
+ "services",
148
+ serviceName,
149
+ ".dockerignore"
150
+ );
151
+ if (!fs.existsSync(serviceDockerignore)) {
152
+ fs.copyFileSync(dockerignorePath, serviceDockerignore);
153
+ }
154
+ }
155
+ };