@arcote.tech/arc-adapter-db-sqlite 0.7.27 → 0.7.29

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 +172 -35
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1832,9 +1832,12 @@ class LocalEventPublisher {
1832
1832
  store: EVENT_TABLES.events,
1833
1833
  changes: [{ type: "set", data: storedEvent }]
1834
1834
  });
1835
- if (event.payload && typeof event.payload === "object") {
1835
+ const tagFields = event.definition?.tagFields ?? [];
1836
+ if (tagFields.length > 0 && event.payload && typeof event.payload === "object") {
1837
+ const payload = event.payload;
1836
1838
  const tagChanges = [];
1837
- for (const [key, value] of Object.entries(event.payload)) {
1839
+ for (const key of tagFields) {
1840
+ const value = payload[key];
1838
1841
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1839
1842
  tagChanges.push({
1840
1843
  type: "set",
@@ -2058,6 +2061,11 @@ class ArcOptional {
2058
2061
  return false;
2059
2062
  return this.parent.validate(value);
2060
2063
  }
2064
+ coerce(value) {
2065
+ if (value == null)
2066
+ return;
2067
+ return this.parent.coerce(value);
2068
+ }
2061
2069
  toJsonSchema() {
2062
2070
  const parentSchema = this.parent.toJsonSchema?.() ?? {};
2063
2071
  return {
@@ -2104,6 +2112,9 @@ class ArcBranded {
2104
2112
  validate(value) {
2105
2113
  return this.parent.validate(value);
2106
2114
  }
2115
+ coerce(value) {
2116
+ return this.parent.coerce(value);
2117
+ }
2107
2118
  toJsonSchema() {
2108
2119
  return this.parent.toJsonSchema?.() ?? {};
2109
2120
  }
@@ -2128,6 +2139,11 @@ class ArcDefault {
2128
2139
  return false;
2129
2140
  return this.parent.validate(value);
2130
2141
  }
2142
+ coerce(value) {
2143
+ if (value === undefined || value === null)
2144
+ return;
2145
+ return this.parent.coerce(value);
2146
+ }
2131
2147
  parse(value) {
2132
2148
  if (value)
2133
2149
  return this.parent.parse(value);
@@ -2210,6 +2226,9 @@ class ArcAbstract {
2210
2226
  }
2211
2227
  return false;
2212
2228
  }
2229
+ coerce(value) {
2230
+ return this.validate(value) ? undefined : value;
2231
+ }
2213
2232
  pipeValidation(name, validator) {
2214
2233
  const newInstance = this.clone();
2215
2234
  newInstance.validations = [...this.validations, { name, validator }];
@@ -2347,6 +2366,17 @@ class ArcArray extends ArcAbstract {
2347
2366
  return { msg: "array is empty" };
2348
2367
  });
2349
2368
  }
2369
+ coerce(value) {
2370
+ if (!Array.isArray(value))
2371
+ return;
2372
+ const out = [];
2373
+ for (const item of value) {
2374
+ const coerced = this.parent.coerce(item);
2375
+ if (coerced !== undefined)
2376
+ out.push(coerced);
2377
+ }
2378
+ return this.validate(out) ? undefined : out;
2379
+ }
2350
2380
  parse(value) {
2351
2381
  return value.map((v) => this.parent.parse(v));
2352
2382
  }
@@ -2418,6 +2448,19 @@ class ArcObject extends ArcAbstract {
2418
2448
  ]);
2419
2449
  this.rawShape = rawShape;
2420
2450
  }
2451
+ coerce(value) {
2452
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
2453
+ return;
2454
+ }
2455
+ const src = value;
2456
+ const out = {};
2457
+ for (const [key, element] of Object.entries(this.rawShape)) {
2458
+ const coerced = element.coerce(src[key]);
2459
+ if (coerced !== undefined)
2460
+ out[key] = coerced;
2461
+ }
2462
+ return this.validate(out) ? undefined : out;
2463
+ }
2421
2464
  parse(value) {
2422
2465
  return Object.entries(this.rawShape).reduce((acc, [key, element]) => {
2423
2466
  acc[key] = element.parse(value[key]);
@@ -2667,6 +2710,25 @@ class ArcAuthorizationError extends Error {
2667
2710
  this.name = "ArcAuthorizationError";
2668
2711
  }
2669
2712
  }
2713
+ function collectFieldPaths(errors, prefix = "") {
2714
+ if (!errors || typeof errors !== "object")
2715
+ return [];
2716
+ const schema = errors.schema;
2717
+ if (!schema || typeof schema !== "object")
2718
+ return [];
2719
+ const out = [];
2720
+ for (const [field, fieldError] of Object.entries(schema)) {
2721
+ if (!fieldError)
2722
+ continue;
2723
+ const path = prefix ? `${prefix}.${field}` : field;
2724
+ const nested = collectFieldPaths(fieldError, path);
2725
+ if (nested.length > 0)
2726
+ out.push(...nested);
2727
+ else
2728
+ out.push(path);
2729
+ }
2730
+ return out;
2731
+ }
2670
2732
 
2671
2733
  class ArcValidationError extends Error {
2672
2734
  arcCode = "VALIDATION";
@@ -2674,7 +2736,8 @@ class ArcValidationError extends Error {
2674
2736
  constructor(errors, message = "Invalid parameters") {
2675
2737
  super(message);
2676
2738
  this.name = "ArcValidationError";
2677
- this.fields = errors && typeof errors === "object" ? Object.keys(errors) : [];
2739
+ const paths = collectFieldPaths(errors);
2740
+ this.fields = paths.length > 0 ? paths : errors && typeof errors === "object" ? Object.keys(errors) : [];
2678
2741
  }
2679
2742
  }
2680
2743
  class ArcPrimitive extends ArcAbstract {
@@ -2851,12 +2914,35 @@ class ArcContextElement extends ArcFragmentBase {
2851
2914
  types = ["context-element"];
2852
2915
  __contextId;
2853
2916
  __contextName;
2917
+ __contextPath;
2854
2918
  get id() {
2855
2919
  return this.name;
2856
2920
  }
2921
+ __declStack;
2857
2922
  constructor(name) {
2858
2923
  super();
2859
2924
  this.name = name;
2925
+ this.__declStack = new Error().stack;
2926
+ }
2927
+ getSourceLocation() {
2928
+ const stack = this.__declStack;
2929
+ if (!stack)
2930
+ return;
2931
+ for (const raw of stack.split(`
2932
+ `).slice(1)) {
2933
+ const m = raw.match(/\(?((?:file:\/\/)?[^()\s]+?):(\d+):(\d+)\)?$/);
2934
+ if (!m)
2935
+ continue;
2936
+ let file = m[1];
2937
+ if (file.startsWith("file://"))
2938
+ file = file.slice(7);
2939
+ const isCoreInternal = /packages\/core\/(src|dist)\//.test(file) && !/\.test\.tsx?$/.test(file);
2940
+ if (file.includes("node_modules") || isCoreInternal || file.includes("native:") || !file.includes("/")) {
2941
+ continue;
2942
+ }
2943
+ return { file, line: Number(m[2]) };
2944
+ }
2945
+ return;
2860
2946
  }
2861
2947
  _seeds;
2862
2948
  getSeeds() {
@@ -3041,7 +3127,8 @@ class ArcEvent extends ArcContextElement {
3041
3127
  payload,
3042
3128
  id: this.eventId.generate(),
3043
3129
  createdAt: new Date,
3044
- authContext
3130
+ authContext,
3131
+ definition: this
3045
3132
  };
3046
3133
  await adapters.eventPublisher.publish(event);
3047
3134
  }
@@ -3094,8 +3181,8 @@ class ArcEvent extends ArcContextElement {
3094
3181
  const tagsSchema = new ArcObject({
3095
3182
  _id: new ArcString().primaryKey(),
3096
3183
  eventId: new ArcString().index(),
3097
- tagKey: new ArcString().index(),
3098
- tagValue: new ArcString().index()
3184
+ tagKey: new ArcString,
3185
+ tagValue: new ArcString
3099
3186
  });
3100
3187
  const syncStatusSchema = new ArcObject({
3101
3188
  _id: new ArcString().primaryKey(),
@@ -3237,6 +3324,34 @@ class ArcFunction {
3237
3324
  };
3238
3325
  }
3239
3326
  }
3327
+ function serializeParams(schema, params) {
3328
+ if (schema && typeof schema.serialize === "function") {
3329
+ return schema.serialize(params ?? {});
3330
+ }
3331
+ return params;
3332
+ }
3333
+ function deserializeParams(schema, params) {
3334
+ if (schema && typeof schema.deserialize === "function") {
3335
+ return schema.deserialize(params ?? {});
3336
+ }
3337
+ return params;
3338
+ }
3339
+ function deserializeResult(schemas, value) {
3340
+ const list = Array.isArray(schemas) ? schemas : undefined;
3341
+ if (!list || list.length !== 1)
3342
+ return value;
3343
+ const schema = list[0];
3344
+ if (!schema || typeof schema.deserialize !== "function")
3345
+ return value;
3346
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
3347
+ return value;
3348
+ }
3349
+ try {
3350
+ return schema.deserialize(value);
3351
+ } catch {
3352
+ return value;
3353
+ }
3354
+ }
3240
3355
  class AggregateBase {
3241
3356
  value;
3242
3357
  _id;
@@ -3363,7 +3478,8 @@ class ArcCommand extends ArcContextElement {
3363
3478
  scope: adapters.scope.scopeName,
3364
3479
  token: adapters.scope.getToken()
3365
3480
  } : undefined;
3366
- return await adapters.commandWire.executeCommand(this.data.name, params, wireAuth);
3481
+ const wireResult = await adapters.commandWire.executeCommand(this.data.name, serializeParams(this.data.params, params), wireAuth);
3482
+ return deserializeResult(this.data.results, wireResult);
3367
3483
  };
3368
3484
  return Object.assign(executeFunc, { params: this.data.params });
3369
3485
  }
@@ -3371,10 +3487,11 @@ class ArcCommand extends ArcContextElement {
3371
3487
  if (!this.data.handler) {
3372
3488
  throw new Error(`Command "${this.data.name}" has no handler`);
3373
3489
  }
3374
- this.#fn.validateParams(params);
3490
+ const input = deserializeParams(this.data.params, params);
3491
+ this.#fn.validateParams(input);
3375
3492
  await this.#fn.authorize(adapters);
3376
3493
  const context2 = this.buildCommandContext(adapters);
3377
- return await this.data.handler(context2, params);
3494
+ return await this.data.handler(context2, input);
3378
3495
  }
3379
3496
  buildCommandContext(adapters) {
3380
3497
  const context2 = this.#fn.buildContext(adapters);
@@ -4036,16 +4153,57 @@ function resolveQueryChange(currentResult, event3, options) {
4036
4153
  }
4037
4154
  const shouldBeInResult = checkItemMatchesWhere(event3.item, options.where);
4038
4155
  if (isInCurrentResult && shouldBeInResult) {
4039
- const newResult = currentResult.toSpliced(index, 1, event3.item);
4040
- return applyOrderByAndLimit(newResult, options);
4156
+ if (!options.orderBy) {
4157
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4158
+ }
4159
+ const cmp = compareByOrderBy(options.orderBy);
4160
+ if (cmp(currentResult[index], event3.item) === 0) {
4161
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4162
+ }
4163
+ const without = currentResult.toSpliced(index, 1);
4164
+ const at = upperBound(without, event3.item, cmp);
4165
+ return applyLimit(without.toSpliced(at, 0, event3.item), options);
4041
4166
  } else if (isInCurrentResult && !shouldBeInResult) {
4042
4167
  return currentResult.toSpliced(index, 1);
4043
4168
  } else if (!isInCurrentResult && shouldBeInResult) {
4044
- const newResult = [...currentResult, event3.item];
4045
- return applyOrderByAndLimit(newResult, options);
4169
+ if (!options.orderBy) {
4170
+ return applyLimit([...currentResult, event3.item], options);
4171
+ }
4172
+ const cmp = compareByOrderBy(options.orderBy);
4173
+ const at = upperBound(currentResult, event3.item, cmp);
4174
+ return applyLimit(currentResult.toSpliced(at, 0, event3.item), options);
4046
4175
  }
4047
4176
  return false;
4048
4177
  }
4178
+ function compareByOrderBy(orderBy) {
4179
+ const entries = Object.entries(orderBy);
4180
+ return (a, b) => {
4181
+ for (const [key, direction] of entries) {
4182
+ const aVal = a[key];
4183
+ const bVal = b[key];
4184
+ if (aVal < bVal)
4185
+ return direction === "asc" ? -1 : 1;
4186
+ if (aVal > bVal)
4187
+ return direction === "asc" ? 1 : -1;
4188
+ }
4189
+ return 0;
4190
+ };
4191
+ }
4192
+ function upperBound(arr, item, cmp) {
4193
+ let lo = 0;
4194
+ let hi = arr.length;
4195
+ while (lo < hi) {
4196
+ const mid = lo + hi >> 1;
4197
+ if (cmp(arr[mid], item) <= 0)
4198
+ lo = mid + 1;
4199
+ else
4200
+ hi = mid;
4201
+ }
4202
+ return lo;
4203
+ }
4204
+ function applyLimit(result, options) {
4205
+ return options.limit !== undefined && result.length > options.limit ? result.slice(0, options.limit) : result;
4206
+ }
4049
4207
  function checkItemMatchesWhere(item, where) {
4050
4208
  if (!where) {
4051
4209
  return true;
@@ -4081,27 +4239,6 @@ function checkItemMatchesWhere(item, where) {
4081
4239
  });
4082
4240
  });
4083
4241
  }
4084
- function applyOrderByAndLimit(result, options) {
4085
- let sorted = result;
4086
- if (options.orderBy) {
4087
- sorted = [...result].sort((a, b) => {
4088
- for (const [key, direction] of Object.entries(options.orderBy)) {
4089
- const aVal = a[key];
4090
- const bVal = b[key];
4091
- if (aVal < bVal)
4092
- return direction === "asc" ? -1 : 1;
4093
- if (aVal > bVal)
4094
- return direction === "asc" ? 1 : -1;
4095
- }
4096
- return 0;
4097
- });
4098
- }
4099
- if (options.limit !== undefined) {
4100
- sorted = sorted.slice(0, options.limit);
4101
- }
4102
- return sorted;
4103
- }
4104
-
4105
4242
  class ObservableDataStorage {
4106
4243
  source;
4107
4244
  onChange;
@@ -4257,7 +4394,7 @@ function extractDatabaseAgnosticSchema(arcObject, tableName) {
4257
4394
  columns
4258
4395
  };
4259
4396
  }
4260
- var dateValidator = typeValidatorBuilder("Date", (value) => value instanceof Date);
4397
+ var dateValidator = typeValidatorBuilder("Date", (value) => value instanceof Date && !isNaN(value.getTime()));
4261
4398
  function buildContextAccessor(context2, adapters, contextMethod, onCall) {
4262
4399
  const result = {};
4263
4400
  for (const element2 of context2.elements) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-adapter-db-sqlite",
3
- "version": "0.7.27",
3
+ "version": "0.7.29",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "test": "bun test"
21
21
  },
22
22
  "peerDependencies": {
23
- "@arcote.tech/arc": "^0.7.27"
23
+ "@arcote.tech/arc": "^0.7.29"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "^5.0.0"