@arcote.tech/arc-adapter-db-sqlite-wasm 0.7.26 → 0.7.28

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.
Files changed (2) hide show
  1. package/dist/index.js +224 -74
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1779,9 +1779,21 @@ class LocalEventPublisher {
1779
1779
  views = [];
1780
1780
  syncCallback;
1781
1781
  subscribers = new Map;
1782
+ pending = new Set;
1782
1783
  constructor(dataStorage) {
1783
1784
  this.dataStorage = dataStorage;
1784
1785
  }
1786
+ track(work) {
1787
+ const wrapped = Promise.resolve(work).catch(() => {}).finally(() => {
1788
+ this.pending.delete(wrapped);
1789
+ });
1790
+ this.pending.add(wrapped);
1791
+ }
1792
+ async whenIdle() {
1793
+ while (this.pending.size > 0) {
1794
+ await Promise.all([...this.pending]);
1795
+ }
1796
+ }
1785
1797
  onPublish(callback) {
1786
1798
  this.syncCallback = callback;
1787
1799
  }
@@ -1817,9 +1829,12 @@ class LocalEventPublisher {
1817
1829
  store: EVENT_TABLES.events,
1818
1830
  changes: [{ type: "set", data: storedEvent }]
1819
1831
  });
1820
- if (event.payload && typeof event.payload === "object") {
1832
+ const tagFields = event.definition?.tagFields ?? [];
1833
+ if (tagFields.length > 0 && event.payload && typeof event.payload === "object") {
1834
+ const payload = event.payload;
1821
1835
  const tagChanges = [];
1822
- for (const [key, value] of Object.entries(event.payload)) {
1836
+ for (const key of tagFields) {
1837
+ const value = payload[key];
1823
1838
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1824
1839
  tagChanges.push({
1825
1840
  type: "set",
@@ -1977,6 +1992,47 @@ class LocalEventPublisher {
1977
1992
  return allViewChanges;
1978
1993
  }
1979
1994
  }
1995
+ function murmurHash(key, seed = 0) {
1996
+ let remainder, bytes, h1, h1b, c1, c2, k1, i;
1997
+ remainder = key.length & 3;
1998
+ bytes = key.length - remainder;
1999
+ h1 = seed;
2000
+ c1 = 3432918353;
2001
+ c2 = 461845907;
2002
+ i = 0;
2003
+ while (i < bytes) {
2004
+ k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
2005
+ ++i;
2006
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
2007
+ k1 = k1 << 15 | k1 >>> 17;
2008
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
2009
+ h1 ^= k1;
2010
+ h1 = h1 << 13 | h1 >>> 19;
2011
+ h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
2012
+ h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
2013
+ }
2014
+ k1 = 0;
2015
+ if (remainder >= 3) {
2016
+ k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
2017
+ }
2018
+ if (remainder >= 2) {
2019
+ k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
2020
+ }
2021
+ if (remainder >= 1) {
2022
+ k1 ^= key.charCodeAt(i) & 255;
2023
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
2024
+ k1 = k1 << 15 | k1 >>> 17;
2025
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
2026
+ h1 ^= k1;
2027
+ }
2028
+ h1 ^= key.length;
2029
+ h1 ^= h1 >>> 16;
2030
+ h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
2031
+ h1 ^= h1 >>> 13;
2032
+ h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
2033
+ h1 ^= h1 >>> 16;
2034
+ return h1 >>> 0;
2035
+ }
1980
2036
  class ArcOptional {
1981
2037
  parent;
1982
2038
  constructor(parent) {
@@ -2002,6 +2058,11 @@ class ArcOptional {
2002
2058
  return false;
2003
2059
  return this.parent.validate(value);
2004
2060
  }
2061
+ coerce(value) {
2062
+ if (value == null)
2063
+ return;
2064
+ return this.parent.coerce(value);
2065
+ }
2005
2066
  toJsonSchema() {
2006
2067
  const parentSchema = this.parent.toJsonSchema?.() ?? {};
2007
2068
  return {
@@ -2048,6 +2109,9 @@ class ArcBranded {
2048
2109
  validate(value) {
2049
2110
  return this.parent.validate(value);
2050
2111
  }
2112
+ coerce(value) {
2113
+ return this.parent.coerce(value);
2114
+ }
2051
2115
  toJsonSchema() {
2052
2116
  return this.parent.toJsonSchema?.() ?? {};
2053
2117
  }
@@ -2068,7 +2132,14 @@ class ArcDefault {
2068
2132
  this.defaultValueOrCallback = defaultValueOrCallback;
2069
2133
  }
2070
2134
  validate(value) {
2071
- throw new Error("Method not implemented.");
2135
+ if (value === undefined || value === null)
2136
+ return false;
2137
+ return this.parent.validate(value);
2138
+ }
2139
+ coerce(value) {
2140
+ if (value === undefined || value === null)
2141
+ return;
2142
+ return this.parent.coerce(value);
2072
2143
  }
2073
2144
  parse(value) {
2074
2145
  if (value)
@@ -2152,6 +2223,9 @@ class ArcAbstract {
2152
2223
  }
2153
2224
  return false;
2154
2225
  }
2226
+ coerce(value) {
2227
+ return this.validate(value) ? undefined : value;
2228
+ }
2155
2229
  pipeValidation(name, validator) {
2156
2230
  const newInstance = this.clone();
2157
2231
  newInstance.validations = [...this.validations, { name, validator }];
@@ -2289,6 +2363,17 @@ class ArcArray extends ArcAbstract {
2289
2363
  return { msg: "array is empty" };
2290
2364
  });
2291
2365
  }
2366
+ coerce(value) {
2367
+ if (!Array.isArray(value))
2368
+ return;
2369
+ const out = [];
2370
+ for (const item of value) {
2371
+ const coerced = this.parent.coerce(item);
2372
+ if (coerced !== undefined)
2373
+ out.push(coerced);
2374
+ }
2375
+ return this.validate(out) ? undefined : out;
2376
+ }
2292
2377
  parse(value) {
2293
2378
  return value.map((v) => this.parent.parse(v));
2294
2379
  }
@@ -2360,6 +2445,19 @@ class ArcObject extends ArcAbstract {
2360
2445
  ]);
2361
2446
  this.rawShape = rawShape;
2362
2447
  }
2448
+ coerce(value) {
2449
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
2450
+ return;
2451
+ }
2452
+ const src = value;
2453
+ const out = {};
2454
+ for (const [key, element] of Object.entries(this.rawShape)) {
2455
+ const coerced = element.coerce(src[key]);
2456
+ if (coerced !== undefined)
2457
+ out[key] = coerced;
2458
+ }
2459
+ return this.validate(out) ? undefined : out;
2460
+ }
2363
2461
  parse(value) {
2364
2462
  return Object.entries(this.rawShape).reduce((acc, [key, element]) => {
2365
2463
  acc[key] = element.parse(value[key]);
@@ -2594,6 +2692,51 @@ class ScopedDataStorage extends DataStorage {
2594
2692
  return this.#inner.getReadWriteTransaction();
2595
2693
  }
2596
2694
  }
2695
+ class ArcAuthenticationError extends Error {
2696
+ arcCode = "AUTHENTICATION";
2697
+ constructor(message = "Authentication required") {
2698
+ super(message);
2699
+ this.name = "ArcAuthenticationError";
2700
+ }
2701
+ }
2702
+
2703
+ class ArcAuthorizationError extends Error {
2704
+ arcCode = "AUTHORIZATION";
2705
+ constructor(message = "Forbidden") {
2706
+ super(message);
2707
+ this.name = "ArcAuthorizationError";
2708
+ }
2709
+ }
2710
+ function collectFieldPaths(errors, prefix = "") {
2711
+ if (!errors || typeof errors !== "object")
2712
+ return [];
2713
+ const schema = errors.schema;
2714
+ if (!schema || typeof schema !== "object")
2715
+ return [];
2716
+ const out = [];
2717
+ for (const [field, fieldError] of Object.entries(schema)) {
2718
+ if (!fieldError)
2719
+ continue;
2720
+ const path = prefix ? `${prefix}.${field}` : field;
2721
+ const nested = collectFieldPaths(fieldError, path);
2722
+ if (nested.length > 0)
2723
+ out.push(...nested);
2724
+ else
2725
+ out.push(path);
2726
+ }
2727
+ return out;
2728
+ }
2729
+
2730
+ class ArcValidationError extends Error {
2731
+ arcCode = "VALIDATION";
2732
+ fields;
2733
+ constructor(errors, message = "Invalid parameters") {
2734
+ super(message);
2735
+ this.name = "ArcValidationError";
2736
+ const paths = collectFieldPaths(errors);
2737
+ this.fields = paths.length > 0 ? paths : errors && typeof errors === "object" ? Object.keys(errors) : [];
2738
+ }
2739
+ }
2597
2740
  class ArcPrimitive extends ArcAbstract {
2598
2741
  serialize(value) {
2599
2742
  return value;
@@ -2766,6 +2909,8 @@ class ArcFragmentBase {
2766
2909
  class ArcContextElement extends ArcFragmentBase {
2767
2910
  name;
2768
2911
  types = ["context-element"];
2912
+ __contextId;
2913
+ __contextName;
2769
2914
  get id() {
2770
2915
  return this.name;
2771
2916
  }
@@ -2956,7 +3101,8 @@ class ArcEvent extends ArcContextElement {
2956
3101
  payload,
2957
3102
  id: this.eventId.generate(),
2958
3103
  createdAt: new Date,
2959
- authContext
3104
+ authContext,
3105
+ definition: this
2960
3106
  };
2961
3107
  await adapters.eventPublisher.publish(event);
2962
3108
  }
@@ -3009,8 +3155,8 @@ class ArcEvent extends ArcContextElement {
3009
3155
  const tagsSchema = new ArcObject({
3010
3156
  _id: new ArcString().primaryKey(),
3011
3157
  eventId: new ArcString().index(),
3012
- tagKey: new ArcString().index(),
3013
- tagValue: new ArcString().index()
3158
+ tagKey: new ArcString,
3159
+ tagValue: new ArcString
3014
3160
  });
3015
3161
  const syncStatusSchema = new ArcObject({
3016
3162
  _id: new ArcString().primaryKey(),
@@ -3105,6 +3251,27 @@ class ArcFunction {
3105
3251
  get results() {
3106
3252
  return this.data.results;
3107
3253
  }
3254
+ validateParams(params) {
3255
+ const schema = this.data.params;
3256
+ if (!schema || typeof schema.validate !== "function")
3257
+ return;
3258
+ const errors = schema.validate(params ?? {});
3259
+ if (errors)
3260
+ throw new ArcValidationError(errors);
3261
+ }
3262
+ async authorize(adapters) {
3263
+ if (!this.hasProtections)
3264
+ return;
3265
+ const decoded = adapters.authAdapter?.getDecoded?.();
3266
+ if (!decoded) {
3267
+ throw new ArcAuthenticationError;
3268
+ }
3269
+ const instances = this.data.protections.filter((p) => p.token?.name === decoded.tokenName).map((p) => p.token.create(decoded.params, adapters));
3270
+ const ok = await this.verifyProtections(instances);
3271
+ if (!ok) {
3272
+ throw new ArcAuthorizationError;
3273
+ }
3274
+ }
3108
3275
  async verifyProtections(tokens) {
3109
3276
  if (!this.data.protections || this.data.protections.length === 0) {
3110
3277
  return true;
@@ -3265,6 +3432,8 @@ class ArcCommand extends ArcContextElement {
3265
3432
  if (!this.data.handler) {
3266
3433
  throw new Error(`Command "${this.data.name}" has no handler`);
3267
3434
  }
3435
+ this.#fn.validateParams(params);
3436
+ await this.#fn.authorize(adapters);
3268
3437
  const context2 = this.buildCommandContext(adapters);
3269
3438
  return await this.data.handler(context2, params);
3270
3439
  }
@@ -3375,9 +3544,10 @@ class ArcListener extends ArcContextElement {
3375
3544
  }
3376
3545
  }
3377
3546
  if (this.data.isAsync) {
3378
- Promise.resolve(this.data.handler(context2, event2)).catch((error) => {
3547
+ const work = Promise.resolve(this.data.handler(context2, event2)).catch((error) => {
3379
3548
  console.error(`Async listener "${this.data.name}" error:`, error);
3380
3549
  });
3550
+ adapters.eventPublisher?.track?.(work);
3381
3551
  } else {
3382
3552
  await this.data.handler(context2, event2);
3383
3553
  }
@@ -3584,48 +3754,6 @@ function deepMerge(target, source) {
3584
3754
  function isPlainObject(item) {
3585
3755
  return item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && Object.prototype.toString.call(item) === "[object Object]";
3586
3756
  }
3587
- function murmurHash(key, seed = 0) {
3588
- let remainder, bytes, h1, h1b, c1, c2, k1, i;
3589
- remainder = key.length & 3;
3590
- bytes = key.length - remainder;
3591
- h1 = seed;
3592
- c1 = 3432918353;
3593
- c2 = 461845907;
3594
- i = 0;
3595
- while (i < bytes) {
3596
- k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
3597
- ++i;
3598
- k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
3599
- k1 = k1 << 15 | k1 >>> 17;
3600
- k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
3601
- h1 ^= k1;
3602
- h1 = h1 << 13 | h1 >>> 19;
3603
- h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
3604
- h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
3605
- }
3606
- k1 = 0;
3607
- if (remainder >= 3) {
3608
- k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
3609
- }
3610
- if (remainder >= 2) {
3611
- k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
3612
- }
3613
- if (remainder >= 1) {
3614
- k1 ^= key.charCodeAt(i) & 255;
3615
- k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
3616
- k1 = k1 << 15 | k1 >>> 17;
3617
- k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
3618
- h1 ^= k1;
3619
- }
3620
- h1 ^= key.length;
3621
- h1 ^= h1 >>> 16;
3622
- h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
3623
- h1 ^= h1 >>> 13;
3624
- h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
3625
- h1 ^= h1 >>> 16;
3626
- return h1 >>> 0;
3627
- }
3628
-
3629
3757
  class ForkedStoreState extends StoreState {
3630
3758
  master;
3631
3759
  changedItems = new Map;
@@ -3969,16 +4097,57 @@ function resolveQueryChange(currentResult, event3, options) {
3969
4097
  }
3970
4098
  const shouldBeInResult = checkItemMatchesWhere(event3.item, options.where);
3971
4099
  if (isInCurrentResult && shouldBeInResult) {
3972
- const newResult = currentResult.toSpliced(index, 1, event3.item);
3973
- return applyOrderByAndLimit(newResult, options);
4100
+ if (!options.orderBy) {
4101
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4102
+ }
4103
+ const cmp = compareByOrderBy(options.orderBy);
4104
+ if (cmp(currentResult[index], event3.item) === 0) {
4105
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4106
+ }
4107
+ const without = currentResult.toSpliced(index, 1);
4108
+ const at = upperBound(without, event3.item, cmp);
4109
+ return applyLimit(without.toSpliced(at, 0, event3.item), options);
3974
4110
  } else if (isInCurrentResult && !shouldBeInResult) {
3975
4111
  return currentResult.toSpliced(index, 1);
3976
4112
  } else if (!isInCurrentResult && shouldBeInResult) {
3977
- const newResult = [...currentResult, event3.item];
3978
- return applyOrderByAndLimit(newResult, options);
4113
+ if (!options.orderBy) {
4114
+ return applyLimit([...currentResult, event3.item], options);
4115
+ }
4116
+ const cmp = compareByOrderBy(options.orderBy);
4117
+ const at = upperBound(currentResult, event3.item, cmp);
4118
+ return applyLimit(currentResult.toSpliced(at, 0, event3.item), options);
3979
4119
  }
3980
4120
  return false;
3981
4121
  }
4122
+ function compareByOrderBy(orderBy) {
4123
+ const entries = Object.entries(orderBy);
4124
+ return (a, b) => {
4125
+ for (const [key, direction] of entries) {
4126
+ const aVal = a[key];
4127
+ const bVal = b[key];
4128
+ if (aVal < bVal)
4129
+ return direction === "asc" ? -1 : 1;
4130
+ if (aVal > bVal)
4131
+ return direction === "asc" ? 1 : -1;
4132
+ }
4133
+ return 0;
4134
+ };
4135
+ }
4136
+ function upperBound(arr, item, cmp) {
4137
+ let lo = 0;
4138
+ let hi = arr.length;
4139
+ while (lo < hi) {
4140
+ const mid = lo + hi >> 1;
4141
+ if (cmp(arr[mid], item) <= 0)
4142
+ lo = mid + 1;
4143
+ else
4144
+ hi = mid;
4145
+ }
4146
+ return lo;
4147
+ }
4148
+ function applyLimit(result, options) {
4149
+ return options.limit !== undefined && result.length > options.limit ? result.slice(0, options.limit) : result;
4150
+ }
3982
4151
  function checkItemMatchesWhere(item, where) {
3983
4152
  if (!where) {
3984
4153
  return true;
@@ -4014,27 +4183,6 @@ function checkItemMatchesWhere(item, where) {
4014
4183
  });
4015
4184
  });
4016
4185
  }
4017
- function applyOrderByAndLimit(result, options) {
4018
- let sorted = result;
4019
- if (options.orderBy) {
4020
- sorted = [...result].sort((a, b) => {
4021
- for (const [key, direction] of Object.entries(options.orderBy)) {
4022
- const aVal = a[key];
4023
- const bVal = b[key];
4024
- if (aVal < bVal)
4025
- return direction === "asc" ? -1 : 1;
4026
- if (aVal > bVal)
4027
- return direction === "asc" ? 1 : -1;
4028
- }
4029
- return 0;
4030
- });
4031
- }
4032
- if (options.limit !== undefined) {
4033
- sorted = sorted.slice(0, options.limit);
4034
- }
4035
- return sorted;
4036
- }
4037
-
4038
4186
  class ObservableDataStorage {
4039
4187
  source;
4040
4188
  onChange;
@@ -4682,6 +4830,8 @@ class SecuredDataStorage {
4682
4830
  return this.dataStorage.fork();
4683
4831
  }
4684
4832
  }
4833
+ var _te = new TextEncoder;
4834
+ var _td = new TextDecoder;
4685
4835
  class TokenCache {
4686
4836
  instanceCache = new Map;
4687
4837
  permissionCache = new Map;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-adapter-db-sqlite-wasm",
3
- "version": "0.7.26",
3
+ "version": "0.7.28",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -39,7 +39,7 @@
39
39
  "dev": "bun build ./src/index.ts ./src/worker.ts --outdir ./dist --target browser --format esm --watch"
40
40
  },
41
41
  "peerDependencies": {
42
- "@arcote.tech/arc": "^0.7.26",
42
+ "@arcote.tech/arc": "^0.7.28",
43
43
  "@sqlite.org/sqlite-wasm": "^3.46.0-build1"
44
44
  },
45
45
  "devDependencies": {