@k3000/store 0.1.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.
package/generator.mjs ADDED
@@ -0,0 +1,1357 @@
1
+ import {copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync} from "node:fs";
2
+ import {buffer, string, Storage, TypeLen} from './architect.mjs'
3
+ import {resolve} from 'node:path'
4
+
5
+ const modulePath = import.meta.url.endsWith('?test=true') ? '../../architect.mjs' : 'dmb3/architect.mjs'
6
+ const modulePath2 = import.meta.url.endsWith('?test=true') ? '../../generator.mjs' : 'dmb3'
7
+
8
+ class Enum {
9
+
10
+ init() {
11
+
12
+ let index = 0
13
+
14
+ for (let key of Object.keys(this)) {
15
+
16
+ Object.defineProperty(this, Number.isSafeInteger(this[key]) && this[key] > index ? index = this[key] : this[key] = index, {
17
+ value: key,
18
+ enumerable: false
19
+ })
20
+
21
+ index++
22
+ }
23
+ }
24
+ }
25
+
26
+ class TypeMap extends Enum {
27
+ id
28
+ uint
29
+ int
30
+ bigUint
31
+ bigint
32
+ time
33
+ float
34
+ string
35
+ buffer
36
+ text
37
+
38
+ constructor() {
39
+
40
+ super().init()
41
+ }
42
+ }
43
+
44
+ const typeMap = new TypeMap()
45
+
46
+ const TimeAttr = {
47
+ now: -1,
48
+ update: -2,
49
+ }
50
+
51
+ const SCOPE = {}
52
+
53
+ export const bigintSerialize = (_, value) => typeof value === "bigint" ? value.toString() : value
54
+
55
+ class Type {
56
+
57
+ #type
58
+ #index
59
+ #value
60
+ #length
61
+ #remark
62
+ #step
63
+
64
+ constructor(type, remark) {
65
+
66
+ this.#type = type;
67
+ this.#remark = string(remark || '');
68
+ }
69
+
70
+ index(scope, support) {
71
+
72
+ if (scope === SCOPE) {
73
+
74
+ this.#index = !!support
75
+ }
76
+
77
+ return this;
78
+ }
79
+
80
+ value(scope, value) {
81
+
82
+ if (scope === SCOPE) {
83
+
84
+ this.#value = value
85
+ }
86
+
87
+ return this;
88
+ }
89
+
90
+ length(scope, length) {
91
+
92
+ if (scope === SCOPE) {
93
+
94
+ length = Number.parseInt(length) || 1
95
+
96
+ this.#length = length > 0 ? length : 1
97
+ }
98
+
99
+ return this;
100
+ }
101
+
102
+ step(scope, step) {
103
+
104
+ if (scope === SCOPE) {
105
+
106
+ step = parseFloat(step) || 1
107
+
108
+ this.#step = step > 0 ? step : 1
109
+ }
110
+
111
+ return this;
112
+ }
113
+
114
+ remark(remark = '') {
115
+
116
+ this.#remark = string(remark || '')
117
+
118
+ return this;
119
+ }
120
+
121
+ toJSON() {
122
+
123
+ const obj = {
124
+ type: this.#type,
125
+ remark: this.#remark,
126
+ }
127
+
128
+ if (this.#index) {
129
+
130
+ obj.index = []
131
+ }
132
+
133
+ if (this.#value !== undefined) {
134
+
135
+ obj.value = this.#value
136
+ }
137
+
138
+ if (this.#length !== undefined) {
139
+
140
+ obj.length = this.#length
141
+ }
142
+
143
+ if (this.#step !== undefined) {
144
+
145
+ obj.step = this.#step
146
+ }
147
+
148
+ return obj
149
+ }
150
+
151
+ toString() {
152
+
153
+ return JSON.stringify(this.toJSON(), bigintSerialize)
154
+ }
155
+ }
156
+
157
+ export const Id = remark => new class Id extends Type {
158
+
159
+ constructor() {
160
+
161
+ super(typeMap.id, remark);
162
+
163
+ super.index(SCOPE, true)
164
+ super.value(SCOPE, 1)
165
+ super.step(SCOPE, 1)
166
+ super.length(SCOPE, TypeLen.id)
167
+ }
168
+
169
+ index(support = true) {
170
+
171
+ return super.index(SCOPE, support);
172
+ }
173
+
174
+ value(value = 0) {
175
+
176
+ return super.value(SCOPE, Number.parseInt(value) || 0);
177
+ }
178
+
179
+ step(step = 1) {
180
+
181
+ step = Number.parseInt(step) || 1
182
+
183
+ return super.step(SCOPE, step > 0 ? step : 1);
184
+ }
185
+
186
+ }()
187
+
188
+ /**
189
+ * @param {1 | 2 | 3 | 4 | String} size
190
+ * @constructor
191
+ */
192
+ export const Uint = size => new class Uint extends Type {
193
+
194
+ constructor() {
195
+
196
+ let remark = ''
197
+
198
+ if (typeof size === "string") {
199
+
200
+ remark = size
201
+ size = TypeLen.uint
202
+
203
+ } else if (Number.isInteger(size)) {
204
+
205
+ size = Math.round(size)
206
+
207
+ if (size < 1) size = 1
208
+ else if (size > TypeLen.uint) size = TypeLen.uint
209
+
210
+ } else {
211
+
212
+ size = TypeLen.uint
213
+ }
214
+
215
+ super(typeMap.uint, remark);
216
+
217
+ super.length(SCOPE, size)
218
+ }
219
+
220
+ index(support = true) {
221
+
222
+ return super.index(SCOPE, support);
223
+ }
224
+
225
+ value(value = 0) {
226
+
227
+ value = Number.parseInt(value) || 0
228
+
229
+ return super.value(SCOPE, value < 0 ? 0 : value);
230
+ }
231
+
232
+ step(step = 1) {
233
+
234
+ step = Number.parseInt(step) || 1
235
+
236
+ return super.step(SCOPE, step > 0 ? step : 1);
237
+ }
238
+
239
+ }()
240
+
241
+ /**
242
+ * @param {1 | 2 | 3 | 4 | String} size
243
+ * @constructor
244
+ */
245
+ export const Int = size => new class Int extends Type {
246
+
247
+ constructor() {
248
+
249
+ let remark = ''
250
+
251
+ if (typeof size === "string") {
252
+
253
+ remark = size
254
+ size = TypeLen.int
255
+
256
+ } else if (Number.isInteger(size)) {
257
+
258
+ size = Math.round(size)
259
+
260
+ if (size < 1) size = 1
261
+ else if (size > TypeLen.int) size = TypeLen.int
262
+
263
+ } else {
264
+
265
+ size = TypeLen.int
266
+ }
267
+
268
+ super(typeMap.int, remark);
269
+
270
+ super.length(SCOPE, size)
271
+ }
272
+
273
+ index(support = true) {
274
+
275
+ return super.index(SCOPE, support);
276
+ }
277
+
278
+ value(value = 0) {
279
+
280
+ return super.value(SCOPE, Number.parseInt(value) || 0);
281
+ }
282
+
283
+ step(step = 1) {
284
+
285
+ step = Number.parseInt(step) || 1
286
+
287
+ return super.step(SCOPE, step === 0 ? 1 : step);
288
+ }
289
+
290
+ }()
291
+
292
+ export const BigUint = remark => new class BigUint extends Type {
293
+
294
+ constructor() {
295
+
296
+ super(typeMap.bigUint, remark);
297
+
298
+ super.length(SCOPE, TypeLen.bigUint)
299
+ }
300
+
301
+ index(support = true) {
302
+
303
+ return super.index(SCOPE, support);
304
+ }
305
+
306
+ value(value = 0) {
307
+
308
+ return super.value(SCOPE, BigInt(value || 0));
309
+ }
310
+
311
+ step(step = 1) {
312
+
313
+ step = BigInt(step || 1)
314
+
315
+ return super.step(SCOPE, step === 0n ? 1n : step);
316
+ }
317
+
318
+ }()
319
+
320
+ export const Bigint = remark => new class Bigint extends Type {
321
+
322
+ constructor() {
323
+
324
+ super(typeMap.bigint, remark);
325
+
326
+ super.length(SCOPE, TypeLen.bigint)
327
+ }
328
+
329
+ index(support = true) {
330
+
331
+ return super.index(SCOPE, support);
332
+ }
333
+
334
+ value(value = 0) {
335
+
336
+ return super.value(SCOPE, BigInt(value || 0));
337
+ }
338
+
339
+ step(step = 1) {
340
+
341
+ step = BigInt(step || 1)
342
+
343
+ return super.step(SCOPE, step === 0n ? 1n : step);
344
+ }
345
+
346
+ }()
347
+
348
+ export const Time = remark => new class Time extends Type {
349
+
350
+ constructor() {
351
+
352
+ super(typeMap.time, remark);
353
+
354
+ super.length(SCOPE, TypeLen.time)
355
+ }
356
+
357
+ index(support = true) {
358
+
359
+ return super.index(SCOPE, support);
360
+ }
361
+
362
+ value(value = 0) {
363
+
364
+ if (typeof value === "string" && Reflect.has(TimeAttr, value)) {
365
+
366
+ return super.value(SCOPE, TimeAttr[value])
367
+
368
+ } else {
369
+
370
+ value = Number.parseInt(value) || 0
371
+
372
+ return super.value(SCOPE, value > 0 ? value : 0);
373
+ }
374
+ }
375
+
376
+ }()
377
+
378
+ Object.defineProperties(Time, {
379
+ now: {
380
+ value: 'now',
381
+ configurable: false,
382
+ writable: false,
383
+ },
384
+ update: {
385
+ value: 'update',
386
+ configurable: false,
387
+ writable: false,
388
+ }
389
+ })
390
+
391
+ export const Float = remark => new class Float extends Type {
392
+
393
+ constructor() {
394
+
395
+ super(typeMap.float, remark);
396
+
397
+ super.length(SCOPE, TypeLen.float)
398
+ }
399
+
400
+ index(support = true) {
401
+
402
+ return super.index(SCOPE, support);
403
+ }
404
+
405
+ value(value = 0) {
406
+
407
+ return super.value(SCOPE, parseFloat(value) || 0);
408
+ }
409
+
410
+ step(step = 1) {
411
+
412
+ step = parseFloat(step) || 1
413
+
414
+ return super.step(SCOPE, step === 0 ? 1 : step);
415
+ }
416
+
417
+ }()
418
+
419
+ export const String = remark => new class String extends Type {
420
+
421
+ constructor() {
422
+
423
+ super(typeMap.string, remark);
424
+
425
+ super.length(SCOPE, TypeLen.string)
426
+ }
427
+
428
+ index(support = true) {
429
+
430
+ return super.index(SCOPE, support);
431
+ }
432
+
433
+ value(value = '') {
434
+
435
+ return super.value(SCOPE, string(value));
436
+ }
437
+
438
+ length(length) {
439
+
440
+ length = Number.parseInt(length) || TypeLen.string
441
+
442
+ return super.length(SCOPE, length > 0 ? length : TypeLen.string);
443
+ }
444
+
445
+ }()
446
+
447
+ export const Buffer = remark => new class Buffer extends Type {
448
+
449
+ constructor() {
450
+
451
+ super(typeMap.buffer, remark);
452
+
453
+ super.length(SCOPE, TypeLen.buffer)
454
+ }
455
+
456
+ }()
457
+
458
+ export const Text = remark => new class Text extends Type {
459
+
460
+ constructor() {
461
+
462
+ super(typeMap.text, remark);
463
+
464
+ super.length(SCOPE, TypeLen.text)
465
+ }
466
+
467
+ }()
468
+
469
+ export const struct = (storage, remark) => {
470
+
471
+ const struct = {}, base = storage.struct.base
472
+
473
+ for (const [key, value] of Object.entries(storage.struct.extra)) {
474
+
475
+ struct[key] = {[remark]: value.remark}
476
+
477
+ for (const [k, v] of Object.entries(base[key])) {
478
+
479
+ const item = {type: typeMap[v.type]}
480
+
481
+ if (Reflect.has(v, 'remark')) {
482
+
483
+ item.remark = v.remark
484
+ }
485
+
486
+ if (v.index) {
487
+
488
+ item.index = true
489
+ }
490
+
491
+ if (v.step) {
492
+
493
+ item.step = v.step
494
+ }
495
+
496
+ if (Reflect.has(v, 'value')) {
497
+
498
+ item.default = v.type === typeMap.time ? v.value === TimeAttr.now ? 'now' : v.value === TimeAttr.update ? 'update' : v.value : v.value
499
+ }
500
+
501
+ if ([typeMap.uint, typeMap.int, typeMap.string].includes(v.type)) {
502
+
503
+ item.length = v.length
504
+ }
505
+
506
+ struct[key][k] = item
507
+ }
508
+ }
509
+
510
+ return struct
511
+ }
512
+
513
+ const updateColPos = (base, extra) => {
514
+
515
+ let position = 0
516
+
517
+ for (const value of Object.values(base)) {
518
+
519
+ value.position = position
520
+
521
+ position += value.length
522
+ }
523
+
524
+ extra.length = position
525
+ }
526
+
527
+ function appendSet(name, set, remark = '') {
528
+
529
+ if (!Reflect.has(this.curr.struct.base, name)) {
530
+
531
+ console.log('append set:', name)
532
+
533
+ this.curr.struct.base[name] = {}
534
+ this.curr.struct.extra[name] = {remark}
535
+ this.curr.record.idle[name] = []
536
+ this.curr.record.index[name] = {}
537
+ this.curr.record.value[name] = {}
538
+ this.curr.record.record[name] = []
539
+
540
+ for (let [key, value] of Object.entries(set)) {
541
+
542
+ if (value instanceof Type) {
543
+
544
+ value = value.toJSON()
545
+
546
+ } else if (this.types.includes(value)) {
547
+
548
+ value = value().toJSON()
549
+ }
550
+
551
+ console.log(' append col:', key)
552
+
553
+ this.curr.struct.base[name][key] = value
554
+
555
+ if (value.index) {
556
+
557
+ this.curr.record.index[name][key] = []
558
+ }
559
+
560
+ if (value.step) {
561
+
562
+ this.curr.record.value[name][key] = value.value
563
+ }
564
+ }
565
+
566
+ updateColPos(this.curr.struct.base[name], this.curr.struct.extra[name])
567
+ }
568
+ }
569
+
570
+ function updateCol(name, set) {
571
+
572
+ if (Reflect.has(this.curr.struct.base, name)) {
573
+
574
+ console.log('current set:', name)
575
+
576
+ for (let [key, value] of Object.entries(set)) {
577
+
578
+ if (value instanceof Type) {
579
+
580
+ value = value.toJSON()
581
+
582
+ } else if (this.types.includes(value)) {
583
+
584
+ value = value().toJSON()
585
+ }
586
+
587
+ console.log(` ${Reflect.has(this.curr.struct.base[name], key) ? 'update' : 'append'} col:`, key)
588
+
589
+ this.curr.struct.base[name][key] = value
590
+
591
+ if (value.index) {
592
+
593
+ this.curr.record.index[name][key] = []
594
+ }
595
+
596
+ if (value.step) {
597
+
598
+ this.curr.record.value[name][key] = value.value
599
+ }
600
+ }
601
+
602
+ updateColPos(this.curr.struct.base[name], this.curr.struct.extra[name])
603
+
604
+ this.updateSet.add(name)
605
+ }
606
+ }
607
+
608
+ function renameSet(name, newName) {
609
+
610
+ if (typeof newName === "string"
611
+ && Reflect.has(this.curr.struct.base, name)
612
+ && !Reflect.has(this.curr.struct.base, newName)) {
613
+
614
+ console.log(`rename set: ${name} -> ${newName}`)
615
+
616
+ this.curr.struct.base[newName] = this.curr.struct.base[name]
617
+
618
+ delete this.curr.struct.base[name]
619
+
620
+ this.curr.struct.extra[newName] = this.curr.struct.extra[name]
621
+
622
+ delete this.curr.struct.extra[name]
623
+
624
+ this.curr.record.idle[newName] = this.curr.record.idle[name]
625
+
626
+ delete this.curr.record.idle[name]
627
+
628
+ this.curr.record.index[newName] = this.curr.record.index[name]
629
+
630
+ delete this.curr.record.index[name]
631
+
632
+ this.curr.record.value[newName] = this.curr.record.value[name]
633
+
634
+ delete this.curr.record.value[name]
635
+
636
+ this.curr.record.record[newName] = this.curr.record.record[name]
637
+
638
+ delete this.curr.record.record[name]
639
+ }
640
+ }
641
+
642
+ function renameCol(name, set) {
643
+
644
+ if (Reflect.has(this.curr.struct.base, name)) {
645
+
646
+ for (let [key, newKey] of Object.entries(set)) {
647
+
648
+ if (typeof newKey === "string"
649
+ && Reflect.has(this.curr.struct.base[name], key)
650
+ && !Reflect.has(this.curr.struct.base[name], newKey)) {
651
+
652
+ console.log(`rename ${name} col: ${key} -> ${newKey}`)
653
+
654
+ this.curr.struct.base[name][newKey] = this.curr.struct.base[name][key]
655
+
656
+ delete this.curr.struct.base[name][key]
657
+
658
+ this.curr.struct.extra[name][newKey] = this.curr.struct.extra[name][key]
659
+
660
+ delete this.curr.struct.extra[name][key]
661
+
662
+ this.curr.record.idle[name][newKey] = this.curr.record.idle[name][key]
663
+
664
+ delete this.curr.record.idle[name][key]
665
+
666
+ this.curr.record.index[name][newKey] = this.curr.record.index[name][key]
667
+
668
+ delete this.curr.record.index[name][key]
669
+
670
+ this.curr.record.value[name][newKey] = this.curr.record.value[name][key]
671
+
672
+ delete this.curr.record.value[name][key]
673
+
674
+ this.curr.record.record[name][newKey] = this.curr.record.record[name][key]
675
+
676
+ delete this.curr.record.record[name][key]
677
+ }
678
+ }
679
+ }
680
+ }
681
+
682
+ function deleteSet(name) {
683
+
684
+ if (Reflect.has(this.curr.struct.base, name)) {
685
+
686
+ console.log(`delete set: ${name}`)
687
+
688
+ delete this.curr.struct.base[name]
689
+ delete this.curr.struct.extra[name]
690
+ delete this.curr.record.idle[name]
691
+ delete this.curr.record.index[name]
692
+ delete this.curr.record.value[name]
693
+ delete this.curr.record.record[name]
694
+ }
695
+ }
696
+
697
+ function deleteCol(name, col) {
698
+
699
+ if (Reflect.has(this.curr.struct.base, name)
700
+ && Reflect.has(this.curr.struct.base[name], col)) {
701
+
702
+ console.log(`delete ${name} col: ${col}`)
703
+
704
+ delete this.curr.struct.base[name][col]
705
+ delete this.curr.struct.extra[name][col]
706
+ delete this.curr.record.idle[name][col]
707
+ delete this.curr.record.index[name][col]
708
+ delete this.curr.record.value[name][col]
709
+ delete this.curr.record.record[name][col]
710
+
711
+ updateColPos(this.curr.struct.base[name], this.curr.struct.extra[name])
712
+
713
+ this.updateSet.add(name)
714
+ }
715
+ }
716
+
717
+ function updateSetRemark(name, remark) {
718
+
719
+ if (Reflect.has(this.curr.struct.base, name)) {
720
+
721
+ console.log(`update ${name} remark:`, remark)
722
+
723
+ this.curr.struct.extra[name].remark = remark
724
+ }
725
+ }
726
+
727
+ const commentRemark = (remark = '') => remark.replace(/\n/g, '\n\t * ')
728
+
729
+ function submit() {
730
+
731
+ this.curr.updateStruct(this.curr.struct)
732
+ this.curr.updateRecord(this.curr.record)
733
+
734
+ this.prev.close()
735
+ this.curr.close()
736
+
737
+ clipTypeTs(this.typePath, this.curr.struct)
738
+ clipIndexMjs(this.currPath, this.curr.struct)
739
+
740
+ const version = readdirSync(this.dir).map(v => parseFloat(v) || 0).sort(sort).pop()
741
+
742
+ writeFileSync(`${this.dir}index.mjs`, `
743
+ const index = import.meta.url.indexOf('?')
744
+
745
+ const url = \`./${version}/index.mjs\${index > -1 ? import.meta.url.substring(index) : ''}\`
746
+
747
+ /**
748
+ * @type {import('./${version}/type').Storage}
749
+ */
750
+ const storage = await new Promise((resolve, reject) => import(url)
751
+ .then(modules => resolve(modules.default)).catch(error => reject(error)))
752
+
753
+ export default storage
754
+ `)
755
+
756
+ if (this.updateSet.size) {
757
+
758
+ return Promise.all([import(this.prevPath + this.prevUrlParams), import(this.currPath + this.currUrlParams)])
759
+ .then(([prev, curr]) => {
760
+
761
+ prev = prev.default
762
+ curr = curr.default
763
+
764
+ for (const name of this.updateSet.values()) {
765
+
766
+ curr[name].remove(...curr[name])
767
+
768
+ this.curr.record.idle[name] = []
769
+
770
+ curr[name].push(...prev[name])
771
+ }
772
+
773
+ prev.close()
774
+ curr.close()
775
+ })
776
+
777
+ } else {
778
+
779
+ return Promise.resolve()
780
+ }
781
+ }
782
+
783
+ const initDir = (name, dir) => {
784
+
785
+ const existsDir = existsSync(name) && statSync(name).isDirectory()
786
+
787
+ if (!existsDir) {
788
+
789
+ mkdirSync(name)
790
+ }
791
+
792
+ if (!existsSync(dir)) {
793
+
794
+ mkdirSync(dir)
795
+ }
796
+
797
+ const indexMjsPath = dir + '/index.mjs'
798
+ const indexPath = dir + '/index'
799
+ const dataPath = dir + '/data'
800
+ const bufPath = dir + '/buffer'
801
+
802
+ if (!existsSync(indexMjsPath)) {
803
+
804
+ writeFileSync(indexMjsPath, `
805
+ import {Storage, Store} from '${modulePath}'
806
+ import {struct} from '${modulePath2}'
807
+
808
+ const storage = new Storage(import.meta.url)
809
+
810
+ export const remark = Symbol('remark')
811
+
812
+ export function getStruct() {
813
+
814
+ return struct(storage, remark)
815
+ }
816
+
817
+ export default new class extends Store {
818
+
819
+ close() {
820
+ storage.close()
821
+ }
822
+ }`)
823
+ }
824
+
825
+ if (!existsSync(indexPath)) {
826
+
827
+ writeFileSync(indexPath, buffer.alloc(0))
828
+ }
829
+
830
+ if (!existsSync(dataPath)) {
831
+
832
+ writeFileSync(dataPath, buffer.alloc(0))
833
+ }
834
+
835
+ if (!existsSync(bufPath)) {
836
+
837
+ mkdirSync(bufPath)
838
+ }
839
+
840
+ return new Storage(dir + '/')
841
+ }
842
+
843
+ const copyDir = (src, dest) => {
844
+
845
+ mkdirSync(dest)
846
+
847
+ for (const name of readdirSync(src)) {
848
+
849
+ const srcPath = `${src}/${name}`
850
+ const destPath = `${dest}/${name}`
851
+
852
+ if (statSync(srcPath).isDirectory()) {
853
+
854
+ copyDir(srcPath, destPath)
855
+
856
+ } else {
857
+
858
+ copyFileSync(srcPath, destPath)
859
+ }
860
+ }
861
+ }
862
+
863
+ const gen = {
864
+ get: [
865
+ code => code + '.readUInt32BE(0)',
866
+ (code, size) => {
867
+ switch (size) {
868
+ case 1:
869
+ return code + '.readUint8(0)'
870
+ case 2:
871
+ return code + '.readUint16BE(0)'
872
+ case 3:
873
+ return `readUint24BE(${code})`
874
+ case 4:
875
+ return code + '.readUInt32BE(0)'
876
+ }
877
+ return code
878
+ },
879
+ (code, size) => {
880
+ switch (size) {
881
+ case 1:
882
+ return code + '.readInt8(0)'
883
+ case 2:
884
+ return code + '.readInt16BE(0)'
885
+ case 3:
886
+ return `readInt24BE(${code})`
887
+ case 4:
888
+ return code + '.readInt32BE(0)'
889
+ }
890
+ return code
891
+ },
892
+ code => code + '.readBigUInt64BE(0)',
893
+ code => code + '.readBigInt64BE(0)',
894
+ code => `b2d(${code})`,
895
+ code => code + '.readDoubleBE(0)',
896
+ code => `b2s(${code})`,
897
+ (code, length) => `${code}[0] ? super.readFileSync(${length}) : null`,
898
+ (code, length) => `${code}[0] ? super.readFileSync(${length}).toString() : ''`,
899
+ ],
900
+ set: [
901
+ 'uInt32BEToBuffer',
902
+ 'super.uintToBuffer',
903
+ 'super.intToBuffer',
904
+ 'bigUint32BEToBuffer',
905
+ 'bigint32BEToBuffer',
906
+ 'd2b',
907
+ 'doubleBEToBuffer',
908
+ 'super.s2b',
909
+ 'super.buffer',
910
+ 'super.textToBuffer',
911
+ ],
912
+ type: [
913
+ 'Number',
914
+ 'Number',
915
+ 'Number',
916
+ 'Number | BigInt',
917
+ 'Number | BigInt',
918
+ 'Number | Date',
919
+ 'Number',
920
+ 'String',
921
+ 'Buffer',
922
+ 'String',
923
+ ]
924
+ }
925
+
926
+ const clipStatic = (name, [key, value]) => {
927
+
928
+ if (!Reflect.has(value, 'value')) return `\t\t\t${key},`
929
+
930
+ let valueStr = ''
931
+
932
+ if (Reflect.has(value, 'step')) return `\t\t\t${key}: storage.updateValue(${key}, ${name}.name, $${key}),`
933
+
934
+ switch (value.type) {
935
+
936
+ case typeMap.string:
937
+
938
+ valueStr = ` || '${value.value}'`
939
+
940
+ break
941
+
942
+ case typeMap.time:
943
+
944
+ if (value.value === TimeAttr.now || value.value === TimeAttr.update) {
945
+
946
+ valueStr = ` || new Date()`
947
+
948
+ } else if (typeof value.value === "string") {
949
+
950
+ valueStr = ` || new Date('${value.value}')`
951
+
952
+ } else {
953
+
954
+ valueStr = ' || ' + value.value
955
+ }
956
+
957
+ break
958
+
959
+ default:
960
+
961
+ valueStr = ' || ' + value.value
962
+ }
963
+
964
+ return `\t\t\t${key}${valueStr ? `: ${key}${valueStr}` : ''},`
965
+ }
966
+
967
+ const clipIndex = (name, key, k, v) => {
968
+
969
+ let main = '0'
970
+
971
+ if (v.type === typeMap.int) {
972
+
973
+ main = `super.intToBuffer(${k}, $${k})`
974
+
975
+ } else if (v.type === typeMap.uint) {
976
+
977
+ main = `super.uintToBuffer(${k}, $${k})`
978
+
979
+ } else {
980
+
981
+ main = `${gen.set[v.type]}(${k}${v.type === typeMap.buffer
982
+ || v.type === typeMap.text ? `, $${k}` : v.type === typeMap.string
983
+ ? `, $${k}` : ''})`
984
+ }
985
+
986
+ if (v.index) {
987
+
988
+ return `super.set2($${k}, ${main})`
989
+
990
+ } else {
991
+
992
+ return `super.set($${k}, ${main})`
993
+ }
994
+ }
995
+
996
+ const clipConst = struct => Array.from(new Set(Object.values(struct)
997
+ .map(struct => Object.keys(struct)).flat()))
998
+ .map(key => `const $${key} = '${key}'`)
999
+ .join('\n')
1000
+
1001
+ const clipProperties = (name, key, update, [k, v]) => `
1002
+ ${k}: {
1003
+ enumerable: true,
1004
+ configurable: false,
1005
+ get: () => ${gen.get[v.type](`super.get($${k})`, v.type === typeMap.buffer
1006
+ || v.type === typeMap.text ? `$${k}` : v.length)},
1007
+ set: ${k} => ${update && k !== update[0] ? `{
1008
+ ${clipIndex(name, key, k, v)}
1009
+ this.#update()
1010
+ }` : clipIndex(name, key, k, v)},
1011
+ },`
1012
+
1013
+ const sort = (a, b) => a - b
1014
+
1015
+ const sort2 = (a, b) => a > b ? 1 : a < b ? -1 : 0
1016
+
1017
+ const sort3 = ([a], [b]) => a > b ? 1 : a < b ? -1 : 0
1018
+
1019
+ const clipEntity = ([key, value]) => {
1020
+
1021
+ const update = Object.entries(value).find(([_, v]) => v.type === typeMap.time && v.value === TimeAttr.update)
1022
+
1023
+ const name = key[0].toUpperCase() + key.substring(1)
1024
+
1025
+ return `
1026
+ class ${name} extends Entity {
1027
+
1028
+ static name = '${key}'
1029
+
1030
+ static create({
1031
+ ${Object.keys(value).sort(sort2).join(',\n\t\t\t')}
1032
+ }) {
1033
+
1034
+ return {
1035
+ ${Object.entries(value).sort(sort3).map(clipStatic.bind(null, name)).join('\n')}
1036
+ }
1037
+ }
1038
+
1039
+ constructor(...arg) {
1040
+
1041
+ super(storage, ...arg)
1042
+
1043
+ return Object.defineProperties({}, {
1044
+ [position]: {
1045
+ enumerable: false,
1046
+ configurable: false,
1047
+ get: () => this[position],
1048
+ },${Object.entries(value).sort(sort3).map(clipProperties.bind(null, name, key, update)).join('')}
1049
+ })
1050
+ }
1051
+ ${update ? `
1052
+
1053
+ #update() {
1054
+
1055
+ this.${update[0]} = Date.now()
1056
+ }` : ''}
1057
+ }
1058
+ `
1059
+ }
1060
+
1061
+ const clipEntities = ([key, value]) => {
1062
+
1063
+ const name = key[0].toUpperCase() + key.substring(1)
1064
+
1065
+ return `
1066
+ class ${name}Set extends Entities {
1067
+
1068
+ constructor() {
1069
+
1070
+ super(storage, ${name})
1071
+ }
1072
+ /**
1073
+ * 内部方法
1074
+ */
1075
+ s2b() {
1076
+
1077
+ throw new TypeError('s2b is not a function')
1078
+ }
1079
+ /**
1080
+ * 内部方法
1081
+ */
1082
+ findByValue() {
1083
+
1084
+ throw new TypeError('findByValue is not a function')
1085
+ }
1086
+ /**
1087
+ * 内部方法
1088
+ */
1089
+ findByTime() {
1090
+
1091
+ throw new TypeError('findByTime is not a function')
1092
+ }
1093
+ /**
1094
+ * 内部方法
1095
+ */
1096
+ stringToBuffer() {
1097
+
1098
+ throw new TypeError('stringToBuffer is not a function')
1099
+ }
1100
+ ${Object.entries(value).map(([k, v]) => {
1101
+
1102
+ const n = k[0].toUpperCase() + k.substring(1)
1103
+
1104
+ if (v.index) {
1105
+
1106
+ if (v.type === typeMap.time) {
1107
+
1108
+ return `
1109
+ indexBy${n}({after, before} = {}) {
1110
+
1111
+ return super.findByTime($${k}, {after, before})
1112
+ }`
1113
+
1114
+ } else {
1115
+
1116
+ return `
1117
+ indexBy${n}(${k}) {
1118
+
1119
+ return super.findByValue($${k}, ${gen.set[v.type]}(${k}, $${k}))
1120
+ }`
1121
+ }
1122
+
1123
+ } else {
1124
+
1125
+ return ''
1126
+ }
1127
+
1128
+ }).filter(lines => lines.length).join('\n')}
1129
+ }
1130
+ `
1131
+ }
1132
+
1133
+ const clipTypeTs = (path, struct) => writeFileSync(path, `${Object.entries(struct.base).map(([key, value]) => {
1134
+ key = key[0].toUpperCase() + key.substring(1)
1135
+
1136
+ return `
1137
+ interface ${key} {
1138
+ ${Object.entries(value).map(([key, value]) => `
1139
+ /**
1140
+ * ${commentRemark(value.remark)}
1141
+ */
1142
+ ${key}: ${gen.type[value.type]}`).join('')}
1143
+ }
1144
+
1145
+ interface ${key}Set extends Array<${key}> {
1146
+ ${Object.entries(value).filter(([, value]) => value.index).map(([k, value]) => {
1147
+ const Key = k[0].toUpperCase() + k.substring(1)
1148
+ return value.type === typeMap.time ? `
1149
+ indexBy${Key}({after, before}): Array<${key}>` : `
1150
+ indexBy${Key}(${k}: ${gen.type[value.type]}): Array<${key}>`
1151
+ }).join('')}
1152
+ /**
1153
+ * 分页查询
1154
+ */
1155
+ page(predicate: Function, index: Number | String, size: Number | String, params: Object): Array<${key}>
1156
+ /**
1157
+ * 移除数据
1158
+ */
1159
+ remove(...items: Array<${key}>): void
1160
+ /**
1161
+ * 联合查询,类似LEFT JOIN
1162
+ */
1163
+ eachFlat(array: Array<Object>, predicate: Function | String): Array<Object>
1164
+ /**
1165
+ * 联合查询,类似INNER JOIN
1166
+ */
1167
+ filterFlat(array: Array<Object>, predicate: Function | String): Array<Object>
1168
+ }
1169
+ `
1170
+ }
1171
+ ).join('')}
1172
+
1173
+ export interface Storage {
1174
+ close(): void${Object.keys(struct.base).map(key => {
1175
+ const Key = key[0].toUpperCase() + key.substring(1)
1176
+ return `
1177
+ ${key}: ${Key}Set`
1178
+ })}
1179
+ }
1180
+ `)
1181
+
1182
+ const clipIndexMjs = (path, struct) => writeFileSync(path, `
1183
+ import {Entities, Entity, Storage, b2d, d2b, b2s, position, uInt32BEToBuffer, int32BEToBuffer,
1184
+ doubleBEToBuffer, bigint32BEToBuffer, bigUint32BEToBuffer, readInt24BE, readUint24BE, Store} from '${modulePath}'
1185
+ import {struct} from '${modulePath2}'
1186
+
1187
+ const storage = new Storage(import.meta.url)
1188
+
1189
+ ${clipConst(struct.base)}
1190
+ ${Object.entries(struct.base).map(clipEntity).join('')}
1191
+ ${Object.entries(struct.base).map(clipEntities).join('')}
1192
+ export const remark = Symbol('remark')
1193
+
1194
+ export function getStruct() {
1195
+
1196
+ return struct(storage, remark)
1197
+ }
1198
+
1199
+ /**
1200
+ * @type {import('./type').Storage}
1201
+ */
1202
+ const store = Object.freeze({
1203
+ close() {
1204
+ storage.close()
1205
+ },${Object.keys(struct.base).map(key => {
1206
+ const Key = key[0].toUpperCase() + key.substring(1)
1207
+ return `
1208
+ ${key}: new Proxy([], {
1209
+ get: new ${Key}Set()
1210
+ }),`
1211
+ }).join('')}
1212
+ })
1213
+
1214
+ export default store
1215
+ `)
1216
+
1217
+ /**
1218
+ * 升级
1219
+ * @param {string} name
1220
+ * @param {string} newPwd
1221
+ * @param {string} password
1222
+ * @param {number} version
1223
+ * @return {import('./type').Gen}
1224
+ * @example
1225
+ * const {submit} = upgrade('test')
1226
+ * submit()
1227
+ */
1228
+ export default function upgrade(name, {
1229
+ newPwd,
1230
+ password = '',
1231
+ version = 1,
1232
+ } = {}) {
1233
+
1234
+ const dir = name[name.length - 1] === '/' ? name : name + '/'
1235
+
1236
+ if (!existsSync(dir)) {
1237
+
1238
+ mkdirSync(dir)
1239
+ }
1240
+
1241
+ let v = readdirSync(dir).map(v => parseFloat(v) || 0).sort(sort).pop()
1242
+
1243
+ let prev
1244
+
1245
+ if (v === undefined) {
1246
+
1247
+ v = 0
1248
+
1249
+ prev = initDir(name, dir + 0)
1250
+
1251
+ prev.init()
1252
+
1253
+ } else {
1254
+
1255
+ prev = new Storage(dir + v + '/', password)
1256
+ }
1257
+
1258
+ if (version <= v) {
1259
+
1260
+ version = v + 1
1261
+ }
1262
+
1263
+ console.log(`version: ${v} -> ${version}`)
1264
+
1265
+ copyDir(dir + v, dir + version)
1266
+
1267
+ const curr = new Storage(dir + version + '/', password, newPwd)
1268
+ const root = resolve('/')
1269
+ const rootDir = (root.length > 1 ? resolve('./').substring(root.length - 1) : resolve('./'))
1270
+ .replace(/\\/g, '/')
1271
+ const prevUrlParams = `?t=${Date.now()}${password ? `&password=${password}` : ''}`
1272
+ const currUrlParams = newPwd ? `${prevUrlParams}&password=${newPwd}` : prevUrlParams
1273
+
1274
+ const scope = {
1275
+ dir: `${rootDir}/${dir}`,
1276
+ prevUrlParams,
1277
+ currUrlParams,
1278
+ prevPath: `${rootDir}/${dir}${v}/index.mjs`,
1279
+ currPath: `${rootDir}/${dir}${version}/index.mjs`,
1280
+ typePath: `${rootDir}/${dir}${version}/type.ts`,
1281
+ prev,
1282
+ curr,
1283
+ types: [Id, Uint, Int, BigUint, Bigint, Time, Float, String, Buffer, Text],
1284
+ updateSet: new Set,
1285
+ }
1286
+
1287
+ return {
1288
+ /**
1289
+ * 添加集合
1290
+ * @type {function}
1291
+ * @param {string} name
1292
+ * @param {Object} set
1293
+ * @param {string} remark
1294
+ * @example
1295
+ * appendSet(name, set, remark)
1296
+ */
1297
+ appendSet: appendSet.bind(scope),
1298
+ /**
1299
+ * 更新集合
1300
+ * @type {function}
1301
+ * @param {string} name
1302
+ * @param {Object} set
1303
+ * @example
1304
+ * updateCol(name, set)
1305
+ */
1306
+ updateCol: updateCol.bind(scope),
1307
+ /**
1308
+ * 集合改名
1309
+ * @type {function}
1310
+ * @param {string} name
1311
+ * @param {string} newName
1312
+ * @example
1313
+ * renameSet(name, newName)
1314
+ */
1315
+ renameSet: renameSet.bind(scope),
1316
+ /**
1317
+ * 改键名
1318
+ * @type {function}
1319
+ * @param {string} name
1320
+ * @param {Object} set
1321
+ * @example
1322
+ * renameCol(name, set)
1323
+ */
1324
+ renameCol: renameCol.bind(scope),
1325
+ /**
1326
+ * 删除集合
1327
+ * @type {function}
1328
+ * @param {string} name
1329
+ * @example
1330
+ * deleteSet(name)
1331
+ */
1332
+ deleteSet: deleteSet.bind(scope),
1333
+ /**
1334
+ * 删除集合
1335
+ * @type {function}
1336
+ * @param {string} name
1337
+ * @param {string} colName
1338
+ * @example
1339
+ * deleteCol(name, colName)
1340
+ */
1341
+ deleteCol: deleteCol.bind(scope),
1342
+ /**
1343
+ * 更新集合备注
1344
+ * @type {function}
1345
+ * @param {string} name
1346
+ * @param {string} remark
1347
+ * @example
1348
+ * updateSetRemark(name, remark)
1349
+ */
1350
+ updateSetRemark: updateSetRemark.bind(scope),
1351
+ /**
1352
+ * 提交跟新
1353
+ * @type {function}
1354
+ */
1355
+ submit: submit.bind(scope),
1356
+ }
1357
+ }