@onurege3467/zerohelper 8.0.0 → 9.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.
- package/README.md +292 -612
- package/dist/database/IDatabase.d.ts +77 -0
- package/dist/database/IDatabase.js +10 -0
- package/dist/database/cacheWrapper.d.ts +31 -0
- package/dist/database/cacheWrapper.js +228 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.js +94 -0
- package/dist/database/json.d.ts +32 -0
- package/dist/database/json.js +210 -0
- package/dist/database/migration.d.ts +21 -0
- package/dist/database/migration.js +97 -0
- package/dist/database/mongodb.d.ts +24 -0
- package/dist/database/mongodb.js +153 -0
- package/dist/database/mysql.d.ts +31 -0
- package/dist/database/mysql.js +385 -0
- package/dist/database/pg.d.ts +30 -0
- package/dist/database/pg.js +300 -0
- package/dist/database/redis.d.ts +23 -0
- package/dist/database/redis.js +157 -0
- package/dist/database/sqlite.d.ts +25 -0
- package/dist/database/sqlite.js +273 -0
- package/dist/database/types.d.ts +76 -0
- package/dist/database/types.js +2 -0
- package/dist/database/zpack.d.ts +59 -0
- package/dist/database/zpack.js +462 -0
- package/dist/functions/index.d.ts +183 -0
- package/dist/functions/index.js +636 -0
- package/dist/functions/temp_isphone.d.ts +1 -0
- package/dist/functions/temp_isphone.js +7 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +45 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +55 -0
- package/dist/test_zpack.d.ts +1 -0
- package/dist/test_zpack.js +64 -0
- package/package.json +23 -6
- package/database/IDatabase.js +0 -92
- package/database/cacheWrapper.js +0 -585
- package/database/index.js +0 -72
- package/database/json.js +0 -281
- package/database/migration.js +0 -227
- package/database/mongodb.js +0 -203
- package/database/mysql.js +0 -526
- package/database/pg.js +0 -527
- package/database/redis.js +0 -342
- package/database/sqlite.js +0 -551
- package/functions/index.js +0 -705
- package/index.js +0 -7
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ZPackAdapter = exports.ZPackDatabase = void 0;
|
|
7
|
+
const IDatabase_1 = require("./IDatabase");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const fsp = fs_1.default.promises;
|
|
10
|
+
class ZPackDatabase {
|
|
11
|
+
constructor(filePath, options = {}) {
|
|
12
|
+
this.fd = null;
|
|
13
|
+
this.fileSize = 0n;
|
|
14
|
+
this.index = new Map();
|
|
15
|
+
this.deleted = new Set();
|
|
16
|
+
this.version = 1;
|
|
17
|
+
this._nextId = 1;
|
|
18
|
+
this._writeQueue = Promise.resolve();
|
|
19
|
+
this._closed = false;
|
|
20
|
+
this._contentEnd = 0n;
|
|
21
|
+
if (!filePath || typeof filePath !== "string")
|
|
22
|
+
throw new Error("ZPackDatabase: 'filePath' zorunludur.");
|
|
23
|
+
this.filePath = filePath;
|
|
24
|
+
this._autoFlush = options.autoFlush === true;
|
|
25
|
+
}
|
|
26
|
+
async open() {
|
|
27
|
+
if (this.fd)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
this.fd = await fsp.open(this.filePath, fs_1.default.constants.O_RDWR);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
if (err && err.code === "ENOENT") {
|
|
34
|
+
this.fd = await fsp.open(this.filePath, fs_1.default.constants.O_RDWR | fs_1.default.constants.O_CREAT);
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
const stat = await this.fd.stat();
|
|
40
|
+
this.fileSize = BigInt(stat.size);
|
|
41
|
+
this._contentEnd = this.fileSize;
|
|
42
|
+
if (!(await this._tryLoadIndexFromFooter()))
|
|
43
|
+
await this._scanAndRebuildIndex();
|
|
44
|
+
if (this.index.size > 0) {
|
|
45
|
+
let maxId = 0;
|
|
46
|
+
for (const docId of this.index.keys())
|
|
47
|
+
if (docId > maxId)
|
|
48
|
+
maxId = docId;
|
|
49
|
+
this._nextId = maxId + 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async close() {
|
|
53
|
+
if (this._closed || !this.fd)
|
|
54
|
+
return;
|
|
55
|
+
await this._writeFooter();
|
|
56
|
+
await this.fd.close();
|
|
57
|
+
this._closed = true;
|
|
58
|
+
}
|
|
59
|
+
async insert(document, docId) {
|
|
60
|
+
this._ensureOpen();
|
|
61
|
+
const payload = this._encodeDocument(document, docId);
|
|
62
|
+
return this._enqueue(async () => {
|
|
63
|
+
const writeOffset = this.fileSize;
|
|
64
|
+
await this.fd.write(payload, 0, payload.length, writeOffset);
|
|
65
|
+
this.fileSize = writeOffset + BigInt(payload.length);
|
|
66
|
+
this._contentEnd = this.fileSize;
|
|
67
|
+
const parsed = this._peekDocMeta(payload);
|
|
68
|
+
if (parsed.fieldCount === 0) {
|
|
69
|
+
this.index.delete(parsed.docId);
|
|
70
|
+
this.deleted.add(parsed.docId);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.index.set(parsed.docId, writeOffset);
|
|
74
|
+
this.deleted.delete(parsed.docId);
|
|
75
|
+
if (parsed.docId >= this._nextId)
|
|
76
|
+
this._nextId = parsed.docId + 1;
|
|
77
|
+
}
|
|
78
|
+
if (this._autoFlush)
|
|
79
|
+
await this._internalWriteFooter();
|
|
80
|
+
return parsed.docId;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async insertBatch(documents) {
|
|
84
|
+
this._ensureOpen();
|
|
85
|
+
if (!Array.isArray(documents) || documents.length === 0)
|
|
86
|
+
return [];
|
|
87
|
+
const payloads = [];
|
|
88
|
+
const metas = [];
|
|
89
|
+
for (const doc of documents) {
|
|
90
|
+
const buf = this._encodeDocument(doc);
|
|
91
|
+
payloads.push(buf);
|
|
92
|
+
metas.push(this._peekDocMeta(buf));
|
|
93
|
+
}
|
|
94
|
+
const totalLen = payloads.reduce((s, b) => s + b.length, 0);
|
|
95
|
+
const buffer = Buffer.alloc(totalLen);
|
|
96
|
+
let pos = 0;
|
|
97
|
+
for (const b of payloads) {
|
|
98
|
+
b.copy(buffer, pos);
|
|
99
|
+
pos += b.length;
|
|
100
|
+
}
|
|
101
|
+
return this._enqueue(async () => {
|
|
102
|
+
const writeOffset = this.fileSize;
|
|
103
|
+
await this.fd.write(buffer, 0, buffer.length, writeOffset);
|
|
104
|
+
let cur = writeOffset;
|
|
105
|
+
const ids = [];
|
|
106
|
+
for (let i = 0; i < payloads.length; i++) {
|
|
107
|
+
const meta = metas[i];
|
|
108
|
+
if (meta.fieldCount === 0) {
|
|
109
|
+
this.index.delete(meta.docId);
|
|
110
|
+
this.deleted.add(meta.docId);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.index.set(meta.docId, cur);
|
|
114
|
+
this.deleted.delete(meta.docId);
|
|
115
|
+
if (meta.docId >= this._nextId)
|
|
116
|
+
this._nextId = meta.docId + 1;
|
|
117
|
+
}
|
|
118
|
+
ids.push(meta.docId);
|
|
119
|
+
cur += BigInt(payloads[i].length);
|
|
120
|
+
}
|
|
121
|
+
this.fileSize = writeOffset + BigInt(buffer.length);
|
|
122
|
+
this._contentEnd = this.fileSize;
|
|
123
|
+
if (this._autoFlush)
|
|
124
|
+
await this._internalWriteFooter();
|
|
125
|
+
return ids;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async delete(docId) {
|
|
129
|
+
if (!Number.isInteger(docId) || docId <= 0)
|
|
130
|
+
throw new Error("delete: 'docId' pozitif bir tamsayı olmalıdır.");
|
|
131
|
+
const tomb = this._encodeTombstone(docId);
|
|
132
|
+
await this._enqueue(async () => {
|
|
133
|
+
const writeOffset = this.fileSize;
|
|
134
|
+
await this.fd.write(tomb, 0, tomb.length, writeOffset);
|
|
135
|
+
this.fileSize = writeOffset + BigInt(tomb.length);
|
|
136
|
+
this._contentEnd = this.fileSize;
|
|
137
|
+
this.index.delete(docId);
|
|
138
|
+
this.deleted.add(docId);
|
|
139
|
+
if (this._autoFlush)
|
|
140
|
+
await this._internalWriteFooter();
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async get(docId) {
|
|
144
|
+
this._ensureOpen();
|
|
145
|
+
const offset = this.index.get(docId);
|
|
146
|
+
if (offset === undefined)
|
|
147
|
+
return null;
|
|
148
|
+
const header = Buffer.alloc(6);
|
|
149
|
+
if (offset + BigInt(header.length) > this._contentEnd)
|
|
150
|
+
return null;
|
|
151
|
+
const { bytesRead: hread } = await this.fd.read(header, 0, header.length, offset);
|
|
152
|
+
if (hread !== header.length)
|
|
153
|
+
return null;
|
|
154
|
+
const docLength = header.readUInt16LE(0);
|
|
155
|
+
const totalSize = 2 + docLength;
|
|
156
|
+
if (docLength < 4 || offset + BigInt(totalSize) > this._contentEnd)
|
|
157
|
+
return null;
|
|
158
|
+
const buf = Buffer.alloc(totalSize);
|
|
159
|
+
const { bytesRead } = await this.fd.read(buf, 0, totalSize, offset);
|
|
160
|
+
if (bytesRead !== totalSize)
|
|
161
|
+
return null;
|
|
162
|
+
const parsed = this._decodeDocument(buf);
|
|
163
|
+
return parsed.fieldCount === 0 ? null : parsed.document;
|
|
164
|
+
}
|
|
165
|
+
keys() { return Array.from(this.index.keys()); }
|
|
166
|
+
_ensureOpen() {
|
|
167
|
+
if (!this.fd)
|
|
168
|
+
throw new Error("ZPackDatabase: önce 'open()' çağrılmalı.");
|
|
169
|
+
if (this._closed)
|
|
170
|
+
throw new Error("ZPackDatabase: dosya kapalı.");
|
|
171
|
+
}
|
|
172
|
+
_enqueue(taskFn) {
|
|
173
|
+
this._writeQueue = this._writeQueue.then(taskFn, taskFn);
|
|
174
|
+
return this._writeQueue;
|
|
175
|
+
}
|
|
176
|
+
async _internalWriteFooter() {
|
|
177
|
+
const entries = Array.from(this.index.entries());
|
|
178
|
+
const footerSize = 9 + entries.length * 12;
|
|
179
|
+
const footer = Buffer.alloc(footerSize + 4);
|
|
180
|
+
footer.write("ZPCK", 0, "utf8");
|
|
181
|
+
footer.writeUInt8(this.version, 4);
|
|
182
|
+
footer.writeUInt32LE(entries.length, 5);
|
|
183
|
+
let p = 9;
|
|
184
|
+
for (const [id, off] of entries) {
|
|
185
|
+
footer.writeUInt32LE(id, p);
|
|
186
|
+
p += 4;
|
|
187
|
+
footer.writeUInt32LE(Number(off & 0xffffffffn), p);
|
|
188
|
+
p += 4;
|
|
189
|
+
footer.writeUInt32LE(Number((off >> 32n) & 0xffffffffn), p);
|
|
190
|
+
p += 4;
|
|
191
|
+
}
|
|
192
|
+
footer.writeUInt32LE(footerSize, p);
|
|
193
|
+
const writeOffset = this.fileSize;
|
|
194
|
+
await this.fd.write(footer, 0, footer.length, writeOffset);
|
|
195
|
+
this._contentEnd = writeOffset;
|
|
196
|
+
this.fileSize = writeOffset + BigInt(footer.length);
|
|
197
|
+
}
|
|
198
|
+
async _writeFooter() {
|
|
199
|
+
await this._enqueue(() => this._internalWriteFooter());
|
|
200
|
+
}
|
|
201
|
+
_encodeDocument(document, docId) {
|
|
202
|
+
let id = docId ?? this._nextId++;
|
|
203
|
+
const fieldBuffers = [];
|
|
204
|
+
for (const [key, value] of Object.entries(document)) {
|
|
205
|
+
const keyBuf = Buffer.from(String(key), "utf8");
|
|
206
|
+
const valBuf = Buffer.from(String(value), "utf8");
|
|
207
|
+
const fb = Buffer.alloc(2 + keyBuf.length + valBuf.length);
|
|
208
|
+
fb.writeUInt8(keyBuf.length, 0);
|
|
209
|
+
keyBuf.copy(fb, 1);
|
|
210
|
+
fb.writeUInt8(valBuf.length, 1 + keyBuf.length);
|
|
211
|
+
valBuf.copy(fb, 2 + keyBuf.length);
|
|
212
|
+
fieldBuffers.push(fb);
|
|
213
|
+
}
|
|
214
|
+
const payloadSize = 4 + fieldBuffers.reduce((s, b) => s + b.length, 0);
|
|
215
|
+
const buf = Buffer.alloc(2 + payloadSize);
|
|
216
|
+
buf.writeUInt16LE(payloadSize, 0);
|
|
217
|
+
buf.writeUInt32LE(id, 2);
|
|
218
|
+
let offset = 6;
|
|
219
|
+
for (const b of fieldBuffers) {
|
|
220
|
+
b.copy(buf, offset);
|
|
221
|
+
offset += b.length;
|
|
222
|
+
}
|
|
223
|
+
return buf;
|
|
224
|
+
}
|
|
225
|
+
_encodeTombstone(docId) {
|
|
226
|
+
const buf = Buffer.alloc(6);
|
|
227
|
+
buf.writeUInt16LE(4, 0);
|
|
228
|
+
buf.writeUInt32LE(docId, 2);
|
|
229
|
+
return buf;
|
|
230
|
+
}
|
|
231
|
+
_peekDocMeta(encodedBuf) {
|
|
232
|
+
const payloadSize = encodedBuf.readUInt16LE(0);
|
|
233
|
+
const docId = encodedBuf.readUInt32LE(2);
|
|
234
|
+
const fieldBytes = payloadSize - 4;
|
|
235
|
+
let p = 6, consumed = 0, fields = 0;
|
|
236
|
+
while (consumed < fieldBytes) {
|
|
237
|
+
const klen = encodedBuf.readUInt8(p);
|
|
238
|
+
p += 1 + klen;
|
|
239
|
+
consumed += 1 + klen;
|
|
240
|
+
if (consumed >= fieldBytes)
|
|
241
|
+
break;
|
|
242
|
+
const vlen = encodedBuf.readUInt8(p);
|
|
243
|
+
p += 1 + vlen;
|
|
244
|
+
consumed += 1 + vlen;
|
|
245
|
+
fields += 1;
|
|
246
|
+
}
|
|
247
|
+
return { docId, fieldCount: fields };
|
|
248
|
+
}
|
|
249
|
+
_decodeDocument(buf) {
|
|
250
|
+
const payloadSize = buf.readUInt16LE(0);
|
|
251
|
+
const docId = buf.readUInt32LE(2);
|
|
252
|
+
let p = 6;
|
|
253
|
+
const end = 2 + payloadSize;
|
|
254
|
+
const obj = {};
|
|
255
|
+
let fields = 0;
|
|
256
|
+
while (p < end) {
|
|
257
|
+
const klen = buf.readUInt8(p);
|
|
258
|
+
p += 1;
|
|
259
|
+
const key = buf.toString("utf8", p, p + klen);
|
|
260
|
+
p += klen;
|
|
261
|
+
if (p >= end)
|
|
262
|
+
break;
|
|
263
|
+
const vlen = buf.readUInt8(p);
|
|
264
|
+
p += 1;
|
|
265
|
+
const val = buf.toString("utf8", p, p + vlen);
|
|
266
|
+
p += vlen;
|
|
267
|
+
obj[key] = val;
|
|
268
|
+
fields += 1;
|
|
269
|
+
}
|
|
270
|
+
return { docId, fieldCount: fields, document: obj };
|
|
271
|
+
}
|
|
272
|
+
async _tryLoadIndexFromFooter() {
|
|
273
|
+
if (this.fileSize < 13n)
|
|
274
|
+
return false;
|
|
275
|
+
const sizeBuf = Buffer.alloc(4);
|
|
276
|
+
await this.fd.read(sizeBuf, 0, 4, this.fileSize - 4n);
|
|
277
|
+
const footerSize = sizeBuf.readUInt32LE(0);
|
|
278
|
+
if (footerSize < 9 || BigInt(footerSize) + 4n > this.fileSize)
|
|
279
|
+
return false;
|
|
280
|
+
const footerStart = this.fileSize - 4n - BigInt(footerSize);
|
|
281
|
+
const footer = Buffer.alloc(footerSize);
|
|
282
|
+
await this.fd.read(footer, 0, footerSize, footerStart);
|
|
283
|
+
if (footer.toString("utf8", 0, 4) !== "ZPCK" || footer.readUInt8(4) !== this.version)
|
|
284
|
+
return false;
|
|
285
|
+
const count = footer.readUInt32LE(5);
|
|
286
|
+
let p = 9;
|
|
287
|
+
this.index.clear();
|
|
288
|
+
for (let i = 0; i < count; i++) {
|
|
289
|
+
const id = footer.readUInt32LE(p);
|
|
290
|
+
p += 4;
|
|
291
|
+
const lo = footer.readUInt32LE(p);
|
|
292
|
+
p += 4;
|
|
293
|
+
const hi = footer.readUInt32LE(p);
|
|
294
|
+
p += 4;
|
|
295
|
+
this.index.set(id, (BigInt(hi) << 32n) + BigInt(lo));
|
|
296
|
+
}
|
|
297
|
+
this._contentEnd = footerStart;
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
async _scanAndRebuildIndex() {
|
|
301
|
+
this.index.clear();
|
|
302
|
+
this.deleted.clear();
|
|
303
|
+
let offset = 0n;
|
|
304
|
+
const headerBuf = Buffer.alloc(2);
|
|
305
|
+
while (offset + 2n <= this.fileSize) {
|
|
306
|
+
const { bytesRead } = await this.fd.read(headerBuf, 0, 2, offset);
|
|
307
|
+
if (bytesRead < 2)
|
|
308
|
+
break;
|
|
309
|
+
const payloadSize = headerBuf.readUInt16LE(0);
|
|
310
|
+
const idBuf = Buffer.alloc(4);
|
|
311
|
+
await this.fd.read(idBuf, 0, 4, offset + 2n);
|
|
312
|
+
const docId = idBuf.readUInt32LE(0);
|
|
313
|
+
if (payloadSize === 4)
|
|
314
|
+
this.index.delete(docId);
|
|
315
|
+
else
|
|
316
|
+
this.index.set(docId, offset);
|
|
317
|
+
offset += BigInt(2 + payloadSize);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
exports.ZPackDatabase = ZPackDatabase;
|
|
322
|
+
class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
323
|
+
constructor(config) {
|
|
324
|
+
super();
|
|
325
|
+
this.tableMaxId = new Map();
|
|
326
|
+
this.keyIndex = new Map();
|
|
327
|
+
this.rowCache = new Map();
|
|
328
|
+
this.secondary = new Map();
|
|
329
|
+
this.db = new ZPackDatabase(config.filePath, { autoFlush: !!config.autoFlush });
|
|
330
|
+
this.initPromise = this._init();
|
|
331
|
+
}
|
|
332
|
+
async _init() {
|
|
333
|
+
await this.db.open();
|
|
334
|
+
for (const physicalDocId of this.db.keys()) {
|
|
335
|
+
const doc = await this.db.get(physicalDocId);
|
|
336
|
+
if (!doc || !doc.t || !Number.isFinite(Number(doc._id)))
|
|
337
|
+
continue;
|
|
338
|
+
const table = String(doc.t), idNum = Number(doc._id);
|
|
339
|
+
if (!this.keyIndex.has(table)) {
|
|
340
|
+
this.keyIndex.set(table, new Map());
|
|
341
|
+
this.tableMaxId.set(table, 0);
|
|
342
|
+
this.rowCache.set(table, new Map());
|
|
343
|
+
this.secondary.set(table, new Map());
|
|
344
|
+
}
|
|
345
|
+
this.keyIndex.get(table).set(idNum, physicalDocId);
|
|
346
|
+
if (idNum > (this.tableMaxId.get(table) || 0))
|
|
347
|
+
this.tableMaxId.set(table, idNum);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async ensureTable(table) {
|
|
351
|
+
await this.initPromise;
|
|
352
|
+
if (!this.tableMaxId.has(table)) {
|
|
353
|
+
this.tableMaxId.set(table, 0);
|
|
354
|
+
this.keyIndex.set(table, new Map());
|
|
355
|
+
this.rowCache.set(table, new Map());
|
|
356
|
+
this.secondary.set(table, new Map());
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
_coerce(table, data, id) {
|
|
360
|
+
const out = { t: table, _id: String(id) };
|
|
361
|
+
for (const [k, v] of Object.entries(data || {})) {
|
|
362
|
+
if (k !== 't' && k !== '_id')
|
|
363
|
+
out[k] = typeof v === 'string' ? v : JSON.stringify(v);
|
|
364
|
+
}
|
|
365
|
+
return out;
|
|
366
|
+
}
|
|
367
|
+
_matches(row, where) {
|
|
368
|
+
if (!where)
|
|
369
|
+
return true;
|
|
370
|
+
return Object.entries(where).every(([k, v]) => String(row[k]) === String(v));
|
|
371
|
+
}
|
|
372
|
+
async select(table, where = null) {
|
|
373
|
+
await this.ensureTable(table);
|
|
374
|
+
const results = [];
|
|
375
|
+
for (const [logicalId, physicalId] of this.keyIndex.get(table).entries()) {
|
|
376
|
+
let row = this.rowCache.get(table).get(logicalId);
|
|
377
|
+
if (!row) {
|
|
378
|
+
const doc = await this.db.get(physicalId);
|
|
379
|
+
if (!doc)
|
|
380
|
+
continue;
|
|
381
|
+
row = { _id: Number(doc._id) };
|
|
382
|
+
for (const [k, v] of Object.entries(doc))
|
|
383
|
+
if (k !== 't' && k !== '_id')
|
|
384
|
+
row[k] = v;
|
|
385
|
+
this.rowCache.get(table).set(logicalId, row);
|
|
386
|
+
}
|
|
387
|
+
if (this._matches(row, where))
|
|
388
|
+
results.push({ ...row });
|
|
389
|
+
}
|
|
390
|
+
return results;
|
|
391
|
+
}
|
|
392
|
+
async selectOne(table, where = null) {
|
|
393
|
+
const res = await this.select(table, where);
|
|
394
|
+
return res[0] || null;
|
|
395
|
+
}
|
|
396
|
+
async insert(table, data) {
|
|
397
|
+
await this.ensureTable(table);
|
|
398
|
+
const nextId = (this.tableMaxId.get(table) || 0) + 1;
|
|
399
|
+
const record = this._coerce(table, data, nextId);
|
|
400
|
+
const physicalId = await this.db.insert(record);
|
|
401
|
+
this.tableMaxId.set(table, nextId);
|
|
402
|
+
this.keyIndex.get(table).set(nextId, physicalId);
|
|
403
|
+
const row = { _id: nextId, ...data };
|
|
404
|
+
this.rowCache.get(table).set(nextId, row);
|
|
405
|
+
return nextId;
|
|
406
|
+
}
|
|
407
|
+
async update(table, data, where) {
|
|
408
|
+
const rows = await this.select(table, where);
|
|
409
|
+
for (const row of rows) {
|
|
410
|
+
const merged = { ...row, ...data };
|
|
411
|
+
const record = this._coerce(table, merged, row._id);
|
|
412
|
+
const physicalId = await this.db.insert(record);
|
|
413
|
+
this.keyIndex.get(table).set(row._id, physicalId);
|
|
414
|
+
this.rowCache.get(table).set(row._id, merged);
|
|
415
|
+
}
|
|
416
|
+
return rows.length;
|
|
417
|
+
}
|
|
418
|
+
async set(table, data, where) {
|
|
419
|
+
const existing = await this.selectOne(table, where);
|
|
420
|
+
return existing ? this.update(table, data, where) : this.insert(table, { ...where, ...data });
|
|
421
|
+
}
|
|
422
|
+
async delete(table, where) {
|
|
423
|
+
const rows = await this.select(table, where);
|
|
424
|
+
for (const row of rows) {
|
|
425
|
+
const physicalId = this.keyIndex.get(table).get(row._id);
|
|
426
|
+
if (physicalId !== undefined) {
|
|
427
|
+
await this.db.delete(physicalId);
|
|
428
|
+
this.keyIndex.get(table).delete(row._id);
|
|
429
|
+
this.rowCache.get(table).delete(row._id);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return rows.length;
|
|
433
|
+
}
|
|
434
|
+
async bulkInsert(table, dataArray) {
|
|
435
|
+
for (const data of dataArray)
|
|
436
|
+
await this.insert(table, data);
|
|
437
|
+
return dataArray.length;
|
|
438
|
+
}
|
|
439
|
+
async increment(table, increments, where = {}) {
|
|
440
|
+
const rows = await this.select(table, where);
|
|
441
|
+
for (const row of rows) {
|
|
442
|
+
const updated = { ...row };
|
|
443
|
+
for (const [f, v] of Object.entries(increments))
|
|
444
|
+
updated[f] = (Number(updated[f]) || 0) + v;
|
|
445
|
+
await this.update(table, updated, { _id: row._id });
|
|
446
|
+
}
|
|
447
|
+
return rows.length;
|
|
448
|
+
}
|
|
449
|
+
async decrement(table, decrements, where = {}) {
|
|
450
|
+
const rows = await this.select(table, where);
|
|
451
|
+
for (const row of rows) {
|
|
452
|
+
const updated = { ...row };
|
|
453
|
+
for (const [f, v] of Object.entries(decrements))
|
|
454
|
+
updated[f] = (Number(updated[f]) || 0) - v;
|
|
455
|
+
await this.update(table, updated, { _id: row._id });
|
|
456
|
+
}
|
|
457
|
+
return rows.length;
|
|
458
|
+
}
|
|
459
|
+
async close() { await this.db.close(); }
|
|
460
|
+
}
|
|
461
|
+
exports.ZPackAdapter = ZPackAdapter;
|
|
462
|
+
exports.default = ZPackAdapter;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export declare function makeUniqueId(): string;
|
|
2
|
+
export declare function randomArray<T>(arr: T[]): T;
|
|
3
|
+
export declare function randomText(length?: number): string;
|
|
4
|
+
export declare function randomNumber(min?: number, max?: number): number;
|
|
5
|
+
export declare function randomEmoji(): string;
|
|
6
|
+
export declare function randomHex(): string;
|
|
7
|
+
export declare function randomFloat(min: number, max: number): number;
|
|
8
|
+
export declare function titleCase(sentence: string): string;
|
|
9
|
+
export declare function generateRandomString(length: number): string;
|
|
10
|
+
export declare function generateSlug(text: string): string;
|
|
11
|
+
export declare function wordCount(text: string): number;
|
|
12
|
+
export declare function shuffleArray<T>(array: T[]): T[];
|
|
13
|
+
export declare function flattenArray(arr: any[]): any[];
|
|
14
|
+
export declare function removeFalsyValues<T>(arr: T[]): T[];
|
|
15
|
+
export declare function groupBy<T>(arr: T[], key: keyof T): Record<string, T[]>;
|
|
16
|
+
export declare function pluck<T, K extends keyof T>(arr: T[], key: K): T[K][];
|
|
17
|
+
export declare function sortBy<T>(arr: T[], key: keyof T): T[];
|
|
18
|
+
export declare function filterObjectByKey<T extends object>(obj: T, keys: string[]): Partial<T>;
|
|
19
|
+
export declare function deepMerge(obj1: any, obj2: any): any;
|
|
20
|
+
export declare function encryptText(text: string, secret: string): {
|
|
21
|
+
encryptedText: string;
|
|
22
|
+
iv: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function decryptText(encryptedText: string, secret: string, ivHex: string): string;
|
|
25
|
+
export declare function hashPassword(password: string): string;
|
|
26
|
+
export declare function verifyPassword(password: string, hash: string): boolean;
|
|
27
|
+
export declare function generateJWT(payload: object, secret: string): string;
|
|
28
|
+
export declare function verifyJWT(token: string, secret: string): any;
|
|
29
|
+
export declare function generateSalt(): string;
|
|
30
|
+
export declare function validateUUID(uuid: string): boolean;
|
|
31
|
+
export declare function isPasswordStrong(password: string): boolean;
|
|
32
|
+
export declare function mean(arr: number[]): number;
|
|
33
|
+
export declare function median(arr: number[]): number;
|
|
34
|
+
export declare function variance(arr: number[]): number;
|
|
35
|
+
export declare function standardDeviation(arr: number[]): number;
|
|
36
|
+
export declare function sum(arr: number[]): number;
|
|
37
|
+
export declare function max(arr: number[]): number;
|
|
38
|
+
export declare function min(arr: number[]): number;
|
|
39
|
+
export declare function range(start: number, end: number): number[];
|
|
40
|
+
export declare function isPrime(num: number): boolean;
|
|
41
|
+
export declare function factorial(n: number): number;
|
|
42
|
+
export declare function combination(n: number, r: number): number;
|
|
43
|
+
export declare function permutation(n: number, r: number): number;
|
|
44
|
+
export declare function formatDate(date: Date, format?: string): string;
|
|
45
|
+
export declare function dateDifference(date1: Date, date2: Date): number;
|
|
46
|
+
export declare function addDays(date: Date, days: number): Date;
|
|
47
|
+
export declare function subtractDays(date: Date, days: number): Date;
|
|
48
|
+
export declare function fetchData(url: string): Promise<any>;
|
|
49
|
+
export declare function postData(url: string, data: any): Promise<any>;
|
|
50
|
+
export declare function isEmail(email: string): boolean;
|
|
51
|
+
export declare function isPhone(phone: string): boolean;
|
|
52
|
+
export declare function isURL(url: string): boolean;
|
|
53
|
+
export declare function sanitizeHTML(html: string): string;
|
|
54
|
+
export declare function validateCreditCard(cardNumber: string): boolean;
|
|
55
|
+
export interface ValidationSchema {
|
|
56
|
+
[key: string]: {
|
|
57
|
+
required?: boolean;
|
|
58
|
+
type?: string;
|
|
59
|
+
minLength?: number;
|
|
60
|
+
maxLength?: number;
|
|
61
|
+
pattern?: RegExp;
|
|
62
|
+
min?: number;
|
|
63
|
+
max?: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export declare function validateSchema(data: any, schema: ValidationSchema): {
|
|
67
|
+
isValid: boolean;
|
|
68
|
+
errors: string[];
|
|
69
|
+
};
|
|
70
|
+
export declare function sanitizeInput(input: any, options?: {
|
|
71
|
+
trim?: boolean;
|
|
72
|
+
removeHTML?: boolean;
|
|
73
|
+
escape?: boolean;
|
|
74
|
+
}): any;
|
|
75
|
+
export type LogLevel = 'error' | 'warn' | 'info' | 'debug';
|
|
76
|
+
export interface LoggerOptions {
|
|
77
|
+
level?: LogLevel;
|
|
78
|
+
enableColors?: boolean;
|
|
79
|
+
enableTimestamp?: boolean;
|
|
80
|
+
logFile?: string | null;
|
|
81
|
+
}
|
|
82
|
+
export declare class Logger {
|
|
83
|
+
private level;
|
|
84
|
+
private enableColors;
|
|
85
|
+
private enableTimestamp;
|
|
86
|
+
private logFile;
|
|
87
|
+
private levels;
|
|
88
|
+
private colors;
|
|
89
|
+
constructor(options?: LoggerOptions);
|
|
90
|
+
private shouldLog;
|
|
91
|
+
private formatMessage;
|
|
92
|
+
private writeToFile;
|
|
93
|
+
log(level: LogLevel, message: string, data?: any): void;
|
|
94
|
+
error(message: string, data?: any): void;
|
|
95
|
+
warn(message: string, data?: any): void;
|
|
96
|
+
info(message: string, data?: any): void;
|
|
97
|
+
debug(message: string, data?: any): void;
|
|
98
|
+
setLevel(level: LogLevel): void;
|
|
99
|
+
getLevel(): LogLevel;
|
|
100
|
+
}
|
|
101
|
+
export declare function createLogger(options?: LoggerOptions): Logger;
|
|
102
|
+
export declare function logInfo(message: string, data?: any): void;
|
|
103
|
+
export declare function logError(message: string, data?: any): void;
|
|
104
|
+
export declare function logWarn(message: string, data?: any): void;
|
|
105
|
+
export declare function logDebug(message: string, data?: any): void;
|
|
106
|
+
export declare const http_module: {
|
|
107
|
+
fetchData: typeof fetchData;
|
|
108
|
+
postData: typeof postData;
|
|
109
|
+
};
|
|
110
|
+
export declare const date_module: {
|
|
111
|
+
formatDate: typeof formatDate;
|
|
112
|
+
dateDifference: typeof dateDifference;
|
|
113
|
+
addDays: typeof addDays;
|
|
114
|
+
subtractDays: typeof subtractDays;
|
|
115
|
+
};
|
|
116
|
+
export declare const random_module: {
|
|
117
|
+
makeUniqueId: typeof makeUniqueId;
|
|
118
|
+
randomArray: typeof randomArray;
|
|
119
|
+
randomText: typeof randomText;
|
|
120
|
+
randomNumber: typeof randomNumber;
|
|
121
|
+
randomEmoji: typeof randomEmoji;
|
|
122
|
+
randomHex: typeof randomHex;
|
|
123
|
+
randomFloat: typeof randomFloat;
|
|
124
|
+
};
|
|
125
|
+
export declare const string_module: {
|
|
126
|
+
titleCase: typeof titleCase;
|
|
127
|
+
generateRandomString: typeof generateRandomString;
|
|
128
|
+
generateSlug: typeof generateSlug;
|
|
129
|
+
wordCount: typeof wordCount;
|
|
130
|
+
};
|
|
131
|
+
export declare const array_module: {
|
|
132
|
+
shuffleArray: typeof shuffleArray;
|
|
133
|
+
flattenArray: typeof flattenArray;
|
|
134
|
+
removeFalsyValues: typeof removeFalsyValues;
|
|
135
|
+
groupBy: typeof groupBy;
|
|
136
|
+
pluck: typeof pluck;
|
|
137
|
+
sortBy: typeof sortBy;
|
|
138
|
+
};
|
|
139
|
+
export declare const object_module: {
|
|
140
|
+
filterObjectByKey: typeof filterObjectByKey;
|
|
141
|
+
deepMerge: typeof deepMerge;
|
|
142
|
+
};
|
|
143
|
+
export declare const crypto_module: {
|
|
144
|
+
encryptText: typeof encryptText;
|
|
145
|
+
decryptText: typeof decryptText;
|
|
146
|
+
hashPassword: typeof hashPassword;
|
|
147
|
+
verifyPassword: typeof verifyPassword;
|
|
148
|
+
generateJWT: typeof generateJWT;
|
|
149
|
+
verifyJWT: typeof verifyJWT;
|
|
150
|
+
generateSalt: typeof generateSalt;
|
|
151
|
+
validateUUID: typeof validateUUID;
|
|
152
|
+
isPasswordStrong: typeof isPasswordStrong;
|
|
153
|
+
};
|
|
154
|
+
export declare const math_module: {
|
|
155
|
+
mean: typeof mean;
|
|
156
|
+
median: typeof median;
|
|
157
|
+
variance: typeof variance;
|
|
158
|
+
standardDeviation: typeof standardDeviation;
|
|
159
|
+
sum: typeof sum;
|
|
160
|
+
max: typeof max;
|
|
161
|
+
min: typeof min;
|
|
162
|
+
range: typeof range;
|
|
163
|
+
isPrime: typeof isPrime;
|
|
164
|
+
combination: typeof combination;
|
|
165
|
+
permutation: typeof permutation;
|
|
166
|
+
};
|
|
167
|
+
export declare const validation_module: {
|
|
168
|
+
isEmail: typeof isEmail;
|
|
169
|
+
isPhone: typeof isPhone;
|
|
170
|
+
isURL: typeof isURL;
|
|
171
|
+
sanitizeHTML: typeof sanitizeHTML;
|
|
172
|
+
validateCreditCard: typeof validateCreditCard;
|
|
173
|
+
validateSchema: typeof validateSchema;
|
|
174
|
+
sanitizeInput: typeof sanitizeInput;
|
|
175
|
+
};
|
|
176
|
+
export declare const logger_module: {
|
|
177
|
+
createLogger: typeof createLogger;
|
|
178
|
+
Logger: typeof Logger;
|
|
179
|
+
info: typeof logInfo;
|
|
180
|
+
error: typeof logError;
|
|
181
|
+
warn: typeof logWarn;
|
|
182
|
+
debug: typeof logDebug;
|
|
183
|
+
};
|