@absolutejs/sync-capacitor 0.6.1 → 0.8.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/dist/index.js CHANGED
@@ -7,9 +7,595 @@ import {
7
7
  createSyncLocalSchemaStatus,
8
8
  migrateSyncLocalCollectionRecord,
9
9
  migrateSyncLocalMutationRecord,
10
- resolveSyncLocalSchemaComponents
10
+ resolveSyncLocalDataPolicy,
11
+ resolveSyncLocalSchemaComponents,
12
+ runSyncLocalPolicyTransaction
11
13
  } from "@absolutejs/sync/client";
12
14
  import { registerPlugin } from "@capacitor/core";
15
+ import { createCapacitorSecureStorage } from "@absolutejs/devices-capacitor";
16
+
17
+ // ../node_modules/.bun/@noble+ciphers@2.3.0/node_modules/@noble/ciphers/utils.js
18
+ /*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */
19
+ function isBytes(a) {
20
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
21
+ }
22
+ var atitle = (title) => title ? `"${title}" ` : "";
23
+ function abool(value, title = "") {
24
+ if (typeof value !== "boolean")
25
+ throw new TypeError(atitle(title) + "expected boolean, got type=" + typeof value);
26
+ return value;
27
+ }
28
+ function anumber(n, title = "") {
29
+ if (typeof n !== "number")
30
+ throw new TypeError(atitle(title) + "expected number, got " + typeof n);
31
+ if (!Number.isSafeInteger(n) || n < 0)
32
+ throw new RangeError(atitle(title) + "expected integer >= 0, got " + n);
33
+ return n;
34
+ }
35
+ function abytes(value, length, title = "") {
36
+ if (isBytes(value) && (length === undefined || value.length === length))
37
+ return value;
38
+ if (length !== undefined)
39
+ anumber(length, "length");
40
+ const bytes = isBytes(value);
41
+ const ofLen = length !== undefined ? ` of length ${length}` : "";
42
+ const got = bytes ? `length=${value.length}` : `type=${typeof value}`;
43
+ const message = atitle(title) + "expected Uint8Array" + ofLen + ", got " + got;
44
+ if (!bytes)
45
+ throw new TypeError(message);
46
+ throw new RangeError(message);
47
+ }
48
+ function aexists(instance, checkFinished = true) {
49
+ if (instance.destroyed)
50
+ throw new Error("hash was destroyed");
51
+ if (checkFinished && instance.finished)
52
+ throw new Error("digest() was already called");
53
+ }
54
+ function aoutput(out, instance) {
55
+ abytes(out, undefined, "output");
56
+ const min = instance.outputLen;
57
+ if (!(out.length >= min)) {
58
+ throw new RangeError('"output" expected length >= ' + min);
59
+ }
60
+ }
61
+ function aoutput32(out, instance) {
62
+ aoutput(out, instance);
63
+ if (!isAligned32(out))
64
+ throw new Error("invalid output, must be aligned");
65
+ }
66
+ function u8(arr) {
67
+ return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
68
+ }
69
+ function u32(arr) {
70
+ return new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
71
+ }
72
+ function clean(...arrays) {
73
+ for (let i = 0;i < arrays.length; i++) {
74
+ arrays[i].fill(0);
75
+ }
76
+ }
77
+ function createView(arr) {
78
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
79
+ }
80
+ var isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
81
+ function byteSwap(word) {
82
+ return word << 24 & 4278190080 | word << 8 & 16711680 | word >>> 8 & 65280 | word >>> 24 & 255;
83
+ }
84
+ var swap8IfBE = isLE ? (n) => n : (n) => byteSwap(n) >>> 0;
85
+ function byteSwap32(arr) {
86
+ for (let i = 0;i < arr.length; i++) {
87
+ arr[i] = byteSwap(arr[i]);
88
+ }
89
+ return arr;
90
+ }
91
+ var swap32IfBE = isLE ? (u) => u : byteSwap32;
92
+ function equalBytes(a, b) {
93
+ a = abytes(a);
94
+ b = abytes(b);
95
+ if (a.length !== b.length)
96
+ return false;
97
+ let diff = 0;
98
+ for (let i = 0;i < a.length; i++)
99
+ diff |= a[i] ^ b[i];
100
+ return diff === 0;
101
+ }
102
+ function wrapMacConstructor(keyLen, macCons, fromMsg) {
103
+ const mac = macCons;
104
+ const getArgs = fromMsg || (() => []);
105
+ const macC = (msg, key) => mac(key, ...getArgs(msg)).update(msg).digest();
106
+ const tmp = mac(new Uint8Array(keyLen), ...getArgs(new Uint8Array(0)));
107
+ macC.outputLen = tmp.outputLen;
108
+ macC.blockLen = tmp.blockLen;
109
+ macC.create = (key, ...args) => mac(key, ...args);
110
+ return macC;
111
+ }
112
+ var wrapCipher = (params, constructor) => {
113
+ function wrappedCipher(key, ...args) {
114
+ abytes(key, undefined, "key");
115
+ if (params.nonceLength !== undefined) {
116
+ const nonce = args[0];
117
+ abytes(nonce, params.varSizeNonce ? undefined : params.nonceLength, "nonce");
118
+ }
119
+ const tagl = params.tagLength;
120
+ const aadStart = params.nonceLength !== undefined ? 1 : 0;
121
+ if (!params.withAAD) {
122
+ for (let i = aadStart;i < args.length; i++)
123
+ if (isBytes(args[i]))
124
+ throw new Error("AAD not supported");
125
+ }
126
+ if (params.withAAD && args[aadStart] !== undefined)
127
+ abytes(args[aadStart], undefined, "AAD");
128
+ const cipher = constructor(key, ...args);
129
+ const checkOutput = (fnLength, output) => {
130
+ if (output !== undefined) {
131
+ if (fnLength !== 2)
132
+ throw new Error("cipher output not supported");
133
+ abytes(output, undefined, "output");
134
+ }
135
+ };
136
+ let called = false;
137
+ const wrCipher = {
138
+ encrypt(data, output) {
139
+ if (called)
140
+ throw new Error("cannot encrypt() twice with same key + nonce");
141
+ called = true;
142
+ abytes(data, undefined, "data");
143
+ checkOutput(cipher.encrypt.length, output);
144
+ return cipher.encrypt(data, output);
145
+ },
146
+ decrypt(data, output) {
147
+ abytes(data, undefined, "data");
148
+ if (tagl && data.length < tagl)
149
+ throw new Error('"ciphertext" expected length >= tagLength=' + tagl);
150
+ checkOutput(cipher.decrypt.length, output);
151
+ return cipher.decrypt(data, output);
152
+ }
153
+ };
154
+ return wrCipher;
155
+ }
156
+ Object.assign(wrappedCipher, params);
157
+ return wrappedCipher;
158
+ };
159
+ function getOutput(expectedLength, out, onlyAligned = true) {
160
+ if (out === undefined)
161
+ return new Uint8Array(expectedLength);
162
+ abytes(out, expectedLength, "output");
163
+ if (onlyAligned && !isAligned32(out))
164
+ throw new Error("invalid output, must be aligned");
165
+ return out;
166
+ }
167
+ function u64Lengths(dataLength, aadLength, isLE2) {
168
+ anumber(dataLength);
169
+ anumber(aadLength);
170
+ abool(isLE2);
171
+ const num = new Uint8Array(16);
172
+ const view = createView(num);
173
+ view.setBigUint64(0, BigInt(aadLength), isLE2);
174
+ view.setBigUint64(8, BigInt(dataLength), isLE2);
175
+ return num;
176
+ }
177
+ function isAligned32(bytes) {
178
+ return bytes.byteOffset % 4 === 0;
179
+ }
180
+ function copyBytes(bytes) {
181
+ return Uint8Array.from(abytes(bytes));
182
+ }
183
+ function randomBytes(bytesLength = 32) {
184
+ anumber(bytesLength, "bytesLength");
185
+ const cr = typeof globalThis === "object" ? globalThis.crypto : null;
186
+ if (typeof cr?.getRandomValues !== "function")
187
+ throw new Error("crypto.getRandomValues must be defined");
188
+ if (bytesLength > 65536)
189
+ throw new RangeError(`"bytesLength" expected <= 65536, got ${bytesLength}`);
190
+ return cr.getRandomValues(new Uint8Array(bytesLength));
191
+ }
192
+
193
+ // ../node_modules/.bun/@noble+ciphers@2.3.0/node_modules/@noble/ciphers/_polyval.js
194
+ var BLOCK_SIZE = 16;
195
+ var ZEROS16 = /* @__PURE__ */ new Uint8Array(16);
196
+ var ZEROS32 = /* @__PURE__ */ u32(ZEROS16);
197
+ var POLY = 225;
198
+ var mul2 = (s0, s1, s2, s3) => {
199
+ const hiBit = s3 & 1;
200
+ return {
201
+ s3: s2 << 31 | s3 >>> 1,
202
+ s2: s1 << 31 | s2 >>> 1,
203
+ s1: s0 << 31 | s1 >>> 1,
204
+ s0: s0 >>> 1 ^ POLY << 24 & -(hiBit & 1)
205
+ };
206
+ };
207
+ var swapLE = (n) => (n >>> 0 & 255) << 24 | (n >>> 8 & 255) << 16 | (n >>> 16 & 255) << 8 | n >>> 24 & 255 | 0;
208
+ var estimateWindow = (bytes) => {
209
+ if (bytes > 64 * 1024)
210
+ return 8;
211
+ if (bytes > 1024)
212
+ return 4;
213
+ return 2;
214
+ };
215
+
216
+ class GHASH {
217
+ blockLen = BLOCK_SIZE;
218
+ outputLen = BLOCK_SIZE;
219
+ s0 = 0;
220
+ s1 = 0;
221
+ s2 = 0;
222
+ s3 = 0;
223
+ finished = false;
224
+ destroyed = false;
225
+ t;
226
+ W;
227
+ windowSize;
228
+ constructor(key, expectedLength) {
229
+ abytes(key, 16, "key");
230
+ key = copyBytes(key);
231
+ const kView = createView(key);
232
+ let k0 = kView.getUint32(0, false);
233
+ let k1 = kView.getUint32(4, false);
234
+ let k2 = kView.getUint32(8, false);
235
+ let k3 = kView.getUint32(12, false);
236
+ const doubles = [];
237
+ for (let i = 0;i < 128; i++) {
238
+ doubles.push({ s0: swapLE(k0), s1: swapLE(k1), s2: swapLE(k2), s3: swapLE(k3) });
239
+ ({ s0: k0, s1: k1, s2: k2, s3: k3 } = mul2(k0, k1, k2, k3));
240
+ }
241
+ const W = estimateWindow(expectedLength || 1024);
242
+ if (![1, 2, 4, 8].includes(W))
243
+ throw new Error("ghash: invalid window size, expected 2, 4 or 8");
244
+ this.W = W;
245
+ const bits = 128;
246
+ const windows = bits / W;
247
+ const windowSize = this.windowSize = 2 ** W;
248
+ const items = [];
249
+ for (let w = 0;w < windows; w++) {
250
+ for (let byte = 0;byte < windowSize; byte++) {
251
+ let s0 = 0, s1 = 0, s2 = 0, s3 = 0;
252
+ for (let j = 0;j < W; j++) {
253
+ const bit = byte >>> W - j - 1 & 1;
254
+ if (!bit)
255
+ continue;
256
+ const { s0: d0, s1: d1, s2: d2, s3: d3 } = doubles[W * w + j];
257
+ s0 ^= d0, s1 ^= d1, s2 ^= d2, s3 ^= d3;
258
+ }
259
+ items.push({ s0, s1, s2, s3 });
260
+ }
261
+ }
262
+ this.t = items;
263
+ }
264
+ _updateBlock(s0, s1, s2, s3) {
265
+ s0 ^= this.s0, s1 ^= this.s1, s2 ^= this.s2, s3 ^= this.s3;
266
+ const { W, t, windowSize } = this;
267
+ let o0 = 0, o1 = 0, o2 = 0, o3 = 0;
268
+ const mask = (1 << W) - 1;
269
+ let w = 0;
270
+ for (const num of [s0, s1, s2, s3]) {
271
+ for (let bytePos = 0;bytePos < 4; bytePos++) {
272
+ const byte = num >>> 8 * bytePos & 255;
273
+ for (let bitPos = 8 / W - 1;bitPos >= 0; bitPos--) {
274
+ const bit = byte >>> W * bitPos & mask;
275
+ const { s0: e0, s1: e1, s2: e2, s3: e3 } = t[w * windowSize + bit];
276
+ o0 ^= e0, o1 ^= e1, o2 ^= e2, o3 ^= e3;
277
+ w += 1;
278
+ }
279
+ }
280
+ }
281
+ this.s0 = o0;
282
+ this.s1 = o1;
283
+ this.s2 = o2;
284
+ this.s3 = o3;
285
+ }
286
+ update(data) {
287
+ aexists(this);
288
+ abytes(data);
289
+ data = copyBytes(data);
290
+ const b32 = u32(data);
291
+ const blocks = Math.floor(data.length / BLOCK_SIZE);
292
+ const left = data.length % BLOCK_SIZE;
293
+ for (let i = 0;i < blocks; i++) {
294
+ this._updateBlock(swap8IfBE(b32[i * 4 + 0]), swap8IfBE(b32[i * 4 + 1]), swap8IfBE(b32[i * 4 + 2]), swap8IfBE(b32[i * 4 + 3]));
295
+ }
296
+ if (left) {
297
+ ZEROS16.set(data.subarray(blocks * BLOCK_SIZE));
298
+ this._updateBlock(swap8IfBE(ZEROS32[0]), swap8IfBE(ZEROS32[1]), swap8IfBE(ZEROS32[2]), swap8IfBE(ZEROS32[3]));
299
+ clean(ZEROS32);
300
+ }
301
+ return this;
302
+ }
303
+ destroy() {
304
+ this.destroyed = true;
305
+ const { t } = this;
306
+ for (const elm of t) {
307
+ elm.s0 = 0, elm.s1 = 0, elm.s2 = 0, elm.s3 = 0;
308
+ }
309
+ }
310
+ digestInto(out) {
311
+ aexists(this);
312
+ aoutput32(out, this);
313
+ this.finished = true;
314
+ const { s0, s1, s2, s3 } = this;
315
+ const o32 = u32(out);
316
+ o32[0] = s0;
317
+ o32[1] = s1;
318
+ o32[2] = s2;
319
+ o32[3] = s3;
320
+ if (!isLE)
321
+ swap32IfBE(o32.subarray(0, BLOCK_SIZE / 4));
322
+ }
323
+ digest() {
324
+ const res = new Uint8Array(BLOCK_SIZE);
325
+ this.digestInto(res);
326
+ this.destroy();
327
+ return res;
328
+ }
329
+ }
330
+ var ghash = /* @__PURE__ */ wrapMacConstructor(16, (key, expectedLength) => new GHASH(key, expectedLength), (msg) => [msg.length]);
331
+
332
+ // ../node_modules/.bun/@noble+ciphers@2.3.0/node_modules/@noble/ciphers/aes.js
333
+ var BLOCK_SIZE2 = 16;
334
+ var BLOCK_SIZE32 = 4;
335
+ var EMPTY_BLOCK = /* @__PURE__ */ new Uint8Array(BLOCK_SIZE2);
336
+ var POLY2 = 283;
337
+ function validateKeyLength(key) {
338
+ if (![16, 24, 32].includes(key.length))
339
+ throw new Error('"aes key" expected Uint8Array of length 16/24/32, got length=' + key.length);
340
+ }
341
+ function mul22(n) {
342
+ return n << 1 ^ POLY2 & -(n >> 7);
343
+ }
344
+ function mul(a, b) {
345
+ let res = 0;
346
+ for (;b > 0; b >>= 1) {
347
+ res ^= a & -(b & 1);
348
+ a = mul22(a);
349
+ }
350
+ return res;
351
+ }
352
+ var sbox = /* @__PURE__ */ (() => {
353
+ const t = new Uint8Array(256);
354
+ for (let i = 0, x = 1;i < 256; i++, x ^= mul22(x))
355
+ t[i] = x;
356
+ const box = new Uint8Array(256);
357
+ box[0] = 99;
358
+ for (let i = 0;i < 255; i++) {
359
+ let x = t[255 - i];
360
+ x |= x << 8;
361
+ box[t[i]] = (x ^ x >> 4 ^ x >> 5 ^ x >> 6 ^ x >> 7 ^ 99) & 255;
362
+ }
363
+ clean(t);
364
+ return box;
365
+ })();
366
+ var rotr32_8 = (n) => n << 24 | n >>> 8;
367
+ var rotl32_8 = (n) => n << 8 | n >>> 24;
368
+ function genTtable(sbox2, fn) {
369
+ if (sbox2.length !== 256)
370
+ throw new Error("wrong sbox length");
371
+ const T0 = new Uint32Array(256).map((_, j) => fn(sbox2[j]));
372
+ const T1 = T0.map(rotl32_8);
373
+ const T2 = T1.map(rotl32_8);
374
+ const T3 = T2.map(rotl32_8);
375
+ const T01 = new Uint32Array(256 * 256);
376
+ const T23 = new Uint32Array(256 * 256);
377
+ const sbox22 = new Uint16Array(256 * 256);
378
+ for (let i = 0;i < 256; i++) {
379
+ for (let j = 0;j < 256; j++) {
380
+ const idx = i * 256 + j;
381
+ T01[idx] = T0[i] ^ T1[j];
382
+ T23[idx] = T2[i] ^ T3[j];
383
+ sbox22[idx] = sbox2[i] << 8 | sbox2[j];
384
+ }
385
+ }
386
+ return { sbox: sbox2, sbox2: sbox22, T0, T1, T2, T3, T01, T23 };
387
+ }
388
+ var tableEncoding = /* @__PURE__ */ genTtable(sbox, (s) => mul(s, 3) << 24 | s << 16 | s << 8 | mul(s, 2));
389
+ var xPowers = /* @__PURE__ */ (() => {
390
+ const p = new Uint8Array(16);
391
+ for (let i = 0, x = 1;i < 16; i++, x = mul22(x))
392
+ p[i] = x;
393
+ return p;
394
+ })();
395
+ function expandKeyLE(key) {
396
+ abytes(key);
397
+ const len = key.length;
398
+ validateKeyLength(key);
399
+ const { sbox2 } = tableEncoding;
400
+ const toClean = [];
401
+ if (!isLE || !isAligned32(key))
402
+ toClean.push(key = copyBytes(key));
403
+ const k32 = swap32IfBE(u32(key));
404
+ const Nk = k32.length;
405
+ const subByte = (n) => applySbox(sbox2, n, n, n, n);
406
+ const xk = new Uint32Array(len + 28);
407
+ xk.set(k32);
408
+ for (let i = Nk;i < xk.length; i++) {
409
+ let t = xk[i - 1];
410
+ if (i % Nk === 0)
411
+ t = subByte(rotr32_8(t)) ^ xPowers[i / Nk - 1];
412
+ else if (Nk > 6 && i % Nk === 4)
413
+ t = subByte(t);
414
+ xk[i] = xk[i - Nk] ^ t;
415
+ }
416
+ clean(...toClean);
417
+ return xk;
418
+ }
419
+ function apply0123(T01, T23, s0, s1, s2, s3) {
420
+ return T01[s0 << 8 & 65280 | s1 >>> 8 & 255] ^ T23[s2 >>> 8 & 65280 | s3 >>> 24 & 255];
421
+ }
422
+ function applySbox(sbox2, s0, s1, s2, s3) {
423
+ return sbox2[s0 & 255 | s1 & 65280] | sbox2[s2 >>> 16 & 255 | s3 >>> 16 & 65280] << 16;
424
+ }
425
+ function encrypt(xk, s0, s1, s2, s3) {
426
+ const { sbox2, T01, T23 } = tableEncoding;
427
+ let k = 0;
428
+ s0 ^= xk[k++], s1 ^= xk[k++], s2 ^= xk[k++], s3 ^= xk[k++];
429
+ const rounds = xk.length / 4 - 2;
430
+ for (let i = 0;i < rounds; i++) {
431
+ const t02 = xk[k++] ^ apply0123(T01, T23, s0, s1, s2, s3);
432
+ const t12 = xk[k++] ^ apply0123(T01, T23, s1, s2, s3, s0);
433
+ const t22 = xk[k++] ^ apply0123(T01, T23, s2, s3, s0, s1);
434
+ const t32 = xk[k++] ^ apply0123(T01, T23, s3, s0, s1, s2);
435
+ s0 = t02, s1 = t12, s2 = t22, s3 = t32;
436
+ }
437
+ const t0 = xk[k++] ^ applySbox(sbox2, s0, s1, s2, s3);
438
+ const t1 = xk[k++] ^ applySbox(sbox2, s1, s2, s3, s0);
439
+ const t2 = xk[k++] ^ applySbox(sbox2, s2, s3, s0, s1);
440
+ const t3 = xk[k++] ^ applySbox(sbox2, s3, s0, s1, s2);
441
+ return { s0: t0, s1: t1, s2: t2, s3: t3 };
442
+ }
443
+ function ctr32(xk, isLE2, nonce, src, dst) {
444
+ abytes(nonce, BLOCK_SIZE2, "nonce");
445
+ abytes(src);
446
+ dst = getOutput(src.length, dst);
447
+ const ctr = nonce;
448
+ const c32 = u32(ctr);
449
+ const view = createView(ctr);
450
+ const src32 = u32(src);
451
+ const dst32 = u32(dst);
452
+ const ctrPos = isLE2 ? 0 : 12;
453
+ const srcLen = src.length;
454
+ let ctrNum = view.getUint32(ctrPos, isLE2);
455
+ for (let i = 0;i + 4 <= src32.length; i += 4) {
456
+ const { s0, s1, s2, s3 } = encrypt(xk, swap8IfBE(c32[0]), swap8IfBE(c32[1]), swap8IfBE(c32[2]), swap8IfBE(c32[3]));
457
+ dst32[i + 0] = src32[i + 0] ^ swap8IfBE(s0);
458
+ dst32[i + 1] = src32[i + 1] ^ swap8IfBE(s1);
459
+ dst32[i + 2] = src32[i + 2] ^ swap8IfBE(s2);
460
+ dst32[i + 3] = src32[i + 3] ^ swap8IfBE(s3);
461
+ ctrNum = ctrNum + 1 >>> 0;
462
+ view.setUint32(ctrPos, ctrNum, isLE2);
463
+ }
464
+ const start = BLOCK_SIZE2 * Math.floor(src32.length / BLOCK_SIZE32);
465
+ if (start < srcLen) {
466
+ const { s0, s1, s2, s3 } = encrypt(xk, swap8IfBE(c32[0]), swap8IfBE(c32[1]), swap8IfBE(c32[2]), swap8IfBE(c32[3]));
467
+ const b32 = new Uint32Array([s0, s1, s2, s3]);
468
+ swap32IfBE(b32);
469
+ const buf = u8(b32);
470
+ for (let i = start, pos = 0;i < srcLen; i++, pos++)
471
+ dst[i] = src[i] ^ buf[pos];
472
+ clean(b32);
473
+ }
474
+ return dst;
475
+ }
476
+ function computeTag(fn, isLE2, key, data, AAD) {
477
+ const aadLength = AAD ? AAD.length : 0;
478
+ const h = fn.create(key, data.length + aadLength);
479
+ if (AAD)
480
+ h.update(AAD);
481
+ const num = u64Lengths(8 * data.length, 8 * aadLength, isLE2);
482
+ h.update(data);
483
+ h.update(num);
484
+ const res = h.digest();
485
+ clean(num);
486
+ return res;
487
+ }
488
+ var gcm = /* @__PURE__ */ wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16, withAAD: true, varSizeNonce: true }, function aesgcm(key, nonce, AAD) {
489
+ if (nonce.length < 8)
490
+ throw new Error("aes/gcm: invalid nonce length");
491
+ const tagLength = 16;
492
+ function _computeTag(authKey, tagMask, data) {
493
+ const tag = computeTag(ghash, false, authKey, data, AAD);
494
+ for (let i = 0;i < tagMask.length; i++)
495
+ tag[i] ^= tagMask[i];
496
+ return tag;
497
+ }
498
+ function deriveKeys() {
499
+ const xk = expandKeyLE(key);
500
+ const authKey = EMPTY_BLOCK.slice();
501
+ const counter = EMPTY_BLOCK.slice();
502
+ ctr32(xk, false, counter, counter, authKey);
503
+ if (nonce.length === 12) {
504
+ counter.set(nonce);
505
+ } else {
506
+ const nonceLen = EMPTY_BLOCK.slice();
507
+ const view = createView(nonceLen);
508
+ view.setBigUint64(8, BigInt(nonce.length * 8), false);
509
+ const g = ghash.create(authKey).update(nonce).update(nonceLen);
510
+ g.digestInto(counter);
511
+ g.destroy();
512
+ }
513
+ const tagMask = ctr32(xk, false, counter, EMPTY_BLOCK);
514
+ return { xk, authKey, counter, tagMask };
515
+ }
516
+ return {
517
+ encrypt(plaintext) {
518
+ const { xk, authKey, counter, tagMask } = deriveKeys();
519
+ const out = new Uint8Array(plaintext.length + tagLength);
520
+ const toClean = [xk, authKey, counter, tagMask];
521
+ if (!isAligned32(plaintext))
522
+ toClean.push(plaintext = copyBytes(plaintext));
523
+ ctr32(xk, false, counter, plaintext, out.subarray(0, plaintext.length));
524
+ const tag = _computeTag(authKey, tagMask, out.subarray(0, out.length - tagLength));
525
+ toClean.push(tag);
526
+ out.set(tag, plaintext.length);
527
+ clean(...toClean);
528
+ return out;
529
+ },
530
+ decrypt(ciphertext) {
531
+ const { xk, authKey, counter, tagMask } = deriveKeys();
532
+ const toClean = [xk, authKey, tagMask, counter];
533
+ if (!isAligned32(ciphertext))
534
+ toClean.push(ciphertext = copyBytes(ciphertext));
535
+ const data = ciphertext.subarray(0, -tagLength);
536
+ const passedTag = ciphertext.subarray(-tagLength);
537
+ const tag = _computeTag(authKey, tagMask, data);
538
+ toClean.push(tag);
539
+ if (!equalBytes(tag, passedTag)) {
540
+ clean(...toClean);
541
+ throw new Error("aes-gcm: invalid tag");
542
+ }
543
+ const out = ctr32(xk, false, counter, data);
544
+ clean(...toClean);
545
+ return out;
546
+ }
547
+ };
548
+ });
549
+
550
+ // src/index.ts
551
+ var textEncoder = new TextEncoder;
552
+ var textDecoder = new TextDecoder;
553
+ var base64 = (value) => {
554
+ let binary = "";
555
+ for (const byte of value)
556
+ binary += String.fromCharCode(byte);
557
+ return btoa(binary);
558
+ };
559
+ var unbase64 = (value) => Uint8Array.from(atob(value), (character) => character.charCodeAt(0));
560
+ var createCapacitorSyncProtection = (options = {}) => {
561
+ const storage = options.secureStorage ?? createCapacitorSecureStorage({ prefix: "absolutejs.sync." });
562
+ const keyName = "data-key.v1";
563
+ return {
564
+ prepare: async () => {
565
+ const capability = await storage.capability();
566
+ if (!capability.available)
567
+ throw new Error("Native Sync data protection requires persistent Keychain/Keystore storage.");
568
+ const load = async () => {
569
+ const existing = await storage.get(keyName);
570
+ if (existing)
571
+ return unbase64(existing);
572
+ const created = randomBytes(32);
573
+ await storage.set(keyName, base64(created));
574
+ return created;
575
+ };
576
+ const key = storage.withLock ? await storage.withLock(keyName, load) : await load();
577
+ if (key.byteLength !== 32)
578
+ throw new Error("Native Sync data-protection key is invalid.");
579
+ const additionalData = (context) => textEncoder.encode(`absolute-sync-v1\x00${context.kind}\x00${context.namespace}\x00${context.name}`);
580
+ return {
581
+ id: "aes-256-gcm-v1",
582
+ open: (value, context) => {
583
+ const bytes = unbase64(value);
584
+ const nonce = bytes.slice(0, 12);
585
+ return textDecoder.decode(gcm(key, nonce, additionalData(context)).decrypt(bytes.slice(12)));
586
+ },
587
+ seal: (value, context) => {
588
+ const nonce = randomBytes(12);
589
+ const encrypted = gcm(key, nonce, additionalData(context)).encrypt(textEncoder.encode(value));
590
+ const output = new Uint8Array(nonce.length + encrypted.length);
591
+ output.set(nonce);
592
+ output.set(encrypted, nonce.length);
593
+ return base64(output);
594
+ }
595
+ };
596
+ }
597
+ };
598
+ };
13
599
  var AbsoluteBackgroundSync = registerPlugin("AbsoluteBackgroundSync");
14
600
  var configureCapacitorBackgroundSync = (options, plugin = AbsoluteBackgroundSync) => plugin.configure(options);
15
601
  var SCHEMA = `
@@ -45,19 +631,36 @@ var firstString = (rows, field) => {
45
631
  const value = rows?.[0]?.[field];
46
632
  return typeof value === "string" ? value : undefined;
47
633
  };
48
- var parseRecord = (value, label) => {
634
+ var parseRecord = (value, label, context, protector) => {
49
635
  if (value === undefined)
50
636
  return;
51
637
  if (typeof value !== "string")
52
638
  throw new Error(`Capacitor Sync SQLite returned invalid ${label} JSON.`);
53
639
  try {
54
- return JSON.parse(value);
640
+ const parsed = JSON.parse(value);
641
+ if (typeof parsed === "object" && parsed !== null && "__absoluteSyncProtected" in parsed) {
642
+ const envelope = parsed.__absoluteSyncProtected;
643
+ if (!context || !protector || protector.id !== envelope.protector)
644
+ throw new Error(`Capacitor Sync ${label} requires unavailable protection provider "${envelope.protector}".`);
645
+ return JSON.parse(protector.open(envelope.value, {
646
+ ...context,
647
+ name: envelope.name
648
+ }));
649
+ }
650
+ return parsed;
55
651
  } catch (cause) {
56
652
  throw new Error(`Capacitor Sync SQLite could not parse ${label} JSON.`, {
57
653
  cause
58
654
  });
59
655
  }
60
656
  };
657
+ var serializeRecord = (value, context, protector) => protector ? JSON.stringify({
658
+ __absoluteSyncProtected: {
659
+ name: context.name,
660
+ protector: protector.id,
661
+ value: protector.seal(JSON.stringify(value), context)
662
+ }
663
+ }) : JSON.stringify(value);
61
664
  var defaultConnection = async (databaseName) => {
62
665
  const sqlite = new SQLiteConnection(CapacitorSQLite);
63
666
  const existing = await sqlite.isConnection(databaseName, false);
@@ -72,12 +675,17 @@ var requireNamespace = (namespace) => {
72
675
  var createCapacitorSyncLocalStore = ({
73
676
  databaseName = "absolutejs-sync-local-v1",
74
677
  connection: createConnection = () => defaultConnection(databaseName),
75
- storageSchema = { version: 1 }
678
+ storageSchema = { version: 1 },
679
+ protection,
680
+ now = Date.now
76
681
  } = {}) => {
77
682
  if (databaseName.length === 0)
78
683
  throw new TypeError("Capacitor Sync databaseName cannot be empty.");
684
+ const localData = resolveSyncLocalDataPolicy(storageSchema);
685
+ let protectorPromise;
686
+ const prepareProtector = () => protectorPromise ??= protection?.prepare();
79
687
  let schemaStatus;
80
- const prepareSchema = async (database) => {
688
+ const prepareSchema = async (database, protector) => {
81
689
  await database.beginTransaction();
82
690
  try {
83
691
  const legacySaved = (await database.query("SELECT logical_version FROM absolute_sync_schema WHERE singleton_id = 1 LIMIT 1")).values?.[0]?.logical_version;
@@ -99,14 +707,22 @@ var createCapacitorSyncLocalStore = ({
99
707
  const key = row.collection_key;
100
708
  if (typeof namespace !== "string" || typeof key !== "string")
101
709
  throw new Error("Capacitor Sync SQLite returned an invalid collection identity.");
102
- const record = parseRecord(row.record_json, "collection");
710
+ const record = parseRecord(row.record_json, "collection", { kind: "collection", namespace }, protector);
103
711
  if (record === undefined)
104
712
  throw new Error("Capacitor Sync SQLite returned a missing collection record.");
105
713
  const migrated = migrateSyncLocalCollectionRecord(record, { key, namespace }, steps);
106
714
  if (migrated === null)
107
715
  await database.run("DELETE FROM absolute_sync_collections WHERE namespace = ? AND collection_key = ?", [namespace, key], false);
108
716
  else
109
- await database.run("UPDATE absolute_sync_collections SET record_json = ? WHERE namespace = ? AND collection_key = ?", [JSON.stringify(migrated), namespace, key], false);
717
+ await database.run("UPDATE absolute_sync_collections SET record_json = ? WHERE namespace = ? AND collection_key = ?", [
718
+ serializeRecord(migrated, {
719
+ kind: "collection",
720
+ name: migrated.collection ?? key,
721
+ namespace
722
+ }, protector),
723
+ namespace,
724
+ key
725
+ ], false);
110
726
  }
111
727
  const mutations = (await database.query("SELECT namespace, operation_id, record_json FROM absolute_sync_mutations ORDER BY namespace, operation_id")).values;
112
728
  for (const row of mutations ?? []) {
@@ -114,7 +730,7 @@ var createCapacitorSyncLocalStore = ({
114
730
  const operationId = row.operation_id;
115
731
  if (typeof namespace !== "string" || typeof operationId !== "string")
116
732
  throw new Error("Capacitor Sync SQLite returned an invalid mutation identity.");
117
- const record = parseRecord(row.record_json, "mutation");
733
+ const record = parseRecord(row.record_json, "mutation", { kind: "mutation", namespace }, protector);
118
734
  if (record === undefined)
119
735
  throw new Error("Capacitor Sync SQLite returned a missing mutation record.");
120
736
  const migrated = migrateSyncLocalMutationRecord(record, { key: operationId, namespace }, steps);
@@ -123,7 +739,11 @@ var createCapacitorSyncLocalStore = ({
123
739
  else
124
740
  await database.run("UPDATE absolute_sync_mutations SET created_at = ?, record_json = ? WHERE namespace = ? AND operation_id = ?", [
125
741
  migrated.createdAt,
126
- JSON.stringify(migrated),
742
+ serializeRecord(migrated, {
743
+ kind: "mutation",
744
+ name: migrated.name,
745
+ namespace
746
+ }, protector),
127
747
  namespace,
128
748
  operationId
129
749
  ], false);
@@ -147,9 +767,12 @@ var createCapacitorSyncLocalStore = ({
147
767
  };
148
768
  let connectionPromise;
149
769
  const connection = () => {
150
- connectionPromise ??= Promise.resolve(createConnection()).then(async (database) => {
770
+ connectionPromise ??= Promise.all([
771
+ Promise.resolve(createConnection()),
772
+ prepareProtector()
773
+ ]).then(async ([database, protector]) => {
151
774
  await database.execute(SCHEMA);
152
- await prepareSchema(database);
775
+ await prepareSchema(database, protector);
153
776
  return database;
154
777
  });
155
778
  return connectionPromise;
@@ -172,6 +795,7 @@ var createCapacitorSyncLocalStore = ({
172
795
  requireNamespace(namespace);
173
796
  return locked(async () => {
174
797
  const database = await connection();
798
+ const protector = await prepareProtector();
175
799
  await database.beginTransaction();
176
800
  const writable = () => {
177
801
  if (mode !== "readwrite")
@@ -185,18 +809,26 @@ var createCapacitorSyncLocalStore = ({
185
809
  throw new Error("Sync installation id must not be empty");
186
810
  await database.run("INSERT INTO absolute_sync_metadata (namespace, installation_id) VALUES (?, ?) ON CONFLICT(namespace) DO UPDATE SET installation_id = excluded.installation_id", [namespace, installationId], false);
187
811
  },
188
- getCollection: async (key) => parseRecord((await database.query("SELECT record_json FROM absolute_sync_collections WHERE namespace = ? AND collection_key = ? LIMIT 1", [namespace, key])).values?.[0]?.record_json, "collection"),
812
+ getCollection: async (key) => parseRecord((await database.query("SELECT record_json FROM absolute_sync_collections WHERE namespace = ? AND collection_key = ? LIMIT 1", [namespace, key])).values?.[0]?.record_json, "collection", { kind: "collection", namespace }, protector),
189
813
  listCollections: async () => {
190
814
  const rows = (await database.query("SELECT collection_key, record_json FROM absolute_sync_collections WHERE namespace = ? ORDER BY collection_key ASC", [namespace])).values;
191
815
  return (rows ?? []).map((row) => {
192
816
  const key = row.collection_key;
193
- const record = parseRecord(row.record_json, "collection");
817
+ const record = parseRecord(row.record_json, "collection", { kind: "collection", namespace }, protector);
194
818
  return typeof key === "string" && record ? { key, record } : undefined;
195
819
  }).filter((entry) => entry !== undefined);
196
820
  },
197
821
  putCollection: async (key, record) => {
198
822
  writable();
199
- await database.run("INSERT INTO absolute_sync_collections (namespace, collection_key, record_json) VALUES (?, ?, ?) ON CONFLICT(namespace, collection_key) DO UPDATE SET record_json = excluded.record_json", [namespace, key, JSON.stringify(record)], false);
823
+ await database.run("INSERT INTO absolute_sync_collections (namespace, collection_key, record_json) VALUES (?, ?, ?) ON CONFLICT(namespace, collection_key) DO UPDATE SET record_json = excluded.record_json", [
824
+ namespace,
825
+ key,
826
+ serializeRecord(record, {
827
+ kind: "collection",
828
+ name: record.collection ?? key,
829
+ namespace
830
+ }, protector)
831
+ ], false);
200
832
  },
201
833
  deleteCollection: async (key) => {
202
834
  writable();
@@ -204,16 +836,20 @@ var createCapacitorSyncLocalStore = ({
204
836
  },
205
837
  listMutations: async () => {
206
838
  const rows = (await database.query("SELECT record_json FROM absolute_sync_mutations WHERE namespace = ? ORDER BY created_at ASC, operation_id ASC", [namespace])).values;
207
- return (rows ?? []).map((row) => parseRecord(row.record_json, "mutation")).filter((record) => record !== undefined);
839
+ return (rows ?? []).map((row) => parseRecord(row.record_json, "mutation", { kind: "mutation", namespace }, protector)).filter((record) => record !== undefined);
208
840
  },
209
- getMutation: async (operationId) => parseRecord((await database.query("SELECT record_json FROM absolute_sync_mutations WHERE namespace = ? AND operation_id = ? LIMIT 1", [namespace, operationId])).values?.[0]?.record_json, "mutation"),
841
+ getMutation: async (operationId) => parseRecord((await database.query("SELECT record_json FROM absolute_sync_mutations WHERE namespace = ? AND operation_id = ? LIMIT 1", [namespace, operationId])).values?.[0]?.record_json, "mutation", { kind: "mutation", namespace }, protector),
210
842
  putMutation: async (record) => {
211
843
  writable();
212
844
  await database.run("INSERT INTO absolute_sync_mutations (namespace, operation_id, created_at, record_json) VALUES (?, ?, ?, ?) ON CONFLICT(namespace, operation_id) DO UPDATE SET created_at = excluded.created_at, record_json = excluded.record_json", [
213
845
  namespace,
214
846
  record.operationId,
215
847
  record.createdAt,
216
- JSON.stringify(record)
848
+ serializeRecord(record, {
849
+ kind: "mutation",
850
+ name: record.name,
851
+ namespace
852
+ }, protector)
217
853
  ], false);
218
854
  },
219
855
  deleteMutation: async (operationId) => {
@@ -222,7 +858,14 @@ var createCapacitorSyncLocalStore = ({
222
858
  }
223
859
  };
224
860
  try {
225
- const result = await run(tx);
861
+ const result = await runSyncLocalPolicyTransaction({
862
+ mode,
863
+ now: now(),
864
+ policy: localData,
865
+ protected: protector !== undefined,
866
+ raw: tx,
867
+ run
868
+ });
226
869
  await database.commitTransaction();
227
870
  return result;
228
871
  } catch (error) {
@@ -296,10 +939,11 @@ var installCapacitorSyncLifecycle = async ({
296
939
  };
297
940
  export {
298
941
  installCapacitorSyncLifecycle,
942
+ createCapacitorSyncProtection,
299
943
  createCapacitorSyncLocalStore,
300
944
  configureCapacitorBackgroundSync,
301
945
  AbsoluteBackgroundSync
302
946
  };
303
947
 
304
- //# debugId=F21A450F9CF54D0C64756E2164756E21
948
+ //# debugId=6ED4C90ACCDBBE6464756E2164756E21
305
949
  //# sourceMappingURL=index.js.map