create-sip 0.14.3 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/create-sip.js +2 -2
- package/expressapi/README.md +38 -3
- package/expressapi/op +142 -22
- package/manager.js +4 -3
- package/package.json +1 -1
package/create-sip.js
CHANGED
|
@@ -61,7 +61,7 @@ const questions = [
|
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
title: 'Express API',
|
|
64
|
-
description: 'Express API with simple Sequelize',
|
|
64
|
+
description: 'Express API with simple Sequelize and ES modules',
|
|
65
65
|
value: 'expressapi'
|
|
66
66
|
},
|
|
67
67
|
{
|
|
@@ -111,7 +111,7 @@ const questions = [
|
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
113
|
if(res.type === 'expressapi') {
|
|
114
|
-
console.log('Create a new Express API...');
|
|
114
|
+
console.log('Create a new Express API with ES modules...');
|
|
115
115
|
genExpressApi(res.name);
|
|
116
116
|
return;
|
|
117
117
|
}
|
package/expressapi/README.md
CHANGED
|
@@ -65,11 +65,46 @@ npm start
|
|
|
65
65
|
You can generate a model and controller with the following commands:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
node op
|
|
69
|
-
node op
|
|
68
|
+
node op make:model something
|
|
69
|
+
node op make:controller something
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
The name after the model and controller statements must be given in the singular.
|
|
72
|
+
The name after the model and controller statements must be given in the singular. Controller generation automatically appends the "Controller" suffix.
|
|
73
|
+
|
|
74
|
+
## Admin user
|
|
75
|
+
|
|
76
|
+
The admin user can be created with the following command:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node op admin:generate
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The command will prompt for the password.
|
|
83
|
+
|
|
84
|
+
## Config generation
|
|
85
|
+
|
|
86
|
+
The next command generates the default config file:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
node op conf:generate
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Database seed
|
|
93
|
+
|
|
94
|
+
The database can be seeded with the following command:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
node op db:seed <model_name> <file_path>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The model name must be given in the singular and lowercase. The file extension must be:
|
|
101
|
+
|
|
102
|
+
* .json
|
|
103
|
+
* .csv
|
|
104
|
+
|
|
105
|
+
The keys in the JSON file and the field names in the CSV file must match the model fields.
|
|
106
|
+
|
|
107
|
+
If the CSV file contains quotation marks, they are automatically removed.
|
|
73
108
|
|
|
74
109
|
## Licence
|
|
75
110
|
|
package/expressapi/op
CHANGED
|
@@ -1,20 +1,55 @@
|
|
|
1
|
-
import replace from 'replace'
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import replace from 'replace'
|
|
2
|
+
import fse from 'fs-extra'
|
|
4
3
|
import fsp from 'fs/promises'
|
|
5
4
|
import { generateApiKey } from 'generate-api-key'
|
|
6
|
-
|
|
7
5
|
import bcrypt from 'bcryptjs';
|
|
8
6
|
import path from 'path';
|
|
9
|
-
|
|
10
7
|
import { read } from 'read'
|
|
11
8
|
|
|
12
|
-
if(process.argv.length == 3 && process.argv[2] == '
|
|
9
|
+
if(process.argv.length == 3 && process.argv[2] == 'help') {
|
|
10
|
+
console.log('Usable commands:');
|
|
11
|
+
console.log(' node op make:model <name>');
|
|
12
|
+
console.log(' node op make:controller <name>');
|
|
13
|
+
console.log(' node op key:generate');
|
|
14
|
+
console.log(' node op conf:generate');
|
|
15
|
+
console.log(' node op admin:generate');
|
|
16
|
+
console.log(' node op db:seed <model> <filePath>');
|
|
17
|
+
process.exit(0);
|
|
18
|
+
} else if(process.argv.length == 3 && process.argv[2] == 'key:generate') {
|
|
13
19
|
startGenerateKey();
|
|
14
20
|
} else if(process.argv.length == 3 && process.argv[2] == 'conf:generate') {
|
|
15
21
|
startGenerateConf();
|
|
16
22
|
} else if(process.argv.length == 3 && process.argv[2] == 'admin:generate') {
|
|
17
23
|
startGenerateAdmin();
|
|
24
|
+
} else if(process.argv[2] === 'db:seed') {
|
|
25
|
+
if(process.argv.length < 5) {
|
|
26
|
+
console.log('Usage:');
|
|
27
|
+
console.log('node op db:seed <model> <filePath>');
|
|
28
|
+
console.log('Examples:');
|
|
29
|
+
console.log('node op db:seed thing somethings.json');
|
|
30
|
+
console.log('node op db:seed thing somethings.csv');
|
|
31
|
+
}
|
|
32
|
+
const model = process.argv[3];
|
|
33
|
+
const filePath = process.argv[4];
|
|
34
|
+
runSeed(model, filePath);
|
|
35
|
+
} else if(process.argv[2] === 'make:model') {
|
|
36
|
+
if(process.argv.length < 4) {
|
|
37
|
+
console.log('Usage:');
|
|
38
|
+
console.log('node op make:model <name>');
|
|
39
|
+
console.log('Examples:');
|
|
40
|
+
console.log('node op make:model something');
|
|
41
|
+
}
|
|
42
|
+
copyModel(process.argv[3]);
|
|
43
|
+
|
|
44
|
+
} else if(process.argv[2] === 'make:controller') {
|
|
45
|
+
if(process.argv.length < 4) {
|
|
46
|
+
console.log('Usage:');
|
|
47
|
+
console.log('node op make:controller <name>');
|
|
48
|
+
console.log('Examples:');
|
|
49
|
+
console.log('node op make:controller something');
|
|
50
|
+
}
|
|
51
|
+
copyController(process.argv[3]);
|
|
52
|
+
|
|
18
53
|
} else if(process.argv.length < 4) {
|
|
19
54
|
console.log('Usage:');
|
|
20
55
|
console.log('node op <command> <type> <name>');
|
|
@@ -27,22 +62,20 @@ if(process.argv.length == 3 && process.argv[2] == 'key:generate') {
|
|
|
27
62
|
if(process.argv[2] === 'create') {
|
|
28
63
|
console.log('Create a new ' + process.argv[3] + '...');
|
|
29
64
|
if(process.argv[3] === 'model') {
|
|
30
|
-
copyModel();
|
|
65
|
+
copyModel(process.argv[4]);
|
|
31
66
|
}
|
|
32
67
|
if(process.argv[3] === 'controller') {
|
|
33
|
-
copyController();
|
|
68
|
+
copyController(process.argv[4]);
|
|
34
69
|
}
|
|
35
70
|
}
|
|
36
71
|
}
|
|
37
72
|
|
|
38
|
-
async function copyController() {
|
|
39
|
-
|
|
40
|
-
const className = process.argv[4]
|
|
73
|
+
async function copyController(className) {
|
|
41
74
|
const lowerName = className.toLowerCase()
|
|
42
75
|
|
|
43
76
|
const src = 'templates/controllerTemplate.js'
|
|
44
77
|
const dest = `app/controllers/${lowerName}controller.js`
|
|
45
|
-
await
|
|
78
|
+
await fse.copy(src, dest)
|
|
46
79
|
|
|
47
80
|
replace({
|
|
48
81
|
regex: 'Thing',
|
|
@@ -61,14 +94,12 @@ async function copyController() {
|
|
|
61
94
|
})
|
|
62
95
|
}
|
|
63
96
|
|
|
64
|
-
async function copyModel() {
|
|
65
|
-
|
|
66
|
-
const className = process.argv[4]
|
|
97
|
+
async function copyModel(className) {
|
|
67
98
|
const lowerName = className.toLowerCase()
|
|
68
|
-
|
|
69
99
|
const src = 'templates/modelTemplate.js'
|
|
70
100
|
const dest = `app/models/${lowerName}.js`
|
|
71
|
-
|
|
101
|
+
|
|
102
|
+
await fse.copy(src, dest)
|
|
72
103
|
|
|
73
104
|
replace({
|
|
74
105
|
regex: 'Thing',
|
|
@@ -96,16 +127,20 @@ function startGenerateKey() {
|
|
|
96
127
|
return json
|
|
97
128
|
})
|
|
98
129
|
.then(json => JSON.stringify(json, null, 4))
|
|
99
|
-
.then(body =>
|
|
130
|
+
.then(body => fse.writeFile(fileName, body, 'utf8'))
|
|
100
131
|
.catch(error => console.log(error))
|
|
101
132
|
}
|
|
102
133
|
|
|
103
|
-
function startGenerateConf() {
|
|
134
|
+
async function startGenerateConf() {
|
|
104
135
|
console.log('Generate conf...');
|
|
105
136
|
const sourceFileName = 'config/default.json.example';
|
|
106
137
|
const destinationFileName = 'config/default.json';
|
|
107
|
-
|
|
108
|
-
|
|
138
|
+
try {
|
|
139
|
+
await fse.copyFile(sourceFileName, destinationFileName)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.log(error)
|
|
142
|
+
}
|
|
143
|
+
|
|
109
144
|
}
|
|
110
145
|
|
|
111
146
|
async function loadConfig() {
|
|
@@ -158,4 +193,89 @@ async function startGenerateAdmin() {
|
|
|
158
193
|
console.error('Error creating admin!')
|
|
159
194
|
console.error(err)
|
|
160
195
|
}
|
|
161
|
-
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const seedFromJson = async (model, filePath) => {
|
|
199
|
+
try {
|
|
200
|
+
const data = JSON.parse(await fsp.readFile(filePath, 'utf8'))
|
|
201
|
+
await model.bulkCreate(data)
|
|
202
|
+
console.log(`Data seeded successfully! ${model.name}`)
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error(error)
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const seedFromCsv = async (model, filePath) => {
|
|
209
|
+
const sep = ','
|
|
210
|
+
try {
|
|
211
|
+
const data = await fsp.readFile(filePath, 'utf8')
|
|
212
|
+
const clearData = data.replace(/"/g, '').trim()
|
|
213
|
+
const rows = clearData.split('\n')
|
|
214
|
+
const headerColumns = rows.shift().split(sep)
|
|
215
|
+
|
|
216
|
+
const dataToInsert = rows.map(row => {
|
|
217
|
+
const columns = row.split(sep).map(item => {
|
|
218
|
+
const number = Number(item)
|
|
219
|
+
return Number.isNaN(number) ? `${item}` : number
|
|
220
|
+
})
|
|
221
|
+
return headerColumns.reduce((obj, header, index) => {
|
|
222
|
+
obj[header] = columns[index]
|
|
223
|
+
return obj
|
|
224
|
+
}, {})
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
await model.bulkCreate(dataToInsert)
|
|
228
|
+
console.log(`Data seeded successfully! ${model.name}`)
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error(error)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function runSeed(model, filePath) {
|
|
235
|
+
|
|
236
|
+
if(!filePath || !model) {
|
|
237
|
+
console.log('Usage: node seed.js <modelName> <filePath>')
|
|
238
|
+
process.exit(1)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
await import(`./app/models/${model}.js`)
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.log(`The ${model} model file does not exist!`)
|
|
245
|
+
process.exit(1)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
await fsp.stat(filePath)
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (error.code === 'ENOENT') {
|
|
252
|
+
console.log(`The file ${filePath} does not exist!`)
|
|
253
|
+
process.exit(1)
|
|
254
|
+
} else {
|
|
255
|
+
console.error(error)
|
|
256
|
+
process.exit(1)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const modelInstance = await import(`./app/models/${model}.js`)
|
|
261
|
+
const modelObject = modelInstance.default
|
|
262
|
+
|
|
263
|
+
const ext = path.extname(filePath).toLowerCase()
|
|
264
|
+
if(ext !== '.json' && ext !== '.csv') {
|
|
265
|
+
console.log('The file must have .json or .csv extension!')
|
|
266
|
+
process.exit(1)
|
|
267
|
+
}
|
|
268
|
+
const { default: sequelize } = await import('./app/database/database.js')
|
|
269
|
+
try {
|
|
270
|
+
await sequelize.sync({ force: true })
|
|
271
|
+
await sequelize.authenticate()
|
|
272
|
+
if(ext === '.csv') {
|
|
273
|
+
await seedFromCsv(modelObject, filePath)
|
|
274
|
+
}else {
|
|
275
|
+
await seedFromJson(modelObject, filePath)
|
|
276
|
+
}
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error(error)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
}
|
package/manager.js
CHANGED
|
@@ -71,10 +71,11 @@ const genExpressApi = (target) => {
|
|
|
71
71
|
console.log(' node op key:generate');
|
|
72
72
|
console.log(' npm run dev');
|
|
73
73
|
console.log('Usable commands:');
|
|
74
|
-
console.log(' node op
|
|
75
|
-
console.log(' node op
|
|
74
|
+
console.log(' node op make:model something');
|
|
75
|
+
console.log(' node op make:controller something');
|
|
76
76
|
console.log('The model and controller names must be');
|
|
77
|
-
console.log('given in the singular');
|
|
77
|
+
console.log('given in the singular. More info:');
|
|
78
|
+
console.log(' node op help')
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
module.exports = {
|