zkjson 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/circomlibjs.js +40504 -0
- package/collection.js +35 -0
- package/db.js +70 -0
- package/encoder.js +458 -0
- package/index.js +5 -0
- package/package.json +7 -0
package/collection.js
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
const newMemEmptyTrie = require("./circomlibjs").newMemEmptyTrie
|
2
|
+
const { pad, str2val, val2str, id2str, encode, str2id } = require("./encoder")
|
3
|
+
|
4
|
+
class Collection {
|
5
|
+
constructor(size = 16) {
|
6
|
+
this.size = size
|
7
|
+
}
|
8
|
+
async init() {
|
9
|
+
this.tree = await newMemEmptyTrie()
|
10
|
+
}
|
11
|
+
async insert(_key, _val) {
|
12
|
+
const doc = encode(_val)
|
13
|
+
const id = str2id(_key)
|
14
|
+
const val = pad(val2str(doc), this.size)
|
15
|
+
return await this.tree.insert(id, val)
|
16
|
+
}
|
17
|
+
async update(_key, _val) {
|
18
|
+
const doc = encode(_val)
|
19
|
+
const id = str2id(_key)
|
20
|
+
const val = pad(val2str(doc), this.size)
|
21
|
+
return await this.tree.update(id, val)
|
22
|
+
}
|
23
|
+
|
24
|
+
async delete(_key) {
|
25
|
+
const id = str2id(_key)
|
26
|
+
return await this.tree.delete(id)
|
27
|
+
}
|
28
|
+
|
29
|
+
async get(_key) {
|
30
|
+
const id = str2id(_key)
|
31
|
+
return await this.tree.find(id)
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
module.exports = Collection
|
package/db.js
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
const newMemEmptyTrie = require("./circomlibjs").newMemEmptyTrie
|
2
|
+
const { str2val, val2str, id2str, encode, str2id } = require("./encoder")
|
3
|
+
const Collection = require("./collection")
|
4
|
+
|
5
|
+
class DB {
|
6
|
+
constructor(size = 16) {
|
7
|
+
this.size = size
|
8
|
+
}
|
9
|
+
async init() {
|
10
|
+
this.tree = await newMemEmptyTrie()
|
11
|
+
this.cols = {}
|
12
|
+
}
|
13
|
+
async addCollection(_key) {
|
14
|
+
const id = str2id(_key)
|
15
|
+
const col = await this.tree.find(id)
|
16
|
+
if (col.found) throw Error("collection exists")
|
17
|
+
const _col = new Collection(this.size)
|
18
|
+
await _col.init()
|
19
|
+
this.cols[_key] = _col
|
20
|
+
const root = _col.tree.F.toObject(_col.tree.root).toString()
|
21
|
+
await this.tree.insert(id, [root])
|
22
|
+
}
|
23
|
+
getColTree(col) {
|
24
|
+
const _col = this.cols[col]
|
25
|
+
if (!_col) throw Error("collection doesn't exist")
|
26
|
+
return _col
|
27
|
+
}
|
28
|
+
async insert(col, _key, _val) {
|
29
|
+
const _col = this.getColTree(col)
|
30
|
+
let update = false
|
31
|
+
let res_doc
|
32
|
+
if ((await _col.get(_key)).found) {
|
33
|
+
update = true
|
34
|
+
res_doc = await _col.update(_key, _val)
|
35
|
+
} else {
|
36
|
+
res_doc = await _col.insert(_key, _val)
|
37
|
+
}
|
38
|
+
const res_col = await this.updateDB(_col, col)
|
39
|
+
return { update, doc: res_doc, col: res_col, tree: _col.tree }
|
40
|
+
}
|
41
|
+
async updateDB(_col, col) {
|
42
|
+
const root = _col.tree.F.toObject(_col.tree.root).toString()
|
43
|
+
const colD = str2id(col)
|
44
|
+
return await this.tree.update(colD, [root])
|
45
|
+
}
|
46
|
+
async update(col, _key, _val) {
|
47
|
+
const _col = this.getColTree(col)
|
48
|
+
const res_doc = await _col.update(_key, _val)
|
49
|
+
const res_col = await this.updateDB(_col, col)
|
50
|
+
return { doc: res_doc, col: res_col, tree: _col.tree }
|
51
|
+
}
|
52
|
+
|
53
|
+
async delete(col, _key) {
|
54
|
+
const _col = this.getColTree(col)
|
55
|
+
const res_doc = await _col.delete(_key)
|
56
|
+
const res_col = await this.updateDB(_col, col)
|
57
|
+
return { doc: res_doc, col: res_col, tree: _col.tree }
|
58
|
+
}
|
59
|
+
|
60
|
+
async get(col, _key) {
|
61
|
+
const _col = this.getColTree(col)
|
62
|
+
return await _col.get(_key)
|
63
|
+
}
|
64
|
+
async getCol(_key) {
|
65
|
+
const id = str2id(_key)
|
66
|
+
return await this.tree.find(id)
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
module.exports = DB
|
package/encoder.js
ADDED
@@ -0,0 +1,458 @@
|
|
1
|
+
const { splitEvery, flatten } = require("ramda")
|
2
|
+
const base64Map = {
|
3
|
+
A: "00",
|
4
|
+
B: "01",
|
5
|
+
C: "02",
|
6
|
+
D: "03",
|
7
|
+
E: "04",
|
8
|
+
F: "05",
|
9
|
+
G: "06",
|
10
|
+
H: "07",
|
11
|
+
I: "08",
|
12
|
+
J: "09",
|
13
|
+
K: "10",
|
14
|
+
L: "11",
|
15
|
+
M: "12",
|
16
|
+
N: "13",
|
17
|
+
O: "14",
|
18
|
+
P: "15",
|
19
|
+
Q: "16",
|
20
|
+
R: "17",
|
21
|
+
S: "18",
|
22
|
+
T: "19",
|
23
|
+
U: "20",
|
24
|
+
V: "21",
|
25
|
+
W: "22",
|
26
|
+
X: "23",
|
27
|
+
Y: "24",
|
28
|
+
Z: "25",
|
29
|
+
a: "26",
|
30
|
+
b: "27",
|
31
|
+
c: "28",
|
32
|
+
d: "29",
|
33
|
+
e: "30",
|
34
|
+
f: "31",
|
35
|
+
g: "32",
|
36
|
+
h: "33",
|
37
|
+
i: "34",
|
38
|
+
j: "35",
|
39
|
+
k: "36",
|
40
|
+
l: "37",
|
41
|
+
m: "38",
|
42
|
+
n: "39",
|
43
|
+
o: "40",
|
44
|
+
p: "41",
|
45
|
+
q: "42",
|
46
|
+
r: "43",
|
47
|
+
s: "44",
|
48
|
+
t: "45",
|
49
|
+
u: "46",
|
50
|
+
v: "47",
|
51
|
+
w: "48",
|
52
|
+
x: "49",
|
53
|
+
y: "50",
|
54
|
+
z: "51",
|
55
|
+
0: "52",
|
56
|
+
1: "53",
|
57
|
+
2: "54",
|
58
|
+
3: "55",
|
59
|
+
4: "56",
|
60
|
+
5: "57",
|
61
|
+
6: "58",
|
62
|
+
7: "59",
|
63
|
+
8: "60",
|
64
|
+
9: "61",
|
65
|
+
"-": "62",
|
66
|
+
_: "63",
|
67
|
+
}
|
68
|
+
|
69
|
+
let strMap = {}
|
70
|
+
for (const k in base64Map) strMap[base64Map[k]] = k
|
71
|
+
|
72
|
+
function pad(arr, max = 0) {
|
73
|
+
arr = arr.map(n => n.toString())
|
74
|
+
for (let i = arr.length; i < max; i++) {
|
75
|
+
arr.push("0")
|
76
|
+
}
|
77
|
+
return arr
|
78
|
+
}
|
79
|
+
|
80
|
+
function encodePath(path) {
|
81
|
+
const parts = []
|
82
|
+
let str = ""
|
83
|
+
let num = 0
|
84
|
+
for (const s of path) {
|
85
|
+
if (num === 2 && !(s === "." || s === "[")) throw Error()
|
86
|
+
if (s === ".") {
|
87
|
+
if (num === 2) {
|
88
|
+
num = 0
|
89
|
+
} else {
|
90
|
+
parts.push(str)
|
91
|
+
str = ""
|
92
|
+
}
|
93
|
+
} else if (s === "[") {
|
94
|
+
if (num !== 2) {
|
95
|
+
if (str !== "" || parts.length > 0) parts.push(str)
|
96
|
+
str = ""
|
97
|
+
}
|
98
|
+
num = 1
|
99
|
+
} else if (s === "]") {
|
100
|
+
if (num !== 1) throw Error()
|
101
|
+
num = 2
|
102
|
+
if (str === "" || Number.isNaN(+str)) throw Error()
|
103
|
+
parts.push(+str)
|
104
|
+
str = ""
|
105
|
+
} else {
|
106
|
+
str += s
|
107
|
+
}
|
108
|
+
}
|
109
|
+
if (str !== "") parts.push(str)
|
110
|
+
if (parts.length === 0) parts.push("")
|
111
|
+
let encoded = [parts.length]
|
112
|
+
for (const p of parts) {
|
113
|
+
if (typeof p === "number") {
|
114
|
+
encoded = encoded.concat([0, 0, p])
|
115
|
+
} else {
|
116
|
+
let plen = [p.length]
|
117
|
+
if (p.length === 0) plen.push(1)
|
118
|
+
encoded = encoded.concat([
|
119
|
+
...plen,
|
120
|
+
...p.split("").map(c => c.charCodeAt(0)),
|
121
|
+
])
|
122
|
+
}
|
123
|
+
}
|
124
|
+
return encoded
|
125
|
+
}
|
126
|
+
|
127
|
+
function decodePath(path) {
|
128
|
+
let str = ""
|
129
|
+
let p = []
|
130
|
+
let len = path.shift()
|
131
|
+
while (path.length > 0) {
|
132
|
+
const type = path.shift()
|
133
|
+
let val = null
|
134
|
+
if (type === 0) {
|
135
|
+
const type2 = path.shift()
|
136
|
+
if (type2 === 0) {
|
137
|
+
val = [type2, path.shift()]
|
138
|
+
} else {
|
139
|
+
val = [type2]
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
val = []
|
143
|
+
for (let i = 0; i < type; i++) {
|
144
|
+
val.push(path.shift())
|
145
|
+
}
|
146
|
+
}
|
147
|
+
p.push([type, ...val])
|
148
|
+
}
|
149
|
+
let i = 0
|
150
|
+
for (let s of p) {
|
151
|
+
if (s[0] === 0 && s[1] === 0) {
|
152
|
+
str += `[${s[2]}]`
|
153
|
+
} else if (s[0] === 0 && s[1] === 1) {
|
154
|
+
if (str !== "") str += "."
|
155
|
+
} else {
|
156
|
+
str += `${i === 0 ? "" : "."}${s
|
157
|
+
.slice(1)
|
158
|
+
.map(c => String.fromCharCode(c))
|
159
|
+
.join("")}`
|
160
|
+
}
|
161
|
+
i++
|
162
|
+
}
|
163
|
+
return str
|
164
|
+
}
|
165
|
+
|
166
|
+
function flattenPath(path) {
|
167
|
+
let p = [path.length]
|
168
|
+
for (const v of path) {
|
169
|
+
p = p.concat(v)
|
170
|
+
}
|
171
|
+
return p
|
172
|
+
}
|
173
|
+
|
174
|
+
function _encode(v, path = []) {
|
175
|
+
let vals = []
|
176
|
+
if (typeof v === "number") {
|
177
|
+
vals.push([path, encodeVal(v)])
|
178
|
+
} else if (typeof v === "boolean") {
|
179
|
+
vals.push([path, encodeVal(v)])
|
180
|
+
} else if (v === null) {
|
181
|
+
vals.push([path, encodeVal(v)])
|
182
|
+
} else if (typeof v === "string") {
|
183
|
+
vals.push([path, encodeVal(v)])
|
184
|
+
} else if (Array.isArray(v)) {
|
185
|
+
let i = 0
|
186
|
+
for (const v2 of v) {
|
187
|
+
for (const v3 of _encode(v2, [...path, [0, 0, i]])) vals.push(v3)
|
188
|
+
i++
|
189
|
+
}
|
190
|
+
} else if (typeof v === "object") {
|
191
|
+
for (const k in v) {
|
192
|
+
const key = k.split("").map(c => c.charCodeAt(0))
|
193
|
+
for (let v4 of _encode(v[k], [
|
194
|
+
...path,
|
195
|
+
[key.length, ...(key.length === 0 ? [1] : key)],
|
196
|
+
])) {
|
197
|
+
vals.push(v4)
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
return vals
|
202
|
+
}
|
203
|
+
|
204
|
+
function encode(json) {
|
205
|
+
let flattened = _encode(json)
|
206
|
+
|
207
|
+
flattened.sort((a, b) => {
|
208
|
+
const isUndefined = v => typeof v === "undefined"
|
209
|
+
const max = Math.max(a[0].length, b[0].length)
|
210
|
+
if (max > 0) {
|
211
|
+
for (let i = 0; i < max; i++) {
|
212
|
+
const exA = !isUndefined(a[0][i])
|
213
|
+
const exB = !isUndefined(b[0][i])
|
214
|
+
if (exA && !exB) return 1
|
215
|
+
if (!exA && exB) return -1
|
216
|
+
const max2 = Math.max(a[0][i].length, b[0][i].length)
|
217
|
+
if (max2 > 0) {
|
218
|
+
for (let i2 = 0; i2 < max2; i2++) {
|
219
|
+
const vA = a[0][i][i2]
|
220
|
+
const vB = b[0][i][i2]
|
221
|
+
const exA = !isUndefined(vA)
|
222
|
+
const exB = !isUndefined(vB)
|
223
|
+
if (exA && !exB) return 1
|
224
|
+
if (!exA && exB) return -1
|
225
|
+
if (vA > vB) return 1
|
226
|
+
if (vA < vB) return -1
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
return 0
|
232
|
+
})
|
233
|
+
|
234
|
+
return flattened.reduce(
|
235
|
+
(arr, v) => arr.concat([...flattenPath(v[0]), ...v[1]]),
|
236
|
+
[]
|
237
|
+
)
|
238
|
+
}
|
239
|
+
|
240
|
+
function _decode(arr) {
|
241
|
+
let vals = []
|
242
|
+
while (arr.length > 0) {
|
243
|
+
let plen = arr.shift()
|
244
|
+
let keys = []
|
245
|
+
let val = null
|
246
|
+
while (plen > 0) {
|
247
|
+
const plen2 = arr.shift()
|
248
|
+
if (plen2 === 0) {
|
249
|
+
const plen3 = arr.shift()
|
250
|
+
if (plen3 === 1) {
|
251
|
+
keys.push([plen2, plen3])
|
252
|
+
} else {
|
253
|
+
keys.push([plen2, plen3, arr.shift()])
|
254
|
+
}
|
255
|
+
} else if (plen2 !== 0) {
|
256
|
+
const plen3 = plen2
|
257
|
+
const key = []
|
258
|
+
for (let i2 = 0; i2 < plen3; i2++) key.push(arr.shift())
|
259
|
+
keys.push([plen2, ...key])
|
260
|
+
}
|
261
|
+
plen--
|
262
|
+
}
|
263
|
+
const type = arr.shift()
|
264
|
+
val = [type]
|
265
|
+
if (type === 2) {
|
266
|
+
val.push(arr.shift())
|
267
|
+
val.push(arr.shift())
|
268
|
+
val.push(arr.shift())
|
269
|
+
} else if (type === 1) {
|
270
|
+
val.push(arr.shift())
|
271
|
+
} else if (type === 3) {
|
272
|
+
const strlen = arr.shift()
|
273
|
+
val.push(strlen)
|
274
|
+
for (let i2 = 0; i2 < strlen; i2++) val.push(arr.shift())
|
275
|
+
}
|
276
|
+
vals.push([keys, val])
|
277
|
+
}
|
278
|
+
return vals
|
279
|
+
}
|
280
|
+
|
281
|
+
function encodeVal(v) {
|
282
|
+
let vals = []
|
283
|
+
if (typeof v === "number") {
|
284
|
+
const int = Number.isInteger(v)
|
285
|
+
let moved = 0
|
286
|
+
let num = v
|
287
|
+
while (num % 1 !== 0) {
|
288
|
+
num *= 10
|
289
|
+
moved += 1
|
290
|
+
}
|
291
|
+
vals = v < 0 ? [2, 0, moved, -num] : [2, 1, moved, num]
|
292
|
+
} else if (typeof v === "boolean") {
|
293
|
+
vals = [1, v ? 1 : 0]
|
294
|
+
} else if (v === null) {
|
295
|
+
vals = [0]
|
296
|
+
} else if (typeof v === "string") {
|
297
|
+
vals = [3, v.length, ...v.split("").map(c => c.charCodeAt(0))]
|
298
|
+
}
|
299
|
+
return vals
|
300
|
+
}
|
301
|
+
|
302
|
+
function decodeVal(arr) {
|
303
|
+
const type = arr[0]
|
304
|
+
const _val = arr[1]
|
305
|
+
let val = null
|
306
|
+
if (type === 0) {
|
307
|
+
val = null
|
308
|
+
} else if (type === 1) {
|
309
|
+
val = arr[1] ? true : false
|
310
|
+
} else if (type === 2) {
|
311
|
+
val = (arr[1] === 0 ? -1 : 1) * arr[3]
|
312
|
+
for (let i = 0; i < arr[2]; i++) {
|
313
|
+
val /= 10
|
314
|
+
}
|
315
|
+
} else if (type === 3) {
|
316
|
+
val = arr
|
317
|
+
.slice(2)
|
318
|
+
.map(c => String.fromCharCode(c))
|
319
|
+
.join("")
|
320
|
+
}
|
321
|
+
return val
|
322
|
+
}
|
323
|
+
|
324
|
+
function decode(arr) {
|
325
|
+
const decoded = _decode(arr)
|
326
|
+
let json =
|
327
|
+
decoded[0]?.[0]?.[0]?.[0] === 0 && decoded[0]?.[0]?.[0]?.[1] === 0 ? [] : {}
|
328
|
+
for (const v of decoded) {
|
329
|
+
const keys = v[0].map(v2 => {
|
330
|
+
if (v2[0] === 0) {
|
331
|
+
if (v2[1] === 1) return ""
|
332
|
+
return v2[2]
|
333
|
+
} else {
|
334
|
+
return v2
|
335
|
+
.slice(1)
|
336
|
+
.map(c => String.fromCharCode(c))
|
337
|
+
.join("")
|
338
|
+
}
|
339
|
+
})
|
340
|
+
if (keys.length === 0) {
|
341
|
+
json = decodeVal(v[1])
|
342
|
+
} else {
|
343
|
+
let obj = json
|
344
|
+
let i = 0
|
345
|
+
for (const k of keys) {
|
346
|
+
if (typeof k === "number") {
|
347
|
+
if (typeof keys[i + 1] === "undefined") {
|
348
|
+
obj[k] = decodeVal(v[1])
|
349
|
+
} else {
|
350
|
+
if (typeof obj[k] === "undefined") {
|
351
|
+
if (typeof keys[i + 1] === "string") {
|
352
|
+
obj[k] = {}
|
353
|
+
} else {
|
354
|
+
obj[k] = []
|
355
|
+
}
|
356
|
+
}
|
357
|
+
}
|
358
|
+
} else {
|
359
|
+
if (typeof obj[k] === "undefined") {
|
360
|
+
if (typeof keys[i + 1] === "undefined") {
|
361
|
+
obj[k] = decodeVal(v[1])
|
362
|
+
} else if (typeof keys[i + 1] === "string") {
|
363
|
+
obj[k] = {}
|
364
|
+
} else {
|
365
|
+
obj[k] = []
|
366
|
+
}
|
367
|
+
}
|
368
|
+
}
|
369
|
+
obj = obj[k]
|
370
|
+
i++
|
371
|
+
}
|
372
|
+
}
|
373
|
+
}
|
374
|
+
return json
|
375
|
+
}
|
376
|
+
|
377
|
+
const str2id = str => {
|
378
|
+
return (
|
379
|
+
"1" +
|
380
|
+
str
|
381
|
+
.split("")
|
382
|
+
.map(s => base64Map[s])
|
383
|
+
.join("")
|
384
|
+
)
|
385
|
+
}
|
386
|
+
|
387
|
+
const id2str = id => {
|
388
|
+
id.shift()
|
389
|
+
return splitEvery(2, id)
|
390
|
+
.map(s => strMap[s])
|
391
|
+
.join("")
|
392
|
+
}
|
393
|
+
|
394
|
+
function val2str(arr) {
|
395
|
+
const _arr = flatten(
|
396
|
+
arr.map(n => {
|
397
|
+
let str = splitEvery(8, n.toString().split(""))
|
398
|
+
let i = 0
|
399
|
+
str = str.map(s => {
|
400
|
+
const len = i === str.length - 1 ? s.length : 9
|
401
|
+
i++
|
402
|
+
return len.toString() + s.join("")
|
403
|
+
})
|
404
|
+
return str
|
405
|
+
})
|
406
|
+
)
|
407
|
+
let arrs = []
|
408
|
+
let len = 0
|
409
|
+
let str = ""
|
410
|
+
for (let v of _arr) {
|
411
|
+
if (len + v.length > 76) {
|
412
|
+
len = 0
|
413
|
+
arrs.push(str)
|
414
|
+
str = ""
|
415
|
+
}
|
416
|
+
len += v.length
|
417
|
+
str += v
|
418
|
+
}
|
419
|
+
if (str !== "") arrs.push(str)
|
420
|
+
return arrs
|
421
|
+
}
|
422
|
+
|
423
|
+
function str2val(arr) {
|
424
|
+
let _arr = []
|
425
|
+
let prev = ""
|
426
|
+
for (const s of arr) {
|
427
|
+
let str = s.split("")
|
428
|
+
while (str.length > 0) {
|
429
|
+
const len = +str.shift()
|
430
|
+
if (len === 9) {
|
431
|
+
prev += str.slice(0, 8).join("")
|
432
|
+
str = str.slice(8)
|
433
|
+
} else {
|
434
|
+
const nums = str.slice(0, len).join("")
|
435
|
+
str = str.slice(len)
|
436
|
+
_arr.push(+(prev + nums))
|
437
|
+
prev = ""
|
438
|
+
}
|
439
|
+
}
|
440
|
+
}
|
441
|
+
return _arr
|
442
|
+
}
|
443
|
+
|
444
|
+
module.exports = {
|
445
|
+
encode,
|
446
|
+
decode,
|
447
|
+
encodePath,
|
448
|
+
decodePath,
|
449
|
+
encodeVal,
|
450
|
+
decodeVal,
|
451
|
+
pad,
|
452
|
+
_encode,
|
453
|
+
flattenPath,
|
454
|
+
str2id,
|
455
|
+
val2str,
|
456
|
+
str2val,
|
457
|
+
id2str,
|
458
|
+
}
|
package/index.js
ADDED