nodejs-quickstart-structure 1.7.5 โ†’ 1.8.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 CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.8.1] - 2026-02-22
9
+ ### Security
10
+ - Resolved all high-severity npm vulnerabilities (0 vulnerabilities detected on install).
11
+ - Upgraded ESLint to v9 and `typescript-eslint` to v8, migrating generated templates from `.eslintrc.json` to Flat Config (`eslint.config.mjs`) to eliminate deprecated `eslint@8` transitive dependencies.
12
+ - Upgraded `supertest` to v7, `rimraf` to v6, and `ejs` to v3.1.10.
13
+ - Replaced vulnerable `copyfiles` dependency with `cpx2` for view template orchestration.
14
+ - Configured npm `overrides` for `minimatch@^10.2.1` to patch outdated `jest` sub-dependencies without breaking the test runner.
15
+
16
+ ### Fixed
17
+ - Fixed `npm install` crashing due to `husky install` expecting an initialized `.git` directory by adding a graceful fallback wrapper.
18
+
19
+ ## [1.8.0] - 2026-02-18
20
+ ### Added
21
+ - Introduced **GitLab CI/CD pipeline support**:
22
+ - Preconfigured `.gitlab-ci.yml` for automated build, test, and deploy steps.
23
+ - End-to-end (e2e) test job included to ensure project reliability.
24
+ - Aligns with existing GitHub Actions and Jenkins workflows for consistent CI/CD coverage.
25
+
26
+ ### Improved
27
+ - Documentation updated to highlight GitLab CI/CD as a supported option.
28
+ - Enhanced CI/CD setup instructions in `README.md` for multi-platform pipelines.
29
+
8
30
  ## [1.7.5] - 2026-02-17
9
31
  > Happy Lunar New Year! This release coincides with Tet Vietnam. ๐ŸŽ†
10
32
  ### Fixed
package/README.md CHANGED
@@ -25,7 +25,7 @@ We don't just generate boilerplate; we generate **production-ready** foundations
25
25
  - **๐Ÿ” Code Quality**: Pre-configured `Eslint` and `Prettier` for consistent coding standards.
26
26
  - **๐Ÿ›ก๏ธ Security**: Built-in `Helmet`, `HPP`, `CORS`, and Rate-Limiting middleware.
27
27
  - **๐Ÿงช Testing Strategy**: Integrated `Jest` and `Supertest` setup for Unit and Integration testing.
28
- - **๐Ÿ”„ CI/CD Support**: Choice between **GitHub Actions** and **Jenkins**.
28
+ - **๐Ÿ”„ CI/CD Integration**: Pre-configured workflows for **GitHub Actions**, **Jenkins**, and **GitLab CI**.
29
29
  - **โš“ Git Hooks**: `Husky` and `Lint-Staged` to ensure no bad code is ever committed.
30
30
  - **๐Ÿณ DevOps**: Highly optimized **Multi-Stage Dockerfile** for small, secure production images.
31
31
 
@@ -68,7 +68,7 @@ The CLI will guide you through the following steps:
68
68
  5. **Database Name**: The name of the initial database.
69
69
  6. **Communication**: `REST APIs` (default) or `Kafka`.
70
70
  7. **Caching**: `Redis` or `None`.
71
- 8. **CI/CD**: `GitHub Actions`, `Jenkins`, or `None`.
71
+ 8. **CI/CD**: `GitHub Actions`, `Jenkins`, `GitLab CI` or `None`.
72
72
 
73
73
  ## Generated Project Structure
74
74
 
@@ -3,6 +3,7 @@
3
3
  This document lists the **112 possible project combinations** supported by the `nodejs-quickstart` CLI. These combinations cover all supported languages, architectures, databases, communication patterns, and caching options.
4
4
 
5
5
  ## Summary
6
+ - **CI Providers**: `None`, `GitHub Actions`, `Jenkins`, `GitLab CI`
6
7
  - **MVC Architecture**: 84 Combinations
7
8
  - **With Database (36)**: 2 Lang ร— 3 View ร— 3 DB ร— 2 Comm = 36 * 2 (Caching: None/Redis) = 72
8
9
  - **No Database (12)**: 2 Lang ร— 3 View ร— 1 DB ร— 2 Comm = 12 * 1 (Caching: None) = 12
@@ -90,7 +90,11 @@ The `generateProject` function in `lib/generator.js` executes the following step
90
90
  16. **Test Setup**:
91
91
  * Generates `jest.config.js` and a sample `health.test.{js|ts}`.
92
92
  17. **CI/CD Setup**:
93
- * Copies GitHub Actions workflow or renders `Jenkinsfile` if selected.
93
+ * Helper: `setupCiCd`
94
+ * Checks `config.ciProvider`:
95
+ * **GitHub Actions**: Copies `.github/workflows/ci.yml`.
96
+ * **Jenkins**: Renders `Jenkinsfile`.
97
+ * **GitLab CI**: Renders `.gitlab-ci.yml` if selected.
94
98
 
95
99
  ## 4. TypeScript vs JavaScript Generation Steps
96
100
 
@@ -0,0 +1,25 @@
1
+ # Development Rules & Conventions
2
+
3
+ ## General Standards
4
+
5
+ ### File Naming
6
+ - **Controllers**: Use camelCase (e.g., `kafkaController.ts`, `userController.ts`).
7
+ - **Services**: Use camelCase (e.g., `kafkaService.ts`, `userService.ts`) or PascalCase depending on export type. Class-based services should generally match class name.
8
+ - **Routes**: Use camelCase (e.g., `userRoutes.ts`, `kafkaRoutes.ts`).
9
+ - **Utilities**: Use camelCase (e.g., `httpCodes.ts`).
10
+
11
+ ### Code Style
12
+ - **Status Codes**: ALWAYS use `HTTP_STATUS` constants from `@/utils/httpCodes` (TS) or `../../utils/httpCodes.js` (JS) instead of hardcoded numbers.
13
+ - Good: `res.status(HTTP_STATUS.OK).json(...)`
14
+ - Bad: `res.status(200).json(...)`
15
+ - **Imports**:
16
+ - **TypeScript**: Use path aliases (e.g., `@/services/...`, `@/utils/...`) instead of relative paths (e.g., `../../utils/...`).
17
+ - **JavaScript**: Use relative paths as configured by the project structure.
18
+
19
+ ### API Response Structure
20
+ - Success: `{ status: string, data: any }` or direct JSON object.
21
+ - Error: `{ error: string }`
22
+
23
+ ## Git Workflow
24
+ - Commit messages should be descriptive.
25
+ - Ensure all tests pass before pushing.
@@ -60,9 +60,9 @@ export const renderDockerfile = async (templatesDir, targetDir, config) => {
60
60
  };
61
61
 
62
62
  export const renderProfessionalConfig = async (templatesDir, targetDir, language) => {
63
- const eslintTemplate = await fs.readFile(path.join(templatesDir, 'common', '.eslintrc.json.ejs'), 'utf-8');
63
+ const eslintTemplate = await fs.readFile(path.join(templatesDir, 'common', 'eslint.config.mjs.ejs'), 'utf-8');
64
64
  const eslintContent = ejs.render(eslintTemplate, { language });
65
- await fs.writeFile(path.join(targetDir, '.eslintrc.json'), eslintContent);
65
+ await fs.writeFile(path.join(targetDir, 'eslint.config.mjs'), eslintContent);
66
66
 
67
67
  await fs.copy(path.join(templatesDir, 'common', '.prettierrc'), path.join(targetDir, '.prettierrc'));
68
68
  await fs.copy(path.join(templatesDir, 'common', '.lintstagedrc'), path.join(targetDir, '.lintstagedrc'));
@@ -81,6 +81,10 @@ export const setupCiCd = async (templatesDir, targetDir, config) => {
81
81
  const jenkinsTemplate = await fs.readFile(path.join(templatesDir, 'common', 'Jenkinsfile.ejs'), 'utf-8');
82
82
  const jenkinsContent = ejs.render(jenkinsTemplate, { projectName });
83
83
  await fs.writeFile(path.join(targetDir, 'Jenkinsfile'), jenkinsContent);
84
+ } else if (ciProvider === 'GitLab CI') {
85
+ const gitlabTemplate = await fs.readFile(path.join(templatesDir, 'common', '.gitlab-ci.yml.ejs'), 'utf-8');
86
+ const gitlabContent = ejs.render(gitlabTemplate, { projectName });
87
+ await fs.writeFile(path.join(targetDir, '.gitlab-ci.yml'), gitlabContent);
84
88
  }
85
89
  };
86
90
 
package/lib/prompts.js CHANGED
@@ -74,7 +74,7 @@ export const getProjectDetails = async (options = {}) => {
74
74
  type: 'list',
75
75
  name: 'ciProvider',
76
76
  message: 'Select CI/CD Provider:',
77
- choices: ['None', 'GitHub Actions', 'Jenkins'],
77
+ choices: ['None', 'GitHub Actions', 'Jenkins', 'GitLab CI'],
78
78
  default: 'None',
79
79
  when: !options.ciProvider
80
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-quickstart-structure",
3
- "version": "1.7.5",
3
+ "version": "1.8.1",
4
4
  "type": "module",
5
5
  "description": "A CLI to scaffold Node.js microservices with MVC or Clean Architecture",
6
6
  "main": "bin/index.js",
@@ -0,0 +1,35 @@
1
+ variables:
2
+ NODE_ENV: 'test'
3
+
4
+ stages:
5
+ - lint
6
+ - test
7
+ - build
8
+
9
+ cache:
10
+ paths:
11
+ - node_modules/
12
+
13
+ install_dependencies:
14
+ stage: .pre
15
+ image: node:18-alpine
16
+ script:
17
+ - npm ci
18
+
19
+ lint_code:
20
+ stage: lint
21
+ image: node:18-alpine
22
+ script:
23
+ - npm run lint
24
+
25
+ run_tests:
26
+ stage: test
27
+ image: node:18-alpine
28
+ script:
29
+ - npm test
30
+
31
+ build_app:
32
+ stage: build
33
+ image: node:18-alpine
34
+ script:
35
+ - npm run build --if-present
@@ -17,12 +17,20 @@ This project comes pre-configured with industry-standard tooling for **Code Qual
17
17
  - **DevOps**: Multi-stage Docker build, CI/CD ready.
18
18
 
19
19
  ## ๐Ÿ”„ CI/CD Pipeline
20
- <% if (ciProvider === 'GitHub Actions') { -%>
20
+ <%_ if (ciProvider === 'GitHub Actions') { -%>
21
+ ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/yourusername/<%= projectName %>/ci.yml?branch=main)
21
22
  This project includes a **GitHub Actions** workflow located in `.github/workflows/ci.yml`.
22
23
  It automatically runs:
23
24
  - Linting
24
25
  - Tests
25
26
  - Builds
27
+ <%_ } else if (ciProvider === 'GitLab CI') { -%>
28
+ ![GitLab CI Status](https://img.shields.io/gitlab/pipeline/yourusername/<%= projectName %>?branch=main)
29
+ This project includes a **GitLab CI** configuration in `.gitlab-ci.yml`.
30
+ It automatically runs:
31
+ - Linting
32
+ - Tests
33
+ - Builds
26
34
  <% } else if (ciProvider === 'Jenkins') { -%>
27
35
  This project includes a **Jenkinsfile** for comprehensive CI/CD.
28
36
  Pipeline stages:
@@ -0,0 +1,41 @@
1
+ import eslint from '@eslint/js';
2
+ import eslintConfigPrettier from 'eslint-config-prettier';
3
+ import globals from 'globals';
4
+ <% if (language === 'TypeScript') { %>import tseslint from 'typescript-eslint';
5
+
6
+ export default tseslint.config(
7
+ eslint.configs.recommended,
8
+ ...tseslint.configs.recommended,
9
+ eslintConfigPrettier,
10
+ {
11
+ languageOptions: {
12
+ globals: {
13
+ ...globals.node,
14
+ ...globals.jest,
15
+ },
16
+ },
17
+ rules: {
18
+ "no-console": "warn",
19
+ "no-unused-vars": "off",
20
+ "@typescript-eslint/no-unused-vars": "warn"
21
+ }
22
+ }
23
+ );<% } else { %>
24
+ export default [
25
+ eslint.configs.recommended,
26
+ eslintConfigPrettier,
27
+ {
28
+ languageOptions: {
29
+ ecmaVersion: 'latest',
30
+ sourceType: 'module',
31
+ globals: {
32
+ ...globals.node,
33
+ ...globals.jest,
34
+ },
35
+ },
36
+ rules: {
37
+ "no-console": "warn",
38
+ "no-unused-vars": "warn"
39
+ }
40
+ }
41
+ ];<% } %>
@@ -6,11 +6,11 @@
6
6
  "scripts": {
7
7
  "start": "<% if (language === 'TypeScript') { %>node dist/index.js<% } else { %>node src/index.js<% } %>",
8
8
  "dev": "<% if (language === 'TypeScript') { %>nodemon --exec ts-node -r tsconfig-paths/register src/index.ts<% } else { %>nodemon src/index.js<% } %>"<% if (language === 'TypeScript') { %>,
9
- "build": "rimraf dist && tsc && tsc-alias<% if (viewEngine && viewEngine !== 'None') { %> && copyfiles -u 1 \"src/views/**/*\" dist/<% } %>"<% } %>,
10
- "lint": "eslint . --ext .ts,.js",
11
- "lint:fix": "eslint . --ext .ts,.js --fix",
9
+ "build": "rimraf dist && tsc && tsc-alias<% if (viewEngine && viewEngine !== 'None') { %> && cpx2 \"src/views/**/*\" dist/views<% } %>"<% } %>,
10
+ "lint": "eslint .",
11
+ "lint:fix": "eslint . --fix",
12
12
  "format": "prettier --write .",
13
- "prepare": "husky install",
13
+ "prepare": "node -e \"try { require('child_process').execSync('husky install'); } catch (e) { console.log('Not a git repository, skipping husky install'); }\"",
14
14
  "test": "jest",
15
15
  "test:watch": "jest --watch",
16
16
  "test:coverage": "jest --coverage"
@@ -34,7 +34,7 @@
34
34
  <% } -%>
35
35
  <% if (caching === 'Redis') { %> "ioredis": "^5.3.2",
36
36
  <% } -%>
37
- <% if (viewEngine === 'EJS') { %> "ejs": "^3.1.9",
37
+ <% if (viewEngine === 'EJS') { %> "ejs": "^3.1.10",
38
38
  <% } -%>
39
39
  <% if (viewEngine === 'Pug') { %> "pug": "^3.0.2",
40
40
  <% } -%>
@@ -55,7 +55,6 @@
55
55
  "@types/node": "^20.10.5",
56
56
  "@types/express": "^4.17.21",
57
57
  "@types/cors": "^2.8.17",
58
- "@types/dotenv": "^8.2.0",
59
58
  "@types/hpp": "^0.2.3",
60
59
  <% if (caching === 'Redis') { %> "@types/ioredis": "^5.0.0",
61
60
  <% } -%>
@@ -65,26 +64,30 @@
65
64
  "@types/sequelize": "^4.28.19",
66
65
  <%_ } -%>
67
66
  "@types/morgan": "^1.9.9",
68
- "rimraf": "^5.0.5"<% if (viewEngine && viewEngine !== 'None') { %>,
69
- "copyfiles": "^2.4.1"<% } %><% } %>,
70
- "eslint": "^8.56.0",
71
- "prettier": "^3.1.1",
72
- "eslint-config-prettier": "^9.1.0",
67
+ "rimraf": "^6.0.1"<% if (viewEngine && viewEngine !== 'None') { %>,
68
+ "cpx2": "^8.0.0"<% } %><% } %>,
69
+ "eslint": "^9.20.1",
70
+ "@eslint/js": "^9.20.0",
71
+ "globals": "^15.14.0",
72
+ "prettier": "^3.5.1",
73
+ "eslint-config-prettier": "^10.0.1",
73
74
  "husky": "^8.0.3",
74
- "lint-staged": "^15.2.0"<% if (language === 'TypeScript') { %>,
75
- "@typescript-eslint/eslint-plugin": "^6.18.1",
76
- "@typescript-eslint/parser": "^6.18.1",
75
+ "lint-staged": "^15.4.3"<% if (language === 'TypeScript') { %>,
76
+ "typescript-eslint": "^8.24.1",
77
77
  <% if (communication === 'REST APIs') { %> "@types/swagger-ui-express": "^4.1.6",
78
78
  "@types/swagger-jsdoc": "^6.0.4",<% } -%>
79
79
  "jest": "^29.7.0",
80
- "ts-jest": "^29.1.1",
81
- "@types/jest": "^29.5.11",
82
- "supertest": "^6.3.3",
80
+ "ts-jest": "^29.2.5",
81
+ "@types/jest": "^29.5.14",
82
+ "supertest": "^7.1.3",
83
83
  "tsconfig-paths": "^4.2.0",
84
- "tsc-alias": "^1.8.8",
84
+ "tsc-alias": "^1.8.10",
85
85
  "@types/supertest": "^6.0.2"<% } else { %>,
86
86
  "jest": "^29.7.0",
87
- "supertest": "^6.3.3"<% } %>
87
+ "supertest": "^7.1.3"<% } %>
88
+ },
89
+ "overrides": {
90
+ "minimatch": "^10.2.1"
88
91
  },
89
92
  "lint-staged": {
90
93
  "*.{js,ts}": [
@@ -1,26 +0,0 @@
1
- {
2
- "env": {
3
- "node": true,
4
- "es2021": true,
5
- "jest": true
6
- },
7
- "extends": [
8
- "eslint:recommended",
9
- "prettier"<% if (language === 'TypeScript') { %>,
10
- "plugin:@typescript-eslint/recommended"<% } %>
11
- ],
12
- "parserOptions": {
13
- "ecmaVersion": "latest",
14
- "sourceType": "module"
15
- }<% if (language === 'TypeScript') { %>,
16
- "parser": "@typescript-eslint/parser",
17
- "plugins": ["@typescript-eslint"]<% } %>,
18
- "rules": {
19
- "no-console": "warn",
20
- <% if (language === 'TypeScript') { %>
21
- "no-unused-vars": "off",
22
- "@typescript-eslint/no-unused-vars": "warn"
23
- <% } else { %>
24
- "no-unused-vars": "warn"<% } %>
25
- }
26
- }