nodejs-quickstart-structure 1.18.1 → 1.19.1
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.
- package/CHANGELOG.md +309 -294
- package/LICENSE +15 -15
- package/README.md +2 -1
- package/lib/generator.js +139 -139
- package/lib/modules/app-setup.js +401 -401
- package/lib/modules/caching-setup.js +76 -73
- package/lib/modules/config-files.js +151 -151
- package/lib/modules/database-setup.js +116 -116
- package/lib/modules/kafka-setup.js +249 -191
- package/lib/modules/project-setup.js +32 -31
- package/lib/prompts.js +100 -100
- package/package.json +78 -67
- package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
- package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
- package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -10
- package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -21
- package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -10
- package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -21
- package/templates/clean-architecture/js/src/index.js.ejs +55 -55
- package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
- package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
- package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +69 -39
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -81
- package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +156 -75
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -138
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
- package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
- package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -21
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -49
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -17
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +12 -10
- package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
- package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
- package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
- package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js +11 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
- package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
- package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
- package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
- package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
- package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
- package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
- package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
- package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -8
- package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -21
- package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -8
- package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
- package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
- package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -85
- package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +74 -0
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -185
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +173 -84
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
- package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -21
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -15
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +13 -11
- package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
- package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
- package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
- package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts +9 -0
- package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
- package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
- package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
- package/templates/common/.cursorrules.ejs +60 -60
- package/templates/common/.dockerignore +12 -12
- package/templates/common/.env.example.ejs +41 -41
- package/templates/common/.gitattributes +46 -0
- package/templates/common/.gitlab-ci.yml.ejs +86 -86
- package/templates/common/.lintstagedrc +6 -6
- package/templates/common/.prettierrc +7 -7
- package/templates/common/Dockerfile +73 -73
- package/templates/common/Jenkinsfile.ejs +87 -87
- package/templates/common/README.md.ejs +294 -270
- package/templates/common/SECURITY.md +20 -20
- package/templates/common/_github/workflows/ci.yml.ejs +46 -46
- package/templates/common/_github/workflows/security.yml.ejs +36 -36
- package/templates/common/_gitignore +5 -5
- package/templates/common/_husky/pre-commit +4 -4
- package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
- package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
- package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
- package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
- package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
- package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
- package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
- package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
- package/templates/common/caching/js/memoryCache.js.ejs +60 -60
- package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
- package/templates/common/caching/js/redisClient.js.ejs +75 -75
- package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
- package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
- package/templates/common/caching/ts/memoryCache.ts.ejs +73 -64
- package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
- package/templates/common/caching/ts/redisClient.ts.ejs +89 -80
- package/templates/common/database/js/database.js.ejs +19 -19
- package/templates/common/database/js/database.spec.js.ejs +56 -56
- package/templates/common/database/js/models/User.js.ejs +79 -53
- package/templates/common/database/js/models/User.js.mongoose.ejs +23 -19
- package/templates/common/database/js/models/User.spec.js.ejs +94 -84
- package/templates/common/database/js/mongoose.js.ejs +33 -33
- package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
- package/templates/common/database/ts/database.spec.ts.ejs +56 -56
- package/templates/common/database/ts/database.ts.ejs +21 -21
- package/templates/common/database/ts/models/User.spec.ts.ejs +100 -84
- package/templates/common/database/ts/models/User.ts.ejs +87 -61
- package/templates/common/database/ts/models/User.ts.mongoose.ejs +30 -25
- package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
- package/templates/common/database/ts/mongoose.ts.ejs +28 -28
- package/templates/common/docker-compose.yml.ejs +159 -159
- package/templates/common/ecosystem.config.js.ejs +40 -40
- package/templates/common/eslint.config.mjs.ejs +77 -77
- package/templates/common/health/js/healthRoute.js.ejs +50 -47
- package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
- package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
- package/templates/common/health/ts/healthRoute.ts.ejs +49 -46
- package/templates/common/jest.config.js.ejs +32 -32
- package/templates/common/jest.e2e.config.js.ejs +8 -8
- package/templates/common/kafka/js/config/kafka.js +9 -9
- package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
- package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -30
- package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
- package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -11
- package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
- package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -31
- package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -49
- package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -93
- package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
- package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
- package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
- package/templates/common/kafka/ts/config/kafka.ts +7 -7
- package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
- package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
- package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -51
- package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -11
- package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -49
- package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -25
- package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
- package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -95
- package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
- package/templates/common/migrate-mongo-config.js.ejs +31 -31
- package/templates/common/migrations/init.js.ejs +23 -23
- package/templates/common/package.json.ejs +119 -118
- package/templates/common/prompts/add-feature.md.ejs +26 -26
- package/templates/common/prompts/project-context.md.ejs +43 -43
- package/templates/common/prompts/troubleshoot.md.ejs +28 -28
- package/templates/common/public/css/style.css +147 -147
- package/templates/common/scripts/run-e2e.js.ejs +63 -63
- package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -61
- package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -160
- package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -158
- package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -55
- package/templates/common/sonar-project.properties.ejs +27 -27
- package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -49
- package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -49
- package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
- package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
- package/templates/common/swagger.yml.ejs +118 -66
- package/templates/common/tsconfig.json +22 -22
- package/templates/common/views/ejs/index.ejs +55 -55
- package/templates/common/views/pug/index.pug +40 -40
- package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -9
- package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -9
- package/templates/mvc/js/src/config/env.js.ejs +46 -46
- package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
- package/templates/mvc/js/src/controllers/userController.js.ejs +246 -105
- package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -209
- package/templates/mvc/js/src/errors/ApiError.js +14 -14
- package/templates/mvc/js/src/errors/BadRequestError.js +11 -10
- package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -21
- package/templates/mvc/js/src/errors/NotFoundError.js +11 -10
- package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -21
- package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
- package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
- package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
- package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -19
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -47
- package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -17
- package/templates/mvc/js/src/index.js.ejs +136 -136
- package/templates/mvc/js/src/routes/api.js +10 -8
- package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -36
- package/templates/mvc/js/src/utils/errorMessages.js +14 -0
- package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
- package/templates/mvc/js/src/utils/httpCodes.js +9 -9
- package/templates/mvc/js/src/utils/logger.js +40 -40
- package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
- package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
- package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
- package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -203
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +248 -107
- package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
- package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
- package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -8
- package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -21
- package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -8
- package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
- package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
- package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
- package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -21
- package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
- package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -15
- package/templates/mvc/ts/src/index.ts.ejs +156 -153
- package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -40
- package/templates/mvc/ts/src/routes/api.ts +12 -10
- package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
- package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
- package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
- package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
- package/templates/mvc/ts/src/utils/logger.ts +36 -36
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.ts.ejs +0 -37
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
# Cursor AI Coding Rules for <%= projectName %>
|
|
2
|
-
|
|
3
|
-
## Project Context
|
|
4
|
-
You are an expert working on **<%= projectName %>**.
|
|
5
|
-
- **Project Goal**: [Replace this with your business logic, e.g., E-commerce API]
|
|
6
|
-
- **Language**: <%= language %>
|
|
7
|
-
- **Architecture**: <%= architecture %>
|
|
8
|
-
- **Database**: <%= database %>
|
|
9
|
-
- **Communication**: <%= communication %>
|
|
10
|
-
|
|
11
|
-
## Excluded Files/Folders
|
|
12
|
-
When indexing or searching the workspace, ignore the following paths to prevent context pollution:
|
|
13
|
-
- `node_modules/`
|
|
14
|
-
- `dist/`
|
|
15
|
-
- `build/`
|
|
16
|
-
- `coverage/`
|
|
17
|
-
- `.git/`
|
|
18
|
-
|
|
19
|
-
## Strict Rules
|
|
20
|
-
|
|
21
|
-
### 1. Testing First
|
|
22
|
-
- Every new service or controller method MUST have a test file in `tests/`.
|
|
23
|
-
- **Coverage Gate**: Aim for > 80% coverage (Statement/Line/Function/Branch).
|
|
24
|
-
- **Format**: Use Jest with the AAA (Arrange, Act, Assert) pattern.
|
|
25
|
-
- **Isolation**: Mock external dependencies (DB, Redis, etc.) using `jest.mock()`.
|
|
26
|
-
|
|
27
|
-
### 2. Error Handling
|
|
28
|
-
- Do NOT use generic `Error`.
|
|
29
|
-
- Use custom classes from `src/errors/` (e.g., `ApiError`, `NotFoundError`, `BadRequestError`).
|
|
30
|
-
<% if (language === 'TypeScript') { -%>
|
|
31
|
-
- Use `HTTP_STATUS` constants from `@/utils/httpCodes` for status codes.
|
|
32
|
-
<% } else { -%>
|
|
33
|
-
- Use `HTTP_STATUS` constants from `../utils/httpCodes.js` for status codes.
|
|
34
|
-
<% } -%>
|
|
35
|
-
|
|
36
|
-
### 3. File Naming & Style
|
|
37
|
-
- **Controllers**: camelCase (e.g., `userController.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
38
|
-
- **Services**: camelCase (e.g., `userService.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
39
|
-
- **Routes**: camelCase (e.g., `userRoutes.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
40
|
-
<% if (language === 'TypeScript') { -%>
|
|
41
|
-
- **Imports**: Use path aliases (e.g., `@/services/...`) instead of relative paths.
|
|
42
|
-
- **Typing**: Ensure strong typing for interfaces and DTOs. Do not use `any` unless absolutely necessary.
|
|
43
|
-
<% } else { -%>
|
|
44
|
-
- **Imports**: Use relative paths as dictated by the directory structure.
|
|
45
|
-
<% } -%>
|
|
46
|
-
|
|
47
|
-
### 4. Architecture Standards
|
|
48
|
-
<% if (architecture === 'Clean Architecture') { -%>
|
|
49
|
-
- Enforce strict separation of concerns:
|
|
50
|
-
- `domain`: Entities and enterprise business rules.
|
|
51
|
-
- `usecases`: Application business rules.
|
|
52
|
-
- `interfaces`: Controllers and Routes.
|
|
53
|
-
- `infrastructure`: Frameworks, Database, Caching, and Web Server.
|
|
54
|
-
- Dependencies point inward toward the `domain`.
|
|
55
|
-
<% } else { -%>
|
|
56
|
-
- Enforce MVC standards:
|
|
57
|
-
- `models`: Data layer.
|
|
58
|
-
- `controllers`: Request handlers and business logic.
|
|
59
|
-
- `routes`: Define endpoints routing to controllers.
|
|
60
|
-
<% } -%>
|
|
1
|
+
# Cursor AI Coding Rules for <%= projectName %>
|
|
2
|
+
|
|
3
|
+
## Project Context
|
|
4
|
+
You are an expert working on **<%= projectName %>**.
|
|
5
|
+
- **Project Goal**: [Replace this with your business logic, e.g., E-commerce API]
|
|
6
|
+
- **Language**: <%= language %>
|
|
7
|
+
- **Architecture**: <%= architecture %>
|
|
8
|
+
- **Database**: <%= database %>
|
|
9
|
+
- **Communication**: <%= communication %>
|
|
10
|
+
|
|
11
|
+
## Excluded Files/Folders
|
|
12
|
+
When indexing or searching the workspace, ignore the following paths to prevent context pollution:
|
|
13
|
+
- `node_modules/`
|
|
14
|
+
- `dist/`
|
|
15
|
+
- `build/`
|
|
16
|
+
- `coverage/`
|
|
17
|
+
- `.git/`
|
|
18
|
+
|
|
19
|
+
## Strict Rules
|
|
20
|
+
|
|
21
|
+
### 1. Testing First
|
|
22
|
+
- Every new service or controller method MUST have a test file in `tests/`.
|
|
23
|
+
- **Coverage Gate**: Aim for > 80% coverage (Statement/Line/Function/Branch).
|
|
24
|
+
- **Format**: Use Jest with the AAA (Arrange, Act, Assert) pattern.
|
|
25
|
+
- **Isolation**: Mock external dependencies (DB, Redis, etc.) using `jest.mock()`.
|
|
26
|
+
|
|
27
|
+
### 2. Error Handling
|
|
28
|
+
- Do NOT use generic `Error`.
|
|
29
|
+
- Use custom classes from `src/errors/` (e.g., `ApiError`, `NotFoundError`, `BadRequestError`).
|
|
30
|
+
<% if (language === 'TypeScript') { -%>
|
|
31
|
+
- Use `HTTP_STATUS` constants from `@/utils/httpCodes` for status codes.
|
|
32
|
+
<% } else { -%>
|
|
33
|
+
- Use `HTTP_STATUS` constants from `../utils/httpCodes.js` for status codes.
|
|
34
|
+
<% } -%>
|
|
35
|
+
|
|
36
|
+
### 3. File Naming & Style
|
|
37
|
+
- **Controllers**: camelCase (e.g., `userController.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
38
|
+
- **Services**: camelCase (e.g., `userService.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
39
|
+
- **Routes**: camelCase (e.g., `userRoutes.<% if (language === 'TypeScript') { %>ts<% } else { %>js<% } %>`).
|
|
40
|
+
<% if (language === 'TypeScript') { -%>
|
|
41
|
+
- **Imports**: Use path aliases (e.g., `@/services/...`) instead of relative paths.
|
|
42
|
+
- **Typing**: Ensure strong typing for interfaces and DTOs. Do not use `any` unless absolutely necessary.
|
|
43
|
+
<% } else { -%>
|
|
44
|
+
- **Imports**: Use relative paths as dictated by the directory structure.
|
|
45
|
+
<% } -%>
|
|
46
|
+
|
|
47
|
+
### 4. Architecture Standards
|
|
48
|
+
<% if (architecture === 'Clean Architecture') { -%>
|
|
49
|
+
- Enforce strict separation of concerns:
|
|
50
|
+
- `domain`: Entities and enterprise business rules.
|
|
51
|
+
- `usecases`: Application business rules.
|
|
52
|
+
- `interfaces`: Controllers and Routes.
|
|
53
|
+
- `infrastructure`: Frameworks, Database, Caching, and Web Server.
|
|
54
|
+
- Dependencies point inward toward the `domain`.
|
|
55
|
+
<% } else { -%>
|
|
56
|
+
- Enforce MVC standards:
|
|
57
|
+
- `models`: Data layer.
|
|
58
|
+
- `controllers`: Request handlers and business logic.
|
|
59
|
+
- `routes`: Define endpoints routing to controllers.
|
|
60
|
+
<% } -%>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
node_modules
|
|
2
|
-
npm-debug.log
|
|
3
|
-
dist
|
|
4
|
-
.env
|
|
5
|
-
.git
|
|
6
|
-
.gitignore
|
|
7
|
-
README.md
|
|
8
|
-
docker-compose.yml
|
|
9
|
-
test_results.log
|
|
10
|
-
flyway/sql
|
|
11
|
-
.cursorrules
|
|
12
|
-
prompts
|
|
1
|
+
node_modules
|
|
2
|
+
npm-debug.log
|
|
3
|
+
dist
|
|
4
|
+
.env
|
|
5
|
+
.git
|
|
6
|
+
.gitignore
|
|
7
|
+
README.md
|
|
8
|
+
docker-compose.yml
|
|
9
|
+
test_results.log
|
|
10
|
+
flyway/sql
|
|
11
|
+
.cursorrules
|
|
12
|
+
prompts
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
# Application
|
|
2
|
-
PORT=3000
|
|
3
|
-
NODE_ENV=development
|
|
4
|
-
|
|
5
|
-
<%_ if (database !== 'None') { -%>
|
|
6
|
-
# Database
|
|
7
|
-
<%_ if (database === 'MySQL') { -%>
|
|
8
|
-
DB_HOST=localhost
|
|
9
|
-
DB_PORT=3306
|
|
10
|
-
DB_USER=root
|
|
11
|
-
DB_PASSWORD=root
|
|
12
|
-
DB_NAME=<%= dbName %>
|
|
13
|
-
<%_ } -%>
|
|
14
|
-
<%_ if (database === 'PostgreSQL') { -%>
|
|
15
|
-
DB_HOST=localhost
|
|
16
|
-
DB_PORT=5432
|
|
17
|
-
DB_USER=postgres
|
|
18
|
-
DB_PASSWORD=root
|
|
19
|
-
DB_NAME=<%= dbName %>
|
|
20
|
-
<%_ } -%>
|
|
21
|
-
<%_ if (database === 'MongoDB') { -%>
|
|
22
|
-
DB_HOST=localhost
|
|
23
|
-
DB_PORT=27017
|
|
24
|
-
DB_NAME=<%= dbName %>
|
|
25
|
-
<%_ } -%>
|
|
26
|
-
<%_ } -%>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<%_ if (communication === 'Kafka') { -%>
|
|
30
|
-
# Communication
|
|
31
|
-
KAFKA_BROKER=localhost:9093
|
|
32
|
-
KAFKA_CLIENT_ID=<%= projectName %>
|
|
33
|
-
KAFKA_GROUP_ID=<%= projectName %>-group
|
|
34
|
-
<%_ } -%>
|
|
35
|
-
|
|
36
|
-
<%_ if (caching === 'Redis') { -%>
|
|
37
|
-
# Caching
|
|
38
|
-
REDIS_HOST=localhost
|
|
39
|
-
REDIS_PORT=6379
|
|
40
|
-
REDIS_PASSWORD=
|
|
41
|
-
<%_ } -%>
|
|
1
|
+
# Application
|
|
2
|
+
PORT=3000
|
|
3
|
+
NODE_ENV=development
|
|
4
|
+
|
|
5
|
+
<%_ if (database !== 'None') { -%>
|
|
6
|
+
# Database
|
|
7
|
+
<%_ if (database === 'MySQL') { -%>
|
|
8
|
+
DB_HOST=localhost
|
|
9
|
+
DB_PORT=3306
|
|
10
|
+
DB_USER=root
|
|
11
|
+
DB_PASSWORD=root
|
|
12
|
+
DB_NAME=<%= dbName %>
|
|
13
|
+
<%_ } -%>
|
|
14
|
+
<%_ if (database === 'PostgreSQL') { -%>
|
|
15
|
+
DB_HOST=localhost
|
|
16
|
+
DB_PORT=5432
|
|
17
|
+
DB_USER=postgres
|
|
18
|
+
DB_PASSWORD=root
|
|
19
|
+
DB_NAME=<%= dbName %>
|
|
20
|
+
<%_ } -%>
|
|
21
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
22
|
+
DB_HOST=localhost
|
|
23
|
+
DB_PORT=27017
|
|
24
|
+
DB_NAME=<%= dbName %>
|
|
25
|
+
<%_ } -%>
|
|
26
|
+
<%_ } -%>
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
30
|
+
# Communication
|
|
31
|
+
KAFKA_BROKER=localhost:9093
|
|
32
|
+
KAFKA_CLIENT_ID=<%= projectName %>
|
|
33
|
+
KAFKA_GROUP_ID=<%= projectName %>-group
|
|
34
|
+
<%_ } -%>
|
|
35
|
+
|
|
36
|
+
<%_ if (caching === 'Redis') { -%>
|
|
37
|
+
# Caching
|
|
38
|
+
REDIS_HOST=localhost
|
|
39
|
+
REDIS_PORT=6379
|
|
40
|
+
REDIS_PASSWORD=
|
|
41
|
+
<%_ } -%>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Enforce LF endings for all text files
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Explicitly handle common text file types
|
|
5
|
+
*.js text eol=lf
|
|
6
|
+
*.ts text eol=lf
|
|
7
|
+
*.tsx text eol=lf
|
|
8
|
+
*.jsx text eol=lf
|
|
9
|
+
*.mjs text eol=lf
|
|
10
|
+
*.cjs text eol=lf
|
|
11
|
+
*.json text eol=lf
|
|
12
|
+
*.md text eol=lf
|
|
13
|
+
*.sh text eol=lf
|
|
14
|
+
*.yml text eol=lf
|
|
15
|
+
*.yaml text eol=lf
|
|
16
|
+
*.html text eol=lf
|
|
17
|
+
*.css text eol=lf
|
|
18
|
+
*.scss text eol=lf
|
|
19
|
+
*.less text eol=lf
|
|
20
|
+
*.graphql text eol=lf
|
|
21
|
+
*.sql text eol=lf
|
|
22
|
+
*.pug text eol=lf
|
|
23
|
+
|
|
24
|
+
# Configuration files
|
|
25
|
+
.env* text eol=lf
|
|
26
|
+
.editorconfig text eol=lf
|
|
27
|
+
.prettierrc text eol=lf
|
|
28
|
+
.eslintrc* text eol=lf
|
|
29
|
+
.gitignore text eol=lf
|
|
30
|
+
.dockerignore text eol=lf
|
|
31
|
+
.gitattributes text eol=lf
|
|
32
|
+
|
|
33
|
+
# Assets
|
|
34
|
+
*.png binary
|
|
35
|
+
*.jpg binary
|
|
36
|
+
*.jpeg binary
|
|
37
|
+
*.gif binary
|
|
38
|
+
*.ico binary
|
|
39
|
+
*.webp binary
|
|
40
|
+
*.avif binary
|
|
41
|
+
*.pdf binary
|
|
42
|
+
*.woff binary
|
|
43
|
+
*.woff2 binary
|
|
44
|
+
*.ttf binary
|
|
45
|
+
*.eot binary
|
|
46
|
+
*.svg text eol=lf
|
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
variables:
|
|
2
|
-
NODE_ENV: 'test'
|
|
3
|
-
|
|
4
|
-
stages:
|
|
5
|
-
- lint
|
|
6
|
-
- test
|
|
7
|
-
<% if (includeSecurity) { %>
|
|
8
|
-
- security
|
|
9
|
-
- quality
|
|
10
|
-
<% } %>
|
|
11
|
-
- build
|
|
12
|
-
|
|
13
|
-
cache:
|
|
14
|
-
paths:
|
|
15
|
-
- node_modules/
|
|
16
|
-
|
|
17
|
-
install_dependencies:
|
|
18
|
-
stage: .pre
|
|
19
|
-
image: node:22-slim
|
|
20
|
-
script:
|
|
21
|
-
- npm ci
|
|
22
|
-
|
|
23
|
-
lint_code:
|
|
24
|
-
stage: lint
|
|
25
|
-
image: node:22-slim
|
|
26
|
-
script:
|
|
27
|
-
- npm run lint
|
|
28
|
-
|
|
29
|
-
run_unit_tests:
|
|
30
|
-
stage: test
|
|
31
|
-
image: node:22-slim
|
|
32
|
-
script:
|
|
33
|
-
- npm run test:coverage
|
|
34
|
-
|
|
35
|
-
run_e2e_tests:
|
|
36
|
-
stage: test
|
|
37
|
-
image: docker:20.10.16
|
|
38
|
-
services:
|
|
39
|
-
- docker:20.10.16-dind
|
|
40
|
-
script:
|
|
41
|
-
- apk add --no-cache nodejs npm docker-compose
|
|
42
|
-
- npm ci
|
|
43
|
-
- npm run test:e2e
|
|
44
|
-
<% if (includeSecurity) { %>
|
|
45
|
-
snyk_scan:
|
|
46
|
-
stage: security
|
|
47
|
-
image: node:22-alpine
|
|
48
|
-
script:
|
|
49
|
-
- npm ci
|
|
50
|
-
- npm run snyk:test
|
|
51
|
-
only:
|
|
52
|
-
- main
|
|
53
|
-
|
|
54
|
-
snyk_container_scan:
|
|
55
|
-
stage: security
|
|
56
|
-
image: docker:20.10.16
|
|
57
|
-
services:
|
|
58
|
-
- docker:20.10.16-dind
|
|
59
|
-
script:
|
|
60
|
-
- apk add --no-cache nodejs npm
|
|
61
|
-
- npm install -g snyk
|
|
62
|
-
- docker build -t <%= projectName %>:latest .
|
|
63
|
-
- snyk container test <%= projectName %>:latest --file=Dockerfile --severity-threshold=high --skip-unused-projects
|
|
64
|
-
|
|
65
|
-
sonarqube_check:
|
|
66
|
-
stage: quality
|
|
67
|
-
image:
|
|
68
|
-
name: sonarsource/sonar-scanner-cli:latest
|
|
69
|
-
entrypoint: [""]
|
|
70
|
-
variables:
|
|
71
|
-
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
|
|
72
|
-
GIT_DEPTH: "0"
|
|
73
|
-
cache:
|
|
74
|
-
key: "${CI_JOB_NAME}"
|
|
75
|
-
paths:
|
|
76
|
-
- .sonar/cache
|
|
77
|
-
script:
|
|
78
|
-
- sonar-scanner
|
|
79
|
-
only:
|
|
80
|
-
- main
|
|
81
|
-
<% } %>
|
|
82
|
-
build_app:
|
|
83
|
-
stage: build
|
|
84
|
-
image: node:22-alpine
|
|
85
|
-
script:
|
|
86
|
-
- npm run build --if-present
|
|
1
|
+
variables:
|
|
2
|
+
NODE_ENV: 'test'
|
|
3
|
+
|
|
4
|
+
stages:
|
|
5
|
+
- lint
|
|
6
|
+
- test
|
|
7
|
+
<% if (includeSecurity) { %>
|
|
8
|
+
- security
|
|
9
|
+
- quality
|
|
10
|
+
<% } %>
|
|
11
|
+
- build
|
|
12
|
+
|
|
13
|
+
cache:
|
|
14
|
+
paths:
|
|
15
|
+
- node_modules/
|
|
16
|
+
|
|
17
|
+
install_dependencies:
|
|
18
|
+
stage: .pre
|
|
19
|
+
image: node:22-slim
|
|
20
|
+
script:
|
|
21
|
+
- npm ci
|
|
22
|
+
|
|
23
|
+
lint_code:
|
|
24
|
+
stage: lint
|
|
25
|
+
image: node:22-slim
|
|
26
|
+
script:
|
|
27
|
+
- npm run lint
|
|
28
|
+
|
|
29
|
+
run_unit_tests:
|
|
30
|
+
stage: test
|
|
31
|
+
image: node:22-slim
|
|
32
|
+
script:
|
|
33
|
+
- npm run test:coverage
|
|
34
|
+
|
|
35
|
+
run_e2e_tests:
|
|
36
|
+
stage: test
|
|
37
|
+
image: docker:20.10.16
|
|
38
|
+
services:
|
|
39
|
+
- docker:20.10.16-dind
|
|
40
|
+
script:
|
|
41
|
+
- apk add --no-cache nodejs npm docker-compose
|
|
42
|
+
- npm ci
|
|
43
|
+
- npm run test:e2e
|
|
44
|
+
<% if (includeSecurity) { %>
|
|
45
|
+
snyk_scan:
|
|
46
|
+
stage: security
|
|
47
|
+
image: node:22-alpine
|
|
48
|
+
script:
|
|
49
|
+
- npm ci
|
|
50
|
+
- npm run snyk:test
|
|
51
|
+
only:
|
|
52
|
+
- main
|
|
53
|
+
|
|
54
|
+
snyk_container_scan:
|
|
55
|
+
stage: security
|
|
56
|
+
image: docker:20.10.16
|
|
57
|
+
services:
|
|
58
|
+
- docker:20.10.16-dind
|
|
59
|
+
script:
|
|
60
|
+
- apk add --no-cache nodejs npm
|
|
61
|
+
- npm install -g snyk
|
|
62
|
+
- docker build -t <%= projectName %>:latest .
|
|
63
|
+
- snyk container test <%= projectName %>:latest --file=Dockerfile --severity-threshold=high --skip-unused-projects
|
|
64
|
+
|
|
65
|
+
sonarqube_check:
|
|
66
|
+
stage: quality
|
|
67
|
+
image:
|
|
68
|
+
name: sonarsource/sonar-scanner-cli:latest
|
|
69
|
+
entrypoint: [""]
|
|
70
|
+
variables:
|
|
71
|
+
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
|
|
72
|
+
GIT_DEPTH: "0"
|
|
73
|
+
cache:
|
|
74
|
+
key: "${CI_JOB_NAME}"
|
|
75
|
+
paths:
|
|
76
|
+
- .sonar/cache
|
|
77
|
+
script:
|
|
78
|
+
- sonar-scanner
|
|
79
|
+
only:
|
|
80
|
+
- main
|
|
81
|
+
<% } %>
|
|
82
|
+
build_app:
|
|
83
|
+
stage: build
|
|
84
|
+
image: node:22-alpine
|
|
85
|
+
script:
|
|
86
|
+
- npm run build --if-present
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"*.{js,ts}": [
|
|
3
|
-
"eslint --fix",
|
|
4
|
-
"prettier --write"
|
|
5
|
-
]
|
|
6
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"*.{js,ts}": [
|
|
3
|
+
"eslint --fix",
|
|
4
|
+
"prettier --write"
|
|
5
|
+
]
|
|
6
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
2
|
-
"semi": true,
|
|
3
|
-
"trailingComma": "all",
|
|
4
|
-
"singleQuote": true,
|
|
5
|
-
"printWidth": 100,
|
|
6
|
-
"tabWidth": 2
|
|
7
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"semi": true,
|
|
3
|
+
"trailingComma": "all",
|
|
4
|
+
"singleQuote": true,
|
|
5
|
+
"printWidth": 100,
|
|
6
|
+
"tabWidth": 2
|
|
7
|
+
}
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
# ==========================================
|
|
2
|
-
# Stage 1: Builder
|
|
3
|
-
# ==========================================
|
|
4
|
-
FROM node:22-alpine AS builder
|
|
5
|
-
|
|
6
|
-
# Upgrade OS packages to fix upstream vulnerabilities (Snyk-detected)
|
|
7
|
-
RUN apk update && apk upgrade && \
|
|
8
|
-
apk add --no-cache ca-certificates zlib>=1.3.2-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
|
9
|
-
|
|
10
|
-
WORKDIR /app
|
|
11
|
-
ENV NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
12
|
-
|
|
13
|
-
# Upgrade npm using corepack (safer in Alpine)
|
|
14
|
-
RUN corepack enable && corepack prepare npm@11.6.4 --activate
|
|
15
|
-
|
|
16
|
-
COPY package*.json ./
|
|
17
|
-
COPY tsconfig*.json ./
|
|
18
|
-
|
|
19
|
-
# Install ALL dependencies (including devDeps for build)
|
|
20
|
-
RUN npm ci --no-audit --no-fund || npm ci --no-audit --no-fund || npm ci --no-audit --no-fund
|
|
21
|
-
|
|
22
|
-
COPY . .
|
|
23
|
-
|
|
24
|
-
# Build for production
|
|
25
|
-
<% if (language === 'TypeScript') { %>RUN npm run build<% } %>
|
|
26
|
-
|
|
27
|
-
# ==========================================
|
|
28
|
-
# Stage 2: Production
|
|
29
|
-
# ==========================================
|
|
30
|
-
FROM node:22-alpine AS production
|
|
31
|
-
|
|
32
|
-
# Upgrade OS packages to fix upstream vulnerabilities (Snyk-detected)
|
|
33
|
-
RUN apk update && apk upgrade && \
|
|
34
|
-
apk add --no-cache ca-certificates zlib>=1.3.2-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
|
35
|
-
|
|
36
|
-
WORKDIR /app
|
|
37
|
-
|
|
38
|
-
ENV NODE_ENV=production
|
|
39
|
-
ENV NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
40
|
-
|
|
41
|
-
# Upgrade npm using corepack (safer in Alpine)
|
|
42
|
-
RUN corepack enable && corepack prepare npm@11.6.4 --activate
|
|
43
|
-
|
|
44
|
-
COPY package*.json ./
|
|
45
|
-
|
|
46
|
-
# Install ONLY production dependencies
|
|
47
|
-
RUN npm ci --only=production --ignore-scripts --no-audit --no-fund || npm ci --only=production --ignore-scripts --no-audit --no-fund || npm ci --only=production --ignore-scripts --no-audit --no-fund
|
|
48
|
-
|
|
49
|
-
# Remove npm and caches to achieve Zero-Vulnerability status in the final image
|
|
50
|
-
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx /root/.npm /root/.cache
|
|
51
|
-
|
|
52
|
-
# Copy built artifacts from builder
|
|
53
|
-
<% if (language === 'TypeScript') { %>
|
|
54
|
-
COPY --from=builder /app/dist ./dist
|
|
55
|
-
<% } else { %>
|
|
56
|
-
COPY --from=builder /app/src ./src
|
|
57
|
-
<% } %>
|
|
58
|
-
|
|
59
|
-
# Copy other necessary files (like views if MVC)
|
|
60
|
-
<% if (viewEngine && viewEngine !== 'None') { %>
|
|
61
|
-
COPY --from=builder /app/src/views ./dist/views
|
|
62
|
-
<% if (viewEngine && viewEngine !== 'None') { %>COPY --from=builder /app/public ./public<% } %>
|
|
63
|
-
<% } %>
|
|
64
|
-
|
|
65
|
-
EXPOSE 3000
|
|
66
|
-
|
|
67
|
-
# Create logs directory and give permissions to node user
|
|
68
|
-
RUN mkdir -p logs && chown -R node:node logs
|
|
69
|
-
|
|
70
|
-
USER node
|
|
71
|
-
|
|
72
|
-
# Start application directly with node (safe even without npm)
|
|
73
|
-
CMD ["node", "<% if (language === 'TypeScript') { %>dist/index.js<% } else { %>src/index.js<% } %>"]
|
|
1
|
+
# ==========================================
|
|
2
|
+
# Stage 1: Builder
|
|
3
|
+
# ==========================================
|
|
4
|
+
FROM node:22-alpine AS builder
|
|
5
|
+
|
|
6
|
+
# Upgrade OS packages to fix upstream vulnerabilities (Snyk-detected)
|
|
7
|
+
RUN apk update && apk upgrade && \
|
|
8
|
+
apk add --no-cache ca-certificates zlib>=1.3.2-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
|
9
|
+
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
ENV NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
12
|
+
|
|
13
|
+
# Upgrade npm using corepack (safer in Alpine)
|
|
14
|
+
RUN corepack enable && corepack prepare npm@11.6.4 --activate
|
|
15
|
+
|
|
16
|
+
COPY package*.json ./
|
|
17
|
+
COPY tsconfig*.json ./
|
|
18
|
+
|
|
19
|
+
# Install ALL dependencies (including devDeps for build)
|
|
20
|
+
RUN npm ci --no-audit --no-fund || npm ci --no-audit --no-fund || npm ci --no-audit --no-fund
|
|
21
|
+
|
|
22
|
+
COPY . .
|
|
23
|
+
|
|
24
|
+
# Build for production
|
|
25
|
+
<% if (language === 'TypeScript') { %>RUN npm run build<% } %>
|
|
26
|
+
|
|
27
|
+
# ==========================================
|
|
28
|
+
# Stage 2: Production
|
|
29
|
+
# ==========================================
|
|
30
|
+
FROM node:22-alpine AS production
|
|
31
|
+
|
|
32
|
+
# Upgrade OS packages to fix upstream vulnerabilities (Snyk-detected)
|
|
33
|
+
RUN apk update && apk upgrade && \
|
|
34
|
+
apk add --no-cache ca-certificates zlib>=1.3.2-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
|
|
35
|
+
|
|
36
|
+
WORKDIR /app
|
|
37
|
+
|
|
38
|
+
ENV NODE_ENV=production
|
|
39
|
+
ENV NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
40
|
+
|
|
41
|
+
# Upgrade npm using corepack (safer in Alpine)
|
|
42
|
+
RUN corepack enable && corepack prepare npm@11.6.4 --activate
|
|
43
|
+
|
|
44
|
+
COPY package*.json ./
|
|
45
|
+
|
|
46
|
+
# Install ONLY production dependencies
|
|
47
|
+
RUN npm ci --only=production --ignore-scripts --no-audit --no-fund || npm ci --only=production --ignore-scripts --no-audit --no-fund || npm ci --only=production --ignore-scripts --no-audit --no-fund
|
|
48
|
+
|
|
49
|
+
# Remove npm and caches to achieve Zero-Vulnerability status in the final image
|
|
50
|
+
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx /root/.npm /root/.cache
|
|
51
|
+
|
|
52
|
+
# Copy built artifacts from builder
|
|
53
|
+
<% if (language === 'TypeScript') { %>
|
|
54
|
+
COPY --from=builder /app/dist ./dist
|
|
55
|
+
<% } else { %>
|
|
56
|
+
COPY --from=builder /app/src ./src
|
|
57
|
+
<% } %>
|
|
58
|
+
|
|
59
|
+
# Copy other necessary files (like views if MVC)
|
|
60
|
+
<% if (viewEngine && viewEngine !== 'None') { %>
|
|
61
|
+
COPY --from=builder /app/src/views ./dist/views
|
|
62
|
+
<% if (viewEngine && viewEngine !== 'None') { %>COPY --from=builder /app/public ./public<% } %>
|
|
63
|
+
<% } %>
|
|
64
|
+
|
|
65
|
+
EXPOSE 3000
|
|
66
|
+
|
|
67
|
+
# Create logs directory and give permissions to node user
|
|
68
|
+
RUN mkdir -p logs && chown -R node:node logs
|
|
69
|
+
|
|
70
|
+
USER node
|
|
71
|
+
|
|
72
|
+
# Start application directly with node (safe even without npm)
|
|
73
|
+
CMD ["node", "<% if (language === 'TypeScript') { %>dist/index.js<% } else { %>src/index.js<% } %>"]
|