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.
@@ -48,7 +48,8 @@
48
48
  <pre class="prettyprint source linenums"><code>import events from 'events'
49
49
  import { Low } from 'lowdb'
50
50
  import { JSONFile } from 'lowdb/node'
51
- import { Query } from 'mingo'
51
+ import { Query } from 'mingo' //須指定安裝6.5.6, 若6.6.0無法匯入Query
52
+ import { Mutex } from 'async-mutex'
52
53
  import get from 'lodash-es/get.js'
53
54
  import each from 'lodash-es/each.js'
54
55
  import map from 'lodash-es/map.js'
@@ -105,10 +106,13 @@ function WOrmLowdb(opt = {}) {
105
106
  //lowdb
106
107
  let lowdb = new Low(adapter, {})
107
108
 
108
- //default
109
- if (!haskey(lowdb.data, key)) {
110
- lowdb.data[key] = []
111
- }
109
+ //mutex
110
+ let mutex = new Mutex()
111
+
112
+ // //default, 此處偵測會失效, 因操作函數內會通過lowdb.read()初始化, 預設創建空陣列會被取代
113
+ // if (!haskey(lowdb.data, key)) {
114
+ // lowdb.data[key] = []
115
+ // }
112
116
 
113
117
  //ee
114
118
  let ee = new events.EventEmitter()
@@ -130,6 +134,11 @@ function WOrmLowdb(opt = {}) {
130
134
  //read
131
135
  await lowdb.read()
132
136
 
137
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
138
+ if (!haskey(lowdb.data, key)) {
139
+ lowdb.data[key] = []
140
+ }
141
+
133
142
  //filter
134
143
  if (iseobj(find)) {
135
144
 
@@ -166,89 +175,96 @@ function WOrmLowdb(opt = {}) {
166
175
  * @returns {Promise} 回傳Promise,resolve回傳插入結果,reject回傳錯誤訊息
167
176
  */
168
177
  async function insert(data) {
169
- let isErr = false
178
+ return await mutex.runExclusive(async () => {
179
+ let isErr = false
170
180
 
171
- //check
172
- if (!iseobj(data) &amp;&amp; !isearr(data)) {
173
- return Promise.reject(`data is not an effective object or array`)
174
- }
181
+ //check
182
+ if (!iseobj(data) &amp;&amp; !isearr(data)) {
183
+ return Promise.reject(`data is not an effective object or array`)
184
+ }
175
185
 
176
- //cloneDeep, 與外部數據脫勾
177
- data = cloneDeep(data)
186
+ //cloneDeep, 與外部數據脫勾
187
+ data = cloneDeep(data)
178
188
 
179
- //res
180
- let res = null
181
- try {
189
+ //res
190
+ let res = null
191
+ try {
182
192
 
183
- //check
184
- if (!isarr(data)) {
185
- data = [data]
186
- }
193
+ //check
194
+ if (!isarr(data)) {
195
+ data = [data]
196
+ }
197
+
198
+ //check id
199
+ data = map(data, function(v) {
200
+ if (!isestr(v.id)) {
201
+ v.id = genID()
202
+ }
203
+ return v
204
+ })
205
+
206
+ //read
207
+ await lowdb.read()
187
208
 
188
- //check id
189
- data = map(data, function(v) {
190
- if (!isestr(v.id)) {
191
- v.id = genID()
209
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
210
+ if (!haskey(lowdb.data, key)) {
211
+ lowdb.data[key] = []
192
212
  }
193
- return v
194
- })
195
213
 
196
- //read
197
- await lowdb.read()
214
+ //kp
215
+ let kp = {}
216
+ each(lowdb.data[key], (v, k) => {
217
+ kp[v.id] = { k, v }
218
+ })
198
219
 
199
- //kp
200
- let kp = {}
201
- each(lowdb.data[key], (v, k) => {
202
- kp[v.id] = { k, v }
203
- })
220
+ //each
221
+ let nAll = size(data)
222
+ let nPush = 0
223
+ let b = false
224
+ each(data, (v) => {
204
225
 
205
- //each
206
- let nAll = size(data)
207
- let nPush = 0
208
- let b = false
209
- each(data, (v) => {
226
+ //check
227
+ if (!haskey(kp, v.id)) {
228
+ //未存在v.id
210
229
 
211
- //check
212
- if (!haskey(kp, v.id)) {
213
- //未存在v.id
230
+ //push
231
+ lowdb.data[key].push(v)
214
232
 
215
- //push
216
- lowdb.data[key].push(v)
233
+ nPush++
234
+ b = true
235
+ }
236
+ else {
237
+ //已存在v.id則不push
238
+ }
217
239
 
218
- nPush++
219
- b = true
240
+ })
241
+
242
+ //write
243
+ if (b) {
244
+ await lowdb.write()
220
245
  }
221
- else {
222
- //已存在v.id則不push
246
+
247
+ //res
248
+ res = {
249
+ n: nAll,
250
+ nInserted: nPush,
251
+ ok: 1,
223
252
  }
224
253
 
225
- })
254
+ //emit
255
+ ee.emit('change', 'insert', data, res)
226
256
 
227
- //write
228
- if (b) {
229
- await lowdb.write()
230
257
  }
231
-
232
- //res
233
- res = {
234
- n: nAll,
235
- nInserted: nPush,
236
- ok: 1,
258
+ catch (err) {
259
+ isErr = true
260
+ res = err
237
261
  }
238
262
 
239
- //emit
240
- ee.emit('change', 'insert', data, res)
241
-
242
- }
243
- catch (err) {
244
- isErr = true
245
- res = err
246
- }
247
-
248
- if (isErr) {
249
- return Promise.reject(res)
250
- }
251
- return res
263
+ if (isErr) {
264
+ return Promise.reject(res)
265
+ }
266
+ return res
267
+ })
252
268
  }
253
269
 
254
270
  /**
@@ -261,117 +277,121 @@ function WOrmLowdb(opt = {}) {
261
277
  * @returns {Promise} 回傳Promise,resolve回傳儲存結果,reject回傳錯誤訊息
262
278
  */
263
279
  async function save(data, option = {}) {
264
- let isErr = false
265
-
266
- //check
267
- if (!iseobj(data) &amp;&amp; !isearr(data)) {
268
- return Promise.reject(`data is not an effective object or array`)
269
- }
280
+ return await mutex.runExclusive(async () => {
281
+ let isErr = false
270
282
 
271
- //cloneDeep, 與外部數據脫勾
272
- data = cloneDeep(data)
283
+ //check
284
+ if (!iseobj(data) &amp;&amp; !isearr(data)) {
285
+ return Promise.reject(`data is not an effective object or array`)
286
+ }
273
287
 
274
- //autoInsert
275
- let autoInsert = get(option, 'autoInsert', true)
288
+ //cloneDeep, 與外部數據脫勾
289
+ data = cloneDeep(data)
276
290
 
277
- //res
278
- let res = null
279
- try {
291
+ //autoInsert
292
+ let autoInsert = get(option, 'autoInsert', true)
280
293
 
281
- //check
282
- if (!isarr(data)) {
283
- data = [data]
284
- }
294
+ //res
295
+ let res = null
296
+ try {
285
297
 
286
- //check id
287
- data = map(data, function(v) {
288
- if (!isestr(v.id)) {
289
- v.id = genID()
298
+ //check
299
+ if (!isarr(data)) {
300
+ data = [data]
290
301
  }
291
- return v
292
- })
293
302
 
294
- //read
295
- await lowdb.read()
303
+ //check id
304
+ data = map(data, function(v) {
305
+ if (!isestr(v.id)) {
306
+ v.id = genID()
307
+ }
308
+ return v
309
+ })
310
+
311
+ //read
312
+ await lowdb.read()
296
313
 
297
- //kp
298
- let kp = {}
299
- each(lowdb.data[key], (v, k) => {
300
- kp[v.id] = { k, v }
301
- })
314
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
315
+ if (!haskey(lowdb.data, key)) {
316
+ lowdb.data[key] = []
317
+ }
302
318
 
303
- //pmSeries
304
- let b = false
305
- res = await pmSeries(data, async(v) => {
319
+ //kp
320
+ let kp = {}
321
+ each(lowdb.data[key], (v, k) => {
322
+ kp[v.id] = { k, v }
323
+ })
306
324
 
307
- //rest
308
- let rest = null
325
+ //pmSeries
326
+ let b = false
327
+ res = await pmSeries(data, async(v) => {
309
328
 
310
- //id
311
- let id = get(v, 'id', '')
329
+ //rest
330
+ let rest = null
312
331
 
313
- //查找資料表內v.id為_v
314
- let r = get(kp, id, null)
332
+ //查找資料表內v.id
333
+ let r = get(kp, v.id, null)
315
334
 
316
- //check
317
- if (iseobj(r)) {
318
- //已存在v.id
319
- if (isEqual(v, r.v)) {
320
- //內容相同不更新
321
- }
322
- else {
323
- //內容不同須更新
335
+ //check
336
+ if (iseobj(r)) {
337
+ //已存在v.id
338
+ if (isEqual(v, r.v)) {
339
+ //內容相同不更新
340
+ }
341
+ else {
342
+ //內容不同須更新
324
343
 
325
- //merge
326
- lowdb.data[key][r.k] = merge(lowdb.data[key][r.k], v)
344
+ //merge
345
+ lowdb.data[key][r.k] = merge(lowdb.data[key][r.k], v)
327
346
 
328
- rest = { update: true }
329
- b = true
347
+ rest = { update: true }
348
+ b = true
349
+ }
330
350
  }
331
- }
332
351
 
333
- //rest
334
- if (iseobj(rest)) {
335
- rest = {
336
- n: 1,
337
- nModified: 1,
338
- ok: 1,
352
+ //rest
353
+ if (iseobj(rest)) {
354
+ rest = {
355
+ n: 1,
356
+ nModified: 1,
357
+ ok: 1,
358
+ }
339
359
  }
340
- }
341
- else {
342
- rest = {
343
- n: 0,
344
- nModified: 0,
345
- ok: 1,
360
+ else {
361
+ rest = {
362
+ n: 0,
363
+ nModified: 0,
364
+ ok: 1,
365
+ }
346
366
  }
347
- }
348
367
 
349
- //autoInsert
350
- if (autoInsert &amp;&amp; rest.n === 0) {
351
- rest = await insert(v)
352
- }
368
+ //autoInsert
369
+ if (autoInsert &amp;&amp; rest.n === 0) {
370
+ rest = await insert(v)
371
+ }
353
372
 
354
- return rest
355
- })
373
+ return rest
374
+ })
356
375
 
357
- //write
358
- if (b) {
359
- await lowdb.write()
360
- }
376
+ //write
377
+ if (b) {
378
+ await lowdb.write()
379
+ }
361
380
 
362
- //emit
363
- ee.emit('change', 'save', data, res)
381
+ //emit
382
+ ee.emit('change', 'save', data, res)
364
383
 
365
- }
366
- catch (err) {
367
- isErr = true
368
- res = err
369
- }
384
+ }
385
+ catch (err) {
386
+ isErr = true
387
+ res = err
388
+ }
370
389
 
371
- if (isErr) {
372
- return Promise.reject(res)
373
- }
374
- return res
390
+ if (isErr) {
391
+ return Promise.reject(res)
392
+ }
393
+ return res
394
+ })
375
395
  }
376
396
 
377
397
  /**
@@ -382,119 +402,126 @@ function WOrmLowdb(opt = {}) {
382
402
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
383
403
  */
384
404
  async function del(data) {
385
- let isErr = false
386
-
387
- //check
388
- if (!iseobj(data) &amp;&amp; !isearr(data)) {
389
- return Promise.reject(`data is not an effective object or array`)
390
- }
391
-
392
- //cloneDeep, 與外部數據脫勾
393
- data = cloneDeep(data)
394
-
395
- //res
396
- let res = null
397
- try {
405
+ return await mutex.runExclusive(async () => {
406
+ let isErr = false
398
407
 
399
408
  //check
400
- if (!isarr(data)) {
401
- data = [data]
409
+ if (!iseobj(data) &amp;&amp; !isearr(data)) {
410
+ return Promise.reject(`data is not an effective object or array`)
402
411
  }
403
412
 
404
- //read
405
- await lowdb.read()
413
+ //cloneDeep, 與外部數據脫勾
414
+ data = cloneDeep(data)
415
+
416
+ //res
417
+ let res = null
418
+ try {
406
419
 
407
- //kp
408
- let kp = {}
409
- each(lowdb.data[key], (v, k) => {
410
- kp[v.id] = { k, v }
411
- })
420
+ //check
421
+ if (!isarr(data)) {
422
+ data = [data]
423
+ }
412
424
 
413
- //pmSeries
414
- let ks = []
415
- let b = false
416
- res = await pmSeries(data, async(v) => {
425
+ //read
426
+ await lowdb.read()
417
427
 
418
- //rest
419
- let rest = null
428
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
429
+ if (!haskey(lowdb.data, key)) {
430
+ lowdb.data[key] = []
431
+ }
420
432
 
421
- //id
422
- let id = get(v, 'id', '')
433
+ //kp
434
+ let kp = {}
435
+ each(lowdb.data[key], (v, k) => {
436
+ kp[v.id] = { k, v }
437
+ })
423
438
 
424
- //check
425
- if (isestr(id)) {
439
+ //pmSeries
440
+ let ks = []
441
+ let b = false
442
+ res = await pmSeries(data, async(v) => {
426
443
 
427
- //查找資料表內v.id為_v
428
- let r = get(kp, id, null)
444
+ //rest
445
+ let rest = null
446
+
447
+ //id
448
+ let id = get(v, 'id', '')
429
449
 
430
450
  //check
431
- if (iseobj(r)) {
432
- //已存在v.id則須刪除
451
+ if (isestr(id)) {
433
452
 
434
- //push
435
- ks.push(r.k)
453
+ //查找資料表內v.id為_v
454
+ let r = get(kp, id, null)
436
455
 
437
- b = true
456
+ //check
457
+ if (iseobj(r)) {
458
+ //已存在v.id則須刪除
459
+
460
+ //push
461
+ ks.push(r.k)
462
+
463
+ b = true
464
+
465
+ //rest
466
+ rest = {
467
+ n: 1,
468
+ nDeleted: 1,
469
+ ok: 1,
470
+ }
471
+
472
+ }
473
+ else {
474
+ //不存在v.id則不刪除
475
+
476
+ //rest
477
+ rest = {
478
+ n: 1,
479
+ nDeleted: 0,
480
+ ok: 1,
481
+ }
438
482
 
439
- //rest
440
- rest = {
441
- n: 1,
442
- nDeleted: 1,
443
- ok: 1,
444
483
  }
445
484
 
446
485
  }
447
486
  else {
448
- //不存在v.id則不刪除
487
+ //未給v.id則不刪除
449
488
 
450
489
  //rest
451
490
  rest = {
452
491
  n: 1,
453
492
  nDeleted: 0,
454
- ok: 1,
493
+ ok: 0, //未給v.id視為有問題數據, 故ok給0
455
494
  }
456
495
 
457
496
  }
458
497
 
459
- }
460
- else {
461
- //未給v.id則不刪除
498
+ return rest
499
+ })
462
500
 
463
- //rest
464
- rest = {
465
- n: 1,
466
- nDeleted: 0,
467
- ok: 0, //未給v.id視為有問題數據, 故ok給0
468
- }
501
+ //update
502
+ if (b) {
503
+ lowdb.data[key] = arrPullAt(lowdb.data[key], ks)
504
+ }
469
505
 
506
+ //write
507
+ if (b) {
508
+ await lowdb.write()
470
509
  }
471
510
 
472
- return rest
473
- })
511
+ //emit
512
+ ee.emit('change', 'del', data, res)
474
513
 
475
- //update
476
- if (b) {
477
- lowdb.data[key] = arrPullAt(lowdb.data[key], ks)
478
514
  }
479
-
480
- //write
481
- if (b) {
482
- await lowdb.write()
515
+ catch (err) {
516
+ isErr = true
517
+ res = err
483
518
  }
484
519
 
485
- //emit
486
- ee.emit('change', 'del', data, res)
487
-
488
- }
489
- catch (err) {
490
- isErr = true
491
- res = err
492
- }
493
-
494
- if (isErr) {
495
- return Promise.reject(res)
496
- }
497
- return res
520
+ if (isErr) {
521
+ return Promise.reject(res)
522
+ }
523
+ return res
524
+ })
498
525
  }
499
526
 
500
527
  /**
@@ -505,104 +532,111 @@ function WOrmLowdb(opt = {}) {
505
532
  * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
506
533
  */
507
534
  async function delAll(find = {}) {
508
- let isErr = false
535
+ return await mutex.runExclusive(async () => {
536
+ let isErr = false
509
537
 
510
- //res
511
- let res = null
512
- try {
538
+ //res
539
+ let res = null
540
+ try {
513
541
 
514
- //read
515
- await lowdb.read()
542
+ //read
543
+ await lowdb.read()
516
544
 
517
- //filter
518
- let nAll = size(lowdb.data[key])
519
- let nDel = 0
520
- let b = false
521
- if (iseobj(find)) {
545
+ //default, 使用lowdb.read()初始化後須馬上檢測, 若無key則須先創建空陣列
546
+ if (!haskey(lowdb.data, key)) {
547
+ lowdb.data[key] = []
548
+ }
522
549
 
523
- //q
524
- let q = new Query(find)
525
- // console.log('q', q)
550
+ //filter
551
+ let nAll = size(lowdb.data[key])
552
+ let nDel = 0
553
+ let b = false
554
+ if (iseobj(find)) {
526
555
 
527
- //find
528
- let _res = q.find(lowdb.data[key]).all()
529
- // console.log('_res', _res)
556
+ //q
557
+ let q = new Query(find)
558
+ // console.log('q', q)
530
559
 
531
- //nDel
532
- nDel = size(_res)
533
- // console.log('nDel', nDel)
560
+ //find
561
+ let _res = q.find(lowdb.data[key]).all()
562
+ // console.log('_res', _res)
563
+
564
+ //nDel
565
+ nDel = size(_res)
566
+ // console.log('nDel', nDel)
567
+
568
+ if (nDel === 0) {
569
+ //未有find結果等於不刪除
570
+ }
571
+ else if (nAll === nDel) {
572
+ //全在find結果內等於全部刪除
534
573
 
535
- if (nDel === 0) {
536
- //未有find結果等於不刪除
574
+ //empty
575
+ lowdb.data[key] = []
576
+
577
+ b = true
578
+ }
579
+ else {
580
+ //部份在find結果內
581
+
582
+ //_kp
583
+ let _kp = {}
584
+ each(_res, (v, k) => {
585
+ _kp[v.id] = { k, v }
586
+ })
587
+
588
+ //arr
589
+ let arr = []
590
+ each(lowdb.data[key], (v, k) => {
591
+ if (!haskey(_kp, v.id)) {
592
+ //未在find結果內代表須保留
593
+ arr.push(v)
594
+ }
595
+ })
596
+
597
+ //update
598
+ lowdb.data[key] = arr
599
+
600
+ b = true
601
+ }
537
602
  }
538
- else if (nAll === nDel) {
539
- //全在find結果內等於全部刪除
603
+ else {
604
+
605
+ //nDel
606
+ nDel = nAll
540
607
 
541
608
  //empty
542
609
  lowdb.data[key] = []
543
610
 
544
611
  b = true
545
612
  }
546
- else {
547
- //部份在find結果內
548
-
549
- //_kp
550
- let _kp = {}
551
- each(_res, (v, k) => {
552
- _kp[v.id] = { k, v }
553
- })
554
-
555
- //arr
556
- let arr = []
557
- each(lowdb.data[key], (v, k) => {
558
- if (!haskey(_kp, v.id)) {
559
- //未在find結果內代表須保留
560
- arr.push(v)
561
- }
562
- })
563
-
564
- //update
565
- lowdb.data[key] = arr
566
613
 
567
- b = true
614
+ //write
615
+ if (b) {
616
+ await lowdb.write()
568
617
  }
569
- }
570
- else {
571
618
 
572
- //nDel
573
- nDel = nAll
619
+ //res
620
+ res = {
621
+ n: nAll,
622
+ nDeleted: nDel,
623
+ ok: 1,
624
+ }
574
625
 
575
- //empty
576
- lowdb.data[key] = []
626
+ //emit
627
+ ee.emit('change', 'delAll', null, res)
577
628
 
578
- b = true
579
629
  }
580
-
581
- //write
582
- if (b) {
583
- await lowdb.write()
630
+ catch (err) {
631
+ isErr = true
632
+ res = err
584
633
  }
585
634
 
586
- //res
587
- res = {
588
- n: nAll,
589
- nDeleted: nDel,
590
- ok: 1,
635
+ if (isErr) {
636
+ return Promise.reject(res)
591
637
  }
592
-
593
- //emit
594
- ee.emit('change', 'delAll', null, res)
595
-
596
- }
597
- catch (err) {
598
- isErr = true
599
- res = err
600
- }
601
-
602
- if (isErr) {
603
- return Promise.reject(res)
604
- }
605
- return res
638
+ return res
639
+ })
606
640
  }
607
641
 
608
642
  //bind
@@ -631,7 +665,7 @@ export default WOrmLowdb
631
665
  <br class="clear">
632
666
 
633
667
  <footer>
634
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.4</a> on Tue Mar 18 2025 21:23:44 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
668
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.4</a> on Fri May 09 2025 11:30:47 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
635
669
  </footer>
636
670
 
637
671
  <script>prettyPrint();</script>