w-orm-lowdb 1.0.0 → 1.0.2

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/src/WOrmLowdb.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import events from 'events'
2
2
  import { Low } from 'lowdb'
3
3
  import { JSONFile } from 'lowdb/node'
4
- import { Query } from 'mingo'
4
+ import { Query } from 'mingo' //須指定安裝6.5.6, 若6.6.0無法匯入Query
5
+ import { Mutex } from 'async-mutex'
5
6
  import get from 'lodash-es/get.js'
6
7
  import each from 'lodash-es/each.js'
7
8
  import map from 'lodash-es/map.js'
@@ -58,10 +59,13 @@ function WOrmLowdb(opt = {}) {
58
59
  //lowdb
59
60
  let lowdb = new Low(adapter, {})
60
61
 
61
- //default
62
- if (!haskey(lowdb.data, key)) {
63
- lowdb.data[key] = []
64
- }
62
+ //mutex
63
+ let mutex = new Mutex()
64
+
65
+ // //default, 此處偵測會失效, 因操作函數內會通過lowdb.read()初始化, 預設創建空陣列會被取代
66
+ // if (!haskey(lowdb.data, key)) {
67
+ // lowdb.data[key] = []
68
+ // }
65
69
 
66
70
  //ee
67
71
  let ee = new events.EventEmitter()
@@ -83,6 +87,11 @@ function WOrmLowdb(opt = {}) {
83
87
  //read
84
88
  await lowdb.read()
85
89
 
90
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
91
+ if (!haskey(lowdb.data, key)) {
92
+ lowdb.data[key] = []
93
+ }
94
+
86
95
  //filter
87
96
  if (iseobj(find)) {
88
97
 
@@ -119,89 +128,96 @@ function WOrmLowdb(opt = {}) {
119
128
  * @returns {Promise} 回傳Promise,resolve回傳插入結果,reject回傳錯誤訊息
120
129
  */
121
130
  async function insert(data) {
122
- let isErr = false
131
+ return await mutex.runExclusive(async () => {
132
+ let isErr = false
123
133
 
124
- //check
125
- if (!iseobj(data) && !isearr(data)) {
126
- return Promise.reject(`data is not an effective object or array`)
127
- }
134
+ //check
135
+ if (!iseobj(data) && !isearr(data)) {
136
+ return Promise.reject(`data is not an effective object or array`)
137
+ }
128
138
 
129
- //cloneDeep, 與外部數據脫勾
130
- data = cloneDeep(data)
139
+ //cloneDeep, 與外部數據脫勾
140
+ data = cloneDeep(data)
131
141
 
132
- //res
133
- let res = null
134
- try {
142
+ //res
143
+ let res = null
144
+ try {
135
145
 
136
- //check
137
- if (!isarr(data)) {
138
- data = [data]
139
- }
146
+ //check
147
+ if (!isarr(data)) {
148
+ data = [data]
149
+ }
150
+
151
+ //check id
152
+ data = map(data, function(v) {
153
+ if (!isestr(v.id)) {
154
+ v.id = genID()
155
+ }
156
+ return v
157
+ })
158
+
159
+ //read
160
+ await lowdb.read()
140
161
 
141
- //check id
142
- data = map(data, function(v) {
143
- if (!isestr(v.id)) {
144
- v.id = genID()
162
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
163
+ if (!haskey(lowdb.data, key)) {
164
+ lowdb.data[key] = []
145
165
  }
146
- return v
147
- })
148
166
 
149
- //read
150
- await lowdb.read()
167
+ //kp
168
+ let kp = {}
169
+ each(lowdb.data[key], (v, k) => {
170
+ kp[v.id] = { k, v }
171
+ })
151
172
 
152
- //kp
153
- let kp = {}
154
- each(lowdb.data[key], (v, k) => {
155
- kp[v.id] = { k, v }
156
- })
173
+ //each
174
+ let nAll = size(data)
175
+ let nPush = 0
176
+ let b = false
177
+ each(data, (v) => {
157
178
 
158
- //each
159
- let nAll = size(data)
160
- let nPush = 0
161
- let b = false
162
- each(data, (v) => {
179
+ //check
180
+ if (!haskey(kp, v.id)) {
181
+ //未存在v.id
163
182
 
164
- //check
165
- if (!haskey(kp, v.id)) {
166
- //未存在v.id
183
+ //push
184
+ lowdb.data[key].push(v)
167
185
 
168
- //push
169
- lowdb.data[key].push(v)
186
+ nPush++
187
+ b = true
188
+ }
189
+ else {
190
+ //已存在v.id則不push
191
+ }
170
192
 
171
- nPush++
172
- b = true
193
+ })
194
+
195
+ //write
196
+ if (b) {
197
+ await lowdb.write()
173
198
  }
174
- else {
175
- //已存在v.id則不push
199
+
200
+ //res
201
+ res = {
202
+ n: nAll,
203
+ nInserted: nPush,
204
+ ok: 1,
176
205
  }
177
206
 
178
- })
207
+ //emit
208
+ ee.emit('change', 'insert', data, res)
179
209
 
180
- //write
181
- if (b) {
182
- await lowdb.write()
183
210
  }
184
-
185
- //res
186
- res = {
187
- n: nAll,
188
- nInserted: nPush,
189
- ok: 1,
211
+ catch (err) {
212
+ isErr = true
213
+ res = err
190
214
  }
191
215
 
192
- //emit
193
- ee.emit('change', 'insert', data, res)
194
-
195
- }
196
- catch (err) {
197
- isErr = true
198
- res = err
199
- }
200
-
201
- if (isErr) {
202
- return Promise.reject(res)
203
- }
204
- return res
216
+ if (isErr) {
217
+ return Promise.reject(res)
218
+ }
219
+ return res
220
+ })
205
221
  }
206
222
 
207
223
  /**
@@ -214,117 +230,121 @@ function WOrmLowdb(opt = {}) {
214
230
  * @returns {Promise} 回傳Promise,resolve回傳儲存結果,reject回傳錯誤訊息
215
231
  */
216
232
  async function save(data, option = {}) {
217
- let isErr = false
218
-
219
- //check
220
- if (!iseobj(data) && !isearr(data)) {
221
- return Promise.reject(`data is not an effective object or array`)
222
- }
233
+ return await mutex.runExclusive(async () => {
234
+ let isErr = false
223
235
 
224
- //cloneDeep, 與外部數據脫勾
225
- data = cloneDeep(data)
236
+ //check
237
+ if (!iseobj(data) && !isearr(data)) {
238
+ return Promise.reject(`data is not an effective object or array`)
239
+ }
226
240
 
227
- //autoInsert
228
- let autoInsert = get(option, 'autoInsert', true)
241
+ //cloneDeep, 與外部數據脫勾
242
+ data = cloneDeep(data)
229
243
 
230
- //res
231
- let res = null
232
- try {
244
+ //autoInsert
245
+ let autoInsert = get(option, 'autoInsert', true)
233
246
 
234
- //check
235
- if (!isarr(data)) {
236
- data = [data]
237
- }
247
+ //res
248
+ let res = null
249
+ try {
238
250
 
239
- //check id
240
- data = map(data, function(v) {
241
- if (!isestr(v.id)) {
242
- v.id = genID()
251
+ //check
252
+ if (!isarr(data)) {
253
+ data = [data]
243
254
  }
244
- return v
245
- })
246
255
 
247
- //read
248
- await lowdb.read()
256
+ //check id
257
+ data = map(data, function(v) {
258
+ if (!isestr(v.id)) {
259
+ v.id = genID()
260
+ }
261
+ return v
262
+ })
263
+
264
+ //read
265
+ await lowdb.read()
249
266
 
250
- //kp
251
- let kp = {}
252
- each(lowdb.data[key], (v, k) => {
253
- kp[v.id] = { k, v }
254
- })
267
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
268
+ if (!haskey(lowdb.data, key)) {
269
+ lowdb.data[key] = []
270
+ }
255
271
 
256
- //pmSeries
257
- let b = false
258
- res = await pmSeries(data, async(v) => {
272
+ //kp
273
+ let kp = {}
274
+ each(lowdb.data[key], (v, k) => {
275
+ kp[v.id] = { k, v }
276
+ })
259
277
 
260
- //rest
261
- let rest = null
278
+ //pmSeries
279
+ let b = false
280
+ res = await pmSeries(data, async(v) => {
262
281
 
263
- //id
264
- let id = get(v, 'id', '')
282
+ //rest
283
+ let rest = null
265
284
 
266
- //查找資料表內v.id為_v
267
- let r = get(kp, id, null)
285
+ //查找資料表內v.id
286
+ let r = get(kp, v.id, null)
268
287
 
269
- //check
270
- if (iseobj(r)) {
271
- //已存在v.id
272
- if (isEqual(v, r.v)) {
273
- //內容相同不更新
274
- }
275
- else {
276
- //內容不同須更新
288
+ //check
289
+ if (iseobj(r)) {
290
+ //已存在v.id
291
+ if (isEqual(v, r.v)) {
292
+ //內容相同不更新
293
+ }
294
+ else {
295
+ //內容不同須更新
277
296
 
278
- //merge
279
- lowdb.data[key][r.k] = merge(lowdb.data[key][r.k], v)
297
+ //merge
298
+ lowdb.data[key][r.k] = merge(lowdb.data[key][r.k], v)
280
299
 
281
- rest = { update: true }
282
- b = true
300
+ rest = { update: true }
301
+ b = true
302
+ }
283
303
  }
284
- }
285
304
 
286
- //rest
287
- if (iseobj(rest)) {
288
- rest = {
289
- n: 1,
290
- nModified: 1,
291
- ok: 1,
305
+ //rest
306
+ if (iseobj(rest)) {
307
+ rest = {
308
+ n: 1,
309
+ nModified: 1,
310
+ ok: 1,
311
+ }
292
312
  }
293
- }
294
- else {
295
- rest = {
296
- n: 0,
297
- nModified: 0,
298
- ok: 1,
313
+ else {
314
+ rest = {
315
+ n: 0,
316
+ nModified: 0,
317
+ ok: 1,
318
+ }
299
319
  }
300
- }
301
320
 
302
- //autoInsert
303
- if (autoInsert && rest.n === 0) {
304
- rest = await insert(v)
305
- }
321
+ //autoInsert
322
+ if (autoInsert && rest.n === 0) {
323
+ rest = await insert(v)
324
+ }
306
325
 
307
- return rest
308
- })
326
+ return rest
327
+ })
309
328
 
310
- //write
311
- if (b) {
312
- await lowdb.write()
313
- }
329
+ //write
330
+ if (b) {
331
+ await lowdb.write()
332
+ }
314
333
 
315
- //emit
316
- ee.emit('change', 'save', data, res)
334
+ //emit
335
+ ee.emit('change', 'save', data, res)
317
336
 
318
- }
319
- catch (err) {
320
- isErr = true
321
- res = err
322
- }
337
+ }
338
+ catch (err) {
339
+ isErr = true
340
+ res = err
341
+ }
323
342
 
324
- if (isErr) {
325
- return Promise.reject(res)
326
- }
327
- return res
343
+ if (isErr) {
344
+ return Promise.reject(res)
345
+ }
346
+ return res
347
+ })
328
348
  }
329
349
 
330
350
  /**
@@ -335,119 +355,126 @@ function WOrmLowdb(opt = {}) {
335
355
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
336
356
  */
337
357
  async function del(data) {
338
- let isErr = false
339
-
340
- //check
341
- if (!iseobj(data) && !isearr(data)) {
342
- return Promise.reject(`data is not an effective object or array`)
343
- }
344
-
345
- //cloneDeep, 與外部數據脫勾
346
- data = cloneDeep(data)
347
-
348
- //res
349
- let res = null
350
- try {
358
+ return await mutex.runExclusive(async () => {
359
+ let isErr = false
351
360
 
352
361
  //check
353
- if (!isarr(data)) {
354
- data = [data]
362
+ if (!iseobj(data) && !isearr(data)) {
363
+ return Promise.reject(`data is not an effective object or array`)
355
364
  }
356
365
 
357
- //read
358
- await lowdb.read()
366
+ //cloneDeep, 與外部數據脫勾
367
+ data = cloneDeep(data)
368
+
369
+ //res
370
+ let res = null
371
+ try {
359
372
 
360
- //kp
361
- let kp = {}
362
- each(lowdb.data[key], (v, k) => {
363
- kp[v.id] = { k, v }
364
- })
373
+ //check
374
+ if (!isarr(data)) {
375
+ data = [data]
376
+ }
365
377
 
366
- //pmSeries
367
- let ks = []
368
- let b = false
369
- res = await pmSeries(data, async(v) => {
378
+ //read
379
+ await lowdb.read()
370
380
 
371
- //rest
372
- let rest = null
381
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
382
+ if (!haskey(lowdb.data, key)) {
383
+ lowdb.data[key] = []
384
+ }
373
385
 
374
- //id
375
- let id = get(v, 'id', '')
386
+ //kp
387
+ let kp = {}
388
+ each(lowdb.data[key], (v, k) => {
389
+ kp[v.id] = { k, v }
390
+ })
376
391
 
377
- //check
378
- if (isestr(id)) {
392
+ //pmSeries
393
+ let ks = []
394
+ let b = false
395
+ res = await pmSeries(data, async(v) => {
379
396
 
380
- //查找資料表內v.id為_v
381
- let r = get(kp, id, null)
397
+ //rest
398
+ let rest = null
399
+
400
+ //id
401
+ let id = get(v, 'id', '')
382
402
 
383
403
  //check
384
- if (iseobj(r)) {
385
- //已存在v.id則須刪除
404
+ if (isestr(id)) {
386
405
 
387
- //push
388
- ks.push(r.k)
406
+ //查找資料表內v.id為_v
407
+ let r = get(kp, id, null)
389
408
 
390
- b = true
409
+ //check
410
+ if (iseobj(r)) {
411
+ //已存在v.id則須刪除
412
+
413
+ //push
414
+ ks.push(r.k)
415
+
416
+ b = true
417
+
418
+ //rest
419
+ rest = {
420
+ n: 1,
421
+ nDeleted: 1,
422
+ ok: 1,
423
+ }
424
+
425
+ }
426
+ else {
427
+ //不存在v.id則不刪除
428
+
429
+ //rest
430
+ rest = {
431
+ n: 1,
432
+ nDeleted: 0,
433
+ ok: 1,
434
+ }
391
435
 
392
- //rest
393
- rest = {
394
- n: 1,
395
- nDeleted: 1,
396
- ok: 1,
397
436
  }
398
437
 
399
438
  }
400
439
  else {
401
- //不存在v.id則不刪除
440
+ //未給v.id則不刪除
402
441
 
403
442
  //rest
404
443
  rest = {
405
444
  n: 1,
406
445
  nDeleted: 0,
407
- ok: 1,
446
+ ok: 0, //未給v.id視為有問題數據, 故ok給0
408
447
  }
409
448
 
410
449
  }
411
450
 
412
- }
413
- else {
414
- //未給v.id則不刪除
451
+ return rest
452
+ })
415
453
 
416
- //rest
417
- rest = {
418
- n: 1,
419
- nDeleted: 0,
420
- ok: 0, //未給v.id視為有問題數據, 故ok給0
421
- }
454
+ //update
455
+ if (b) {
456
+ lowdb.data[key] = arrPullAt(lowdb.data[key], ks)
457
+ }
422
458
 
459
+ //write
460
+ if (b) {
461
+ await lowdb.write()
423
462
  }
424
463
 
425
- return rest
426
- })
464
+ //emit
465
+ ee.emit('change', 'del', data, res)
427
466
 
428
- //update
429
- if (b) {
430
- lowdb.data[key] = arrPullAt(lowdb.data[key], ks)
431
467
  }
432
-
433
- //write
434
- if (b) {
435
- await lowdb.write()
468
+ catch (err) {
469
+ isErr = true
470
+ res = err
436
471
  }
437
472
 
438
- //emit
439
- ee.emit('change', 'del', data, res)
440
-
441
- }
442
- catch (err) {
443
- isErr = true
444
- res = err
445
- }
446
-
447
- if (isErr) {
448
- return Promise.reject(res)
449
- }
450
- return res
473
+ if (isErr) {
474
+ return Promise.reject(res)
475
+ }
476
+ return res
477
+ })
451
478
  }
452
479
 
453
480
  /**
@@ -458,104 +485,111 @@ function WOrmLowdb(opt = {}) {
458
485
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
459
486
  */
460
487
  async function delAll(find = {}) {
461
- let isErr = false
488
+ return await mutex.runExclusive(async () => {
489
+ let isErr = false
462
490
 
463
- //res
464
- let res = null
465
- try {
491
+ //res
492
+ let res = null
493
+ try {
466
494
 
467
- //read
468
- await lowdb.read()
495
+ //read
496
+ await lowdb.read()
469
497
 
470
- //filter
471
- let nAll = size(lowdb.data[key])
472
- let nDel = 0
473
- let b = false
474
- if (iseobj(find)) {
498
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
499
+ if (!haskey(lowdb.data, key)) {
500
+ lowdb.data[key] = []
501
+ }
475
502
 
476
- //q
477
- let q = new Query(find)
478
- // console.log('q', q)
503
+ //filter
504
+ let nAll = size(lowdb.data[key])
505
+ let nDel = 0
506
+ let b = false
507
+ if (iseobj(find)) {
479
508
 
480
- //find
481
- let _res = q.find(lowdb.data[key]).all()
482
- // console.log('_res', _res)
509
+ //q
510
+ let q = new Query(find)
511
+ // console.log('q', q)
483
512
 
484
- //nDel
485
- nDel = size(_res)
486
- // console.log('nDel', nDel)
513
+ //find
514
+ let _res = q.find(lowdb.data[key]).all()
515
+ // console.log('_res', _res)
516
+
517
+ //nDel
518
+ nDel = size(_res)
519
+ // console.log('nDel', nDel)
520
+
521
+ if (nDel === 0) {
522
+ //未有find結果等於不刪除
523
+ }
524
+ else if (nAll === nDel) {
525
+ //全在find結果內等於全部刪除
487
526
 
488
- if (nDel === 0) {
489
- //未有find結果等於不刪除
527
+ //empty
528
+ lowdb.data[key] = []
529
+
530
+ b = true
531
+ }
532
+ else {
533
+ //部份在find結果內
534
+
535
+ //_kp
536
+ let _kp = {}
537
+ each(_res, (v, k) => {
538
+ _kp[v.id] = { k, v }
539
+ })
540
+
541
+ //arr
542
+ let arr = []
543
+ each(lowdb.data[key], (v, k) => {
544
+ if (!haskey(_kp, v.id)) {
545
+ //未在find結果內代表須保留
546
+ arr.push(v)
547
+ }
548
+ })
549
+
550
+ //update
551
+ lowdb.data[key] = arr
552
+
553
+ b = true
554
+ }
490
555
  }
491
- else if (nAll === nDel) {
492
- //全在find結果內等於全部刪除
556
+ else {
557
+
558
+ //nDel
559
+ nDel = nAll
493
560
 
494
561
  //empty
495
562
  lowdb.data[key] = []
496
563
 
497
564
  b = true
498
565
  }
499
- else {
500
- //部份在find結果內
501
-
502
- //_kp
503
- let _kp = {}
504
- each(_res, (v, k) => {
505
- _kp[v.id] = { k, v }
506
- })
507
-
508
- //arr
509
- let arr = []
510
- each(lowdb.data[key], (v, k) => {
511
- if (!haskey(_kp, v.id)) {
512
- //未在find結果內代表須保留
513
- arr.push(v)
514
- }
515
- })
516
-
517
- //update
518
- lowdb.data[key] = arr
519
566
 
520
- b = true
567
+ //write
568
+ if (b) {
569
+ await lowdb.write()
521
570
  }
522
- }
523
- else {
524
571
 
525
- //nDel
526
- nDel = nAll
572
+ //res
573
+ res = {
574
+ n: nAll,
575
+ nDeleted: nDel,
576
+ ok: 1,
577
+ }
527
578
 
528
- //empty
529
- lowdb.data[key] = []
579
+ //emit
580
+ ee.emit('change', 'delAll', null, res)
530
581
 
531
- b = true
532
582
  }
533
-
534
- //write
535
- if (b) {
536
- await lowdb.write()
583
+ catch (err) {
584
+ isErr = true
585
+ res = err
537
586
  }
538
587
 
539
- //res
540
- res = {
541
- n: nAll,
542
- nDeleted: nDel,
543
- ok: 1,
588
+ if (isErr) {
589
+ return Promise.reject(res)
544
590
  }
545
-
546
- //emit
547
- ee.emit('change', 'delAll', null, res)
548
-
549
- }
550
- catch (err) {
551
- isErr = true
552
- res = err
553
- }
554
-
555
- if (isErr) {
556
- return Promise.reject(res)
557
- }
558
- return res
591
+ return res
592
+ })
559
593
  }
560
594
 
561
595
  //bind