crabatool 1.0.410 → 1.0.414
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/apis/data.js +105 -23
- package/lib/jsoncrud.js +84 -24
- package/package.json +1 -1
- package/tool/checkjs.js +3 -2
- package/tool/compress.js +5 -0
- package/tool/gspxHash.js +0 -90
package/apis/data.js
CHANGED
|
@@ -10,13 +10,15 @@ class data {
|
|
|
10
10
|
constructor() {
|
|
11
11
|
this.dslMap = {};
|
|
12
12
|
this.pagesDataChanged = {};
|
|
13
|
+
this.dsl = {};
|
|
14
|
+
this.dataRefs = [];
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
_init(req) {
|
|
16
18
|
if (req.app.jsoncrud) { // 每个server只创建1个实例
|
|
17
19
|
return;
|
|
18
20
|
}
|
|
19
|
-
req.app.jsoncrud = new JSONCRUD({ storagePath: path.join(req.app.webPath, '../data/
|
|
21
|
+
req.app.jsoncrud = new JSONCRUD({ storagePath: path.join(req.app.webPath, '../data/entities'), separateFiles: true });
|
|
20
22
|
|
|
21
23
|
//读取dsl数据
|
|
22
24
|
var dslData = fs.readFileSync(path.join(req.app.webPath, '../data/dslData.json'));
|
|
@@ -25,9 +27,9 @@ class data {
|
|
|
25
27
|
} else {
|
|
26
28
|
dslData = JSON.parse(dslData)
|
|
27
29
|
}
|
|
28
|
-
|
|
30
|
+
this.dsl = dslData.dsl;
|
|
29
31
|
var _this = this;
|
|
30
|
-
dsl && dsl.forEach(item => {
|
|
32
|
+
_this.dsl && _this.dsl.forEach(item => {
|
|
31
33
|
_this.dslMap[crabatool.stringUtils.getFullPinyinCode(item.name)] = JSON.parse(JSON.stringify(item));
|
|
32
34
|
});
|
|
33
35
|
var dataRefs = dslData.dataRefs;
|
|
@@ -56,7 +58,6 @@ class data {
|
|
|
56
58
|
async get(req, res) {
|
|
57
59
|
var body = utils.getReqBody(req);
|
|
58
60
|
var that = this;
|
|
59
|
-
|
|
60
61
|
var queryParams = body.queryParams;
|
|
61
62
|
var filterParams = body.filter;
|
|
62
63
|
var items = null;
|
|
@@ -84,8 +85,8 @@ class data {
|
|
|
84
85
|
items.push({ dataField: key, type: 0, value: queryParams[key] });
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
var info = await
|
|
88
|
+
var db = this._getDb(req);
|
|
89
|
+
var info = await db.find(body.name, {
|
|
89
90
|
page: body.pageIndex,
|
|
90
91
|
pageSize: body.pageSize,
|
|
91
92
|
filterFunc: function (item) {
|
|
@@ -95,7 +96,7 @@ class data {
|
|
|
95
96
|
return true;
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
|
-
|
|
99
|
+
await this.fillData(body.name, info.data, db, true);
|
|
99
100
|
crabatool.utils.end(res, {
|
|
100
101
|
code: 200,
|
|
101
102
|
msg: '操作成功',
|
|
@@ -104,6 +105,62 @@ class data {
|
|
|
104
105
|
});
|
|
105
106
|
}
|
|
106
107
|
|
|
108
|
+
async fillData(name, rows, db, searchDataRef) {
|
|
109
|
+
if (this.dslMap[name]) {
|
|
110
|
+
if (rows) {
|
|
111
|
+
for (var i = 0; i < rows.length; i++) {
|
|
112
|
+
var row = rows[i];
|
|
113
|
+
var dsl = this.dslMap[name];
|
|
114
|
+
for (var j = 0; j < dsl.fields.length; j++) { //join扩展表数据
|
|
115
|
+
var field = dsl.fields[j];
|
|
116
|
+
if (field.type != 'table') {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
var temp = await db.getByField(crabatool.stringUtils.getFullPinyinCode(field.ref), crabatool.stringUtils.getFullPinyinCode(field.refField), row[crabatool.stringUtils.getFullPinyinCode(field.name)]);
|
|
120
|
+
if (!temp) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
var str = crabatool.stringUtils.getFullPinyinCode(field.refShowField ? field.refShowField : field.refField);
|
|
124
|
+
row[str] = temp[str];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (searchDataRef) {
|
|
128
|
+
//查询关联明细数据
|
|
129
|
+
var dataRefs = this.dslMap[name].dataRefs;
|
|
130
|
+
if (dataRefs) {
|
|
131
|
+
for (var m = 0; m < dataRefs.length; m++) {
|
|
132
|
+
var dataRef = dataRefs[m];
|
|
133
|
+
var detailPy = crabatool.stringUtils.getFullPinyinCode(dataRef.detail);
|
|
134
|
+
var masterFieldPy = crabatool.stringUtils.getFullPinyinCode(dataRef.masterField);
|
|
135
|
+
var obj = row[masterFieldPy];
|
|
136
|
+
var detailFieldPy = crabatool.stringUtils.getFullPinyinCode(dataRef.detailField);
|
|
137
|
+
var size = 100;
|
|
138
|
+
var rtSize = 0;
|
|
139
|
+
var array = [];
|
|
140
|
+
do {
|
|
141
|
+
//循环取外表数据
|
|
142
|
+
var page = 1;
|
|
143
|
+
var t = await db.find(detailPy, {
|
|
144
|
+
page: page,
|
|
145
|
+
pageSize: size,
|
|
146
|
+
filterFunc: function (row) {
|
|
147
|
+
return obj && obj === row[detailFieldPy];
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
page++;
|
|
151
|
+
rtSize = t.pageData.count;
|
|
152
|
+
array = array.concat(t.data);
|
|
153
|
+
} while (rtSize == size);
|
|
154
|
+
row[detailPy] = array;
|
|
155
|
+
await this.fillData(detailPy, row[detailPy], db, false);//只查一级
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
107
164
|
async reverseData(req, pageName, body) {
|
|
108
165
|
var oldEntity = await this._getDb(req).get(body.name, body.data.id);
|
|
109
166
|
if (!oldEntity) {
|
|
@@ -125,6 +182,8 @@ class data {
|
|
|
125
182
|
|
|
126
183
|
var newData;
|
|
127
184
|
var pageName = body.pageName;
|
|
185
|
+
var db = this._getDb(req);
|
|
186
|
+
var rtData = JSON.parse(JSON.stringify(body.data));
|
|
128
187
|
if (body.data.id) {
|
|
129
188
|
var oldData = await this.reverseData(req, pageName, body);
|
|
130
189
|
if (!oldData) {
|
|
@@ -133,23 +192,46 @@ class data {
|
|
|
133
192
|
await this.buildDataPrimaryAndForeignKey(body.name, body.data, true);
|
|
134
193
|
//更新联动新数据
|
|
135
194
|
await this.pageSaveToDataLinkage(req, body.name, pageName, body.data, oldData);
|
|
136
|
-
|
|
195
|
+
var name = body.name;
|
|
196
|
+
await this._saveRefData(name, body.data, rtData, db);
|
|
197
|
+
await db.update(body.name, body.data.id, body.data);
|
|
137
198
|
newData = body.data;
|
|
138
199
|
} else {
|
|
139
200
|
//提前制定ID
|
|
140
201
|
body.data.id = cuid.newCuidString()
|
|
141
202
|
await this.buildDataPrimaryAndForeignKey(body.name, body.data);
|
|
142
203
|
await this.pageSaveToDataLinkage(req, body.name, pageName, body.data)
|
|
143
|
-
|
|
204
|
+
await this._saveRefData(name, body.data, rtData, db);
|
|
205
|
+
newData = await db.create(body.name, body.data);
|
|
144
206
|
}
|
|
145
207
|
|
|
146
208
|
crabatool.utils.end(res, {
|
|
147
209
|
code: 200,
|
|
148
210
|
msg: '操作成功',
|
|
149
|
-
data:
|
|
211
|
+
data: rtData
|
|
150
212
|
});
|
|
151
213
|
}
|
|
152
214
|
|
|
215
|
+
async _saveRefData(name, data, rtData, db) {
|
|
216
|
+
var dataRefs = this.dslMap[name].dataRefs;
|
|
217
|
+
for (var i = 0; dataRefs && i < dataRefs.length; i++) {
|
|
218
|
+
var dataRef = dataRefs[i];
|
|
219
|
+
var detailPy = crabatool.stringUtils.getFullPinyinCode(dataRef.detail)
|
|
220
|
+
var details = data[detailPy] ? data[detailPy] : [];
|
|
221
|
+
delete data[detailPy];
|
|
222
|
+
for (var j = 0; j < details.length; j++) {
|
|
223
|
+
var detail = details[j];
|
|
224
|
+
if (detail.id) {
|
|
225
|
+
await db.update(detailPy, detail.id, detail)
|
|
226
|
+
} else {
|
|
227
|
+
await db.create(detailPy, detail)
|
|
228
|
+
rtData[detailPy][j].id = detail.id;//补充新增行的ID
|
|
229
|
+
}
|
|
230
|
+
await this._saveRefData(detailPy, detail, rtData[detailPy][j], db);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
153
235
|
findLayerData(data, items, layer) {
|
|
154
236
|
if (!data) {
|
|
155
237
|
return null;
|
|
@@ -205,9 +287,9 @@ class data {
|
|
|
205
287
|
}
|
|
206
288
|
//查找涉及的所有实体
|
|
207
289
|
var _this = this;
|
|
208
|
-
for(var i = 0
|
|
290
|
+
for (var i = 0; i < actions.length; i++) {
|
|
209
291
|
var action = actions[i];
|
|
210
|
-
for(var j = 0
|
|
292
|
+
for (var j = 0; j < action.length; j++) {
|
|
211
293
|
var item = action[j];
|
|
212
294
|
if (item.type == 'external') {//外表处理
|
|
213
295
|
await _this.externalDataLinkage(req, name, data, item, reverseNumber);
|
|
@@ -232,17 +314,17 @@ class data {
|
|
|
232
314
|
//根据refData和sourceData计算结果
|
|
233
315
|
var refNamePy = crabatool.stringUtils.getFullPinyinCode(item.ref);
|
|
234
316
|
var fieldNamePy = crabatool.stringUtils.getFullPinyinCode(item.field);
|
|
235
|
-
Object.keys(refData).forEach(key => {
|
|
317
|
+
refData && Object.keys(refData).forEach(key => {
|
|
236
318
|
var target = refData[key][0];
|
|
237
319
|
//目标值为单一对象
|
|
238
320
|
if (!target[refNamePy]) {
|
|
239
321
|
return;
|
|
240
322
|
}
|
|
241
323
|
if (oldData) {
|
|
242
|
-
if(name != refNamePy){
|
|
324
|
+
if (name != refNamePy) {
|
|
243
325
|
//传入了老数据,当前计算的值可以直接取老数据的对应值,因为它已经排除本单
|
|
244
326
|
var oldDataTemp = oldData[name][refNamePy];
|
|
245
|
-
if(oldDataTemp instanceof Array){
|
|
327
|
+
if (oldDataTemp instanceof Array) {
|
|
246
328
|
target[refNamePy][fieldNamePy] = oldDataTemp[0][fieldNamePy];//强制取第一行
|
|
247
329
|
} else {
|
|
248
330
|
target[refNamePy][fieldNamePy] = oldDataTemp[fieldNamePy] ? oldDataTemp[fieldNamePy] : 0;
|
|
@@ -271,10 +353,10 @@ class data {
|
|
|
271
353
|
if (refNamePy != name) {
|
|
272
354
|
targetObj = data[refNamePy];
|
|
273
355
|
}
|
|
274
|
-
if(targetObj instanceof Array){
|
|
275
|
-
targetObj.forEach(titem => {
|
|
356
|
+
if (targetObj instanceof Array) {
|
|
357
|
+
targetObj.forEach(titem => {
|
|
276
358
|
var primaryKey = titem[targetArray[1]];
|
|
277
|
-
if(!refData[primaryKey]){//没找到对应行,直接返回
|
|
359
|
+
if (!refData[primaryKey]) {//没找到对应行,直接返回
|
|
278
360
|
return;
|
|
279
361
|
}
|
|
280
362
|
var refDataTemp = refData[primaryKey][0][refNamePy];
|
|
@@ -289,7 +371,7 @@ class data {
|
|
|
289
371
|
}
|
|
290
372
|
//将结果赋值给实体对象
|
|
291
373
|
var t = targetValue[refNamePy];
|
|
292
|
-
Object.keys(t).forEach(key => {
|
|
374
|
+
t && Object.keys(t).forEach(key => {
|
|
293
375
|
targetObj[key] = t[key];
|
|
294
376
|
});
|
|
295
377
|
}
|
|
@@ -324,7 +406,7 @@ class data {
|
|
|
324
406
|
page: page,
|
|
325
407
|
pageSize: size,
|
|
326
408
|
filterFunc: function (row) {
|
|
327
|
-
if (filterValue[row[refFieldPy]]) {
|
|
409
|
+
if (filterValue && filterValue[row[refFieldPy]]) {
|
|
328
410
|
changeRefData.push({
|
|
329
411
|
ref: row,
|
|
330
412
|
formateValue: filterValue[row[refFieldPy]]
|
|
@@ -496,9 +578,9 @@ class data {
|
|
|
496
578
|
}
|
|
497
579
|
data[detailName].forEach(detail => {
|
|
498
580
|
detail[crabatool.stringUtils.getFullPinyinCode(item.detailField)] = data[crabatool.stringUtils.getFullPinyinCode(item.masterField)];
|
|
499
|
-
if (!detail.id) {//明细行ID为空时需要生成新值
|
|
500
|
-
|
|
501
|
-
}
|
|
581
|
+
// if (!detail.id) {//明细行ID为空时需要生成新值
|
|
582
|
+
// detail.id = cuid.newCuidString()
|
|
583
|
+
// }
|
|
502
584
|
//嵌套处理明细中关联的主键和外键
|
|
503
585
|
_this.buildDataPrimaryAndForeignKey(detailName, detail)
|
|
504
586
|
});
|
package/lib/jsoncrud.js
CHANGED
|
@@ -7,6 +7,7 @@ class JSONCRUD {
|
|
|
7
7
|
* @param {Object} config - 配置项
|
|
8
8
|
* @param {string} [config.storagePath] - 文件存储路径
|
|
9
9
|
* @param {boolean} [config.useMemory] - 是否使用内存存储
|
|
10
|
+
* @param {boolean} [config.separateFiles] - 按实体分文件存储
|
|
10
11
|
*/
|
|
11
12
|
constructor(config = {}) {
|
|
12
13
|
this.config = config
|
|
@@ -33,29 +34,54 @@ class JSONCRUD {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// 保存到文件
|
|
36
|
-
async saveToFile() {
|
|
37
|
+
async saveToFile(entityName) {
|
|
37
38
|
if (!this.useMemory) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
var data = Object.entries(this.entities);
|
|
40
|
+
var tempStorageFile = this.storageFile;
|
|
41
|
+
var dataToSave = null;
|
|
42
|
+
if (this.config.separateFiles) {
|
|
43
|
+
//按文件拆分存储
|
|
44
|
+
data = entityName && this.entities[entityName] ? this.entities[entityName].data : {};
|
|
45
|
+
dataToSave = data;
|
|
46
|
+
tempStorageFile = path.join(tempStorageFile, entityName + '.json');
|
|
47
|
+
} else {
|
|
48
|
+
// 构建包含所有实体的存储对象
|
|
49
|
+
dataToSave = data.reduce((acc, [entityName, entityData]) => {
|
|
50
|
+
acc[entityName] = entityData.data
|
|
51
|
+
return acc
|
|
52
|
+
}, {})
|
|
53
|
+
}
|
|
43
54
|
|
|
44
55
|
// 创建存储目录(如果不存在)
|
|
45
|
-
await fs.mkdir(path.dirname(
|
|
56
|
+
await fs.mkdir(path.dirname(tempStorageFile), { recursive: true })
|
|
46
57
|
|
|
47
58
|
// 原子化写入(避免写入过程中崩溃导致数据丢失)
|
|
48
|
-
const tmpFile = `${
|
|
49
|
-
try{
|
|
59
|
+
const tmpFile = `${tempStorageFile}.tmp`
|
|
60
|
+
try {
|
|
50
61
|
//频繁写入时会导致数据错误
|
|
51
62
|
await fs.writeFile(tmpFile, JSON.stringify(dataToSave, null, 2))
|
|
52
|
-
await fs.rename(tmpFile,
|
|
53
|
-
}catch(e){
|
|
63
|
+
await fs.rename(tmpFile, tempStorageFile)
|
|
64
|
+
} catch (e) {
|
|
54
65
|
console.log(e);
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
}
|
|
58
69
|
|
|
70
|
+
async batchCreate(entityName, items) {
|
|
71
|
+
await this.ready()
|
|
72
|
+
this.verifyEntityExists(entityName)
|
|
73
|
+
var _this = this;
|
|
74
|
+
items.forEach(item=>{
|
|
75
|
+
const newItem = {
|
|
76
|
+
id: cuid.newCuidString(),//允许外部提前制定ID
|
|
77
|
+
...item,
|
|
78
|
+
createdAt: new Date().toISOString()
|
|
79
|
+
}
|
|
80
|
+
_this.entities[entityName].data.push(newItem)
|
|
81
|
+
})
|
|
82
|
+
await this.persist(entityName)
|
|
83
|
+
}
|
|
84
|
+
|
|
59
85
|
// 核心CRUD方法
|
|
60
86
|
async create(entityName, item) {
|
|
61
87
|
await this.ready()
|
|
@@ -67,7 +93,7 @@ class JSONCRUD {
|
|
|
67
93
|
createdAt: new Date().toISOString()
|
|
68
94
|
}
|
|
69
95
|
this.entities[entityName].data.push(newItem)
|
|
70
|
-
await this.persist()
|
|
96
|
+
await this.persist(entityName)
|
|
71
97
|
return newItem
|
|
72
98
|
}
|
|
73
99
|
|
|
@@ -135,6 +161,15 @@ class JSONCRUD {
|
|
|
135
161
|
return this.entities[entityName].data[index]
|
|
136
162
|
}
|
|
137
163
|
|
|
164
|
+
async getByField(entityName, field, value) {
|
|
165
|
+
await this.ready()
|
|
166
|
+
this.verifyEntityExists(entityName)
|
|
167
|
+
|
|
168
|
+
const index = this.entities[entityName].data.findIndex(item => item[field] === value)
|
|
169
|
+
if (index === -1) return null
|
|
170
|
+
return this.entities[entityName].data[index]
|
|
171
|
+
}
|
|
172
|
+
|
|
138
173
|
async update(entityName, id, updates) {
|
|
139
174
|
await this.ready()
|
|
140
175
|
this.verifyEntityExists(entityName)
|
|
@@ -147,15 +182,15 @@ class JSONCRUD {
|
|
|
147
182
|
...updates,
|
|
148
183
|
updatedAt: new Date().toISOString()
|
|
149
184
|
}
|
|
150
|
-
await this.persist()
|
|
185
|
+
await this.persist(entityName)
|
|
151
186
|
return this.entities[entityName].data[index]
|
|
152
187
|
}
|
|
153
188
|
|
|
154
|
-
async batchUpdate(entityName, items){
|
|
189
|
+
async batchUpdate(entityName, items) {
|
|
155
190
|
await this.ready()
|
|
156
191
|
this.verifyEntityExists(entityName)
|
|
157
192
|
|
|
158
|
-
items.forEach(entity =>{
|
|
193
|
+
items.forEach(entity => {
|
|
159
194
|
const index = this.entities[entityName].data.findIndex(item => item.id === entity.id)
|
|
160
195
|
if (index === -1) return null
|
|
161
196
|
|
|
@@ -165,7 +200,7 @@ class JSONCRUD {
|
|
|
165
200
|
updatedAt: new Date().toISOString()
|
|
166
201
|
}
|
|
167
202
|
})
|
|
168
|
-
await this.persist()
|
|
203
|
+
await this.persist(entityName)
|
|
169
204
|
}
|
|
170
205
|
|
|
171
206
|
async delete(entityName, id) {
|
|
@@ -177,7 +212,7 @@ class JSONCRUD {
|
|
|
177
212
|
item => item.id !== id
|
|
178
213
|
)
|
|
179
214
|
const success = this.entities[entityName].data.length < initialLength
|
|
180
|
-
if (success) await this.persist()
|
|
215
|
+
if (success) await this.persist(entityName)
|
|
181
216
|
return success
|
|
182
217
|
}
|
|
183
218
|
|
|
@@ -194,14 +229,40 @@ class JSONCRUD {
|
|
|
194
229
|
await new Promise(resolve => setTimeout(resolve, 50))
|
|
195
230
|
}
|
|
196
231
|
}
|
|
232
|
+
async readAllFilesInDirectory(dirPath) {
|
|
233
|
+
try {
|
|
234
|
+
var fileContent = {};
|
|
235
|
+
const files = await fs.readdir(dirPath);
|
|
236
|
+
for (const file of files) {
|
|
237
|
+
const filePath = path.join(dirPath, file);
|
|
238
|
+
var stats = await fs.stat(filePath);
|
|
239
|
+
if (stats.isFile()) {
|
|
240
|
+
var entityName = file.substring(0, file.lastIndexOf('.'));
|
|
241
|
+
var temp = await fs.readFile(filePath, 'utf-8')
|
|
242
|
+
fileContent[entityName] = temp?JSON.parse(temp):{};
|
|
243
|
+
} else if (stats.isDirectory()) {
|
|
244
|
+
// 如果需要递归处理子目录,可以在这里调用readAllFilesInDirectory(filePath)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return fileContent;
|
|
248
|
+
} catch (err) {
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
197
252
|
|
|
198
253
|
// 初始化文件存储
|
|
199
254
|
async initFileStorage() {
|
|
200
255
|
try {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
256
|
+
var fileContent = null;
|
|
257
|
+
var storedData = {};
|
|
258
|
+
if (this.config.separateFiles) {
|
|
259
|
+
var dir = this.storageFile;
|
|
260
|
+
storedData = await this.readAllFilesInDirectory(dir);//读取文件夹中的所有文件
|
|
261
|
+
} else {
|
|
262
|
+
// 1. 读取存储文件内容
|
|
263
|
+
fileContent = await fs.readFile(this.storageFile, 'utf-8')
|
|
264
|
+
storedData = JSON.parse(fileContent || '{}')
|
|
265
|
+
}
|
|
205
266
|
// 2. 自动创建存储中的实体(如果尚未定义)
|
|
206
267
|
Object.keys(storedData).forEach(entityName => {
|
|
207
268
|
if (!this.entities[entityName]) {
|
|
@@ -221,7 +282,6 @@ class JSONCRUD {
|
|
|
221
282
|
}))
|
|
222
283
|
}
|
|
223
284
|
})
|
|
224
|
-
|
|
225
285
|
} catch (err) {
|
|
226
286
|
if (err.code === 'ENOENT') {
|
|
227
287
|
// 4. 文件不存在时初始化空文件
|
|
@@ -240,9 +300,9 @@ class JSONCRUD {
|
|
|
240
300
|
}
|
|
241
301
|
|
|
242
302
|
// 通用保存方法
|
|
243
|
-
async persist() {
|
|
303
|
+
async persist(entityName) {
|
|
244
304
|
if (this.useMemory) return
|
|
245
|
-
await this.saveToFile()
|
|
305
|
+
await this.saveToFile(entityName)
|
|
246
306
|
}
|
|
247
307
|
|
|
248
308
|
}
|
package/package.json
CHANGED
package/tool/checkjs.js
CHANGED
|
@@ -250,7 +250,8 @@ module.exports.start = async function() {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
reportData.data = {
|
|
253
|
-
errorCount: errKeys.length
|
|
253
|
+
errorCount: errKeys.length,
|
|
254
|
+
undefCount: undefKeys.length, // 未定义总数
|
|
254
255
|
warnCount: warnKeys.length,
|
|
255
256
|
tipCount: infoKeys.length,
|
|
256
257
|
fileSize: fileSize,
|
|
@@ -281,7 +282,7 @@ module.exports.start = async function() {
|
|
|
281
282
|
webhookList.push(`1. js语法undefined:${undefKeys.length}个,占比${calc(undefKeys.length, jsFiles.length)}`);
|
|
282
283
|
|
|
283
284
|
// 随机显示5个异常文件到钉钉消息
|
|
284
|
-
var errCount = reportData.data.errCount;
|
|
285
|
+
var errCount = reportData.data.errCount + reportData.data.undefCount;
|
|
285
286
|
/*
|
|
286
287
|
if (errCount > 0) {
|
|
287
288
|
var list0 = [];
|
package/tool/compress.js
CHANGED
|
@@ -88,6 +88,11 @@ function doCompress() {
|
|
|
88
88
|
inNames = ['grid.js', 'controlsEx.js', 'treeView.js', 'print.js', 'workflow.js', '../../Carpa.Dress/Dress.js', 'htmlEditor.js'];
|
|
89
89
|
compressCrabaJs(inNames, 'crabaEx.min.js');
|
|
90
90
|
|
|
91
|
+
// workflow流程图
|
|
92
|
+
//inNames = ['workflow.js'];
|
|
93
|
+
//compressCrabaJs(inNames, 'workflow.js');
|
|
94
|
+
|
|
95
|
+
|
|
91
96
|
// echarts
|
|
92
97
|
inNames = ['echarts4-all.js'];
|
|
93
98
|
compressCrabaJs(inNames, 'echarts-all.js');
|
package/tool/gspxHash.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
var config = require('../lib/config.js');
|
|
3
|
-
var path = require('path');
|
|
4
|
-
var fs = require('fs');
|
|
5
|
-
var utils = require('../lib/utils.js');
|
|
6
|
-
var os = require('os');
|
|
7
|
-
const crypto = require('crypto');
|
|
8
|
-
var requestSync = require('sync-request');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
module.exports.start = function() {
|
|
12
|
-
if (!config.hashName) {
|
|
13
|
-
config.hashName = 'sha384';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (!config.files) {
|
|
17
|
-
config.files = [];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
var results = {};
|
|
21
|
-
buildFiles(results, config.files);
|
|
22
|
-
|
|
23
|
-
utils.mkdirsSync(config.outJson);
|
|
24
|
-
fs.writeFileSync(config.outJson, JSON.stringify(results));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function buildFiles(results, files) {
|
|
28
|
-
files.forEach(function(f) {
|
|
29
|
-
console.log(f);
|
|
30
|
-
|
|
31
|
-
var content;
|
|
32
|
-
var isHttp = f.startsWith('http');
|
|
33
|
-
if (isHttp) {
|
|
34
|
-
var res = requestSync("GET", f);
|
|
35
|
-
content = res.getBody();
|
|
36
|
-
} else if (fs.existsSync(f)) {
|
|
37
|
-
|
|
38
|
-
// 磁盘目录
|
|
39
|
-
var statFs = fs.statSync(f);
|
|
40
|
-
if (!statFs.isFile()) {
|
|
41
|
-
var files2 = fs.readdirSync(f);
|
|
42
|
-
files2 = files2.map(function(s) {
|
|
43
|
-
return utils.join(f, s);
|
|
44
|
-
});
|
|
45
|
-
buildFiles(results, files2);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (config.exts && config.exts.length > 0) {
|
|
50
|
-
var ext = path.extname(f).toLowerCase();
|
|
51
|
-
if (!config.exts.includes(ext)) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
content = fs.readFileSync(f);
|
|
57
|
-
} else {
|
|
58
|
-
console.error('文件不存在:' + f);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
var index = f.indexOf('?');
|
|
63
|
-
if (index > 0) {
|
|
64
|
-
f = f.substr(0, index);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// 转为相对webPath的路径
|
|
68
|
-
if (!isHttp) {
|
|
69
|
-
f = path.resolve(f);
|
|
70
|
-
var webPath = path.resolve(config.webPath);
|
|
71
|
-
f = f.replace(webPath, '');
|
|
72
|
-
if (config.modName) {
|
|
73
|
-
f = path.join(config.modName, f);
|
|
74
|
-
}
|
|
75
|
-
f = f.replace(/\\/g, '/');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// SRI Hash Generator
|
|
79
|
-
// https://www.srihash.org/
|
|
80
|
-
|
|
81
|
-
var base64 = makeHash(content, config.hashName); // 将文件内容进行hash计算
|
|
82
|
-
results[f] = config.hashName + '-' + base64; // 使用 base64 编码 sha384 算法计算出摘要后的 integrity 值的示例
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function makeHash(str, name) {
|
|
87
|
-
const hash = crypto.createHash(name);
|
|
88
|
-
hash.update(str);
|
|
89
|
-
return hash.digest('base64');
|
|
90
|
-
}
|