@arcote.tech/arc-adapter-db-sqlite 0.7.27 → 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 +115 -31
  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 {
@@ -3041,7 +3104,8 @@ class ArcEvent extends ArcContextElement {
3041
3104
  payload,
3042
3105
  id: this.eventId.generate(),
3043
3106
  createdAt: new Date,
3044
- authContext
3107
+ authContext,
3108
+ definition: this
3045
3109
  };
3046
3110
  await adapters.eventPublisher.publish(event);
3047
3111
  }
@@ -3094,8 +3158,8 @@ class ArcEvent extends ArcContextElement {
3094
3158
  const tagsSchema = new ArcObject({
3095
3159
  _id: new ArcString().primaryKey(),
3096
3160
  eventId: new ArcString().index(),
3097
- tagKey: new ArcString().index(),
3098
- tagValue: new ArcString().index()
3161
+ tagKey: new ArcString,
3162
+ tagValue: new ArcString
3099
3163
  });
3100
3164
  const syncStatusSchema = new ArcObject({
3101
3165
  _id: new ArcString().primaryKey(),
@@ -4036,16 +4100,57 @@ function resolveQueryChange(currentResult, event3, options) {
4036
4100
  }
4037
4101
  const shouldBeInResult = checkItemMatchesWhere(event3.item, options.where);
4038
4102
  if (isInCurrentResult && shouldBeInResult) {
4039
- const newResult = currentResult.toSpliced(index, 1, event3.item);
4040
- return applyOrderByAndLimit(newResult, options);
4103
+ if (!options.orderBy) {
4104
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4105
+ }
4106
+ const cmp = compareByOrderBy(options.orderBy);
4107
+ if (cmp(currentResult[index], event3.item) === 0) {
4108
+ return applyLimit(currentResult.toSpliced(index, 1, event3.item), options);
4109
+ }
4110
+ const without = currentResult.toSpliced(index, 1);
4111
+ const at = upperBound(without, event3.item, cmp);
4112
+ return applyLimit(without.toSpliced(at, 0, event3.item), options);
4041
4113
  } else if (isInCurrentResult && !shouldBeInResult) {
4042
4114
  return currentResult.toSpliced(index, 1);
4043
4115
  } else if (!isInCurrentResult && shouldBeInResult) {
4044
- const newResult = [...currentResult, event3.item];
4045
- return applyOrderByAndLimit(newResult, options);
4116
+ if (!options.orderBy) {
4117
+ return applyLimit([...currentResult, event3.item], options);
4118
+ }
4119
+ const cmp = compareByOrderBy(options.orderBy);
4120
+ const at = upperBound(currentResult, event3.item, cmp);
4121
+ return applyLimit(currentResult.toSpliced(at, 0, event3.item), options);
4046
4122
  }
4047
4123
  return false;
4048
4124
  }
4125
+ function compareByOrderBy(orderBy) {
4126
+ const entries = Object.entries(orderBy);
4127
+ return (a, b) => {
4128
+ for (const [key, direction] of entries) {
4129
+ const aVal = a[key];
4130
+ const bVal = b[key];
4131
+ if (aVal < bVal)
4132
+ return direction === "asc" ? -1 : 1;
4133
+ if (aVal > bVal)
4134
+ return direction === "asc" ? 1 : -1;
4135
+ }
4136
+ return 0;
4137
+ };
4138
+ }
4139
+ function upperBound(arr, item, cmp) {
4140
+ let lo = 0;
4141
+ let hi = arr.length;
4142
+ while (lo < hi) {
4143
+ const mid = lo + hi >> 1;
4144
+ if (cmp(arr[mid], item) <= 0)
4145
+ lo = mid + 1;
4146
+ else
4147
+ hi = mid;
4148
+ }
4149
+ return lo;
4150
+ }
4151
+ function applyLimit(result, options) {
4152
+ return options.limit !== undefined && result.length > options.limit ? result.slice(0, options.limit) : result;
4153
+ }
4049
4154
  function checkItemMatchesWhere(item, where) {
4050
4155
  if (!where) {
4051
4156
  return true;
@@ -4081,27 +4186,6 @@ function checkItemMatchesWhere(item, where) {
4081
4186
  });
4082
4187
  });
4083
4188
  }
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
4189
  class ObservableDataStorage {
4106
4190
  source;
4107
4191
  onChange;
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.28",
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.28"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "^5.0.0"