corebasic 1.0.211 → 1.0.213
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/dist/index.js +10 -0
- package/dist/libs/ObjectId.js +114 -0
- package/dist/libs/auth.js +103 -0
- package/dist/libs/compression.js +11 -0
- package/dist/libs/cpp.js +154 -0
- package/dist/libs/dip/suffix/date.js +89 -0
- package/dist/libs/dip/suffix/index.js +227 -0
- package/dist/libs/dip/suffix/policy.js +113 -0
- package/dist/libs/dip/suffix/query.js +279 -0
- package/dist/libs/dip/suffix/suffix.js +99 -0
- package/dist/libs/dip/suffix/tests/date.test.js +187 -0
- package/dist/libs/dip/suffix/tests/index.test.js +441 -0
- package/dist/libs/dip/suffix/tests/policy.applySuffixPolicy.test.js +489 -0
- package/dist/libs/dip/suffix/tests/policy.test.js +329 -0
- package/dist/libs/dip/suffix/tests/suffix.test.js +316 -0
- package/dist/libs/dip.js +102 -0
- package/dist/libs/dipper.js +73 -0
- package/dist/libs/elabase.js +656 -0
- package/dist/libs/features.js +366 -0
- package/dist/libs/kafka.js +121 -0
- package/dist/libs/messaging.js +130 -0
- package/dist/libs/mobilecodes.js +562 -0
- package/dist/libs/session.js +96 -0
- package/dist/libs/utils.js +297 -0
- package/index.ts +23 -0
- package/libs/{auth.js → auth.ts} +3 -3
- package/libs/{compression.js → compression.ts} +1 -1
- package/libs/dip/suffix/date.ts +121 -0
- package/libs/dip/suffix/{index.js → index.ts} +7 -18
- package/libs/dip/suffix/{policy.js → policy.ts} +2 -2
- package/libs/dip/suffix/{suffix.js → suffix.ts} +2 -2
- package/libs/dip/suffix/tests/{date.test.js → date.test.ts} +1 -1
- package/libs/dip/suffix/tests/{index.test.js → index.test.ts} +1 -1
- package/libs/dip/suffix/tests/{policy.applySuffixPolicy.test.js → policy.applySuffixPolicy.test.ts} +1 -1
- package/libs/dip/suffix/tests/{policy.test.js → policy.test.ts} +1 -1
- package/libs/dip/suffix/tests/{suffix.test.js → suffix.test.ts} +1 -1
- package/libs/{dip.js → dip.ts} +1 -1
- package/libs/{elabase.js → elabase.ts} +4 -4
- package/libs/{features.js → features.ts} +5 -5
- package/libs/{messaging.js → messaging.ts} +1 -1
- package/libs/{session.js → session.ts} +2 -2
- package/libs/{utils.js → utils.ts} +80 -9
- package/package.json +3 -2
- package/tsc/@typescript/typescript-linux-x64/LICENSE +55 -0
- package/tsc/@typescript/typescript-linux-x64/NOTICE.txt +436 -0
- package/tsc/@typescript/typescript-linux-x64/README.md +3 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.d.ts +20 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.decorators.d.ts +382 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.decorators.legacy.d.ts +20 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.dom.asynciterable.d.ts +18 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.dom.d.ts +45125 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.dom.iterable.d.ts +18 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.collection.d.ts +159 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.core.d.ts +595 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.d.ts +26 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.generator.d.ts +75 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.iterable.d.ts +603 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.promise.d.ts +79 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.proxy.d.ts +126 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.reflect.d.ts +142 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.symbol.d.ts +44 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2015.symbol.wellknown.d.ts +324 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2016.array.include.d.ts +114 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2016.d.ts +19 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2016.full.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2016.intl.d.ts +29 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.arraybuffer.d.ts +19 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.d.ts +24 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.date.d.ts +29 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.full.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.intl.d.ts +42 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.object.d.ts +47 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.sharedmemory.d.ts +133 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.string.d.ts +47 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2017.typedarrays.d.ts +51 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.asyncgenerator.d.ts +75 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.asynciterable.d.ts +51 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.intl.d.ts +81 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.promise.d.ts +28 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2018.regexp.d.ts +35 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.array.d.ts +77 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.intl.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.object.d.ts +31 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.string.d.ts +35 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2019.symbol.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.bigint.d.ts +763 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.d.ts +25 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.date.d.ts +40 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.intl.d.ts +472 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.number.d.ts +26 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.promise.d.ts +45 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.sharedmemory.d.ts +97 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.string.d.ts +42 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2020.symbol.wellknown.d.ts +39 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.intl.d.ts +164 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.promise.d.ts +46 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.string.d.ts +31 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2021.weakref.d.ts +76 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.array.d.ts +119 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.d.ts +23 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.error.d.ts +73 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.intl.d.ts +143 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.object.d.ts +24 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.regexp.d.ts +37 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2022.string.d.ts +23 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2023.array.d.ts +922 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2023.collection.d.ts +19 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2023.d.ts +20 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2023.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2023.intl.d.ts +62 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.arraybuffer.d.ts +63 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.collection.d.ts +27 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.d.ts +24 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.object.d.ts +27 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.promise.d.ts +33 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.regexp.d.ts +23 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.sharedmemory.d.ts +66 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2024.string.d.ts +27 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.collection.d.ts +94 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.d.ts +23 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.float16.d.ts +443 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.intl.d.ts +200 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.iterator.d.ts +146 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.promise.d.ts +32 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es2025.regexp.d.ts +30 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es5.d.ts +4599 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.es6.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.array.d.ts +33 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.collection.d.ts +47 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.d.ts +27 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.date.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.decorators.d.ts +26 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.disposable.d.ts +191 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.error.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.full.d.ts +22 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.intl.d.ts +107 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.sharedmemory.d.ts +23 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.temporal.d.ts +485 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.esnext.typedarrays.d.ts +90 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.scripthost.d.ts +320 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.webworker.asynciterable.d.ts +18 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.webworker.d.ts +15606 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.webworker.importscripts.d.ts +21 -0
- package/tsc/@typescript/typescript-linux-x64/lib/lib.webworker.iterable.d.ts +18 -0
- package/tsc/@typescript/typescript-linux-x64/lib/tsc +0 -0
- package/tsc/@typescript/typescript-linux-x64/lib/tsc.sig +11 -0
- package/tsc/@typescript/typescript-linux-x64/package.json +45 -0
- package/tsc/notes +14 -0
- package/tsconfig.json +48 -0
- package/index.js +0 -23
- package/libs/dip/suffix/date.js +0 -103
- /package/libs/{ObjectId.js → ObjectId.ts} +0 -0
- /package/libs/{cpp.js → cpp.ts} +0 -0
- /package/libs/dip/suffix/{query.js → query.ts} +0 -0
- /package/libs/{dipper.js → dipper.ts} +0 -0
- /package/libs/{kafka.js → kafka.ts} +0 -0
- /package/libs/{mobilecodes.js → mobilecodes.ts} +0 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { default as dipper, shard_stats as ShardStats } from './dipper.js';
|
|
3
|
+
import * as Utils from './utils.js';
|
|
4
|
+
import * as Cpp from './cpp.js';
|
|
5
|
+
import { applySuffixPolicy } from './dip/suffix/policy.js';
|
|
6
|
+
export const shard_stats = ShardStats;
|
|
7
|
+
let Events = {
|
|
8
|
+
send: function () { }
|
|
9
|
+
};
|
|
10
|
+
const url = process.env.DIP_URL || "http://127.0.0.1"; // Set DIP_URL to "http://dip" (Prod) or http://dip-dev (Dev) in CI/CD
|
|
11
|
+
let port = process.env.DIP_PORT || 9401;
|
|
12
|
+
let api = 'execute';
|
|
13
|
+
let fullurl = `${url}:${port}/${api}`;
|
|
14
|
+
let Elabase = {
|
|
15
|
+
Engine: {
|
|
16
|
+
Lmdb: 1,
|
|
17
|
+
Sled: 2,
|
|
18
|
+
Sanakirja: 3,
|
|
19
|
+
Singularity: 4,
|
|
20
|
+
Memory: 5,
|
|
21
|
+
Analytics: 6,
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
let engine = Elabase.Engine.Lmdb;
|
|
25
|
+
let internal = {
|
|
26
|
+
db: undefined,
|
|
27
|
+
engineName: engine === Elabase.Engine.Lmdb ? "lmdb" : (engine === Elabase.Engine.Sled ? "sled" : engine === Elabase.Engine.Sanakirja ? "sanakirja" : "lmdb")
|
|
28
|
+
};
|
|
29
|
+
let db = internal.db; // default database
|
|
30
|
+
export function start(dbName) {
|
|
31
|
+
if (!Utils.isEmpty(dbName) && Utils.isEmpty(db)) {
|
|
32
|
+
internal.db = "data/" + dbName;
|
|
33
|
+
db = "data/" + dbName;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function deepFreeze(obj) {
|
|
37
|
+
if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
|
|
38
|
+
Object.freeze(obj);
|
|
39
|
+
for (const key of Object.keys(obj)) {
|
|
40
|
+
deepFreeze(obj[key]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
class DipMeta {
|
|
46
|
+
constructor(obj) {
|
|
47
|
+
Object.assign(this, deepFreeze(obj));
|
|
48
|
+
Object.freeze(this);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export const isDipMeta = meta => meta instanceof DipMeta;
|
|
52
|
+
export const globalMeta = args => {
|
|
53
|
+
return new DipMeta({ ...args, company: "GLOBAL", outlet: "GLOBAL" });
|
|
54
|
+
};
|
|
55
|
+
export const companyMeta = (company, args) => {
|
|
56
|
+
if (typeof company !== "string" && !Array.isArray(company))
|
|
57
|
+
throw new Error("Error: Invalid company provided in Dip.companyMeta()");
|
|
58
|
+
if (!company || (typeof company === "string" && company.trim() === "") || company === "GLOBAL" || (Array.isArray(company) && (!company.length || company.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL"))))
|
|
59
|
+
throw new Error("Error: Invalid company provided in Dip.companyMeta()");
|
|
60
|
+
return new DipMeta({ ...args, outlet: "GLOBAL", company });
|
|
61
|
+
};
|
|
62
|
+
export const outletMeta = (outlet, args) => {
|
|
63
|
+
if (typeof outlet !== "string" && !Array.isArray(outlet))
|
|
64
|
+
throw new Error("Error: Invalid outlet provided in Dip.outletMeta()");
|
|
65
|
+
if (!outlet || (typeof outlet === "string" && outlet.trim() === "") || outlet === "GLOBAL" || (Array.isArray(outlet) && (!outlet.length || outlet.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL"))))
|
|
66
|
+
throw new Error("Error: Invalid outlet provided in Dip.outletMeta()");
|
|
67
|
+
return new DipMeta({ ...args, company: "GLOBAL", outlet });
|
|
68
|
+
};
|
|
69
|
+
export const customMeta = (company, outlet, args) => {
|
|
70
|
+
if (typeof company !== "string" && !Array.isArray(company))
|
|
71
|
+
throw new Error("Error: Invalid company provided in Dip.customMeta()");
|
|
72
|
+
if (typeof outlet !== "string" && !Array.isArray(outlet))
|
|
73
|
+
throw new Error("Error: Invalid outlet provided in Dip.customMeta()");
|
|
74
|
+
if (!company || (typeof company === "string" && company.trim() === "") || company === "GLOBAL" || (Array.isArray(company) && (!company.length || company.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL"))))
|
|
75
|
+
throw new Error("Error: Invalid company provided in Dip.customMeta()");
|
|
76
|
+
if (!outlet || (typeof outlet === "string" && outlet.trim() === "") || outlet === "GLOBAL" || (Array.isArray(outlet) && (!outlet.length || outlet.some(item => typeof item !== "string" || item.trim() === "" || item === "GLOBAL"))))
|
|
77
|
+
throw new Error("Error: Invalid outlet provided in Dip.customMeta()");
|
|
78
|
+
return new DipMeta({ ...args, company, outlet });
|
|
79
|
+
};
|
|
80
|
+
function validate_collection(collection, fn_name) {
|
|
81
|
+
if ((typeof collection === 'string' && collection.trim() === "") || (typeof collection !== 'string' && !Array.isArray(collection)) || (Array.isArray(collection) && (!collection.length || collection.some(item => typeof item !== "string" || item.trim() === "")))) {
|
|
82
|
+
throw new Error(`Error: Invalid collection ${fn_name}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function validate_meta(meta, fn_name) {
|
|
86
|
+
if (!meta || typeof meta !== 'object') {
|
|
87
|
+
throw new Error(`Error: Invalid meta ${fn_name}`);
|
|
88
|
+
}
|
|
89
|
+
if ((typeof meta.company === 'string' && meta.company.trim() === "") || (typeof meta.company !== 'string' && !Array.isArray(meta.company)) || (Array.isArray(meta.company) && (!meta.company.length || meta.company.some(item => typeof item !== "string" || item.trim() === "")))) {
|
|
90
|
+
throw new Error(`Error: Invalid meta.company ${fn_name}`);
|
|
91
|
+
}
|
|
92
|
+
if ((typeof meta.outlet === 'string' && meta.outlet.trim() === "") || (typeof meta.outlet !== 'string' && !Array.isArray(meta.outlet)) || (Array.isArray(meta.outlet) && (!meta.outlet.length || meta.outlet.some(item => typeof item !== "string" || item.trim() === "")))) {
|
|
93
|
+
throw new Error(`Error: Invalid meta.outlet ${fn_name}`);
|
|
94
|
+
}
|
|
95
|
+
if ((meta.suffix !== undefined && typeof meta.suffix !== 'string' && !Array.isArray(meta.suffix)) || (Array.isArray(meta.suffix) && meta.suffix.some(item => typeof item !== "string" || item.trim() === ""))) {
|
|
96
|
+
throw new Error(`Error: Invalid meta.suffix ${fn_name}`);
|
|
97
|
+
}
|
|
98
|
+
else if (typeof meta.suffix === 'string' && meta.suffix.trim() === "")
|
|
99
|
+
throw new Error(`Error: Invalid meta.suffix ${fn_name}`);
|
|
100
|
+
}
|
|
101
|
+
function generate_suffix(meta) {
|
|
102
|
+
// Assuming validate_meta() is called before reaching here. If not then this is intentional validation bypass
|
|
103
|
+
let company = typeof meta.company == 'string' ? [meta.company] : (meta.company?.length ? meta.company : []);
|
|
104
|
+
let outlet = typeof meta.outlet == 'string' ? [meta.outlet] : (meta.outlet?.length ? meta.outlet : []);
|
|
105
|
+
let suffix = typeof meta.suffix == 'string' ? [meta.suffix] : (meta.suffix?.length ? meta.suffix : []);
|
|
106
|
+
company = company.filter(item => item.trim() !== "");
|
|
107
|
+
outlet = outlet.filter(item => item.trim() !== "");
|
|
108
|
+
suffix = suffix.filter(item => item.trim() !== "");
|
|
109
|
+
company = company.length ? company : [""];
|
|
110
|
+
outlet = outlet.length ? outlet : [""];
|
|
111
|
+
suffix = suffix.length ? suffix : [""];
|
|
112
|
+
company = new Set(company);
|
|
113
|
+
outlet = new Set(outlet);
|
|
114
|
+
suffix = new Set(suffix);
|
|
115
|
+
// console.log(company, outlet, suffix)
|
|
116
|
+
let suffixes = [];
|
|
117
|
+
for (let c of company) {
|
|
118
|
+
for (let o of outlet) {
|
|
119
|
+
for (let s of suffix) {
|
|
120
|
+
let pathSegments = [c, o, s].filter(segment => segment !== "");
|
|
121
|
+
if (pathSegments.length > 0) {
|
|
122
|
+
suffixes.push(pathSegments.join('/'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return suffixes;
|
|
128
|
+
}
|
|
129
|
+
// Ported
|
|
130
|
+
let BATCH_COUNTER = 0n;
|
|
131
|
+
let batches = {};
|
|
132
|
+
// Ported
|
|
133
|
+
export function batchBegin() {
|
|
134
|
+
const uid = ++BATCH_COUNTER; // Safe. No skew in async ++BATCH_COUNTER as single thread and ++COUNTER is atomic in event loop sense. ⚠️ Only breaks on worker_threads or cluster (multi-process)
|
|
135
|
+
batches[uid] = [];
|
|
136
|
+
return uid;
|
|
137
|
+
}
|
|
138
|
+
// Ported
|
|
139
|
+
export function batchAbort(batch_id) {
|
|
140
|
+
delete batches[batch_id];
|
|
141
|
+
}
|
|
142
|
+
// Ported
|
|
143
|
+
export const batch = async (callback, arg) => {
|
|
144
|
+
/**
|
|
145
|
+
* Usage:
|
|
146
|
+
* const result = await Dip.batch(async batch => {
|
|
147
|
+
* for (let i = 0; i < 45000; i++)
|
|
148
|
+
* Dip.insert({...meta, batch}, collection, {_id: i})
|
|
149
|
+
* })
|
|
150
|
+
*
|
|
151
|
+
* Note: Nested batch is supported as they are just independant batches.
|
|
152
|
+
*/
|
|
153
|
+
const batch = batchBegin();
|
|
154
|
+
try {
|
|
155
|
+
await callback(batch);
|
|
156
|
+
return await batchSubmit(batch, arg);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
batchAbort(batch);
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
// Ported
|
|
164
|
+
export function batchSubmit(batch_id, arg) {
|
|
165
|
+
if (!batch_id || !batches[batch_id] || !batches[batch_id].length)
|
|
166
|
+
throw new Error(`Error: Invalid batch in Dip.batchSubmit()`);
|
|
167
|
+
let txns = batches[batch_id];
|
|
168
|
+
const executor = arg?.executor ?? batches[batch_id].find(txn => txn.executor)?.executor;
|
|
169
|
+
const syncMode = arg?.syncMode ?? batches[batch_id].find(txn => txn.syncMode)?.syncMode;
|
|
170
|
+
const raw = arg?.raw;
|
|
171
|
+
const engine = arg?.engine;
|
|
172
|
+
const port = arg?.port;
|
|
173
|
+
const timeout = arg?.timeout;
|
|
174
|
+
delete batches[batch_id];
|
|
175
|
+
return new Promise((resolve, reject) => resolve())
|
|
176
|
+
.then(() => execute({ "batch": txns, version: arg?.version, raw, engine, compression: arg?.compression, executor, syncMode, port, timeout }))
|
|
177
|
+
.then(result => {
|
|
178
|
+
Events.send("Dip.batchSubmit", { response: result });
|
|
179
|
+
return result;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
const SCHEMAS_JSON_PROMISES = {};
|
|
183
|
+
export const schema = async (name) => {
|
|
184
|
+
// Cache the loading promise right away so parallel requests share it
|
|
185
|
+
if (!SCHEMAS_JSON_PROMISES[name])
|
|
186
|
+
SCHEMAS_JSON_PROMISES[name] = Utils.fileToJson(new URL('../../..', import.meta.url), `schemas/${name}.json`);
|
|
187
|
+
try {
|
|
188
|
+
const schema = await SCHEMAS_JSON_PROMISES[name];
|
|
189
|
+
return structuredClone(schema);
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
// Delete the broken promise from cache so a retry can occur later
|
|
193
|
+
delete SCHEMAS_JSON_PROMISES[name];
|
|
194
|
+
throw new Error(`Error: Failed to load schema ${name} in Dip`);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const COLLECTIONS_JSON = await (async () => {
|
|
198
|
+
try {
|
|
199
|
+
return await Utils.fileToJson(new URL('../../..', import.meta.url), 'collections.json');
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
console.error(e);
|
|
203
|
+
console.warn("Warn: Dip Failed to load collections.json. Semantics, topology and legality enforcement is not active");
|
|
204
|
+
}
|
|
205
|
+
})();
|
|
206
|
+
function init_collections_config() {
|
|
207
|
+
for (let collection in COLLECTIONS_JSON) {
|
|
208
|
+
let config = COLLECTIONS_JSON[collection];
|
|
209
|
+
if (config.suffix !== undefined && (typeof config.suffix !== "object" || Array.isArray(config.suffix))) {
|
|
210
|
+
throw new Error(`Error: Initiating collection configs failed. Invalid suffix in collection: ${collection}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (COLLECTIONS_JSON)
|
|
215
|
+
init_collections_config();
|
|
216
|
+
const EXCLUDED_COLLECTIONS_CONFIG = {};
|
|
217
|
+
export function excludeCollectionConfig(collection) {
|
|
218
|
+
EXCLUDED_COLLECTIONS_CONFIG[collection] = true;
|
|
219
|
+
}
|
|
220
|
+
export function includeCollectionConfig(collection) {
|
|
221
|
+
delete EXCLUDED_COLLECTIONS_CONFIG[collection];
|
|
222
|
+
}
|
|
223
|
+
function validate_topology(meta, collection, fn_name) {
|
|
224
|
+
let new_meta = meta;
|
|
225
|
+
let config = COLLECTIONS_JSON?.[collection];
|
|
226
|
+
if (!config) {
|
|
227
|
+
if (!EXCLUDED_COLLECTIONS_CONFIG[collection])
|
|
228
|
+
console.warn(`Warn: Missing config for collection: ${collection}${fn_name ? ` ${fn_name}` : ''}`);
|
|
229
|
+
return new_meta;
|
|
230
|
+
}
|
|
231
|
+
function check_core_meta(config, meta, suffix) {
|
|
232
|
+
if (config.company !== meta.company && typeof config.company !== "object")
|
|
233
|
+
throw new Error(`Error: Incompatible meta.company config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`);
|
|
234
|
+
if (config.outlet !== meta.outlet && typeof config.outlet !== "object")
|
|
235
|
+
throw new Error(`Error: Incompatible meta.outlet config for collection: ${collection}${suffix ? ' suffix: ' + suffix : ''}${fn_name ? ` ${fn_name}` : ''}`);
|
|
236
|
+
}
|
|
237
|
+
check_core_meta(config, meta);
|
|
238
|
+
if (config.suffix && meta.suffix) {
|
|
239
|
+
if (!config.suffix[meta.suffix]) {
|
|
240
|
+
console.warn(`Warn: Missing suffix config for collection: ${collection} suffix:${meta.suffix}${fn_name ? ` ${fn_name}` : ''}`);
|
|
241
|
+
return new_meta;
|
|
242
|
+
}
|
|
243
|
+
check_core_meta(config.suffix[meta.suffix], meta, meta.suffix);
|
|
244
|
+
new_meta = Object.assign({}, { ...config, suffix: undefined, company: undefined, outlet: undefined }, { ...config.suffix[meta.suffix], company: undefined, outlet: undefined }, meta);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
new_meta = Object.assign({}, { ...config, suffix: undefined, company: undefined, outlet: undefined }, { company: undefined, outlet: undefined }, meta);
|
|
248
|
+
}
|
|
249
|
+
return new_meta;
|
|
250
|
+
}
|
|
251
|
+
// Ported
|
|
252
|
+
export const operation = async (name, extras) => {
|
|
253
|
+
return execute({ operation: name, ...extras });
|
|
254
|
+
};
|
|
255
|
+
// Ported
|
|
256
|
+
export const insert = async (meta, collection, value, options, extras) => {
|
|
257
|
+
if (!(meta instanceof DipMeta))
|
|
258
|
+
console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.insert()'); // TODO: throw error once review completes
|
|
259
|
+
validate_collection(collection, 'in Dip.insert()');
|
|
260
|
+
validate_meta(meta, 'in Dip.insert()');
|
|
261
|
+
const topology_meta = validate_topology(meta, collection, 'in Dip.insert()'); // TODO: loop for arrays
|
|
262
|
+
let arg = {
|
|
263
|
+
collection: collection,
|
|
264
|
+
insert: value,
|
|
265
|
+
options: options ? options : {},
|
|
266
|
+
syncMode: meta.syncMode,
|
|
267
|
+
...(meta.DIP_URL ? { DIP_URL: meta.DIP_URL } : {}),
|
|
268
|
+
...(meta.DIP_DB ? { db: meta.DIP_DB } : {}),
|
|
269
|
+
};
|
|
270
|
+
arg = Object.assign(arg, extras);
|
|
271
|
+
let suffix_from_policy = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.insert, true, arg);
|
|
272
|
+
let suffix_from_meta = generate_suffix(meta);
|
|
273
|
+
arg.suffix = (suffix_from_meta.length ? suffix_from_meta : [""]).flatMap(meta => (suffix_from_policy.length ? suffix_from_policy : [""]).map(policy => meta + policy));
|
|
274
|
+
arg.executor = meta.executor ?? "native";
|
|
275
|
+
arg = Object.assign({}, topology_meta, arg);
|
|
276
|
+
if (options?._id) {
|
|
277
|
+
arg._id = options._id;
|
|
278
|
+
arg.options = { ...options, _id: undefined };
|
|
279
|
+
}
|
|
280
|
+
if (meta.batch) {
|
|
281
|
+
if (!batches[meta.batch])
|
|
282
|
+
throw new Error('Error: Invalid batch in Dip.insert()');
|
|
283
|
+
batches[meta.batch].push(arg);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
return new Promise((resolve, reject) => resolve())
|
|
287
|
+
.then(() => execute(arg))
|
|
288
|
+
.then(result => {
|
|
289
|
+
Events.send("Dip.insert", { collection: collectionArray(collection), response: result });
|
|
290
|
+
return result;
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
// Ported
|
|
294
|
+
export const query = async (meta, collection, query, options, extras) => {
|
|
295
|
+
if (!(meta instanceof DipMeta))
|
|
296
|
+
console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.query()'); // TODO: throw error once review completes
|
|
297
|
+
validate_collection(collection, 'in Dip.query()');
|
|
298
|
+
validate_meta(meta, 'in Dip.query()');
|
|
299
|
+
const topology_meta = validate_topology(meta, collection, 'in Dip.query()'); // TODO: loop for arrays
|
|
300
|
+
let arg = {
|
|
301
|
+
collection: collection,
|
|
302
|
+
query: query,
|
|
303
|
+
options: options ? options : {},
|
|
304
|
+
syncMode: meta.syncMode,
|
|
305
|
+
...(meta.DIP_URL ? { DIP_URL: meta.DIP_URL } : {}),
|
|
306
|
+
...(meta.DIP_DB ? { db: meta.DIP_DB } : {}),
|
|
307
|
+
};
|
|
308
|
+
arg = Object.assign(arg, extras);
|
|
309
|
+
let suffix_from_policy = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg);
|
|
310
|
+
let suffix_from_meta = generate_suffix(meta);
|
|
311
|
+
arg.suffix = (suffix_from_meta.length ? suffix_from_meta : [""]).flatMap(meta => (suffix_from_policy.length ? suffix_from_policy : [""]).map(policy => meta + policy));
|
|
312
|
+
arg.executor = meta.executor ?? "native";
|
|
313
|
+
arg = Object.assign({}, topology_meta, arg);
|
|
314
|
+
if (meta.batch) {
|
|
315
|
+
if (!batches[meta.batch])
|
|
316
|
+
throw new Error('Error: Invalid batch in Dip.query()');
|
|
317
|
+
batches[meta.batch].push(arg);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
return new Promise((resolve, reject) => resolve())
|
|
321
|
+
.then(() => execute(arg));
|
|
322
|
+
};
|
|
323
|
+
function collectionArray(col) {
|
|
324
|
+
let type = Object.prototype.toString.call(col);
|
|
325
|
+
if (type === '[object Array]') {
|
|
326
|
+
let newcol = [];
|
|
327
|
+
for (let i in col) {
|
|
328
|
+
if (!Utils.isEmpty(col[i]))
|
|
329
|
+
newcol.push(col[i]);
|
|
330
|
+
}
|
|
331
|
+
return newcol;
|
|
332
|
+
}
|
|
333
|
+
else if (type === '[object String]') {
|
|
334
|
+
if (!Utils.isEmpty(col))
|
|
335
|
+
return [col];
|
|
336
|
+
}
|
|
337
|
+
return [];
|
|
338
|
+
}
|
|
339
|
+
// Ported
|
|
340
|
+
export const update = async (meta, collection, query, update, options, extras) => {
|
|
341
|
+
if (!(meta instanceof DipMeta))
|
|
342
|
+
console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.update()'); // TODO: throw error once review completes
|
|
343
|
+
validate_collection(collection, 'in Dip.update()');
|
|
344
|
+
validate_meta(meta, 'in Dip.update()');
|
|
345
|
+
const topology_meta = validate_topology(meta, collection, 'in Dip.update()'); // TODO: loop for arrays
|
|
346
|
+
let arg = {
|
|
347
|
+
collection: collection,
|
|
348
|
+
query: query,
|
|
349
|
+
update: update,
|
|
350
|
+
options: options ? options : {},
|
|
351
|
+
syncMode: meta.syncMode,
|
|
352
|
+
...(meta.DIP_URL ? { DIP_URL: meta.DIP_URL } : {}),
|
|
353
|
+
...(meta.DIP_DB ? { db: meta.DIP_DB } : {}),
|
|
354
|
+
};
|
|
355
|
+
arg = Object.assign(arg, extras);
|
|
356
|
+
let suffix_from_policy = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg);
|
|
357
|
+
let suffix_from_meta = generate_suffix(meta);
|
|
358
|
+
arg.suffix = (suffix_from_meta.length ? suffix_from_meta : [""]).flatMap(meta => (suffix_from_policy.length ? suffix_from_policy : [""]).map(policy => meta + policy));
|
|
359
|
+
arg.executor = meta.executor ?? "native";
|
|
360
|
+
arg = Object.assign({}, topology_meta, arg);
|
|
361
|
+
if (meta.batch) {
|
|
362
|
+
if (!batches[meta.batch])
|
|
363
|
+
throw new Error('Error: Invalid batch in Dip.update()');
|
|
364
|
+
batches[meta.batch].push(arg);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
return new Promise((resolve, reject) => resolve())
|
|
368
|
+
.then(() => execute(arg))
|
|
369
|
+
.then(result => {
|
|
370
|
+
Events.send("Dip.update", { collection: collectionArray(collection), response: result });
|
|
371
|
+
return result;
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
// Ported
|
|
375
|
+
export const remove = async (meta, collection, query, options, extras) => {
|
|
376
|
+
if (!(meta instanceof DipMeta))
|
|
377
|
+
console.warn('Warn: Provided meta is not an instance of DipMeta in Dip.remove()'); // TODO: throw error once review completes
|
|
378
|
+
validate_collection(collection, 'in Dip.remove()');
|
|
379
|
+
if (Utils.isEmpty(query._id) && !meta.allowDangerousRemove)
|
|
380
|
+
throw new Error("Error: Dip.remove() without _id blocked by default (Dangerous Operation). Set meta.allowDangerousRemove if intentional.");
|
|
381
|
+
validate_meta(meta, 'in Dip.remove()');
|
|
382
|
+
const topology_meta = validate_topology(meta, collection, 'in Dip.remove()'); // TODO: loop for arrays
|
|
383
|
+
let arg = {
|
|
384
|
+
collection: collection,
|
|
385
|
+
query: query,
|
|
386
|
+
options: options ? options : {},
|
|
387
|
+
delete: true,
|
|
388
|
+
syncMode: meta.syncMode,
|
|
389
|
+
...(meta.DIP_URL ? { DIP_URL: meta.DIP_URL } : {}),
|
|
390
|
+
...(meta.DIP_DB ? { db: meta.DIP_DB } : {}),
|
|
391
|
+
};
|
|
392
|
+
arg = Object.assign(arg, extras);
|
|
393
|
+
let suffix_from_policy = await applySuffixPolicy(COLLECTIONS_JSON, collection, arg.query, false, arg);
|
|
394
|
+
let suffix_from_meta = generate_suffix(meta);
|
|
395
|
+
arg.suffix = (suffix_from_meta.length ? suffix_from_meta : [""]).flatMap(meta => (suffix_from_policy.length ? suffix_from_policy : [""]).map(policy => meta + policy));
|
|
396
|
+
arg.executor = meta.executor ?? "native";
|
|
397
|
+
arg = Object.assign({}, topology_meta, arg);
|
|
398
|
+
if (meta.batch) {
|
|
399
|
+
if (!batches[meta.batch])
|
|
400
|
+
throw new Error('Error: Invalid batch in Dip.query()');
|
|
401
|
+
batches[meta.batch].push(arg);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
return new Promise((resolve, reject) => resolve())
|
|
405
|
+
.then(() => execute(arg))
|
|
406
|
+
.then(result => {
|
|
407
|
+
Events.send("Dip.remove", { collection: collectionArray(collection), response: result });
|
|
408
|
+
return result;
|
|
409
|
+
});
|
|
410
|
+
};
|
|
411
|
+
export let config = {
|
|
412
|
+
useDipper: false
|
|
413
|
+
};
|
|
414
|
+
function execute(arg) {
|
|
415
|
+
// arg example
|
|
416
|
+
// {
|
|
417
|
+
// db: "middle-earth",
|
|
418
|
+
// collection: "staff",
|
|
419
|
+
// query: "[@][?name == 'Bilbo'] | [0]",
|
|
420
|
+
// insert: { "name": "Bilbo" },
|
|
421
|
+
// query: { "name": "Frodo"},
|
|
422
|
+
// update: { "$set": { "age": 21 } }
|
|
423
|
+
// _id: 1 // Optional. Used with insert
|
|
424
|
+
// }
|
|
425
|
+
arg.db = arg.db ?? db;
|
|
426
|
+
arg.executor = arg.executor ?? "native";
|
|
427
|
+
arg.engine = arg.engine ?? internal.engineName;
|
|
428
|
+
if (arg.compression === undefined)
|
|
429
|
+
arg.compression = true; // Compress all for now by default
|
|
430
|
+
let fullurl = `${url}:${arg?.port ?? port}/${api}`;
|
|
431
|
+
delete arg.port;
|
|
432
|
+
const timeout = arg.timeout;
|
|
433
|
+
delete arg.timeout;
|
|
434
|
+
return config.useDipper ? dipper(arg)
|
|
435
|
+
: axios
|
|
436
|
+
.post(arg.DIP_URL ?? fullurl, buildHybridRequest({ ...arg, DIP_URL: undefined }), { responseType: 'arraybuffer', timeout: timeout ?? 5000, headers: { "Content-Type": "application/dip" } })
|
|
437
|
+
.then(result => {
|
|
438
|
+
// console.log(res.status);
|
|
439
|
+
// console.log(JSON.stringify(res.header, null, 4));
|
|
440
|
+
// console.log(JSON.stringify(res.body, null, 4));
|
|
441
|
+
result.getSliceAsText = (offset, length) => Cpp.getSliceAsText(result.data, offset, length);
|
|
442
|
+
result.getSliceAsArrayBuffer = (offset, length) => Cpp.getSliceAsArrayBuffer(result.data, offset, length);
|
|
443
|
+
result["Content-Type"] = result.headers["content-type"];
|
|
444
|
+
result.body = result.data;
|
|
445
|
+
if (result.headers["content-type"].includes("application/json"))
|
|
446
|
+
result.body = JSON.parse(result.data);
|
|
447
|
+
let parsed = parseBinaryResponse(result);
|
|
448
|
+
let response = prepareResult(parsed);
|
|
449
|
+
return response;
|
|
450
|
+
});
|
|
451
|
+
// .catch(err => { console.log(err.message); console.log(err.response); return err});
|
|
452
|
+
}
|
|
453
|
+
let Essentials = {
|
|
454
|
+
vlqToUint64: Cpp.vlqToUint64,
|
|
455
|
+
sliceArrayBuffer: Cpp.sliceArrayBuffer,
|
|
456
|
+
stringToUtf8ArrayBuffer: Cpp.stringToUtf8ArrayBuffer,
|
|
457
|
+
numberToSortableBytes: Cpp.numberToSortableBytes,
|
|
458
|
+
defaultHash: Cpp.defaultHash,
|
|
459
|
+
memcmpEqual: Cpp.memcmpEqual,
|
|
460
|
+
uint64ToVlq: Cpp.uint64ToVlq,
|
|
461
|
+
arrayBufferToString: Cpp.arrayBufferToString,
|
|
462
|
+
};
|
|
463
|
+
function prepareResult(result) {
|
|
464
|
+
let res = result.content?.length === 1 ? result.content[0].items : result.content; // For raw, this resolves to result.content which is ArrayBuffer
|
|
465
|
+
res.metadata = _ => result.metadata;
|
|
466
|
+
if (result.metadata.executor === "raw")
|
|
467
|
+
setRawBatchIterator(res);
|
|
468
|
+
return res;
|
|
469
|
+
}
|
|
470
|
+
function parseBinaryResponse(result) {
|
|
471
|
+
const contentType = (result["Content-Type"] || "").toLowerCase();
|
|
472
|
+
if (contentType.includes("application/json")) {
|
|
473
|
+
return { metadata: result.body, content: result.body.items };
|
|
474
|
+
}
|
|
475
|
+
if (!contentType.includes("application/dip")) {
|
|
476
|
+
throw new Error("Error: Dip unsupported media. Invalid content-type.");
|
|
477
|
+
}
|
|
478
|
+
const arrayBuffer = result.body;
|
|
479
|
+
// let wire = parseWireFormat(arrayBuffer)
|
|
480
|
+
// let meta = wireFormat.metadata
|
|
481
|
+
// let content = wireFormat.content
|
|
482
|
+
// try {
|
|
483
|
+
// meta = JSON.parse(meta);
|
|
484
|
+
// } catch (_) {
|
|
485
|
+
// throw {contentType, meta, content, message: "Error: Dip failed to parse metadata. Unsupported response format. Response format does not match content-type."}
|
|
486
|
+
// }
|
|
487
|
+
// parseWireFormat() equivalent
|
|
488
|
+
// =============================
|
|
489
|
+
let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
|
|
490
|
+
let offset = 0;
|
|
491
|
+
// 1. Read the metadata size header
|
|
492
|
+
let vlq = Essentials.vlqToUint64(Essentials.sliceArrayBuffer(arrayBuffer, offset, 10));
|
|
493
|
+
let metaSize = vlq.value;
|
|
494
|
+
offset += vlq.bytes;
|
|
495
|
+
// 2. Extract and parse metadata string via C++ instantly
|
|
496
|
+
let metaText = result.getSliceAsText(offset, metaSize);
|
|
497
|
+
let nativeResponse = JSON.parse(metaText);
|
|
498
|
+
offset += metaSize;
|
|
499
|
+
// Extract everything remaining automatically by passing -1
|
|
500
|
+
let content = result.getSliceAsArrayBuffer(offset, -1); // content is already ArrayBuffer but QByteArray to ArrayBuffer cannot be Uint8Array() wrapped
|
|
501
|
+
// content = new Uint8Array(content ?? new ArrayBuffer(0))
|
|
502
|
+
return { metadata: nativeResponse, content: content };
|
|
503
|
+
}
|
|
504
|
+
function setRawBatchIterator(arrayBuffer) {
|
|
505
|
+
arrayBuffer.metadata().items.forEach(batch => {
|
|
506
|
+
batch.kv = _ => {
|
|
507
|
+
const batchItem = {
|
|
508
|
+
count: batch.count,
|
|
509
|
+
slice: Essentials.sliceArrayBuffer(arrayBuffer, batch.offset, batch.size),
|
|
510
|
+
[Symbol.iterator]() {
|
|
511
|
+
let index = 0;
|
|
512
|
+
let offset = 0;
|
|
513
|
+
return {
|
|
514
|
+
next: () => {
|
|
515
|
+
if (index < this.count) {
|
|
516
|
+
let kv = getRawKeyValue(this.slice, offset);
|
|
517
|
+
offset = kv.next;
|
|
518
|
+
index++;
|
|
519
|
+
return { value: kv, done: false };
|
|
520
|
+
}
|
|
521
|
+
return { done: true };
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
return batchItem;
|
|
527
|
+
};
|
|
528
|
+
});
|
|
529
|
+
arrayBuffer.items = arrayBuffer.metadata().items;
|
|
530
|
+
}
|
|
531
|
+
// ===============
|
|
532
|
+
function convert_to_array_buffer(value) {
|
|
533
|
+
if (typeof value === "string")
|
|
534
|
+
return Essentials.stringToUtf8ArrayBuffer(value);
|
|
535
|
+
else if (typeof value === "number")
|
|
536
|
+
return Essentials.numberToSortableBytes(value);
|
|
537
|
+
return Essentials.stringToUtf8ArrayBuffer(JSON.stringify(value));
|
|
538
|
+
}
|
|
539
|
+
export function newRaw() {
|
|
540
|
+
let obj = { buffers: [], size: 0, hashes: {} };
|
|
541
|
+
obj.add = value => {
|
|
542
|
+
if (value === undefined)
|
|
543
|
+
return undefined;
|
|
544
|
+
const buf = (value instanceof ArrayBuffer) ? value : convert_to_array_buffer(value);
|
|
545
|
+
const hash = Essentials.defaultHash(buf);
|
|
546
|
+
for (let item of obj.hashes[hash] ?? []) { // Conflict. Fallback to verify
|
|
547
|
+
if (Essentials.memcmpEqual(buf, item.buf))
|
|
548
|
+
return item.offset;
|
|
549
|
+
}
|
|
550
|
+
const vlq = new Uint8Array(Essentials.uint64ToVlq(buf.byteLength));
|
|
551
|
+
obj.buffers.push({ buf, vlq });
|
|
552
|
+
let offset = obj.size;
|
|
553
|
+
obj.size += vlq.byteLength + buf.byteLength;
|
|
554
|
+
obj.hashes[hash] = obj.hashes[hash] ?? [];
|
|
555
|
+
obj.hashes[hash].push({ offset, buf });
|
|
556
|
+
return offset;
|
|
557
|
+
};
|
|
558
|
+
return obj;
|
|
559
|
+
}
|
|
560
|
+
function buildHybridRequest(request) {
|
|
561
|
+
const batch = request.batch ?? [request];
|
|
562
|
+
let raw = request.raw ?? newRaw();
|
|
563
|
+
request.raw = undefined;
|
|
564
|
+
// Pass 1: Direct offset assignment & exact size calculation (Zero allocation)
|
|
565
|
+
for (let i = 0; i < batch.length; i++) {
|
|
566
|
+
const item = batch[i];
|
|
567
|
+
delete item.batch;
|
|
568
|
+
if (item.update) {
|
|
569
|
+
if (item._id === undefined && item.options?.upsert && item.query?._id !== undefined)
|
|
570
|
+
item._id = item.query._id;
|
|
571
|
+
item.update = raw.add(item.update);
|
|
572
|
+
}
|
|
573
|
+
else if (item.insert) {
|
|
574
|
+
if (item._id === undefined && item.insert?._id !== undefined)
|
|
575
|
+
item._id = item.insert._id;
|
|
576
|
+
item.insert = raw.add(item.insert);
|
|
577
|
+
}
|
|
578
|
+
item._id = raw.add(item._id);
|
|
579
|
+
if (item.options?.$rangeFrom !== undefined)
|
|
580
|
+
item.options.$rangeFrom = raw.add(item.options.$rangeFrom);
|
|
581
|
+
if (item.options?.$rangeTo !== undefined)
|
|
582
|
+
item.options.$rangeTo = raw.add(item.options.$rangeTo);
|
|
583
|
+
}
|
|
584
|
+
// Pass 2: Generate the final JSON payload string
|
|
585
|
+
const jsonBuffer = convert_to_array_buffer(request);
|
|
586
|
+
const jsonByteLen = jsonBuffer.byteLength;
|
|
587
|
+
// Pass 3: Allocate the exact Master Buffer ONCE
|
|
588
|
+
let vlq = new Uint8Array(Essentials.uint64ToVlq(jsonByteLen));
|
|
589
|
+
const totalSize = vlq.byteLength + jsonByteLen + raw.size;
|
|
590
|
+
const masterBuffer = new ArrayBuffer(totalSize);
|
|
591
|
+
const masterView = new Uint8Array(masterBuffer);
|
|
592
|
+
// Write the JSON size prefix
|
|
593
|
+
masterView.set(vlq, 0);
|
|
594
|
+
// Direct copy of JSON string bytes into their final destination
|
|
595
|
+
masterView.set(new Uint8Array(jsonBuffer), vlq.byteLength);
|
|
596
|
+
// Copy binary payloads directly into their final destination window
|
|
597
|
+
let writeOffset = vlq.byteLength + jsonByteLen;
|
|
598
|
+
for (const buffer of raw.buffers) {
|
|
599
|
+
const buf = buffer.buf;
|
|
600
|
+
const vlq = buffer.vlq;
|
|
601
|
+
// Write length prefix directly into final master buffer
|
|
602
|
+
masterView.set(vlq, writeOffset);
|
|
603
|
+
writeOffset += vlq.byteLength;
|
|
604
|
+
// Blit bytes directly from source into final master buffer destination
|
|
605
|
+
masterView.set(new Uint8Array(buf), writeOffset);
|
|
606
|
+
writeOffset += buf.byteLength;
|
|
607
|
+
}
|
|
608
|
+
return masterBuffer;
|
|
609
|
+
}
|
|
610
|
+
// Usage getRawKeyValue()
|
|
611
|
+
// Dip.query()
|
|
612
|
+
// .then(r => {
|
|
613
|
+
// let count = r.metadata().count
|
|
614
|
+
// let offset = 0
|
|
615
|
+
// for (let i = 0; i < count; i++) {
|
|
616
|
+
// let item = getKeyValue(r, offset)
|
|
617
|
+
// offset = item.next
|
|
618
|
+
// let res = Utils.arrayBufferToFile(item.data, '/home/khayaali/Downloads/zdip.png')
|
|
619
|
+
// console.log(item._id,res)
|
|
620
|
+
// }
|
|
621
|
+
// })
|
|
622
|
+
function bufferToString(arrayBuffer) {
|
|
623
|
+
return Essentials.arrayBufferToString(arrayBuffer);
|
|
624
|
+
}
|
|
625
|
+
function getRawKeyValue(arrayBuffer, offset) {
|
|
626
|
+
let dataView = new DataView(arrayBuffer.buffer, arrayBuffer.byteOffset, arrayBuffer.byteLength);
|
|
627
|
+
let masterView = new Uint8Array(arrayBuffer);
|
|
628
|
+
// 1. Extract Key Size and Key
|
|
629
|
+
let vlq = Essentials.vlqToUint64(Essentials.sliceArrayBuffer(arrayBuffer, offset, 10));
|
|
630
|
+
let keySize = vlq.value;
|
|
631
|
+
offset += vlq.bytes;
|
|
632
|
+
// Zero-copy view window bounded strictly to the key bytes
|
|
633
|
+
let _id = masterView.subarray(offset, offset + keySize);
|
|
634
|
+
let _id_string;
|
|
635
|
+
_id.toText = _ => {
|
|
636
|
+
// Fix: Pass the typed array view itself, NOT the underlying root buffer
|
|
637
|
+
_id_string = _id_string === undefined ? _id.buffer.slice(_id.byteOffset, _id.byteOffset + _id.byteLength) : _id_string;
|
|
638
|
+
return bufferToString(_id_string);
|
|
639
|
+
};
|
|
640
|
+
offset += keySize;
|
|
641
|
+
// 2. Extract Data Size and Data Binary Payload
|
|
642
|
+
vlq = Essentials.vlqToUint64(Essentials.sliceArrayBuffer(arrayBuffer, offset, 10));
|
|
643
|
+
let dataSize = vlq.value;
|
|
644
|
+
offset += vlq.bytes;
|
|
645
|
+
// Optimization: Use subarray() instead of .slice() to make the data payload 100% zero-copy too
|
|
646
|
+
let _val = masterView.subarray(offset, offset + dataSize);
|
|
647
|
+
offset += dataSize;
|
|
648
|
+
_val = Essentials.sliceArrayBuffer(arrayBuffer, _val.byteOffset, _val.byteLength);
|
|
649
|
+
// _val = _val.buffer.slice(_val.byteOffset, _val.byteOffset + _val.byteLength);
|
|
650
|
+
_val.toText = _ => bufferToString(_val);
|
|
651
|
+
return { _id, _val, next: offset };
|
|
652
|
+
}
|
|
653
|
+
// Axios usage
|
|
654
|
+
//--------------
|
|
655
|
+
// const axios = require('axios')
|
|
656
|
+
// axios.get('http://www.floatrates.com/daily/usd.json').then(data => console.log(data)).catch(error=> console.log(error))
|