nodejs-quickstart-structure 1.9.1 → 1.9.4
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 +19 -0
- package/bin/index.js +17 -1
- package/lib/generator.js +1 -1
- package/lib/modules/app-setup.js +19 -9
- package/package.json +1 -1
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js +4 -21
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +0 -67
- package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +4 -21
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +0 -66
- package/templates/common/Dockerfile +2 -2
- package/templates/common/README.md.ejs +38 -1
- package/templates/common/database/js/database.js.ejs +1 -2
- package/templates/common/database/ts/database.ts.ejs +1 -2
- package/templates/common/package.json.ejs +4 -4
- package/templates/common/swagger.yml.ejs +66 -0
- package/templates/mvc/js/src/config/swagger.js +4 -21
- package/templates/mvc/js/src/routes/api.js +0 -66
- package/templates/mvc/ts/src/config/swagger.ts.ejs +4 -21
- package/templates/mvc/ts/src/routes/api.ts +0 -66
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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.9.4] - 2026-02-26
|
|
9
|
+
### Fixed
|
|
10
|
+
- Fixed an `EBADENGINE` compatibility issue during Docker builds by upgrading the default template `Dockerfile` base image from `node:18-alpine` to `node:22-alpine`, supporting modern dependencies like `eslint@9` and `cpx2`.
|
|
11
|
+
- Fixed a port collision bug (`Bind for 0.0.0.0:6379 failed: port is already allocated`) during parallel E2E testing. The `validation-core.js` script now dynamically assigns random network ports for `REDIS_PORT` when running concurrent testing matrices.
|
|
12
|
+
|
|
13
|
+
## [1.9.3] - 2026-02-26
|
|
14
|
+
### Added
|
|
15
|
+
- Refactored Swagger documentation to use a standalone `swagger.yml` file instead of inline JSDoc comments across all templates (MVC, Clean Architecture, TS, and JS).
|
|
16
|
+
- Integrated `yamljs` to parse the `swagger.yml` file and removed the `swagger-jsdoc` dependency, significantly reducing boilerplate in route files.
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Fixed an issue in `package.json.ejs` where `jest` configuration had malformed JSON due to whitespace stripping.
|
|
20
|
+
- Fixed a Docker build crash for non-REST API projects caused by the build script unconditionally attempting to copy `swagger.yml` using `cpx2`.
|
|
21
|
+
|
|
22
|
+
## [1.9.2] - 2026-02-23
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fixed an issue where the generator output misleading instructions (`DATABASE_URL`) for standalone `docker run` executions. The CLI success commands and `README.md` now conditionally include dynamic compose network bindings (`--network`) and accurate environment variables matching the user's selected DB stack.
|
|
25
|
+
- Fixed a bug where `DB_PASSWORD` in `database.ts.ejs` and `database.js.ejs` defaulted to `postgres` instead of `root` for PostgreSQL configurations, causing standalone Node local servers (`npm run dev`) to fail connection handshakes with default `docker-compose` clusters.
|
|
26
|
+
|
|
8
27
|
## [1.9.1] - 2026-02-22
|
|
9
28
|
### Added
|
|
10
29
|
- Implemented **Daily Template Vulnerability Audit** via GitHub Actions (`.github/workflows/daily-audit.yml`). A custom script now parses `package.json.ejs` daily to proactively scan for high-severity vulnerabilities in generated dependencies, ensuring generated projects are eternally secure.
|
package/bin/index.js
CHANGED
|
@@ -51,7 +51,23 @@ program
|
|
|
51
51
|
await generateProject(answers);
|
|
52
52
|
|
|
53
53
|
console.log(chalk.green('\n✔ Project generated successfully!'));
|
|
54
|
-
|
|
54
|
+
|
|
55
|
+
let manualStartInstructions = `\nStart the app manually:\n cd ${answers.projectName}\n npm install`;
|
|
56
|
+
|
|
57
|
+
const needsInfrastructure = answers.database !== 'None' || answers.caching === 'Redis' || answers.communication === 'Kafka';
|
|
58
|
+
|
|
59
|
+
if (needsInfrastructure) {
|
|
60
|
+
let servicesToStart = '';
|
|
61
|
+
if (answers.database !== 'None') servicesToStart += ' db';
|
|
62
|
+
if (answers.caching === 'Redis') servicesToStart += ' redis';
|
|
63
|
+
if (answers.communication === 'Kafka') servicesToStart += ' zookeeper kafka';
|
|
64
|
+
|
|
65
|
+
manualStartInstructions += `\n docker-compose up -d${servicesToStart} # Start infrastructure first\n npm run dev`;
|
|
66
|
+
} else {
|
|
67
|
+
manualStartInstructions += `\n npm run dev`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(chalk.cyan(`\nNext steps:\n cd ${answers.projectName}\n npm install\n docker-compose up\n-----------------------${manualStartInstructions}`));
|
|
55
71
|
|
|
56
72
|
} catch (error) {
|
|
57
73
|
console.error(chalk.red('Error generating project:'), error);
|
package/lib/generator.js
CHANGED
|
@@ -58,7 +58,7 @@ export const generateProject = async (config) => {
|
|
|
58
58
|
await setupSrcViews(templatesDir, targetDir, config);
|
|
59
59
|
|
|
60
60
|
// 12. Swagger Config
|
|
61
|
-
await renderSwaggerConfig(targetDir, config);
|
|
61
|
+
await renderSwaggerConfig(templatesDir, targetDir, config);
|
|
62
62
|
|
|
63
63
|
// 13. Professional Config & Tests
|
|
64
64
|
await renderProfessionalConfig(templatesDir, targetDir, language);
|
package/lib/modules/app-setup.js
CHANGED
|
@@ -63,24 +63,34 @@ export const renderDynamicComponents = async (templatePath, targetDir, config) =
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
export const renderSwaggerConfig = async (targetDir, config) => {
|
|
67
|
-
const { communication } = config;
|
|
66
|
+
export const renderSwaggerConfig = async (templatesDir, targetDir, config) => {
|
|
67
|
+
const { communication, projectName, architecture, language } = config;
|
|
68
68
|
|
|
69
|
-
// Check for Swagger config template (typically in src/config/swagger.ts.ejs)
|
|
70
|
-
// This path is common for both MVC and Clean Arch TS templates based on current structure
|
|
71
69
|
// Check for Swagger config template (typically in src/config/swagger.ts.ejs)
|
|
72
70
|
const swaggerTsTemplate = path.join(targetDir, 'src', 'config', 'swagger.ts.ejs');
|
|
73
71
|
|
|
74
72
|
// Ensure config directory exists
|
|
75
|
-
|
|
73
|
+
let configDir = path.join(targetDir, 'src', 'config');
|
|
74
|
+
if (architecture === 'Clean Architecture' && language === 'JavaScript') {
|
|
75
|
+
configDir = path.join(targetDir, 'src', 'infrastructure', 'webserver');
|
|
76
|
+
}
|
|
77
|
+
await fs.ensureDir(configDir);
|
|
76
78
|
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
if (
|
|
79
|
+
if (communication === 'REST APIs') {
|
|
80
|
+
const swaggerYmlTemplateSource = path.join(templatesDir, 'common', 'swagger.yml.ejs');
|
|
81
|
+
if (await fs.pathExists(swaggerYmlTemplateSource)) {
|
|
82
|
+
const ymlContent = ejs.render(await fs.readFile(swaggerYmlTemplateSource, 'utf-8'), { projectName });
|
|
83
|
+
await fs.writeFile(path.join(configDir, 'swagger.yml'), ymlContent);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (await fs.pathExists(swaggerTsTemplate)) {
|
|
80
87
|
const content = ejs.render(await fs.readFile(swaggerTsTemplate, 'utf-8'), { communication });
|
|
81
88
|
await fs.writeFile(path.join(targetDir, 'src', 'config', 'swagger.ts'), content);
|
|
82
89
|
}
|
|
83
|
-
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Always remove the template after processing or if not needed
|
|
93
|
+
if (await fs.pathExists(swaggerTsTemplate)) {
|
|
84
94
|
await fs.remove(swaggerTsTemplate);
|
|
85
95
|
}
|
|
86
96
|
};
|
package/package.json
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const YAML = require('yamljs');
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
definition: {
|
|
5
|
-
openapi: '3.0.0',
|
|
6
|
-
info: {
|
|
7
|
-
title: 'NodeJS API Service',
|
|
8
|
-
version: '1.0.0',
|
|
9
|
-
description: 'API documentation for the NodeJS Service',
|
|
10
|
-
},
|
|
11
|
-
servers: [
|
|
12
|
-
{
|
|
13
|
-
url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
|
|
14
|
-
description: 'Server',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
apis: ['./src/interfaces/routes/*.js'], // Path to the API docs
|
|
19
|
-
};
|
|
4
|
+
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
20
5
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
module.exports = specs;
|
|
6
|
+
module.exports = swaggerDocument;
|
|
@@ -2,75 +2,8 @@ const express = require('express');
|
|
|
2
2
|
const router = express.Router();
|
|
3
3
|
const UserController = require('../controllers/userController');
|
|
4
4
|
|
|
5
|
-
// Should inject dependencies here in a real app
|
|
6
5
|
const userController = new UserController();
|
|
7
6
|
|
|
8
|
-
/**
|
|
9
|
-
* @swagger
|
|
10
|
-
* components:
|
|
11
|
-
* schemas:
|
|
12
|
-
* User:
|
|
13
|
-
* type: object
|
|
14
|
-
* required:
|
|
15
|
-
* - name
|
|
16
|
-
* - email
|
|
17
|
-
* properties:
|
|
18
|
-
* id:
|
|
19
|
-
* type: integer
|
|
20
|
-
* description: The auto-generated id of the user
|
|
21
|
-
* name:
|
|
22
|
-
* type: string
|
|
23
|
-
* description: The name of the user
|
|
24
|
-
* email:
|
|
25
|
-
* type: string
|
|
26
|
-
* description: The email of the user
|
|
27
|
-
* example:
|
|
28
|
-
* id: 1
|
|
29
|
-
* name: John Doe
|
|
30
|
-
* email: john@example.com
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @swagger
|
|
35
|
-
* tags:
|
|
36
|
-
* name: Users
|
|
37
|
-
* description: The users managing API
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @swagger
|
|
42
|
-
* /api/users:
|
|
43
|
-
* get:
|
|
44
|
-
* summary: Returns the list of all the users
|
|
45
|
-
* tags: [Users]
|
|
46
|
-
* responses:
|
|
47
|
-
* 200:
|
|
48
|
-
* description: The list of the users
|
|
49
|
-
* content:
|
|
50
|
-
* application/json:
|
|
51
|
-
* schema:
|
|
52
|
-
* type: array
|
|
53
|
-
* items:
|
|
54
|
-
* $ref: '#/components/schemas/User'
|
|
55
|
-
* post:
|
|
56
|
-
* summary: Create a new user
|
|
57
|
-
* tags: [Users]
|
|
58
|
-
* requestBody:
|
|
59
|
-
* required: true
|
|
60
|
-
* content:
|
|
61
|
-
* application/json:
|
|
62
|
-
* schema:
|
|
63
|
-
* $ref: '#/components/schemas/User'
|
|
64
|
-
* responses:
|
|
65
|
-
* 201:
|
|
66
|
-
* description: The created user.
|
|
67
|
-
* content:
|
|
68
|
-
* application/json:
|
|
69
|
-
* schema:
|
|
70
|
-
* $ref: '#/components/schemas/User'
|
|
71
|
-
* 500:
|
|
72
|
-
* description: Some server error
|
|
73
|
-
*/
|
|
74
7
|
router.post('/users', (req, res) => userController.createUser(req, res));
|
|
75
8
|
router.get('/users', (req, res) => userController.getUsers(req, res));
|
|
76
9
|
|
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
<% if (communication === 'REST APIs') { %>import
|
|
1
|
+
<% if (communication === 'REST APIs') { %>import path from 'path';
|
|
2
|
+
import YAML from 'yamljs';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
definition: {
|
|
5
|
-
openapi: '3.0.0',
|
|
6
|
-
info: {
|
|
7
|
-
title: 'NodeJS API Service',
|
|
8
|
-
version: '1.0.0',
|
|
9
|
-
description: 'API documentation for the NodeJS Service',
|
|
10
|
-
},
|
|
11
|
-
servers: [
|
|
12
|
-
{
|
|
13
|
-
url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
|
|
14
|
-
description: 'Server',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
apis: ['./src/interfaces/routes/*.ts', './dist/interfaces/routes/*.js'], // Path to the API docs
|
|
19
|
-
};
|
|
4
|
+
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
20
5
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export default specs;<% } %>
|
|
6
|
+
export default swaggerDocument;<% } %>
|
|
@@ -4,72 +4,6 @@ import { UserController } from '@/interfaces/controllers/userController';
|
|
|
4
4
|
const router = Router();
|
|
5
5
|
const userController = new UserController();
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @swagger
|
|
9
|
-
* components:
|
|
10
|
-
* schemas:
|
|
11
|
-
* User:
|
|
12
|
-
* type: object
|
|
13
|
-
* required:
|
|
14
|
-
* - name
|
|
15
|
-
* - email
|
|
16
|
-
* properties:
|
|
17
|
-
* id:
|
|
18
|
-
* type: integer
|
|
19
|
-
* description: The auto-generated id of the user
|
|
20
|
-
* name:
|
|
21
|
-
* type: string
|
|
22
|
-
* description: The name of the user
|
|
23
|
-
* email:
|
|
24
|
-
* type: string
|
|
25
|
-
* description: The email of the user
|
|
26
|
-
* example:
|
|
27
|
-
* id: 1
|
|
28
|
-
* name: John Doe
|
|
29
|
-
* email: john@example.com
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @swagger
|
|
34
|
-
* tags:
|
|
35
|
-
* name: Users
|
|
36
|
-
* description: The users managing API
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @swagger
|
|
41
|
-
* /api/users:
|
|
42
|
-
* get:
|
|
43
|
-
* summary: Returns the list of all the users
|
|
44
|
-
* tags: [Users]
|
|
45
|
-
* responses:
|
|
46
|
-
* 200:
|
|
47
|
-
* description: The list of the users
|
|
48
|
-
* content:
|
|
49
|
-
* application/json:
|
|
50
|
-
* schema:
|
|
51
|
-
* type: array
|
|
52
|
-
* items:
|
|
53
|
-
* $ref: '#/components/schemas/User'
|
|
54
|
-
* post:
|
|
55
|
-
* summary: Create a new user
|
|
56
|
-
* tags: [Users]
|
|
57
|
-
* requestBody:
|
|
58
|
-
* required: true
|
|
59
|
-
* content:
|
|
60
|
-
* application/json:
|
|
61
|
-
* schema:
|
|
62
|
-
* $ref: '#/components/schemas/User'
|
|
63
|
-
* responses:
|
|
64
|
-
* 201:
|
|
65
|
-
* description: The created user.
|
|
66
|
-
* content:
|
|
67
|
-
* application/json:
|
|
68
|
-
* schema:
|
|
69
|
-
* $ref: '#/components/schemas/User'
|
|
70
|
-
* 500:
|
|
71
|
-
* description: Some server error
|
|
72
|
-
*/
|
|
73
7
|
router.post('/', (req: Request, res: Response) => userController.createUser(req, res));
|
|
74
8
|
router.get('/', (req: Request, res: Response) => userController.getUsers(req, res));
|
|
75
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# ==========================================
|
|
2
2
|
# Stage 1: Builder
|
|
3
3
|
# ==========================================
|
|
4
|
-
FROM node:
|
|
4
|
+
FROM node:22-alpine AS builder
|
|
5
5
|
|
|
6
6
|
WORKDIR /app
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ COPY . .
|
|
|
19
19
|
# ==========================================
|
|
20
20
|
# Stage 2: Production
|
|
21
21
|
# ==========================================
|
|
22
|
-
FROM node:
|
|
22
|
+
FROM node:22-alpine AS production
|
|
23
23
|
|
|
24
24
|
WORKDIR /app
|
|
25
25
|
|
|
@@ -111,13 +111,50 @@ This project uses **Winston** for structured logging.
|
|
|
111
111
|
## 🐳 Docker Deployment
|
|
112
112
|
This project uses a **Multi-Stage Dockerfile** for optimized production images.
|
|
113
113
|
|
|
114
|
+
<% if (database !== 'None' || caching === 'Redis' || communication === 'Kafka') { -%>
|
|
115
|
+
### 1. Running Locally (Development)
|
|
116
|
+
To run the Node.js application locally while using Docker for the infrastructure (Database, Redis, Kafka, etc.):
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Start infrastructure
|
|
120
|
+
docker-compose up -d<% if (database !== 'None') { %> db<% } %><% if (caching === 'Redis') { %> redis<% } %><% if (communication === 'Kafka') { %> zookeeper kafka<% } %>
|
|
121
|
+
|
|
122
|
+
# Start the application
|
|
123
|
+
npm run dev
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 2. Running the App Container with Compose Infrastructure
|
|
127
|
+
If you want to run the application itself inside a Docker container while connecting to the infrastructure managed by your `docker-compose.yml`:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# First, ensure your infrastructure is running
|
|
131
|
+
docker-compose up -d
|
|
132
|
+
|
|
133
|
+
# Build Production Image
|
|
134
|
+
docker build -t <%= projectName %> .
|
|
135
|
+
|
|
136
|
+
# Run Container (attached to the compose network)
|
|
137
|
+
docker run -p 3000:3000 --network <%= projectName %>_default \
|
|
138
|
+
<% if (database !== 'None') { -%>
|
|
139
|
+
-e DB_HOST=db \
|
|
140
|
+
<% } -%>
|
|
141
|
+
<% if (caching === 'Redis') { -%>
|
|
142
|
+
-e REDIS_HOST=redis \
|
|
143
|
+
<% } -%>
|
|
144
|
+
<% if (communication === 'Kafka') { -%>
|
|
145
|
+
-e KAFKA_BROKER=kafka:29092 \
|
|
146
|
+
<% } -%>
|
|
147
|
+
<%= projectName %>
|
|
148
|
+
```
|
|
149
|
+
<% } else { -%>
|
|
114
150
|
```bash
|
|
115
151
|
# Build Production Image
|
|
116
152
|
docker build -t <%= projectName %> .
|
|
117
153
|
|
|
118
154
|
# Run Container
|
|
119
|
-
docker run -p 3000:3000
|
|
155
|
+
docker run -p 3000:3000 <%= projectName %>
|
|
120
156
|
```
|
|
157
|
+
<% } -%>
|
|
121
158
|
|
|
122
159
|
## 🔒 Security Features
|
|
123
160
|
- **Helmet**: Sets secure HTTP headers.
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
const { Sequelize } = require('sequelize');
|
|
2
2
|
require('dotenv').config();
|
|
3
3
|
|
|
4
|
-
// Determine dialect
|
|
5
4
|
<% if (database === 'MySQL') { %>const dialect = 'mysql';<% } -%>
|
|
6
5
|
<% if (database === 'PostgreSQL') { %>const dialect = 'postgres';<% } -%>
|
|
7
6
|
|
|
8
7
|
const sequelize = new Sequelize(
|
|
9
8
|
process.env.DB_NAME || '<%= dbName %>',
|
|
10
9
|
process.env.DB_USER || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
|
|
11
|
-
process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>
|
|
10
|
+
process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>root<% } %>',
|
|
12
11
|
{
|
|
13
12
|
host: process.env.DB_HOST || '127.0.0.1',
|
|
14
13
|
dialect: dialect,
|
|
@@ -3,14 +3,13 @@ import dotenv from 'dotenv';
|
|
|
3
3
|
|
|
4
4
|
dotenv.config();
|
|
5
5
|
|
|
6
|
-
// Determine dialect
|
|
7
6
|
<% if (database === 'MySQL') { %>const dialect = 'mysql';<% } -%>
|
|
8
7
|
<% if (database === 'PostgreSQL') { %>const dialect = 'postgres';<% } -%>
|
|
9
8
|
|
|
10
9
|
const sequelize = new Sequelize(
|
|
11
10
|
process.env.DB_NAME || '<%= dbName %>',
|
|
12
11
|
process.env.DB_USER || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
|
|
13
|
-
process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>
|
|
12
|
+
process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>root<% } %>',
|
|
14
13
|
{
|
|
15
14
|
host: process.env.DB_HOST || '127.0.0.1',
|
|
16
15
|
dialect: dialect,
|
|
@@ -6,7 +6,7 @@
|
|
|
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') { %> && cpx \"src/views/**/*\" dist/views<% } %>"<% } %>,
|
|
9
|
+
"build": "rimraf dist && tsc && tsc-alias<% if (viewEngine && viewEngine !== 'None') { %> && cpx \"src/views/**/*\" dist/views<% } %><% if (communication === 'REST APIs') { %> && cpx \"src/**/*.yml\" dist/<% } %>"<% } %>,
|
|
10
10
|
"lint": "eslint .",
|
|
11
11
|
"lint:fix": "eslint . --fix",
|
|
12
12
|
"format": "prettier --write .",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"winston-daily-rotate-file": "^5.0.0",
|
|
49
49
|
"morgan": "^1.10.0"<% if (communication === 'REST APIs') { %>,
|
|
50
50
|
"swagger-ui-express": "^5.0.0",
|
|
51
|
-
"
|
|
51
|
+
"yamljs": "^0.3.0"<% } %>
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"nodemon": "^3.0.2"<% if (language === 'TypeScript') { %>,
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@types/sequelize": "^4.28.19",
|
|
69
69
|
<%_ } -%>
|
|
70
70
|
"@types/morgan": "^1.9.9",
|
|
71
|
-
"rimraf": "^6.0.1"<% if (viewEngine && viewEngine !== 'None') { %>,
|
|
71
|
+
"rimraf": "^6.0.1"<% if ((viewEngine && viewEngine !== 'None') || communication === 'REST APIs') { %>,
|
|
72
72
|
"cpx2": "^8.0.0"<% } %><% } %>,
|
|
73
73
|
"eslint": "^9.20.1",
|
|
74
74
|
"@eslint/js": "^9.20.0",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"lint-staged": "^15.4.3"<% if (language === 'TypeScript') { %>,
|
|
80
80
|
"typescript-eslint": "^8.24.1",
|
|
81
81
|
<% if (communication === 'REST APIs') { %> "@types/swagger-ui-express": "^4.1.6",
|
|
82
|
-
"@types/
|
|
82
|
+
"@types/yamljs": "^0.2.34",<% } %>
|
|
83
83
|
"jest": "^29.7.0",
|
|
84
84
|
"ts-jest": "^29.2.5",
|
|
85
85
|
"@types/jest": "^29.5.14",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
openapi: 3.0.0
|
|
2
|
+
info:
|
|
3
|
+
title: <%= projectName %> API
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: API documentation for <%= projectName %>
|
|
6
|
+
servers:
|
|
7
|
+
- url: http://localhost:3000
|
|
8
|
+
description: Local Server
|
|
9
|
+
components:
|
|
10
|
+
schemas:
|
|
11
|
+
User:
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- name
|
|
15
|
+
- email
|
|
16
|
+
properties:
|
|
17
|
+
id:
|
|
18
|
+
type: integer
|
|
19
|
+
description: The auto-generated id of the user
|
|
20
|
+
name:
|
|
21
|
+
type: string
|
|
22
|
+
description: The name of the user
|
|
23
|
+
email:
|
|
24
|
+
type: string
|
|
25
|
+
description: The email of the user
|
|
26
|
+
example:
|
|
27
|
+
id: 1
|
|
28
|
+
name: John Doe
|
|
29
|
+
email: john@example.com
|
|
30
|
+
tags:
|
|
31
|
+
- name: Users
|
|
32
|
+
description: The users managing API
|
|
33
|
+
paths:
|
|
34
|
+
/api/users:
|
|
35
|
+
get:
|
|
36
|
+
summary: Returns the list of all the users
|
|
37
|
+
tags:
|
|
38
|
+
- Users
|
|
39
|
+
responses:
|
|
40
|
+
'200':
|
|
41
|
+
description: The list of the users
|
|
42
|
+
content:
|
|
43
|
+
application/json:
|
|
44
|
+
schema:
|
|
45
|
+
type: array
|
|
46
|
+
items:
|
|
47
|
+
$ref: '#/components/schemas/User'
|
|
48
|
+
post:
|
|
49
|
+
summary: Create a new user
|
|
50
|
+
tags:
|
|
51
|
+
- Users
|
|
52
|
+
requestBody:
|
|
53
|
+
required: true
|
|
54
|
+
content:
|
|
55
|
+
application/json:
|
|
56
|
+
schema:
|
|
57
|
+
$ref: '#/components/schemas/User'
|
|
58
|
+
responses:
|
|
59
|
+
'201':
|
|
60
|
+
description: The created user.
|
|
61
|
+
content:
|
|
62
|
+
application/json:
|
|
63
|
+
schema:
|
|
64
|
+
$ref: '#/components/schemas/User'
|
|
65
|
+
'500':
|
|
66
|
+
description: Some server error
|
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const YAML = require('yamljs');
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
definition: {
|
|
5
|
-
openapi: '3.0.0',
|
|
6
|
-
info: {
|
|
7
|
-
title: 'NodeJS API Service',
|
|
8
|
-
version: '1.0.0',
|
|
9
|
-
description: 'API documentation for the NodeJS Service',
|
|
10
|
-
},
|
|
11
|
-
servers: [
|
|
12
|
-
{
|
|
13
|
-
url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
|
|
14
|
-
description: 'Server',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
apis: ['./src/routes/*.js'], // Path to the API docs
|
|
19
|
-
};
|
|
4
|
+
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
20
5
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
module.exports = specs;
|
|
6
|
+
module.exports = swaggerDocument;
|
|
@@ -2,72 +2,6 @@ const express = require('express');
|
|
|
2
2
|
const router = express.Router();
|
|
3
3
|
const userController = require('../controllers/userController');
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @swagger
|
|
7
|
-
* components:
|
|
8
|
-
* schemas:
|
|
9
|
-
* User:
|
|
10
|
-
* type: object
|
|
11
|
-
* required:
|
|
12
|
-
* - name
|
|
13
|
-
* - email
|
|
14
|
-
* properties:
|
|
15
|
-
* id:
|
|
16
|
-
* type: integer
|
|
17
|
-
* description: The auto-generated id of the user
|
|
18
|
-
* name:
|
|
19
|
-
* type: string
|
|
20
|
-
* description: The name of the user
|
|
21
|
-
* email:
|
|
22
|
-
* type: string
|
|
23
|
-
* description: The email of the user
|
|
24
|
-
* example:
|
|
25
|
-
* id: 1
|
|
26
|
-
* name: John Doe
|
|
27
|
-
* email: john@example.com
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @swagger
|
|
32
|
-
* tags:
|
|
33
|
-
* name: Users
|
|
34
|
-
* description: The users managing API
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @swagger
|
|
39
|
-
* /api/users:
|
|
40
|
-
* get:
|
|
41
|
-
* summary: Returns the list of all the users
|
|
42
|
-
* tags: [Users]
|
|
43
|
-
* responses:
|
|
44
|
-
* 200:
|
|
45
|
-
* description: The list of the users
|
|
46
|
-
* content:
|
|
47
|
-
* application/json:
|
|
48
|
-
* schema:
|
|
49
|
-
* type: array
|
|
50
|
-
* items:
|
|
51
|
-
* $ref: '#/components/schemas/User'
|
|
52
|
-
* post:
|
|
53
|
-
* summary: Create a new user
|
|
54
|
-
* tags: [Users]
|
|
55
|
-
* requestBody:
|
|
56
|
-
* required: true
|
|
57
|
-
* content:
|
|
58
|
-
* application/json:
|
|
59
|
-
* schema:
|
|
60
|
-
* $ref: '#/components/schemas/User'
|
|
61
|
-
* responses:
|
|
62
|
-
* 201:
|
|
63
|
-
* description: The created user.
|
|
64
|
-
* content:
|
|
65
|
-
* application/json:
|
|
66
|
-
* schema:
|
|
67
|
-
* $ref: '#/components/schemas/User'
|
|
68
|
-
* 500:
|
|
69
|
-
* description: Some server error
|
|
70
|
-
*/
|
|
71
5
|
router.get('/users', userController.getUsers);
|
|
72
6
|
router.post('/users', userController.createUser);
|
|
73
7
|
|
|
@@ -1,23 +1,6 @@
|
|
|
1
|
-
<% if (communication === 'REST APIs') { %>import
|
|
1
|
+
<% if (communication === 'REST APIs') { %>import path from 'path';
|
|
2
|
+
import YAML from 'yamljs';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
definition: {
|
|
5
|
-
openapi: '3.0.0',
|
|
6
|
-
info: {
|
|
7
|
-
title: 'NodeJS API Service',
|
|
8
|
-
version: '1.0.0',
|
|
9
|
-
description: 'API documentation for the NodeJS Service',
|
|
10
|
-
},
|
|
11
|
-
servers: [
|
|
12
|
-
{
|
|
13
|
-
url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
|
|
14
|
-
description: 'Server',
|
|
15
|
-
},
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
apis: ['./src/routes/*.ts', './dist/routes/*.js'], // Path to the API docs
|
|
19
|
-
};
|
|
4
|
+
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
20
5
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export default specs;<% } %>
|
|
6
|
+
export default swaggerDocument;<% } %>
|
|
@@ -4,72 +4,6 @@ import { UserController } from '@/controllers/userController';
|
|
|
4
4
|
const router = Router();
|
|
5
5
|
const userController = new UserController();
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @swagger
|
|
9
|
-
* components:
|
|
10
|
-
* schemas:
|
|
11
|
-
* User:
|
|
12
|
-
* type: object
|
|
13
|
-
* required:
|
|
14
|
-
* - name
|
|
15
|
-
* - email
|
|
16
|
-
* properties:
|
|
17
|
-
* id:
|
|
18
|
-
* type: integer
|
|
19
|
-
* description: The auto-generated id of the user
|
|
20
|
-
* name:
|
|
21
|
-
* type: string
|
|
22
|
-
* description: The name of the user
|
|
23
|
-
* email:
|
|
24
|
-
* type: string
|
|
25
|
-
* description: The email of the user
|
|
26
|
-
* example:
|
|
27
|
-
* id: 1
|
|
28
|
-
* name: John Doe
|
|
29
|
-
* email: john@example.com
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @swagger
|
|
34
|
-
* tags:
|
|
35
|
-
* name: Users
|
|
36
|
-
* description: The users managing API
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @swagger
|
|
41
|
-
* /api/users:
|
|
42
|
-
* get:
|
|
43
|
-
* summary: Returns the list of all the users
|
|
44
|
-
* tags: [Users]
|
|
45
|
-
* responses:
|
|
46
|
-
* 200:
|
|
47
|
-
* description: The list of the users
|
|
48
|
-
* content:
|
|
49
|
-
* application/json:
|
|
50
|
-
* schema:
|
|
51
|
-
* type: array
|
|
52
|
-
* items:
|
|
53
|
-
* $ref: '#/components/schemas/User'
|
|
54
|
-
* post:
|
|
55
|
-
* summary: Create a new user
|
|
56
|
-
* tags: [Users]
|
|
57
|
-
* requestBody:
|
|
58
|
-
* required: true
|
|
59
|
-
* content:
|
|
60
|
-
* application/json:
|
|
61
|
-
* schema:
|
|
62
|
-
* $ref: '#/components/schemas/User'
|
|
63
|
-
* responses:
|
|
64
|
-
* 201:
|
|
65
|
-
* description: The created user.
|
|
66
|
-
* content:
|
|
67
|
-
* application/json:
|
|
68
|
-
* schema:
|
|
69
|
-
* $ref: '#/components/schemas/User'
|
|
70
|
-
* 500:
|
|
71
|
-
* description: Some server error
|
|
72
|
-
*/
|
|
73
7
|
router.get('/users', (req: Request, res: Response) => userController.getUsers(req, res));
|
|
74
8
|
router.post('/users', (req: Request, res: Response) => userController.createUser(req, res));
|
|
75
9
|
|