w-orm-lowdb 1.0.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.
Files changed (53) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.js +55 -0
  4. package/.jsdoc +25 -0
  5. package/LICENSE +21 -0
  6. package/README.md +162 -0
  7. package/SECURITY.md +5 -0
  8. package/babel.config.js +15 -0
  9. package/db.json +14 -0
  10. package/dist/w-orm-lowdb.umd.js +7 -0
  11. package/dist/w-orm-lowdb.umd.js.map +1 -0
  12. package/docs/WOrmLowdb.html +1406 -0
  13. package/docs/WOrmLowdb.mjs.html +644 -0
  14. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  15. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  16. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  17. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  18. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  19. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  20. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  21. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  22. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  23. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  24. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  25. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  26. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  27. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  28. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  29. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  30. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  31. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  32. package/docs/index.html +84 -0
  33. package/docs/scripts/collapse.js +39 -0
  34. package/docs/scripts/commonNav.js +28 -0
  35. package/docs/scripts/linenumber.js +25 -0
  36. package/docs/scripts/nav.js +12 -0
  37. package/docs/scripts/polyfill.js +4 -0
  38. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  39. package/docs/scripts/prettify/lang-css.js +2 -0
  40. package/docs/scripts/prettify/prettify.js +28 -0
  41. package/docs/scripts/search.js +99 -0
  42. package/docs/styles/jsdoc.css +776 -0
  43. package/docs/styles/prettify.css +80 -0
  44. package/g-basic.mjs +178 -0
  45. package/g.mjs +24 -0
  46. package/package.json +32 -0
  47. package/script.txt +18 -0
  48. package/src/WOrmLowdb.mjs +572 -0
  49. package/test/basic.test.mjs +376 -0
  50. package/toolg/addVersion.mjs +4 -0
  51. package/toolg/cleanFolder.mjs +4 -0
  52. package/toolg/gDistRollup.mjs +23 -0
  53. package/toolg/modifyReadme.mjs +4 -0
@@ -0,0 +1,572 @@
1
+ import events from 'events'
2
+ import { Low } from 'lowdb'
3
+ import { JSONFile } from 'lowdb/node'
4
+ import { Query } from 'mingo'
5
+ import get from 'lodash-es/get.js'
6
+ import each from 'lodash-es/each.js'
7
+ import map from 'lodash-es/map.js'
8
+ import merge from 'lodash-es/merge.js'
9
+ import isEqual from 'lodash-es/isEqual.js'
10
+ import size from 'lodash-es/size.js'
11
+ import cloneDeep from 'lodash-es/cloneDeep.js'
12
+ import genID from 'wsemi/src/genID.mjs'
13
+ import pmSeries from 'wsemi/src/pmSeries.mjs'
14
+ import isarr from 'wsemi/src/isarr.mjs'
15
+ import isestr from 'wsemi/src/isestr.mjs'
16
+ import iseobj from 'wsemi/src/iseobj.mjs'
17
+ import isearr from 'wsemi/src/isearr.mjs'
18
+ import haskey from 'wsemi/src/haskey.mjs'
19
+ import arrPullAt from 'wsemi/src/arrPullAt.mjs'
20
+
21
+
22
+ /**
23
+ * 操作資料庫(lowdb)
24
+ *
25
+ * @class
26
+ * @param {Object} [opt={}] 輸入設定物件,預設{}
27
+ * @param {String} [opt.url='./db.json'] 輸入資料庫位置字串,預設'./db.json'
28
+ * @param {String} [opt.db='worm'] 輸入使用資料庫名稱字串,預設'worm'
29
+ * @param {String} [opt.cl='test'] 輸入使用資料表名稱字串,預設'test'
30
+ * @returns {Object} 回傳操作資料庫物件,各事件功能詳見說明
31
+ */
32
+ function WOrmLowdb(opt = {}) {
33
+
34
+ //url
35
+ let url = get(opt, 'url')
36
+ if (!isestr(url)) {
37
+ url = './db.json'
38
+ }
39
+
40
+ //db
41
+ let db = get(opt, 'db')
42
+ if (!isestr(db)) {
43
+ db = 'worm'
44
+ }
45
+
46
+ //cl
47
+ let cl = get(opt, 'cl')
48
+ if (!isestr(cl)) {
49
+ cl = 'test'
50
+ }
51
+
52
+ //key
53
+ let key = `${db}:${cl}`
54
+
55
+ //adapter
56
+ let adapter = new JSONFile(url)
57
+
58
+ //lowdb
59
+ let lowdb = new Low(adapter, {})
60
+
61
+ //default
62
+ if (!haskey(lowdb.data, key)) {
63
+ lowdb.data[key] = []
64
+ }
65
+
66
+ //ee
67
+ let ee = new events.EventEmitter()
68
+
69
+ /**
70
+ * 查詢數據
71
+ *
72
+ * @memberOf WOrmLowdb
73
+ * @param {Object} [find={}] 輸入查詢條件物件
74
+ * @returns {Promise} 回傳Promise,resolve回傳數據,reject回傳錯誤訊息
75
+ */
76
+ async function select(find = {}) {
77
+ let isErr = false
78
+
79
+ //res
80
+ let res = null
81
+ try {
82
+
83
+ //read
84
+ await lowdb.read()
85
+
86
+ //filter
87
+ if (iseobj(find)) {
88
+
89
+ //q
90
+ let q = new Query(find)
91
+ // console.log('q', q)
92
+
93
+ //find
94
+ res = q.find(lowdb.data[key]).all()
95
+ // console.log('res', res)
96
+
97
+ }
98
+ else {
99
+ res = lowdb.data[key]
100
+ }
101
+
102
+ }
103
+ catch (err) {
104
+ isErr = true
105
+ res = err
106
+ }
107
+
108
+ if (isErr) {
109
+ return Promise.reject(res)
110
+ }
111
+ return res
112
+ }
113
+
114
+ /**
115
+ * 插入數據,插入同樣數據會自動產生不同_id,故insert前需自行判斷有無重複
116
+ *
117
+ * @memberOf WOrmLowdb
118
+ * @param {Object|Array} data 輸入數據物件或陣列
119
+ * @returns {Promise} 回傳Promise,resolve回傳插入結果,reject回傳錯誤訊息
120
+ */
121
+ async function insert(data) {
122
+ let isErr = false
123
+
124
+ //check
125
+ if (!iseobj(data) && !isearr(data)) {
126
+ return Promise.reject(`data is not an effective object or array`)
127
+ }
128
+
129
+ //cloneDeep, 與外部數據脫勾
130
+ data = cloneDeep(data)
131
+
132
+ //res
133
+ let res = null
134
+ try {
135
+
136
+ //check
137
+ if (!isarr(data)) {
138
+ data = [data]
139
+ }
140
+
141
+ //check id
142
+ data = map(data, function(v) {
143
+ if (!isestr(v.id)) {
144
+ v.id = genID()
145
+ }
146
+ return v
147
+ })
148
+
149
+ //read
150
+ await lowdb.read()
151
+
152
+ //kp
153
+ let kp = {}
154
+ each(lowdb.data[key], (v, k) => {
155
+ kp[v.id] = { k, v }
156
+ })
157
+
158
+ //each
159
+ let nAll = size(data)
160
+ let nPush = 0
161
+ let b = false
162
+ each(data, (v) => {
163
+
164
+ //check
165
+ if (!haskey(kp, v.id)) {
166
+ //未存在v.id
167
+
168
+ //push
169
+ lowdb.data[key].push(v)
170
+
171
+ nPush++
172
+ b = true
173
+ }
174
+ else {
175
+ //已存在v.id則不push
176
+ }
177
+
178
+ })
179
+
180
+ //write
181
+ if (b) {
182
+ await lowdb.write()
183
+ }
184
+
185
+ //res
186
+ res = {
187
+ n: nAll,
188
+ nInserted: nPush,
189
+ ok: 1,
190
+ }
191
+
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
205
+ }
206
+
207
+ /**
208
+ * 儲存數據
209
+ *
210
+ * @memberOf WOrmLowdb
211
+ * @param {Object|Array} data 輸入數據物件或陣列
212
+ * @param {Object} [option={}] 輸入設定物件,預設為{}
213
+ * @param {boolean} [option.autoInsert=true] 輸入是否於儲存時發現原本無數據,則自動改以插入處理,預設為true
214
+ * @returns {Promise} 回傳Promise,resolve回傳儲存結果,reject回傳錯誤訊息
215
+ */
216
+ 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
+ }
223
+
224
+ //cloneDeep, 與外部數據脫勾
225
+ data = cloneDeep(data)
226
+
227
+ //autoInsert
228
+ let autoInsert = get(option, 'autoInsert', true)
229
+
230
+ //res
231
+ let res = null
232
+ try {
233
+
234
+ //check
235
+ if (!isarr(data)) {
236
+ data = [data]
237
+ }
238
+
239
+ //check id
240
+ data = map(data, function(v) {
241
+ if (!isestr(v.id)) {
242
+ v.id = genID()
243
+ }
244
+ return v
245
+ })
246
+
247
+ //read
248
+ await lowdb.read()
249
+
250
+ //kp
251
+ let kp = {}
252
+ each(lowdb.data[key], (v, k) => {
253
+ kp[v.id] = { k, v }
254
+ })
255
+
256
+ //pmSeries
257
+ let b = false
258
+ res = await pmSeries(data, async(v) => {
259
+
260
+ //rest
261
+ let rest = null
262
+
263
+ //id
264
+ let id = get(v, 'id', '')
265
+
266
+ //查找資料表內v.id為_v
267
+ let r = get(kp, id, null)
268
+
269
+ //check
270
+ if (iseobj(r)) {
271
+ //已存在v.id
272
+ if (isEqual(v, r.v)) {
273
+ //內容相同不更新
274
+ }
275
+ else {
276
+ //內容不同須更新
277
+
278
+ //merge
279
+ lowdb.data[key][r.k] = merge(lowdb.data[key][r.k], v)
280
+
281
+ rest = { update: true }
282
+ b = true
283
+ }
284
+ }
285
+
286
+ //rest
287
+ if (iseobj(rest)) {
288
+ rest = {
289
+ n: 1,
290
+ nModified: 1,
291
+ ok: 1,
292
+ }
293
+ }
294
+ else {
295
+ rest = {
296
+ n: 0,
297
+ nModified: 0,
298
+ ok: 1,
299
+ }
300
+ }
301
+
302
+ //autoInsert
303
+ if (autoInsert && rest.n === 0) {
304
+ rest = await insert(v)
305
+ }
306
+
307
+ return rest
308
+ })
309
+
310
+ //write
311
+ if (b) {
312
+ await lowdb.write()
313
+ }
314
+
315
+ //emit
316
+ ee.emit('change', 'save', data, res)
317
+
318
+ }
319
+ catch (err) {
320
+ isErr = true
321
+ res = err
322
+ }
323
+
324
+ if (isErr) {
325
+ return Promise.reject(res)
326
+ }
327
+ return res
328
+ }
329
+
330
+ /**
331
+ * 刪除數據
332
+ *
333
+ * @memberOf WOrmLowdb
334
+ * @param {Object|Array} data 輸入數據物件或陣列
335
+ * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
336
+ */
337
+ 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 {
351
+
352
+ //check
353
+ if (!isarr(data)) {
354
+ data = [data]
355
+ }
356
+
357
+ //read
358
+ await lowdb.read()
359
+
360
+ //kp
361
+ let kp = {}
362
+ each(lowdb.data[key], (v, k) => {
363
+ kp[v.id] = { k, v }
364
+ })
365
+
366
+ //pmSeries
367
+ let ks = []
368
+ let b = false
369
+ res = await pmSeries(data, async(v) => {
370
+
371
+ //rest
372
+ let rest = null
373
+
374
+ //id
375
+ let id = get(v, 'id', '')
376
+
377
+ //check
378
+ if (isestr(id)) {
379
+
380
+ //查找資料表內v.id為_v
381
+ let r = get(kp, id, null)
382
+
383
+ //check
384
+ if (iseobj(r)) {
385
+ //已存在v.id則須刪除
386
+
387
+ //push
388
+ ks.push(r.k)
389
+
390
+ b = true
391
+
392
+ //rest
393
+ rest = {
394
+ n: 1,
395
+ nDeleted: 1,
396
+ ok: 1,
397
+ }
398
+
399
+ }
400
+ else {
401
+ //不存在v.id則不刪除
402
+
403
+ //rest
404
+ rest = {
405
+ n: 1,
406
+ nDeleted: 0,
407
+ ok: 1,
408
+ }
409
+
410
+ }
411
+
412
+ }
413
+ else {
414
+ //未給v.id則不刪除
415
+
416
+ //rest
417
+ rest = {
418
+ n: 1,
419
+ nDeleted: 0,
420
+ ok: 0, //未給v.id視為有問題數據, 故ok給0
421
+ }
422
+
423
+ }
424
+
425
+ return rest
426
+ })
427
+
428
+ //update
429
+ if (b) {
430
+ lowdb.data[key] = arrPullAt(lowdb.data[key], ks)
431
+ }
432
+
433
+ //write
434
+ if (b) {
435
+ await lowdb.write()
436
+ }
437
+
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
451
+ }
452
+
453
+ /**
454
+ * 刪除全部數據,需與del分開,避免未傳數據導致直接刪除全表
455
+ *
456
+ * @memberOf WOrmLowdb
457
+ * @param {Object} [find={}] 輸入刪除條件物件
458
+ * @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
459
+ */
460
+ async function delAll(find = {}) {
461
+ let isErr = false
462
+
463
+ //res
464
+ let res = null
465
+ try {
466
+
467
+ //read
468
+ await lowdb.read()
469
+
470
+ //filter
471
+ let nAll = size(lowdb.data[key])
472
+ let nDel = 0
473
+ let b = false
474
+ if (iseobj(find)) {
475
+
476
+ //q
477
+ let q = new Query(find)
478
+ // console.log('q', q)
479
+
480
+ //find
481
+ let _res = q.find(lowdb.data[key]).all()
482
+ // console.log('_res', _res)
483
+
484
+ //nDel
485
+ nDel = size(_res)
486
+ // console.log('nDel', nDel)
487
+
488
+ if (nDel === 0) {
489
+ //未有find結果等於不刪除
490
+ }
491
+ else if (nAll === nDel) {
492
+ //全在find結果內等於全部刪除
493
+
494
+ //empty
495
+ lowdb.data[key] = []
496
+
497
+ b = true
498
+ }
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
+
520
+ b = true
521
+ }
522
+ }
523
+ else {
524
+
525
+ //nDel
526
+ nDel = nAll
527
+
528
+ //empty
529
+ lowdb.data[key] = []
530
+
531
+ b = true
532
+ }
533
+
534
+ //write
535
+ if (b) {
536
+ await lowdb.write()
537
+ }
538
+
539
+ //res
540
+ res = {
541
+ n: nAll,
542
+ nDeleted: nDel,
543
+ ok: 1,
544
+ }
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
559
+ }
560
+
561
+ //bind
562
+ ee.select = select
563
+ ee.insert = insert
564
+ ee.save = save
565
+ ee.del = del
566
+ ee.delAll = delAll
567
+
568
+ return ee
569
+ }
570
+
571
+
572
+ export default WOrmLowdb