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/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
@@ -0,0 +1,5 @@
1
+ const encoder = require("./encoder")
2
+ const DB = require("./db")
3
+ const Collection = require("./collection")
4
+
5
+ module.exports = { ...encoder, DB, Collection }
package/package.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "zkjson",
3
+ "version": "0.1.0",
4
+ "description": "Zero Knowledge Provable JSON",
5
+ "main": "index.js",
6
+ "license": "MIT"
7
+ }