@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/architect.mjs ADDED
@@ -0,0 +1,1400 @@
1
+ import {dirname, resolve} from "node:path"
2
+ import {openSync, closeSync, readFileSync, writeFileSync, readSync, writeSync, unlinkSync} from "node:fs"
3
+ import {createCipheriv, createDecipheriv, createHash, scryptSync} from "node:crypto"
4
+
5
+ /**
6
+ *
7
+ * @param {Array} array
8
+ * @param {Function | String} predicate
9
+ * @return {Array}
10
+ */
11
+ Array.prototype.eachFlat = function (array, predicate) {
12
+
13
+ if (typeof predicate === "string") {
14
+
15
+ const key = predicate
16
+
17
+ predicate = (a, b) => a[key] === b[key]
18
+ }
19
+
20
+ return this.map(item => {
21
+
22
+ const result = array.filter(entry => predicate(item, entry))
23
+
24
+ if (result.length === 0) return item
25
+
26
+ return result.map(entry => ({...entry, ...item}))
27
+
28
+ }).flat()
29
+ }
30
+
31
+ /**
32
+ *
33
+ * @param {Array} array
34
+ * @param {Function | String} predicate
35
+ * @return {Array}
36
+ */
37
+ Array.prototype.filterFlat = function (array, predicate) {
38
+
39
+ if (typeof predicate === "string") {
40
+
41
+ const key = predicate
42
+
43
+ predicate = (a, b) => a[key] === b[key]
44
+ }
45
+
46
+ return this.map(item => array
47
+ .filter(entry => predicate(item, entry))
48
+ .map(entry => ({...entry, ...item}))
49
+ ).flat()
50
+ }
51
+
52
+ /**
53
+ * 时间筛选的最大值
54
+ * @type {number}
55
+ */
56
+ export const MaxTime = 99999999999999
57
+ /**
58
+ * 用于获取存储的位置
59
+ * @type {symbol}
60
+ */
61
+ export const position = Symbol('position')
62
+
63
+ export const TypeLen = {
64
+
65
+ id: 4,
66
+ int: 4,
67
+ text: 1,
68
+ time: 6,
69
+ uint: 4,
70
+ float: 8,
71
+ bigint: 8,
72
+ bigUint: 8,
73
+ buffer: 1,
74
+ string: 12
75
+ }
76
+
77
+ /**
78
+ * 加解密的类
79
+ */
80
+ class Cipher {
81
+ /**
82
+ * 加密的键
83
+ * @type {string}
84
+ */
85
+ #key
86
+ /**
87
+ * 加密方式
88
+ * @type {string}
89
+ */
90
+ #algorithm = 'aes-192-cbc'
91
+ /**
92
+ * 加密向量
93
+ * @type {Int8Array}
94
+ */
95
+ #iv
96
+
97
+ constructor(key) {
98
+
99
+ if (!key) return
100
+
101
+ this.update(key)
102
+ }
103
+
104
+ /**
105
+ * 计算md5值
106
+ * @param {string} data
107
+ * @returns {Promise<ArrayBuffer>}
108
+ */
109
+ md5(data) {
110
+
111
+ const hash = createHash('md5')
112
+
113
+ hash.update(data)
114
+
115
+ return hash.digest('hex')
116
+ }
117
+
118
+ /**
119
+ * 加密
120
+ * @param {buffer} buffer
121
+ * @returns {buffer}
122
+ */
123
+ encrypt(buffer) {
124
+
125
+ if (!this.#key) return buffer
126
+
127
+ const cipher = createCipheriv(this.#algorithm, this.#key, this.#iv)
128
+
129
+ return Buffer.concat([cipher.update(buffer), cipher.final()])
130
+ }
131
+
132
+ /**
133
+ * 解密
134
+ * @param {buffer} buffer
135
+ * @returns {buffer}
136
+ */
137
+ decrypt(buffer) {
138
+
139
+ if (!this.#key) return buffer
140
+
141
+ const decipher = createDecipheriv(this.#algorithm, this.#key, this.#iv)
142
+
143
+ return Buffer.concat([decipher.update(buffer), decipher.final()])
144
+ }
145
+
146
+ /**
147
+ * 更新键
148
+ * @param {string} key
149
+ */
150
+ update(key) {
151
+
152
+ if (!key) return this.#key = undefined
153
+
154
+ this.#key = this.md5(key)
155
+ this.#iv = Buffer.from(this.#key).subarray(8, 24)
156
+ this.#key = scryptSync(this.#key, 'salt', 24)
157
+ }
158
+ }
159
+
160
+ export class Entity {
161
+
162
+ #storage
163
+ #position
164
+
165
+ #indexSet
166
+ #lengthSet
167
+ #positionSet
168
+
169
+ constructor(storage, position, indexSet, lengthSet, positionSet) {
170
+
171
+ this.#storage = storage
172
+ this.#position = position
173
+ this.#indexSet = indexSet
174
+ this.#lengthSet = lengthSet
175
+ this.#positionSet = positionSet
176
+ }
177
+
178
+ get [position]() {
179
+
180
+ return this.#position
181
+ }
182
+
183
+ get(name) {
184
+
185
+ return this.#storage.getValue(this.#position + this.#positionSet[name], this.#lengthSet[name])
186
+ }
187
+
188
+ set(name, buffer) {
189
+
190
+ this.#storage.setValue(this.#position + this.#positionSet[name], this.#lengthSet[name], buffer)
191
+ }
192
+
193
+ #indexPosition(index, buffer, length, s, e) {
194
+
195
+ if (e < s) return s
196
+ if (s === e) return buffer < this.#storage.getValue(index[s], length) ? s : s + 1
197
+ if (buffer <= this.#storage.getValue(index[s], length)) return s
198
+ if (buffer >= this.#storage.getValue(index[e], length)) return e + 1
199
+
200
+ let m = Math.floor((s + e) / 2), buf = this.#storage.getValue(index[m], length)
201
+
202
+ if (buffer < buf) return this.#indexPosition(index, buffer, length, s + 1, m - 1)
203
+ if (buffer > buf) return this.#indexPosition(index, buffer, length, m + 1, e - 1)
204
+
205
+ return m
206
+ }
207
+
208
+ set2(name, buffer) {
209
+
210
+ const position = this.#position + this.#positionSet[name]
211
+ const index = this.#indexSet[name]
212
+ const length = this.#lengthSet[name]
213
+ const buf = this.#storage.getValue(position, length)
214
+ const changed = !buf.equals(buffer)
215
+
216
+ if (changed) {
217
+
218
+ this.#storage.setValue(position, length, buffer)
219
+ }
220
+
221
+ let i = index.indexOf(position)
222
+
223
+ if (changed || i === -1) {
224
+
225
+ let s = 0, e = index.length - 1
226
+
227
+ if (i >= 0) {
228
+
229
+ index.splice(i, 1)
230
+
231
+ if (buf > buffer) {
232
+
233
+ e = i - 1
234
+
235
+ } else {
236
+
237
+ e--
238
+
239
+ s = i
240
+ }
241
+ }
242
+
243
+ i = index.length === 0 ? 0 : this.#indexPosition(index, buffer, length, s, e)
244
+
245
+ index.splice(i, 0, position)
246
+ }
247
+ }
248
+
249
+ readFileSync(name) {
250
+
251
+ return readFileSync(this.#storage.bufferDir + (this.#position + this.#positionSet[name]))
252
+ }
253
+
254
+ buffer(value, name) {
255
+
256
+ const buffer = Buffer.alloc(TypeLen.buffer)
257
+
258
+ if (value instanceof Buffer) {
259
+
260
+ writeFileSync(this.#storage.bufferDir + (this.#position + this.#positionSet[name]), value)
261
+
262
+ buffer[0] = 1
263
+ }
264
+
265
+ return buffer
266
+ }
267
+
268
+ intToBuffer(value, name) {
269
+
270
+ const size = this.#lengthSet[name]
271
+
272
+ const buffer = Buffer.alloc(size)
273
+
274
+ switch (size) {
275
+
276
+ case 1:
277
+ buffer.writeInt8(value)
278
+ break
279
+ case 2:
280
+ buffer.writeInt16BE(value)
281
+ break
282
+ case 3:
283
+ writeInt24BE(buffer, value)
284
+ break
285
+ case 4:
286
+ buffer.writeInt32BE(value)
287
+ break
288
+ }
289
+
290
+ return buffer
291
+ }
292
+
293
+ uintToBuffer(value, name) {
294
+
295
+ const size = this.#lengthSet[name]
296
+
297
+ const buffer = Buffer.alloc(size)
298
+
299
+ switch (size) {
300
+
301
+ case 1:
302
+ buffer.writeUint8(value)
303
+ break
304
+ case 2:
305
+ buffer.writeUint16BE(value)
306
+ break
307
+ case 3:
308
+ writeUint24BE(buffer, value)
309
+ break
310
+ case 4:
311
+ buffer.writeUint32BE(value)
312
+ break
313
+ }
314
+
315
+ return buffer
316
+ }
317
+
318
+ textToBuffer(value = '', name) {
319
+
320
+ const buffer = Buffer.alloc(TypeLen.text)
321
+
322
+ writeFileSync(this.#storage.bufferDir + (this.#position + this.#positionSet[name]),
323
+ typeof value === "string" ? value : String(value))
324
+
325
+ buffer[0] = 1
326
+
327
+ return buffer
328
+ }
329
+
330
+ s2b(value = '', name) {
331
+
332
+ return s2b(value, this.#lengthSet[name])
333
+ }
334
+ }
335
+
336
+ export class Entities extends Array {
337
+
338
+ #idle
339
+ #name
340
+ #index
341
+ #value
342
+ #length
343
+ #record
344
+ #bufferSet = {}
345
+ #lengthSet = {}
346
+ #positionSet = {}
347
+ #storage
348
+ #classify
349
+
350
+ constructor(storage, classify) {
351
+
352
+ const name = classify.name
353
+ const record = storage.record.record[name]
354
+
355
+ super()
356
+
357
+ this.#name = name
358
+ this.#storage = storage
359
+ this.#classify = classify
360
+ this.#idle = storage.record.idle[name]
361
+ this.#index = storage.record.index[name]
362
+ this.#value = storage.record.value[name]
363
+ this.#length = storage.struct.extra[name].length
364
+ this.#record = record
365
+
366
+ for (const [key, value] of Object.entries(storage.struct.base[name])) {
367
+
368
+ this.#lengthSet[key] = value.length
369
+ this.#positionSet[key] = value.position
370
+ }
371
+
372
+ const methods = {
373
+ push: this.push.bind(this),
374
+ pop: this.pop.bind(this),
375
+ unshift: this.unshift.bind(this),
376
+ shift: this.shift.bind(this),
377
+ splice: this.splice.bind(this),
378
+ page: this.page.bind(this),
379
+ remove: this.remove.bind(this),
380
+ s2b: this.s2b.bind(this),
381
+ findByValue: this.findByValue.bind(this),
382
+ findByTime: this.findByTime.bind(this),
383
+ }
384
+
385
+ for (const [key, value] of Object.entries(storage.struct.base[name])) {
386
+
387
+ if (Reflect.has(value, 'index')) {
388
+
389
+ const name = `indexBy${key[0].toUpperCase()}${key.substring(1)}`
390
+
391
+ methods[name] = this[name].bind(this)
392
+ }
393
+ }
394
+
395
+ return (target, p) => {
396
+
397
+ const index = Number.parseInt(String(p))
398
+
399
+ if (Number.isInteger(index)) {
400
+
401
+ if (index >= record.length || index < 0) return null
402
+
403
+ return storage.getEntity(record[p], classify, this.#index, this.#lengthSet, this.#positionSet)
404
+ }
405
+
406
+ if (Reflect.has(methods, p)) return methods[p]
407
+
408
+ const result = record[p]
409
+
410
+ if (typeof result !== "function") return result
411
+
412
+ return (...arg) => result.call(record.map(position => storage.getEntity(position, classify,
413
+ this.#index, this.#lengthSet, this.#positionSet)), ...arg)
414
+ }
415
+ }
416
+
417
+ #recycle(index) {
418
+
419
+ let i
420
+
421
+ for (const value of Object.values(this.#index)) {
422
+
423
+ i = value.indexOf(index)
424
+
425
+ if (i >= 0) {
426
+
427
+ value.splice(i, 1)
428
+ }
429
+ }
430
+
431
+ for (const value of Object.values(this.#bufferSet)) {
432
+
433
+ unlinkSync(`${this.#storage.bufferDir}/${index + value}`)
434
+ }
435
+ }
436
+
437
+ #getEntity(position) {
438
+
439
+ return this.#storage.getEntity(position, this.#classify, this.#index, this.#lengthSet, this.#positionSet)
440
+ }
441
+
442
+ #assign(position, item) {
443
+
444
+ Object.assign(new this.#classify(position, this.#index, this.#lengthSet, this.#positionSet),
445
+ this.#classify.create(item))
446
+ }
447
+
448
+ push(...items) {
449
+
450
+ if (this.#storage.needSave === false) {
451
+
452
+ this.#storage.needSave = true
453
+ }
454
+
455
+ for (const item of items) {
456
+
457
+ let position
458
+
459
+ if (this.#idle.length) {
460
+
461
+ position = this.#idle.pop()
462
+
463
+ } else {
464
+
465
+ position = this.#storage.pointer
466
+
467
+ this.#storage.pointer += this.#length
468
+ }
469
+
470
+ this.#record.push(position)
471
+
472
+ this.#assign(position, item)
473
+ }
474
+
475
+ return items.length
476
+ }
477
+
478
+ pop() {
479
+
480
+ if (this.#storage.needSave === false) {
481
+
482
+ this.#storage.needSave = true
483
+ }
484
+
485
+ const index = this.#record.pop()
486
+
487
+ this.#recycle(index)
488
+
489
+ this.#idle.push(index)
490
+
491
+ return this.#getEntity(index)
492
+ }
493
+
494
+ unshift(...items) {
495
+
496
+ if (this.#storage.needSave === false) {
497
+
498
+ this.#storage.needSave = true
499
+ }
500
+
501
+ for (const item of items) {
502
+
503
+ let position
504
+
505
+ if (this.#idle.length) {
506
+
507
+ position = this.#idle.pop()
508
+
509
+ } else {
510
+
511
+ position = this.#storage.pointer
512
+
513
+ this.#storage.pointer += this.#length
514
+ }
515
+
516
+ this.#record.unshift(position)
517
+
518
+ this.#assign(position, item)
519
+ }
520
+
521
+ return items.length
522
+ }
523
+
524
+ shift() {
525
+
526
+ if (this.#storage.needSave === false) {
527
+
528
+ this.#storage.needSave = true
529
+ }
530
+
531
+ const index = this.#record.shift()
532
+
533
+ this.#recycle(index)
534
+ this.#idle.push(index)
535
+
536
+ return this.#getEntity(index)
537
+ }
538
+
539
+ splice(start, deleteCount, ...items) {
540
+
541
+ if (this.#storage.needSave === false) {
542
+
543
+ this.#storage.needSave = true
544
+ }
545
+
546
+ const record = items.map(item => {
547
+
548
+ let position
549
+
550
+ if (this.#idle.length) {
551
+
552
+ position = this.#idle.pop()
553
+
554
+ } else {
555
+
556
+ position = this.#storage.pointer
557
+
558
+ this.#storage.pointer += this.#length
559
+ }
560
+
561
+ this.#assign(position, item)
562
+
563
+ return position
564
+ })
565
+
566
+ const idle = this.#record.splice(start, deleteCount, ...record)
567
+
568
+ for (let index of idle) {
569
+
570
+ this.#recycle(index)
571
+ }
572
+
573
+ this.#idle.push(...idle)
574
+
575
+ return idle
576
+ }
577
+
578
+ #page(predicate, page, size, params) {
579
+
580
+ const result = this.#storage.getCache(params,
581
+ () => this.#record.filter(position => predicate(this.#getEntity(position))))
582
+
583
+ const list = result.slice((page - 1) * size, page * size).map(position => this.#getEntity(position))
584
+
585
+ list.total = result.length
586
+
587
+ return list
588
+ }
589
+
590
+ /**
591
+ * 分页
592
+ * @param {Function} predicate
593
+ * @param index
594
+ * @param size
595
+ * @param params
596
+ * @return {*[]|*|*[]}
597
+ */
598
+ page(predicate, page, size, params) {
599
+
600
+ if (typeof page === "string" && typeof size === "string" && typeof params === "object") {
601
+
602
+ return this.#page(predicate, params[page], params[size], this.#name + ' ' +
603
+ JSON.stringify(params, (replacer, target) => replacer === page || replacer === size ? undefined : target)
604
+ )
605
+ }
606
+
607
+ if (size <= 0) {
608
+
609
+ return []
610
+ }
611
+
612
+ if (page < 1) {
613
+
614
+ page = 1
615
+ }
616
+
617
+ const total = size * page
618
+
619
+ const result = []
620
+
621
+ for (let i = 0; i < this.#record.length; i++) {
622
+
623
+ if (predicate(this.#record[i], i, this.#record)) {
624
+
625
+ result.push(this.#record[i])
626
+
627
+ if (result.length >= total) {
628
+
629
+ return result.slice((page - 1) * size).map(index => this.#getEntity(index))
630
+ }
631
+ }
632
+ }
633
+
634
+ return result.slice((page - 1) * size).map(index => this.#getEntity(index))
635
+ }
636
+
637
+ remove(...items) {
638
+
639
+ let index
640
+
641
+ if (Array.isArray(items[0])) {
642
+
643
+ items = items[0]
644
+ }
645
+
646
+ for (const item of items) {
647
+
648
+ if (item === undefined) continue
649
+
650
+ index = this.#record.findIndex(pos => item[position] === pos)
651
+
652
+ if (index >= 0) {
653
+
654
+ this.splice(index, 1)
655
+ }
656
+ }
657
+ }
658
+
659
+ #findByValue(index, buffer, length, s, e) {
660
+
661
+ if (e < s) return []
662
+
663
+ let m = Math.floor((s + e) / 2), buf = this.#storage.getValue(index[m], length)
664
+
665
+ if (buffer < buf) return this.#findByValue(index, buffer, length, s, m - 1)
666
+ if (buffer > buf) return this.#findByValue(index, buffer, length, m + 1, e)
667
+
668
+ let result = [index[m]], i
669
+
670
+ for (i = m - 1; i >= 0; i--) {
671
+
672
+ if (!this.#storage.getValue(index[i], length).equals(buffer)) break
673
+
674
+ result.unshift(index[i])
675
+ }
676
+
677
+ for (i = m + 1; i < index.length; i++) {
678
+
679
+ if (!this.#storage.getValue(index[i], length).equals(buffer)) break
680
+
681
+ result.push(index[i])
682
+ }
683
+
684
+ return result
685
+ }
686
+
687
+ findByValue(name, value) {
688
+
689
+ const index = this.#index[name]
690
+ const position = this.#positionSet[name]
691
+
692
+ return this.#findByValue(index, value, this.#lengthSet[name], 0, index.length - 1)
693
+ .map(index => this.#getEntity(index - position))
694
+ }
695
+
696
+ #findByTime(index, after, before, length, s, e) {
697
+
698
+ if (e < s) return []
699
+
700
+ let m = Math.floor((s + e) / 2), buffer = this.#storage.getValue(index[m], length)
701
+
702
+ if (before < buffer) return this.#findByTime(index, after, before, length, s, m - 1)
703
+ if (after > buffer) return this.#findByTime(index, after, before, length, m + 1, e)
704
+
705
+ let result = [index[m]], i
706
+
707
+ for (i = m - 1; i >= 0; i--) {
708
+
709
+ if (this.#storage.getValue(index[i], length) < after) break
710
+
711
+ result.unshift(index[i])
712
+ }
713
+
714
+ for (i = m + 1; i < index.length; i++) {
715
+
716
+ if (this.#storage.getValue(index[i], length) > before) break
717
+
718
+ result.push(index[i])
719
+ }
720
+
721
+ return result
722
+ }
723
+
724
+ findByTime(name, {after = 0, before = MaxTime}) {
725
+
726
+ const index = this.#index[name]
727
+ const position = this.#positionSet[name]
728
+
729
+ if (after > before) {
730
+
731
+ [after, before] = [before, after]
732
+ }
733
+
734
+ if (after < 0 || after > MaxTime) {
735
+
736
+ after = 0
737
+ }
738
+
739
+ if (before < 0 || before > MaxTime) {
740
+
741
+ before = MaxTime
742
+ }
743
+
744
+ return this.#findByTime(index, d2b(after), d2b(before), TypeLen.time, 0, index.length - 1)
745
+ .map(index => this.#getEntity(index - position))
746
+ }
747
+
748
+ s2b(value = '', name) {
749
+
750
+ return s2b(value, this.#lengthSet[name])
751
+ }
752
+ }
753
+
754
+ const u2o = (url = '') => {
755
+
756
+ const obj = {}
757
+
758
+ let index = url.indexOf('?')
759
+
760
+ if (index >= 0) {
761
+
762
+ for (const params of url.substring(index + 1).split('&')) {
763
+
764
+ index = params.indexOf('=')
765
+
766
+ if (index === -1) {
767
+
768
+ obj[decodeURI(params)] = decodeURI(params)
769
+
770
+ } else {
771
+
772
+ obj[decodeURI(params.substring(0, index))] = decodeURI(params.substring(index + 1))
773
+ }
774
+ }
775
+ }
776
+
777
+ return obj
778
+ }
779
+
780
+ export class Storage {
781
+
782
+ needSave = false
783
+
784
+ #cipher
785
+ #buffer
786
+ #struct
787
+ #record
788
+ #fd_data
789
+ #fd_index
790
+ #caches = new Map
791
+ #values = new Map
792
+ #entities = new Map
793
+ #interval
794
+
795
+ constructor(url, password, newPwd) {
796
+
797
+ url = decodeURI(url)
798
+
799
+ let dir = url.endsWith('/') ? url : dirname(url) + '/'
800
+
801
+ const root = resolve('/')
802
+
803
+ if (dir.startsWith('file:///')) {
804
+
805
+ dir = root.length > 1 ? dir.substring(7 + root.length) : dir.substring(7)
806
+ }
807
+
808
+ this.#fd_data = openSync(dir + 'data', 'r+')
809
+ this.#fd_index = openSync(dir + 'index', 'r+')
810
+
811
+ const params = u2o(url)
812
+
813
+ this.#cipher = new Cipher(params.password || password || '')
814
+
815
+ newPwd = newPwd || params.newPwd
816
+
817
+ try {
818
+
819
+ this.#struct = this.#getStruct()
820
+ this.#record = this.#getRecord()
821
+
822
+ if (newPwd !== undefined) {
823
+
824
+ this.#cipher.update(newPwd)
825
+
826
+ this.updateStruct(this.#struct)
827
+ this.updateRecord(this.#record)
828
+ }
829
+
830
+ } catch (e) {
831
+
832
+ throw new Error('密码不匹配或者存储文件不正确')
833
+ }
834
+
835
+ this.#buffer = dir + '/buffer/'
836
+
837
+ const id = this.#getId() + 1
838
+
839
+ this.#updateId(id)
840
+
841
+ this.#interval = setInterval(() => {
842
+
843
+ this.#save()
844
+
845
+ this.#check(this.#caches, this.#values, this.#entities)
846
+
847
+ if (id !== this.#getId()) {
848
+
849
+ throw new Error(dir + '已在其他地方打开')
850
+ }
851
+
852
+ }, 3000)
853
+ }
854
+
855
+ #save() {
856
+
857
+ for (const [position, item] of this.#values.entries()) {
858
+
859
+ if (item.needsSave) {
860
+
861
+ item.needsSave = false
862
+
863
+ writeSync(this.#fd_data, item.value, 0, item.value.length, position)
864
+ }
865
+ }
866
+
867
+ if (this.needSave) {
868
+
869
+ this.updateRecord(this.#record)
870
+ }
871
+ }
872
+
873
+ #check(...arg) {
874
+
875
+ for (const map of arg) {
876
+
877
+ for (const [key, value] of map) {
878
+
879
+ if (value.expired === false) {
880
+
881
+ value.expired = true
882
+
883
+ } else {
884
+
885
+ map.delete(key)
886
+ }
887
+ }
888
+ }
889
+ }
890
+
891
+ #writeNumber(number, position) {
892
+
893
+ const buffer = Buffer.alloc(4)
894
+
895
+ buffer.writeUint32BE(number, 0)
896
+
897
+ writeSync(this.#fd_index, buffer, 0, 4, position)
898
+ }
899
+
900
+ #updateId(id = 0) {
901
+
902
+ this.#writeNumber(id, 0)
903
+ }
904
+
905
+ updateStruct(struct = {
906
+ base: {},
907
+ extra: {},
908
+ }) {
909
+
910
+ this.#struct = struct
911
+
912
+ this.#update(struct)
913
+ }
914
+
915
+ updateRecord(record = {
916
+ idle: {},
917
+ index: {},
918
+ value: {},
919
+ record: {},
920
+ pointer: 0,
921
+ }, length = 4 + this.#getLength()) {
922
+
923
+ this.#record = record
924
+
925
+ this.#update(record, length)
926
+ }
927
+
928
+ #update(object = {}, position = 0) {
929
+
930
+ object = Buffer.from(JSON.stringify(object))
931
+ object = this.#cipher.encrypt(object)
932
+
933
+ this.#writeNumber(object.length, 4 + position)
934
+
935
+ writeSync(this.#fd_index, object, 0, object.length, 8 + position)
936
+ }
937
+
938
+ #getId() {
939
+
940
+ const buffer = Buffer.alloc(4)
941
+
942
+ readSync(this.#fd_index, buffer, {
943
+ offset: 0,
944
+ length: 4,
945
+ position: 0,
946
+ })
947
+
948
+ return buffer.readUInt32BE(0)
949
+ }
950
+
951
+ #getLength(position = 0) {
952
+
953
+ const buffer = Buffer.alloc(4)
954
+
955
+ readSync(this.#fd_index, buffer, 0, 4, 4 + position)
956
+
957
+ return buffer.readUInt32BE(0)
958
+ }
959
+
960
+ #getJson(length, position = 0) {
961
+
962
+ const buffer = Buffer.alloc(length)
963
+
964
+ readSync(this.#fd_index, buffer, 0, length, 8 + position)
965
+
966
+ return JSON.parse(this.#cipher.decrypt(buffer).toString() || '{}')
967
+ }
968
+
969
+ #getStruct() {
970
+
971
+ return this.#getJson(this.#getLength())
972
+ }
973
+
974
+ #getRecord() {
975
+
976
+ const position = this.#getLength() + 4
977
+
978
+ return this.#getJson(this.#getLength(position), position)
979
+ }
980
+
981
+ init() {
982
+
983
+ this.#updateId(1)
984
+ this.updateStruct()
985
+ this.updateRecord()
986
+ }
987
+
988
+ getCache(params, predicate) {
989
+
990
+ if (this.#caches.has(params)) {
991
+
992
+ const item = this.#caches.get(params)
993
+
994
+ if (item.expired === false) {
995
+
996
+ item.expired = true
997
+ }
998
+
999
+ return item.cache
1000
+
1001
+ } else {
1002
+
1003
+ const cache = predicate()
1004
+
1005
+ this.#caches.set(params, {
1006
+ expired: false,
1007
+ cache,
1008
+ })
1009
+
1010
+ return cache
1011
+ }
1012
+ }
1013
+
1014
+ getValue(position, length) {
1015
+
1016
+ if (this.#values.has(position)) {
1017
+
1018
+ const item = this.#values.get(position)
1019
+
1020
+ if (item.expired === true) {
1021
+
1022
+ item.expired = false
1023
+ }
1024
+
1025
+ return item.value
1026
+
1027
+ } else {
1028
+
1029
+ const value = Buffer.alloc(length)
1030
+
1031
+ readSync(this.#fd_data, value, 0, length, position)
1032
+
1033
+ this.#values.set(position, {
1034
+ value,
1035
+ expired: false,
1036
+ needsSave: true,
1037
+ })
1038
+
1039
+ return value
1040
+ }
1041
+ }
1042
+
1043
+ setValue(position, length, value) {
1044
+
1045
+ if (this.#values.has(position)) {
1046
+
1047
+ const item = this.#values.get(position)
1048
+
1049
+ if (!item.value.equals(value)) {
1050
+
1051
+ if (item.needsSave === false) {
1052
+
1053
+ item.needsSave = true
1054
+ }
1055
+
1056
+ item.value = value
1057
+ }
1058
+
1059
+ } else {
1060
+
1061
+ const val = Buffer.alloc(length)
1062
+
1063
+ readSync(this.#fd_data, val, 0, length, position)
1064
+
1065
+ this.#values.set(position, {
1066
+ value,
1067
+ expired: true,
1068
+ needsSave: value !== val,
1069
+ })
1070
+ }
1071
+ }
1072
+
1073
+ getEntity(position, classify, ...arg) {
1074
+
1075
+ if (this.#entities.has(position)) {
1076
+
1077
+ const item = this.#entities.get(position)
1078
+
1079
+ if (item.expired === false) {
1080
+
1081
+ item.expired = true
1082
+ }
1083
+
1084
+ return item.entity
1085
+
1086
+ } else {
1087
+
1088
+ const entity = new classify(position, ...arg)
1089
+
1090
+ this.#entities.set(position, {
1091
+ entity,
1092
+ expired: false
1093
+ })
1094
+
1095
+ return entity
1096
+ }
1097
+ }
1098
+
1099
+ get struct() {
1100
+
1101
+ return this.#struct
1102
+ }
1103
+
1104
+ get record() {
1105
+
1106
+ return this.#record
1107
+ }
1108
+
1109
+ get bufferDir() {
1110
+
1111
+ return this.#buffer
1112
+ }
1113
+
1114
+ get pointer() {
1115
+
1116
+ return this.#record.pointer
1117
+ }
1118
+
1119
+ set pointer(pointer) {
1120
+
1121
+ this.#record.pointer = pointer
1122
+ }
1123
+
1124
+ close() {
1125
+
1126
+ this.#save()
1127
+
1128
+ clearInterval(this.#interval)
1129
+
1130
+ closeSync(this.#fd_data)
1131
+ closeSync(this.#fd_index)
1132
+ }
1133
+
1134
+ updateValue(value, name, key) {
1135
+
1136
+ if (!value) return this.#record.value[name][key] += this.#struct.base[name][key].step
1137
+
1138
+ value = Number.parseFloat(value) || 1
1139
+
1140
+ if (value > this.#record.value[name][key]) this.#record.value[name][key] = value
1141
+
1142
+ return value
1143
+ }
1144
+ }
1145
+
1146
+ export class Store {
1147
+ }
1148
+
1149
+ export const buffer = Buffer
1150
+ export const string = String
1151
+
1152
+ const now = Date.now().toString(16)
1153
+
1154
+ const length = now.length % 2 === 0 ? now.length : now.length + 1
1155
+
1156
+ /**
1157
+ * @param {Buffer} buffer
1158
+ * @param {Number} value
1159
+ */
1160
+ const writeInt24BE = (buffer, value) => {
1161
+
1162
+ if (value > 8388607 || value < -8388608) throw new RangeError(
1163
+ 'RangeError [ERR_OUT_OF_RANGE]: The value of "value" is out of range. It must be >= -8388608 and <= 8388607. Received ' + value)
1164
+
1165
+ if (value > 65535) {
1166
+
1167
+ buffer.writeUInt8(value >> 16)
1168
+ buffer.writeUint16BE(value % 65536, 1)
1169
+
1170
+ } else if (value > 0) {
1171
+
1172
+ buffer.writeUInt8(0)
1173
+ buffer.writeUint16BE(value, 1)
1174
+
1175
+ } else if (value === -8388608) {
1176
+
1177
+ buffer.writeUInt8(128)
1178
+ buffer.writeUint16BE(0, 1)
1179
+
1180
+ } else if (value < -65535) {
1181
+
1182
+ value = -value
1183
+ buffer.writeUInt8((value >> 16) + 128)
1184
+ buffer.writeUint16BE(value % 65536, 1)
1185
+
1186
+ } else if (value < 0) {
1187
+
1188
+ value = -value
1189
+ buffer.writeUInt8(128)
1190
+ buffer.writeUint16BE(value, 1)
1191
+ }
1192
+ }
1193
+
1194
+ /**
1195
+ * @param {Buffer} buffer
1196
+ * @param {Number} value
1197
+ */
1198
+ const writeUint24BE = (buffer, value) => {
1199
+
1200
+ if (value > 16777215 || value < 0) throw new RangeError(
1201
+ 'RangeError [ERR_OUT_OF_RANGE]: The value of "value" is out of range. It must be >= -8388608 and <= 8388607. Received ' + value)
1202
+
1203
+ if (value > 65535) {
1204
+
1205
+ buffer.writeUInt8(value >> 16)
1206
+ buffer.writeUint16BE(value % 65536, 1)
1207
+
1208
+ } else if (value >= 0) {
1209
+
1210
+ buffer.writeUInt8(0)
1211
+ buffer.writeUint16BE(value, 1)
1212
+ }
1213
+ }
1214
+
1215
+ /**
1216
+ * @param {Buffer} buffer
1217
+ * @return {Number}
1218
+ */
1219
+ export const readInt24BE = buffer => {
1220
+
1221
+ let n1 = buffer.readUint8()
1222
+ const n2 = buffer.readUInt16BE(1)
1223
+
1224
+ if (n1 === 0) return n2
1225
+
1226
+ if (n1 === 128 && n2 === 0) return -8388608
1227
+
1228
+ if (n1 >= 128) {
1229
+
1230
+ n1 -= 128
1231
+
1232
+ return -(n1 * 65536 + n2)
1233
+ }
1234
+
1235
+ return n1 * 65536 + n2
1236
+ }
1237
+
1238
+ /**
1239
+ * @param {Buffer} buffer
1240
+ * @return {Number}
1241
+ */
1242
+ export const readUint24BE = buffer => {
1243
+
1244
+ let n1 = buffer.readUint8()
1245
+ const n2 = buffer.readUInt16BE(1)
1246
+
1247
+ if (n1 === 0) return n2
1248
+
1249
+ return n1 * 65536 + n2
1250
+ }
1251
+
1252
+ export const b2d = buffer => {
1253
+
1254
+ let n = 0
1255
+
1256
+ for (let i = 0; i < buffer.length; i++) {
1257
+
1258
+ n = n * 256 + buffer[i]
1259
+ }
1260
+
1261
+ return n
1262
+ }
1263
+
1264
+ export const d2b = tick => {
1265
+
1266
+ tick = tick || 0
1267
+
1268
+ if (tick instanceof Date) {
1269
+
1270
+ tick = tick.getTime()
1271
+ }
1272
+
1273
+ tick = tick.toString(16).padStart(length, '0')
1274
+
1275
+ const buffer = Buffer.alloc(length / 2)
1276
+
1277
+ for (let i = 0; i < length; i += 2) {
1278
+
1279
+ buffer[i / 2] = Number.parseInt(tick.substring(i, i + 2), 16)
1280
+ }
1281
+
1282
+ return buffer
1283
+ }
1284
+
1285
+ const s2b = (value, length) => {
1286
+
1287
+ value = typeof value === "string" ? value : String(value)
1288
+
1289
+ let buffer = Buffer.from(value)
1290
+
1291
+ if (buffer.length > length) {
1292
+
1293
+ let len = 0
1294
+
1295
+ for (let i = value.length - 1; i >= 0; i--) {
1296
+
1297
+ const byteLength = Buffer.byteLength(value[i])
1298
+
1299
+ if (len + byteLength > length) break
1300
+
1301
+ len += byteLength
1302
+ }
1303
+
1304
+ buffer = buffer.subarray(buffer.length - len)
1305
+ }
1306
+
1307
+ return Buffer.concat([Buffer.alloc(length - buffer.length), buffer])
1308
+ }
1309
+
1310
+ export const b2s = buffer => {
1311
+
1312
+ for (let i = 0; i < buffer.length; i++) {
1313
+
1314
+ if (buffer[i] !== 0) {
1315
+
1316
+ return buffer.subarray(i).toString()
1317
+ }
1318
+ }
1319
+ }
1320
+
1321
+ export const bufferToInt = buffer => {
1322
+
1323
+ switch (buffer.length) {
1324
+
1325
+ case 1: return buffer.readInt8()
1326
+ case 2: return buffer.readInt16BE()
1327
+ case 3: return readInt24BE(buffer)
1328
+ case 4: return buffer.readInt32BE()
1329
+ }
1330
+ }
1331
+
1332
+ export const bufferToUint = buffer => {
1333
+
1334
+ switch (buffer.length) {
1335
+
1336
+ case 1: return buffer.readUint8()
1337
+ case 2: return buffer.readUint16BE()
1338
+ case 3: return readUint24BE(buffer)
1339
+ case 4: return buffer.readUint32BE()
1340
+ }
1341
+ }
1342
+
1343
+ export const uInt32BEToBuffer = value => {
1344
+
1345
+ const buffer = Buffer.alloc(TypeLen.uint)
1346
+
1347
+ buffer.writeUInt32BE(value, 0)
1348
+
1349
+ return buffer
1350
+ }
1351
+
1352
+ export const int32BEToBuffer = value => {
1353
+
1354
+ const buffer = Buffer.alloc(TypeLen.int)
1355
+
1356
+ buffer.writeInt32BE(value, 0)
1357
+
1358
+ return buffer
1359
+ }
1360
+
1361
+ export const bigUint32BEToBuffer = value => {
1362
+
1363
+ const buffer = Buffer.alloc(TypeLen.bigUint)
1364
+
1365
+ buffer.writeBigUint64BE(value, 0)
1366
+
1367
+ return buffer
1368
+ }
1369
+
1370
+ export const bigint32BEToBuffer = value => {
1371
+
1372
+ const buffer = Buffer.alloc(TypeLen.bigint)
1373
+
1374
+ buffer.writeBigInt64BE(value, 0)
1375
+
1376
+ return buffer
1377
+ }
1378
+
1379
+ export const doubleBEToBuffer = value => {
1380
+
1381
+ const buffer = Buffer.alloc(TypeLen.float)
1382
+
1383
+ buffer.writeDoubleBE(value, 0)
1384
+
1385
+ return buffer
1386
+ }
1387
+
1388
+ export const cloneObjByKey = (obj, ...keys) => {
1389
+
1390
+ if (!obj) return obj
1391
+
1392
+ const result = {}
1393
+
1394
+ for (const key of keys) {
1395
+
1396
+ result[key] = obj[key]
1397
+ }
1398
+
1399
+ return result
1400
+ }