w-orm-lmdb 1.0.1

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