clwy-express-generator 5.1.4 → 5.2.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/README.md +125 -25
- package/bin/express-cli.js +106 -58
- package/package.json +4 -8
- package/templates/docker-compose.yml +26 -0
- package/templates/env.ejs +7 -0
- package/templates/prisma/prisma/schema.prisma +18 -0
- package/templates/prisma/prisma.config.js +13 -0
- package/templates/sequelize/config/config.json +27 -0
- package/templates/sequelize/models/js/index.js +42 -0
- package/templates/sequelize/models/mjs/index.js +47 -0
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
- **🚀 ES6 支持**:代码更现代简洁。
|
|
12
12
|
- **🔀 路由拆分**:独立文件,便于管理维护。
|
|
13
|
+
- **🗄️ ORM 支持**:支持 Prisma 或 Sequelize ORM。
|
|
13
14
|
- **📁 中间件模块化**:新增文件夹存放中间件。
|
|
14
15
|
- **🔧 增加环境变量配置**:多环境管理更便捷。
|
|
15
16
|
- **🔄 集成 nodemon**:开发时自动重启服务。
|
|
@@ -19,12 +20,15 @@
|
|
|
19
20
|
|
|
20
21
|
## 快速开始
|
|
21
22
|
|
|
23
|
+
### 基础使用
|
|
24
|
+
|
|
22
25
|
使用express最快的方式是利用可执行文件`express(1)`来生成一个应用,如下所示:
|
|
23
26
|
|
|
24
27
|
创建应用:
|
|
25
28
|
|
|
26
29
|
```bash
|
|
27
|
-
$ npx clwy-express-generator --view=ejs --es6 es6-demo
|
|
30
|
+
$ npx clwy-express-generator --view=ejs --es6 es6-demo
|
|
31
|
+
$ cd es6-demo
|
|
28
32
|
```
|
|
29
33
|
|
|
30
34
|
安装依赖:
|
|
@@ -39,6 +43,51 @@ $ npm install
|
|
|
39
43
|
$ npm start
|
|
40
44
|
```
|
|
41
45
|
|
|
46
|
+
## 使用 ORM
|
|
47
|
+
|
|
48
|
+
### 使用数据库
|
|
49
|
+
|
|
50
|
+
安装好 Docker 并启动后:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
$ docker-compose up -d
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
默认将启动 MySQL 数据库,PostgreSQL 和 Redis 配置已在 `docker-compose.yml` 中,请根据需求调整。
|
|
57
|
+
|
|
58
|
+
### 使用 Prisma
|
|
59
|
+
|
|
60
|
+
创建应用:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
$ npx clwy-express-generator --view=ejs --orm=prisma --es6 es6-prisma-demo
|
|
64
|
+
$ cd es6-prisma-demo
|
|
65
|
+
$ npm i
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
初始化数据库客户端:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
$ npx prisma generate
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 使用 Sequelize
|
|
75
|
+
|
|
76
|
+
创建应用:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
$ npx clwy-express-generator --view=ejs --orm=sequelize --es6 es6-sequelize-demo
|
|
80
|
+
$ cd es6-sequelize-demo
|
|
81
|
+
$ npm i
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
根据需求安装数据库引擎:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
$ npm install --save mysql2 # MySQL
|
|
88
|
+
$ npm install --save pg pg-hstore # Postgres
|
|
89
|
+
```
|
|
90
|
+
|
|
42
91
|
## 命令行选项
|
|
43
92
|
|
|
44
93
|
此生成器还可以通过以下命令行标志进行进一步配置。
|
|
@@ -46,6 +95,7 @@ $ npm start
|
|
|
46
95
|
--version 输出版本号
|
|
47
96
|
-v, --view <engine> 添加视图引擎 <engine> 支持 (dust|ejs|hbs|hjs|pug|twig|vash|api)(默认为 ejs)
|
|
48
97
|
--no-view 使用静态html而不是视图引擎
|
|
98
|
+
-o, --orm <orm> 添加 ORM <orm> 支持 (prisma|sequelize)
|
|
49
99
|
-c, --css <engine> 添加样式表引擎 <engine> 支持 (less|stylus|compass|sass)(默认为纯 css)
|
|
50
100
|
--git 添加 .gitignore 文件
|
|
51
101
|
--es6 生成 ES6 代码和模块类型项目(需要Node 22.x或更高版本)
|
|
@@ -54,31 +104,35 @@ $ npm start
|
|
|
54
104
|
|
|
55
105
|
------------
|
|
56
106
|
|
|
57
|
-
# clwy-express-generator: [Express
|
|
107
|
+
# clwy-express-generator: [Express](https://www.npmjs.com/package/express) Application Generator
|
|
58
108
|
|
|
59
|
-
**This project is
|
|
109
|
+
**This project is forked from [express-generator](https://github.com/expressjs/generator) with additional features.**
|
|
60
110
|
|
|
61
|
-
**
|
|
111
|
+
**ES6 support is implemented based on the [Pull Request](https://github.com/expressjs/generator/pull/316) submitted by [Dr. Jeff Jackson](https://github.com/drjeffjackson), with further optimizations and adjustments.**
|
|
62
112
|
|
|
63
113
|
## Features
|
|
64
114
|
|
|
65
|
-
- **🚀 ES6 Support**:
|
|
66
|
-
- **🔀
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
115
|
+
- **🚀 ES6 Support**: More modern and concise code.
|
|
116
|
+
- **🔀 Route Splitting**: Independent files for easier management and maintenance.
|
|
117
|
+
- **🗄️ ORM Support**: Supports Prisma or Sequelize ORM.
|
|
118
|
+
- **📁 Modular Middleware**: New folder for storing middleware.
|
|
119
|
+
- **🔧 Enhanced Environment Variable Configuration**: More convenient multi-environment management.
|
|
120
|
+
- **🔄 Integrated Nodemon**: Automatic service restart during development.
|
|
121
|
+
- **🌐 Integrated CORS**: Allows cross-origin requests.
|
|
122
|
+
- **📄 Added README.md**: Contains project introduction and basic feature descriptions.
|
|
123
|
+
- **📦 Built-in Configuration**: Includes `.prettierrc` (code formatting) and `.gitignore` (file ignore) by default.
|
|
73
124
|
|
|
74
125
|
## Quick Start
|
|
75
126
|
|
|
76
|
-
|
|
127
|
+
### Basic Usage
|
|
77
128
|
|
|
78
|
-
|
|
129
|
+
The fastest way to create an Express application is by using the executable `express(1)` to generate an app, as shown below:
|
|
130
|
+
|
|
131
|
+
Create the application:
|
|
79
132
|
|
|
80
133
|
```bash
|
|
81
|
-
$ npx clwy-express-generator --view=ejs --es6 es6-demo
|
|
134
|
+
$ npx clwy-express-generator --view=ejs --es6 es6-demo
|
|
135
|
+
$ cd es6-demo
|
|
82
136
|
```
|
|
83
137
|
|
|
84
138
|
Install dependencies:
|
|
@@ -93,18 +147,64 @@ Start your Express.js app at `http://localhost:3000/`:
|
|
|
93
147
|
$ npm start
|
|
94
148
|
```
|
|
95
149
|
|
|
96
|
-
##
|
|
150
|
+
## Using ORM
|
|
151
|
+
|
|
152
|
+
### Using a Database
|
|
153
|
+
|
|
154
|
+
After installing and starting Docker:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
$ docker-compose up -d
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This will start a MySQL database by default. PostgreSQL and Redis configurations are already in `docker-compose.yml`; adjust them according to your needs.
|
|
161
|
+
|
|
162
|
+
### Using Prisma
|
|
163
|
+
|
|
164
|
+
Create the application:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
$ npx clwy-express-generator --view=ejs --orm=prisma --es6 es6-prisma-demo
|
|
168
|
+
$ cd es6-prisma-demo
|
|
169
|
+
$ npm i
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Initialize the database client:
|
|
97
173
|
|
|
98
|
-
|
|
174
|
+
```bash
|
|
175
|
+
$ npx prisma generate
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Using Sequelize
|
|
179
|
+
|
|
180
|
+
Create the application:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
$ npx clwy-express-generator --view=ejs --orm=sequelize --es6 es6-sequelize-demo
|
|
184
|
+
$ cd es6-sequelize-demo
|
|
185
|
+
$ npm i
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Install the database engine as needed:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
$ npm install --save mysql2 # MySQL
|
|
192
|
+
$ npm install --save pg pg-hstore # Postgres
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Command Line Options
|
|
99
196
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
--
|
|
103
|
-
-
|
|
104
|
-
--
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
|
|
197
|
+
This generator can be further configured with the following command line flags.
|
|
198
|
+
|
|
199
|
+
--version Output the version number
|
|
200
|
+
-v, --view <engine> Add view engine <engine> support (dust|ejs|hbs|hjs|pug|twig|vash|api) (defaults to ejs)
|
|
201
|
+
--no-view Use static HTML instead of a view engine
|
|
202
|
+
-o, --orm <orm> Add ORM <orm> support (prisma|sequelize)
|
|
203
|
+
-c, --css <engine> Add stylesheet engine <engine> support (less|stylus|compass|sass) (defaults to plain css)
|
|
204
|
+
--git Add .gitignore file
|
|
205
|
+
--es6 Generate ES6 code and module type project (requires Node 22.x or higher)
|
|
206
|
+
-f, --force Force operation on non-empty directory
|
|
207
|
+
-h, --help Output usage information
|
|
108
208
|
|
|
109
209
|
------------
|
|
110
210
|
|
package/bin/express-cli.js
CHANGED
|
@@ -14,7 +14,7 @@ const MODE_0666 = parseInt('0666', 8)
|
|
|
14
14
|
const MODE_0755 = parseInt('0755', 8)
|
|
15
15
|
const TEMPLATE_DIR = path.join(__dirname, '..', 'templates')
|
|
16
16
|
const VERSION = require('../package').version
|
|
17
|
-
const MIN_ES6_VERSION =
|
|
17
|
+
const MIN_ES6_VERSION = 22
|
|
18
18
|
|
|
19
19
|
// parse args
|
|
20
20
|
const unknown = []
|
|
@@ -25,16 +25,17 @@ const args = parseArgs(process.argv.slice(2), {
|
|
|
25
25
|
f: 'force',
|
|
26
26
|
h: 'help',
|
|
27
27
|
H: 'hogan',
|
|
28
|
-
v: 'view'
|
|
28
|
+
v: 'view',
|
|
29
|
+
o: 'orm',
|
|
29
30
|
},
|
|
30
31
|
boolean: ['ejs', 'es6', 'force', 'git', 'hbs', 'help', 'hogan', 'pug', 'version'],
|
|
31
|
-
default: { css: true, view: true },
|
|
32
|
+
default: { css: true, view: true, orm: false },
|
|
32
33
|
string: ['css', 'view'],
|
|
33
34
|
unknown: function (s) {
|
|
34
35
|
if (s.charAt(0) === '-') {
|
|
35
36
|
unknown.push(s)
|
|
36
37
|
}
|
|
37
|
-
}
|
|
38
|
+
},
|
|
38
39
|
})
|
|
39
40
|
|
|
40
41
|
args['!'] = unknown
|
|
@@ -46,10 +47,10 @@ main(args, exit)
|
|
|
46
47
|
* Prompt for confirmation on STDOUT/STDIN
|
|
47
48
|
*/
|
|
48
49
|
|
|
49
|
-
function confirm
|
|
50
|
+
function confirm(msg, callback) {
|
|
50
51
|
const rl = readline.createInterface({
|
|
51
52
|
input: process.stdin,
|
|
52
|
-
output: process.stdout
|
|
53
|
+
output: process.stdout,
|
|
53
54
|
})
|
|
54
55
|
|
|
55
56
|
rl.question(msg, function (input) {
|
|
@@ -62,7 +63,7 @@ function confirm (msg, callback) {
|
|
|
62
63
|
* Copy file from template directory.
|
|
63
64
|
*/
|
|
64
65
|
|
|
65
|
-
function copyTemplate
|
|
66
|
+
function copyTemplate(from, to) {
|
|
66
67
|
write(to, fs.readFileSync(path.join(TEMPLATE_DIR, from), 'utf-8'))
|
|
67
68
|
}
|
|
68
69
|
|
|
@@ -70,7 +71,7 @@ function copyTemplate (from, to) {
|
|
|
70
71
|
* Copy multiple files from template directory.
|
|
71
72
|
*/
|
|
72
73
|
|
|
73
|
-
function copyTemplateMulti
|
|
74
|
+
function copyTemplateMulti(fromDir, toDir, nameGlob) {
|
|
74
75
|
fs.readdirSync(path.join(TEMPLATE_DIR, fromDir))
|
|
75
76
|
.filter(minimatch.filter(nameGlob, { matchBase: true }))
|
|
76
77
|
.forEach(function (name) {
|
|
@@ -87,7 +88,7 @@ function copyTemplateMulti (fromDir, toDir, nameGlob) {
|
|
|
87
88
|
* @param {function} done
|
|
88
89
|
*/
|
|
89
90
|
|
|
90
|
-
function createApplication
|
|
91
|
+
function createApplication(name, dir, options, done) {
|
|
91
92
|
console.log()
|
|
92
93
|
|
|
93
94
|
// Package
|
|
@@ -98,18 +99,18 @@ function createApplication (name, dir, options, done) {
|
|
|
98
99
|
type: options.es6 ? 'module' : 'commonjs',
|
|
99
100
|
scripts: {
|
|
100
101
|
start: 'nodemon ./bin/www',
|
|
101
|
-
format: 'prettier --write "**/*.{js,json,md}"'
|
|
102
|
+
format: 'prettier --write "**/*.{js,json,md}"',
|
|
102
103
|
},
|
|
103
104
|
dependencies: {
|
|
104
105
|
cors: '^2.8.5',
|
|
105
|
-
debug: '~4.4.
|
|
106
|
-
dotenv: '^
|
|
107
|
-
express: '~5.1
|
|
106
|
+
debug: '~4.4.3',
|
|
107
|
+
dotenv: '^17.2.3',
|
|
108
|
+
express: '~5.2.1',
|
|
108
109
|
},
|
|
109
110
|
devDependencies: {
|
|
110
|
-
nodemon: '^3.1.
|
|
111
|
-
prettier: '^3.
|
|
112
|
-
}
|
|
111
|
+
nodemon: '^3.1.11',
|
|
112
|
+
prettier: '^3.7.4',
|
|
113
|
+
},
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
// JavaScript
|
|
@@ -127,7 +128,7 @@ function createApplication (name, dir, options, done) {
|
|
|
127
128
|
// Request logger
|
|
128
129
|
app.locals.modules.logger = 'morgan'
|
|
129
130
|
app.locals.uses.push("logger('dev')")
|
|
130
|
-
pkg.dependencies.morgan = '~1.10.
|
|
131
|
+
pkg.dependencies.morgan = '~1.10.1'
|
|
131
132
|
|
|
132
133
|
// Body parsers
|
|
133
134
|
app.locals.uses.push('express.json()')
|
|
@@ -153,6 +154,9 @@ function createApplication (name, dir, options, done) {
|
|
|
153
154
|
mkdir(dir, 'middlewares')
|
|
154
155
|
mkdir(dir, 'utils')
|
|
155
156
|
|
|
157
|
+
// copy docker-compose.yml
|
|
158
|
+
copyTemplate('docker-compose.yml', path.join(dir, 'docker-compose.yml'))
|
|
159
|
+
|
|
156
160
|
// copy css templates
|
|
157
161
|
switch (options.css) {
|
|
158
162
|
case 'less':
|
|
@@ -173,28 +177,27 @@ function createApplication (name, dir, options, done) {
|
|
|
173
177
|
}
|
|
174
178
|
|
|
175
179
|
// copy Prettier templates
|
|
176
|
-
copyTemplate(
|
|
180
|
+
copyTemplate(
|
|
181
|
+
options.es6 ? 'mjs/prettierrc.json' : 'js/prettierrc.json',
|
|
182
|
+
path.join(dir, '.prettierrc.json'),
|
|
183
|
+
)
|
|
177
184
|
|
|
178
185
|
// copy config templates
|
|
179
186
|
mkdir(dir, 'config')
|
|
180
|
-
copyTemplateMulti(
|
|
181
|
-
options.es6 ? 'mjs/config' : 'js/config',
|
|
182
|
-
dir + '/config', '*.js'
|
|
183
|
-
)
|
|
187
|
+
copyTemplateMulti(options.es6 ? 'mjs/config' : 'js/config', dir + '/config', '*.js')
|
|
184
188
|
|
|
185
189
|
// copy route templates
|
|
186
190
|
mkdir(dir, 'routes')
|
|
187
|
-
copyTemplateMulti(
|
|
188
|
-
options.es6 ? 'mjs/routes' : 'js/routes',
|
|
189
|
-
dir + '/routes', '*.js')
|
|
191
|
+
copyTemplateMulti(options.es6 ? 'mjs/routes' : 'js/routes', dir + '/routes', '*.js')
|
|
190
192
|
|
|
191
193
|
if (options.view) {
|
|
192
194
|
// Copy view templates
|
|
193
195
|
mkdir(dir, 'views')
|
|
194
|
-
pkg.dependencies['http-errors'] = '~2.0.
|
|
196
|
+
pkg.dependencies['http-errors'] = '~2.0.1'
|
|
195
197
|
copyTemplateMulti(
|
|
196
198
|
options.es6 ? 'mjs/middlewares' : 'js/middlewares',
|
|
197
|
-
dir + '/middlewares',
|
|
199
|
+
dir + '/middlewares',
|
|
200
|
+
'*.js',
|
|
198
201
|
)
|
|
199
202
|
|
|
200
203
|
switch (options.view) {
|
|
@@ -239,7 +242,9 @@ function createApplication (name, dir, options, done) {
|
|
|
239
242
|
break
|
|
240
243
|
case 'sass':
|
|
241
244
|
app.locals.modules.sassMiddleware = 'node-sass-middleware'
|
|
242
|
-
app.locals.uses.push(
|
|
245
|
+
app.locals.uses.push(
|
|
246
|
+
"sassMiddleware({\n src: path.join(__dirname, 'public'),\n dest: path.join(__dirname, 'public'),\n indentedSyntax: true, // true = .sass and false = .scss\n sourceMap: true\n})",
|
|
247
|
+
)
|
|
243
248
|
pkg.dependencies['node-sass-middleware'] = '~1.1.0'
|
|
244
249
|
break
|
|
245
250
|
case 'stylus':
|
|
@@ -255,7 +260,7 @@ function createApplication (name, dir, options, done) {
|
|
|
255
260
|
app.locals.modules.adaro = 'adaro'
|
|
256
261
|
app.locals.view = {
|
|
257
262
|
engine: 'dust',
|
|
258
|
-
render: 'adaro.dust()'
|
|
263
|
+
render: 'adaro.dust()',
|
|
259
264
|
}
|
|
260
265
|
pkg.dependencies.adaro = '~1.0.4'
|
|
261
266
|
break
|
|
@@ -288,6 +293,34 @@ function createApplication (name, dir, options, done) {
|
|
|
288
293
|
break
|
|
289
294
|
}
|
|
290
295
|
|
|
296
|
+
// ORM
|
|
297
|
+
env.locals.orm = false
|
|
298
|
+
if (options.orm) {
|
|
299
|
+
env.locals.orm = options.orm
|
|
300
|
+
|
|
301
|
+
switch (options.orm) {
|
|
302
|
+
case 'prisma':
|
|
303
|
+
// copy Prisma templates
|
|
304
|
+
pkg.dependencies.prisma = '^7.2.0'
|
|
305
|
+
pkg.dependencies['@prisma/client'] = '^7.2.0'
|
|
306
|
+
|
|
307
|
+
mkdir(dir, 'prisma')
|
|
308
|
+
copyTemplateMulti('prisma', dir, 'prisma.config.js')
|
|
309
|
+
copyTemplateMulti('prisma/prisma', dir + '/prisma', 'schema.prisma')
|
|
310
|
+
break
|
|
311
|
+
case 'sequelize':
|
|
312
|
+
// copy Sequelize templates
|
|
313
|
+
pkg.dependencies.sequelize = '^6.37.7'
|
|
314
|
+
|
|
315
|
+
mkdir(dir, 'migrations')
|
|
316
|
+
mkdir(dir, 'seeders')
|
|
317
|
+
mkdir(dir, 'models')
|
|
318
|
+
copyTemplateMulti(options.es6 ? 'sequelize/models/mjs' : 'sequelize/models/js', dir + '/models', 'index.js')
|
|
319
|
+
copyTemplateMulti('sequelize/config', dir + '/config', 'config.json')
|
|
320
|
+
break
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
291
324
|
// Static files
|
|
292
325
|
app.locals.uses.push("express.static(path.join(__dirname, 'public'))")
|
|
293
326
|
|
|
@@ -338,8 +371,9 @@ function createApplication (name, dir, options, done) {
|
|
|
338
371
|
* @param {String} pathName
|
|
339
372
|
*/
|
|
340
373
|
|
|
341
|
-
function createAppName
|
|
342
|
-
return path
|
|
374
|
+
function createAppName(pathName) {
|
|
375
|
+
return path
|
|
376
|
+
.basename(pathName)
|
|
343
377
|
.replace(/[^A-Za-z0-9.-]+/g, '-')
|
|
344
378
|
.replace(/^[-_.]+|-+$/g, '')
|
|
345
379
|
.toLowerCase()
|
|
@@ -352,7 +386,7 @@ function createAppName (pathName) {
|
|
|
352
386
|
* @param {Function} fn
|
|
353
387
|
*/
|
|
354
388
|
|
|
355
|
-
function emptyDirectory
|
|
389
|
+
function emptyDirectory(dir, fn) {
|
|
356
390
|
fs.readdir(dir, function (err, files) {
|
|
357
391
|
if (err && err.code !== 'ENOENT') throw err
|
|
358
392
|
fn(!files || !files.length)
|
|
@@ -365,7 +399,7 @@ function emptyDirectory (dir, fn) {
|
|
|
365
399
|
* @param {String} message
|
|
366
400
|
*/
|
|
367
401
|
|
|
368
|
-
function error
|
|
402
|
+
function error(message) {
|
|
369
403
|
console.error()
|
|
370
404
|
message.split('\n').forEach(function (line) {
|
|
371
405
|
console.error(' error: %s', line)
|
|
@@ -377,12 +411,12 @@ function error (message) {
|
|
|
377
411
|
* Graceful exit for async STDIO
|
|
378
412
|
*/
|
|
379
413
|
|
|
380
|
-
function exit
|
|
414
|
+
function exit(code) {
|
|
381
415
|
// flush output for Node.js Windows pipe bug
|
|
382
416
|
// https://github.com/joyent/node/issues/6247 is just one bug example
|
|
383
417
|
// https://github.com/visionmedia/mocha/issues/333 has a good discussion
|
|
384
|
-
function done
|
|
385
|
-
if (!
|
|
418
|
+
function done() {
|
|
419
|
+
if (!draining--) process.exit(code)
|
|
386
420
|
}
|
|
387
421
|
|
|
388
422
|
let draining = 0
|
|
@@ -403,28 +437,27 @@ function exit (code) {
|
|
|
403
437
|
* Determine if launched from cmd.exe
|
|
404
438
|
*/
|
|
405
439
|
|
|
406
|
-
function launchedFromCmd
|
|
407
|
-
return process.platform === 'win32' &&
|
|
408
|
-
process.env._ === undefined
|
|
440
|
+
function launchedFromCmd() {
|
|
441
|
+
return process.platform === 'win32' && process.env._ === undefined
|
|
409
442
|
}
|
|
410
443
|
|
|
411
444
|
/**
|
|
412
445
|
* Load template file.
|
|
413
446
|
*/
|
|
414
447
|
|
|
415
|
-
function loadTemplate
|
|
416
|
-
const contents = fs.readFileSync(path.join(__dirname, '..', 'templates',
|
|
448
|
+
function loadTemplate(name) {
|
|
449
|
+
const contents = fs.readFileSync(path.join(__dirname, '..', 'templates', name + '.ejs'), 'utf-8')
|
|
417
450
|
const locals = Object.create(null)
|
|
418
451
|
|
|
419
|
-
function render
|
|
452
|
+
function render() {
|
|
420
453
|
return ejs.render(contents, locals, {
|
|
421
|
-
escape: util.inspect
|
|
454
|
+
escape: util.inspect,
|
|
422
455
|
})
|
|
423
456
|
}
|
|
424
457
|
|
|
425
458
|
return {
|
|
426
459
|
locals: locals,
|
|
427
|
-
render: render
|
|
460
|
+
render: render,
|
|
428
461
|
}
|
|
429
462
|
}
|
|
430
463
|
|
|
@@ -432,7 +465,7 @@ function loadTemplate (name) {
|
|
|
432
465
|
* Main program.
|
|
433
466
|
*/
|
|
434
467
|
|
|
435
|
-
function main
|
|
468
|
+
function main(options, done) {
|
|
436
469
|
// top-level argument direction
|
|
437
470
|
if (options['!'].length > 0) {
|
|
438
471
|
usage()
|
|
@@ -446,15 +479,19 @@ function main (options, done) {
|
|
|
446
479
|
done(0)
|
|
447
480
|
} else if (options.css === '') {
|
|
448
481
|
usage()
|
|
449
|
-
error(
|
|
482
|
+
error("option `-c, --css <engine>' argument missing")
|
|
450
483
|
done(1)
|
|
451
484
|
} else if (options.view === '') {
|
|
452
485
|
usage()
|
|
453
|
-
error(
|
|
486
|
+
error("option `-v, --view <engine>' argument missing")
|
|
487
|
+
done(1)
|
|
488
|
+
} else if (options.orm === '') {
|
|
489
|
+
usage()
|
|
490
|
+
error("option `-o, --orm <engine>' argument missing")
|
|
454
491
|
done(1)
|
|
455
492
|
} else if (options.es6 && process.versions.node.split('.')[0] < MIN_ES6_VERSION) {
|
|
456
493
|
usage()
|
|
457
|
-
error(
|
|
494
|
+
error("option `--es6' requires Node version " + MIN_ES6_VERSION + '.x or higher')
|
|
458
495
|
done(1)
|
|
459
496
|
} else {
|
|
460
497
|
console.log(options.view)
|
|
@@ -489,8 +526,10 @@ function main (options, done) {
|
|
|
489
526
|
|
|
490
527
|
// Default view engine
|
|
491
528
|
if (options.view === true) {
|
|
492
|
-
warning(
|
|
493
|
-
|
|
529
|
+
warning(
|
|
530
|
+
'the default view engine is ejs\n' +
|
|
531
|
+
"use `--view=ejs' or `--help' for additional options",
|
|
532
|
+
)
|
|
494
533
|
options.view = 'ejs'
|
|
495
534
|
}
|
|
496
535
|
|
|
@@ -520,7 +559,7 @@ function main (options, done) {
|
|
|
520
559
|
* @param {string} dir
|
|
521
560
|
*/
|
|
522
561
|
|
|
523
|
-
function mkdir
|
|
562
|
+
function mkdir(base, dir) {
|
|
524
563
|
const loc = path.join(base, dir)
|
|
525
564
|
|
|
526
565
|
console.log(' \x1b[36mcreate\x1b[0m : ' + loc + path.sep)
|
|
@@ -531,7 +570,7 @@ function mkdir (base, dir) {
|
|
|
531
570
|
* Display the usage.
|
|
532
571
|
*/
|
|
533
572
|
|
|
534
|
-
function usage
|
|
573
|
+
function usage() {
|
|
535
574
|
console.log('')
|
|
536
575
|
console.log(' Usage: express [options] [dir]')
|
|
537
576
|
console.log('')
|
|
@@ -541,11 +580,20 @@ function usage () {
|
|
|
541
580
|
console.log(' --pug add pug engine support')
|
|
542
581
|
console.log(' --hbs add handlebars engine support')
|
|
543
582
|
console.log(' -H, --hogan add hogan.js engine support')
|
|
544
|
-
console.log(
|
|
583
|
+
console.log(
|
|
584
|
+
' -v, --view <engine> add view <engine> support (dust|ejs|hbs|hjs|pug|twig|vash) (defaults to ejs)',
|
|
585
|
+
)
|
|
545
586
|
console.log(' --no-view use static html instead of view engine')
|
|
546
|
-
console.log(
|
|
587
|
+
console.log(
|
|
588
|
+
' -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)',
|
|
589
|
+
)
|
|
547
590
|
console.log(' --git add .gitignore')
|
|
548
|
-
console.log(
|
|
591
|
+
console.log(
|
|
592
|
+
' --es6 generate ES6 code and module-type project (requires Node 22.x or higher)',
|
|
593
|
+
)
|
|
594
|
+
console.log(
|
|
595
|
+
' -o, --orm <orm> add ORM <orm> support (prisma|sequelize)',
|
|
596
|
+
)
|
|
549
597
|
console.log(' -f, --force force on non-empty directory')
|
|
550
598
|
console.log(' --version output the version number')
|
|
551
599
|
console.log(' -h, --help output usage information')
|
|
@@ -555,7 +603,7 @@ function usage () {
|
|
|
555
603
|
* Display the version.
|
|
556
604
|
*/
|
|
557
605
|
|
|
558
|
-
function version
|
|
606
|
+
function version() {
|
|
559
607
|
console.log(VERSION)
|
|
560
608
|
}
|
|
561
609
|
|
|
@@ -565,7 +613,7 @@ function version () {
|
|
|
565
613
|
* @param {String} message
|
|
566
614
|
*/
|
|
567
615
|
|
|
568
|
-
function warning
|
|
616
|
+
function warning(message) {
|
|
569
617
|
console.error()
|
|
570
618
|
message.split('\n').forEach(function (line) {
|
|
571
619
|
console.error(' warning: %s', line)
|
|
@@ -580,7 +628,7 @@ function warning (message) {
|
|
|
580
628
|
* @param {String} str
|
|
581
629
|
*/
|
|
582
630
|
|
|
583
|
-
function write
|
|
631
|
+
function write(file, str, mode) {
|
|
584
632
|
fs.writeFileSync(file, str, { mode: mode || MODE_0666 })
|
|
585
633
|
console.log(' \x1b[36mcreate\x1b[0m : ' + file)
|
|
586
634
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "clwy-express-generator",
|
|
3
3
|
"description": "Express' application generator",
|
|
4
4
|
"homepage": "https://github.com/clwy-cn/clwy-express-generator",
|
|
5
|
-
"version": "5.1
|
|
5
|
+
"version": "5.2.1",
|
|
6
6
|
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
|
7
7
|
"contributors": [
|
|
8
8
|
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
|
|
@@ -40,13 +40,8 @@
|
|
|
40
40
|
"clwy-express": "./bin/express-cli.js"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"eslint": "7.32.0",
|
|
44
|
-
"eslint-config-standard": "14.1.1",
|
|
45
|
-
"eslint-plugin-import": "2.25.4",
|
|
46
|
-
"eslint-plugin-node": "11.1.0",
|
|
47
|
-
"eslint-plugin-promise": "5.2.0",
|
|
48
|
-
"eslint-plugin-standard": "4.1.0",
|
|
49
43
|
"mocha": "9.1.3",
|
|
44
|
+
"prettier": "^3.7.4",
|
|
50
45
|
"rimraf": "3.0.2",
|
|
51
46
|
"supertest": "6.1.4",
|
|
52
47
|
"tree-kill": "1.2.2",
|
|
@@ -64,6 +59,7 @@
|
|
|
64
59
|
"scripts": {
|
|
65
60
|
"lint": "eslint .",
|
|
66
61
|
"test": "mocha --reporter spec --bail --check-leaks test/",
|
|
67
|
-
"test-ci": "mocha --reporter spec --check-leaks test/"
|
|
62
|
+
"test-ci": "mocha --reporter spec --check-leaks test/",
|
|
63
|
+
"format": "prettier --write \"bin/*.{js,json,md,ts,jsx,tsx}\""
|
|
68
64
|
}
|
|
69
65
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
services:
|
|
2
|
+
mysql:
|
|
3
|
+
image: mysql:latest
|
|
4
|
+
command:
|
|
5
|
+
--character-set-server=utf8mb4
|
|
6
|
+
--collation-server=utf8mb4_general_ci
|
|
7
|
+
environment:
|
|
8
|
+
- MYSQL_ROOT_PASSWORD=root
|
|
9
|
+
ports:
|
|
10
|
+
- "3306:3306"
|
|
11
|
+
volumes:
|
|
12
|
+
- ./data/mysql:/var/lib/mysql
|
|
13
|
+
# postgresql:
|
|
14
|
+
# image: postgres:latest
|
|
15
|
+
# ports:
|
|
16
|
+
# - "5432:5432"
|
|
17
|
+
# environment:
|
|
18
|
+
# POSTGRES_PASSWORD: postgres
|
|
19
|
+
# volumes:
|
|
20
|
+
# - ./data/postgresql:/var/lib/postgresql/data
|
|
21
|
+
# redis:
|
|
22
|
+
# image: redis:latest
|
|
23
|
+
# ports:
|
|
24
|
+
# - "6379:6379"
|
|
25
|
+
# volumes:
|
|
26
|
+
# - ./data/redis:/data
|
package/templates/env.ejs
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
# your environment variables
|
|
2
2
|
NODE_ENV=development
|
|
3
3
|
PORT=3000
|
|
4
|
+
|
|
5
|
+
<% if (orm === 'prisma') { -%>
|
|
6
|
+
# If you want to use PostgresSQL or SQLite, change the provider and uncomment the following line
|
|
7
|
+
# DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"
|
|
8
|
+
# DATABASE_URL="file:./dev.db"
|
|
9
|
+
DATABASE_URL="mysql://root:root@localhost:3306/mydb"
|
|
10
|
+
<% } -%>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// This is your Prisma schema file,
|
|
2
|
+
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
3
|
+
|
|
4
|
+
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
|
5
|
+
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
|
6
|
+
|
|
7
|
+
generator client {
|
|
8
|
+
provider = "prisma-client"
|
|
9
|
+
output = "../generated/prisma"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
datasource db {
|
|
13
|
+
provider = "mysql"
|
|
14
|
+
|
|
15
|
+
// If you want to use PostgresSQL or SQLite, change the provider and uncomment the following line
|
|
16
|
+
// provider = "postgresql"
|
|
17
|
+
// provider = "sqlite"
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This file was generated by Prisma:
|
|
2
|
+
import 'dotenv/config'
|
|
3
|
+
import { defineConfig } from 'prisma/config'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
schema: 'prisma/schema.prisma',
|
|
7
|
+
migrations: {
|
|
8
|
+
path: 'prisma/migrations',
|
|
9
|
+
},
|
|
10
|
+
datasource: {
|
|
11
|
+
url: process.env['DATABASE_URL'],
|
|
12
|
+
},
|
|
13
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"development": {
|
|
3
|
+
"username": "root",
|
|
4
|
+
"password": "root",
|
|
5
|
+
"database": "database_development",
|
|
6
|
+
"host": "127.0.0.1",
|
|
7
|
+
"dialect": "mysql",
|
|
8
|
+
"timezone": "+08:00",
|
|
9
|
+
"logQueryParameters": true
|
|
10
|
+
},
|
|
11
|
+
"test": {
|
|
12
|
+
"username": "root",
|
|
13
|
+
"password": null,
|
|
14
|
+
"database": "database_test",
|
|
15
|
+
"host": "127.0.0.1",
|
|
16
|
+
"dialect": "mysql",
|
|
17
|
+
"timezone": "+08:00"
|
|
18
|
+
},
|
|
19
|
+
"production": {
|
|
20
|
+
"username": "root",
|
|
21
|
+
"password": null,
|
|
22
|
+
"database": "database_production",
|
|
23
|
+
"host": "127.0.0.1",
|
|
24
|
+
"dialect": "mysql",
|
|
25
|
+
"timezone": "+08:00"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const Sequelize = require('sequelize');
|
|
6
|
+
const process = require('process');
|
|
7
|
+
const basename = path.basename(__filename);
|
|
8
|
+
const env = process.env.NODE_ENV || 'development';
|
|
9
|
+
const config = require(__dirname + '/../config/config.json')[env];
|
|
10
|
+
const db = {};
|
|
11
|
+
|
|
12
|
+
let sequelize;
|
|
13
|
+
if (config.use_env_variable) {
|
|
14
|
+
sequelize = new Sequelize(process.env[config.use_env_variable], config);
|
|
15
|
+
} else {
|
|
16
|
+
sequelize = new Sequelize(config.database, config.username, config.password, config);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fs.readdirSync(__dirname)
|
|
20
|
+
.filter((file) => {
|
|
21
|
+
return (
|
|
22
|
+
file.indexOf('.') !== 0 &&
|
|
23
|
+
file !== basename &&
|
|
24
|
+
file.slice(-3) === '.js' &&
|
|
25
|
+
file.indexOf('.test.js') === -1
|
|
26
|
+
);
|
|
27
|
+
})
|
|
28
|
+
.forEach((file) => {
|
|
29
|
+
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
|
|
30
|
+
db[model.name] = model;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
Object.keys(db).forEach((modelName) => {
|
|
34
|
+
if (db[modelName].associate) {
|
|
35
|
+
db[modelName].associate(db);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
db.sequelize = sequelize;
|
|
40
|
+
db.Sequelize = Sequelize;
|
|
41
|
+
|
|
42
|
+
module.exports = db;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
import Sequelize from 'sequelize'
|
|
5
|
+
import process from 'process'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
8
|
+
const basename = path.basename(__filename)
|
|
9
|
+
const env = process.env.NODE_ENV || 'development'
|
|
10
|
+
const configPath = path.join(path.dirname(__filename), '../config/config.json')
|
|
11
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'))[env]
|
|
12
|
+
const db = {}
|
|
13
|
+
|
|
14
|
+
let sequelize
|
|
15
|
+
if (config.use_env_variable) {
|
|
16
|
+
sequelize = new Sequelize(process.env[config.use_env_variable], config)
|
|
17
|
+
} else {
|
|
18
|
+
sequelize = new Sequelize(config.database, config.username, config.password, config)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const files = fs.readdirSync(path.dirname(__filename)).filter((file) => {
|
|
22
|
+
return (
|
|
23
|
+
file.indexOf('.') !== 0 &&
|
|
24
|
+
file !== basename &&
|
|
25
|
+
file.slice(-3) === '.js' &&
|
|
26
|
+
file.indexOf('.test.js') === -1
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
const model = (await import(`./${file}`)).default(
|
|
32
|
+
sequelize,
|
|
33
|
+
Sequelize.DataTypes,
|
|
34
|
+
)
|
|
35
|
+
db[model.name] = model
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Object.keys(db).forEach((modelName) => {
|
|
39
|
+
if (db[modelName].associate) {
|
|
40
|
+
db[modelName].associate(db)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
db.sequelize = sequelize
|
|
45
|
+
db.Sequelize = Sequelize
|
|
46
|
+
|
|
47
|
+
export default db
|