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