@arcote.tech/arc 0.0.27 → 0.1.2

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 (91) hide show
  1. package/dist/collection/collection.d.ts +28 -48
  2. package/dist/collection/queries/abstract-collection-query.d.ts +4 -6
  3. package/dist/collection/queries/{abstract-many-items.d.ts → find.d.ts} +8 -8
  4. package/dist/collection/queries/one-item.d.ts +1 -18
  5. package/dist/collection/query-builders/find-by-id.d.ts +2 -0
  6. package/dist/collection/query-builders/find-one.d.ts +2 -0
  7. package/dist/collection/query-builders/find.d.ts +13 -0
  8. package/dist/command/command.d.ts +29 -0
  9. package/dist/command/index.d.ts +2 -0
  10. package/dist/context/context.d.ts +34 -18
  11. package/dist/context/element.d.ts +36 -6
  12. package/dist/context/event.d.ts +39 -0
  13. package/dist/context/index.d.ts +4 -0
  14. package/dist/context/query-builder-context.d.ts +15 -0
  15. package/dist/context/query-builders.d.ts +11 -2
  16. package/dist/context/query-cache.d.ts +9 -0
  17. package/dist/context/query.d.ts +5 -3
  18. package/dist/context/reactive-query.d.ts +23 -0
  19. package/dist/context/serializable-query.d.ts +11 -0
  20. package/dist/data-storage/store-state-fork.d.ts +2 -3
  21. package/dist/data-storage/store-state-master.d.ts +2 -5
  22. package/dist/data-storage/store-state.abstract.d.ts +2 -3
  23. package/dist/data-storage/types.d.ts +28 -0
  24. package/dist/db/index.d.ts +1 -0
  25. package/dist/db/interface.d.ts +2 -17
  26. package/dist/db/sqliteAdapter.d.ts +39 -0
  27. package/dist/dist/index.d.ts +513 -0
  28. package/dist/elements/abstract-primitive.d.ts +0 -1
  29. package/dist/elements/abstract.d.ts +2 -1
  30. package/dist/elements/array.d.ts +61 -3
  31. package/dist/elements/class.d.ts +1 -24
  32. package/dist/elements/date.d.ts +35 -2
  33. package/dist/elements/index.d.ts +2 -0
  34. package/dist/elements/number.d.ts +21 -6
  35. package/dist/elements/object.d.ts +38 -11
  36. package/dist/elements/or.d.ts +1 -11
  37. package/dist/elements/record.d.ts +16 -4
  38. package/dist/elements/string-enum.d.ts +17 -3
  39. package/dist/elements/string.d.ts +74 -6
  40. package/dist/elements/utils/type-validator-builder.d.ts +8 -0
  41. package/dist/index.d.ts +3 -0
  42. package/dist/index.js +1481 -752
  43. package/dist/model/index.d.ts +2 -0
  44. package/dist/model/model.d.ts +44 -38
  45. package/dist/state/query-builder.d.ts +1 -8
  46. package/dist/state/query.d.ts +1 -14
  47. package/dist/state/state.d.ts +1 -31
  48. package/dist/tests/context/context.test.d.ts +2 -0
  49. package/dist/tests/pipe.d.ts +2 -0
  50. package/dist/tests/query/advance-query.test.d.ts +2 -0
  51. package/dist/tests/query/collection-all.test.d.ts +2 -0
  52. package/dist/tests/utils/expect-not-false.d.ts +2 -0
  53. package/dist/tests/utils/sqlite-adapter.d.ts +3 -0
  54. package/dist/tests/utils/test-model.d.ts +26 -0
  55. package/dist/tests/validations/array.test.d.ts +2 -0
  56. package/dist/tests/validations/date.test.d.ts +2 -0
  57. package/dist/tests/validations/record.test.d.ts +2 -0
  58. package/dist/tests/validations/string-enum.test.d.ts +2 -0
  59. package/dist/utils/arcObjectToStoreSchema.d.ts +4 -0
  60. package/dist/utils/murmur-hash.d.ts +2 -0
  61. package/dist/utils.d.ts +4 -4
  62. package/dist/view/view.d.ts +49 -0
  63. package/package.json +11 -4
  64. package/dist/collection/collection-change.d.ts +0 -18
  65. package/dist/collection/db.d.ts +0 -17
  66. package/dist/collection/queries/all-items.d.ts +0 -7
  67. package/dist/collection/queries/indexed.d.ts +0 -13
  68. package/dist/collection/query-builders/abstract-many-items.d.ts +0 -11
  69. package/dist/collection/query-builders/all-items.d.ts +0 -9
  70. package/dist/collection/query-builders/indexed.d.ts +0 -11
  71. package/dist/collection/query-builders/one-item.d.ts +0 -11
  72. package/dist/collection/utils/index-query.d.ts +0 -6
  73. package/dist/data-storage/DataStorage.d.ts +0 -11
  74. package/dist/data-storage/ForkStoreState.d.ts +0 -32
  75. package/dist/data-storage/StoreState.d.ts +0 -39
  76. package/dist/data-storage/data-storage.d.ts +0 -2
  77. package/dist/data-storage/data-storage.interface.d.ts +0 -46
  78. package/dist/data-storage/master-store-state.d.ts +0 -30
  79. package/dist/data-storage/store-state.d.ts +0 -39
  80. package/dist/elements/object copy.d.ts +0 -29
  81. package/dist/rtc/deserializeChanges.d.ts +0 -3
  82. package/dist/state/db.d.ts +0 -15
  83. package/dist/state/state-change.d.ts +0 -14
  84. package/dist/state/util.d.ts +0 -3
  85. package/dist/tests/query/query.test.d.ts +0 -2
  86. package/dist/tests/query-notification-optimization.test copy.d.ts +0 -2
  87. package/dist/tests/query-notification-optimization.test.d.ts +0 -2
  88. package/dist/tests/validation.test.d.ts +0 -2
  89. package/dist/tests/validations/validation.test.d.ts +0 -2
  90. package/dist/utils/deep-merge.d.ts +0 -6
  91. /package/dist/{elements/tests → tests/validations}/object.test.d.ts +0 -0
package/dist/index.js CHANGED
@@ -1,6 +1,13 @@
1
1
  // context/element.ts
2
2
  class ArcContextElement {
3
3
  $event;
4
+ name;
5
+ commandContext;
6
+ commandClient;
7
+ observer;
8
+ }
9
+
10
+ class ArcContextElementWithStore extends ArcContextElement {
4
11
  }
5
12
 
6
13
  // elements/optional.ts
@@ -26,7 +33,7 @@ class ArcOptional {
26
33
  }
27
34
  validate(value) {
28
35
  if (!value)
29
- return {};
36
+ return false;
30
37
  return this.parent.validate(value);
31
38
  }
32
39
  }
@@ -90,7 +97,10 @@ class ArcDefault {
90
97
 
91
98
  // elements/abstract.ts
92
99
  class ArcAbstract {
93
- validations = [];
100
+ validations;
101
+ constructor(validations = []) {
102
+ this.validations = validations;
103
+ }
94
104
  default(defaultValueOrCallback) {
95
105
  return new ArcDefault(this, defaultValueOrCallback);
96
106
  }
@@ -106,10 +116,18 @@ class ArcAbstract {
106
116
  return newInstance;
107
117
  }
108
118
  validate(value) {
109
- return this.validations.reduce((acc, { name, validator }) => {
110
- acc[name] = validator(value);
119
+ const errors = this.validations.reduce((acc, { name, validator }) => {
120
+ try {
121
+ acc[name] = validator(value);
122
+ } catch (error) {
123
+ acc[name] = error;
124
+ }
111
125
  return acc;
112
126
  }, {});
127
+ if (Object.values(errors).some((result) => !!result)) {
128
+ return errors;
129
+ }
130
+ return false;
113
131
  }
114
132
  pipeValidation(name, validator) {
115
133
  const newInstance = this.clone();
@@ -123,9 +141,6 @@ class ArcAbstract {
123
141
 
124
142
  // elements/abstract-primitive.ts
125
143
  class ArcPrimitive extends ArcAbstract {
126
- constructor() {
127
- super();
128
- }
129
144
  serialize(value) {
130
145
  return value;
131
146
  }
@@ -137,8 +152,30 @@ class ArcPrimitive extends ArcAbstract {
137
152
  }
138
153
  }
139
154
 
155
+ // elements/utils/type-validator-builder.ts
156
+ function primitiveTypeComparatorStrategyFactory(type) {
157
+ return (value) => typeof value === type;
158
+ }
159
+ function typeValidatorBuilder(typeName, comparatorStrategy) {
160
+ const comparator = comparatorStrategy || primitiveTypeComparatorStrategyFactory(typeName);
161
+ return {
162
+ name: "type",
163
+ validator: (value) => {
164
+ const valueType = typeof value;
165
+ if (!comparator(value))
166
+ return { current: valueType, expected: typeName };
167
+ return false;
168
+ }
169
+ };
170
+ }
171
+
140
172
  // elements/string.ts
173
+ var stringValidator = typeValidatorBuilder("string");
174
+
141
175
  class ArcString extends ArcPrimitive {
176
+ constructor() {
177
+ super([stringValidator]);
178
+ }
142
179
  minLength(min) {
143
180
  return this.validation("minLength", (value) => {
144
181
  if (value.length < min)
@@ -157,6 +194,87 @@ class ArcString extends ArcPrimitive {
157
194
  };
158
195
  });
159
196
  }
197
+ length(number) {
198
+ return this.validation("length", (value) => {
199
+ if (value.length !== number) {
200
+ return {
201
+ currentLength: value.length,
202
+ length: number
203
+ };
204
+ }
205
+ });
206
+ }
207
+ includes(str) {
208
+ return this.validation("includes", (value) => {
209
+ if (!value.includes(str)) {
210
+ return {
211
+ currentValue: value,
212
+ includes: str
213
+ };
214
+ }
215
+ });
216
+ }
217
+ startsWith(str) {
218
+ return this.validation("startsWith", (value) => {
219
+ if (!value.startsWith(str)) {
220
+ return {
221
+ currentValue: value,
222
+ startsWith: str
223
+ };
224
+ }
225
+ });
226
+ }
227
+ endsWith(str) {
228
+ return this.validation("endsWith", (value) => {
229
+ if (!value.endsWith(str)) {
230
+ return {
231
+ currentValue: value,
232
+ endsWith: str
233
+ };
234
+ }
235
+ });
236
+ }
237
+ regex(regex) {
238
+ return this.validation("regex", (value) => {
239
+ if (!regex.test(value)) {
240
+ return {
241
+ currentValue: value,
242
+ regex
243
+ };
244
+ }
245
+ });
246
+ }
247
+ email() {
248
+ const regex = /^(?:(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+)*)|(?:"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f])*"))@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$|(?:\[(?:\d{1,3}\.){3}\d{1,3}\])$/;
249
+ return this.validation("email", (value) => {
250
+ if (!regex.test(value)) {
251
+ return {
252
+ currentEmail: value
253
+ };
254
+ }
255
+ });
256
+ }
257
+ url() {
258
+ const regex = /^(https?):\/\/(?![-0-9])(?!www\.[0-9])(?:[a-zA-Z0-9-]+(?::[a-zA-Z0-9-]+)?@)?(?:localhost|\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b|[a-zA-Z0-9-]+\.)?[a-zA-Z0-9-]+\.(?:[a-zA-Z]{2,}|[a-zA-Z]{2}\.[a-zA-Z]{2})(?::\d{1,5})?(?!\/\/)(?:\/[a-zA-Z0-9-._~:?#\[\]@!$&'()*+,;=]*)*(?!\/{2})(?:;[a-zA-Z0-9-._~:?#\[\]@!$&'()*+,;=]*)*(\?(?!=)[a-zA-Z0-9&=;]*)?(\#[a-zA-Z0-9-]*)?$|^(https?):\/\/(localhost|\b(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b)(?::\d{1,5})?(?!\/\/)(?:\/[a-zA-Z0-9-._~:?#\[\]@!$&'()*+,;=]*)*(?!\/{2})(?:;[a-zA-Z0-9-._~:?#\[\]@!$&'()*+,;=]*)*(\?(?!=)[a-zA-Z0-9&=;]*)?(\#[a-zA-Z0-9-]*)?$/;
259
+ return this.validation("url", (value) => {
260
+ if (!regex.test(value)) {
261
+ return {
262
+ currentUrl: value
263
+ };
264
+ }
265
+ });
266
+ }
267
+ ip() {
268
+ const IPv4regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
269
+ const IPv6regex = /^(?:([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|:(:[0-9a-fA-F]{1,4}){1,7}|([0-9a-fA-F]{1,4}:){1,6}:([0-9a-fA-F]{1,4}:){1,6}[0-9a-fA-F]{1,4})$/;
270
+ return this.validation("ip", (value) => {
271
+ if (!(IPv4regex.test(value) || IPv6regex.test(value))) {
272
+ return {
273
+ currentIP: value
274
+ };
275
+ }
276
+ });
277
+ }
160
278
  validation(name, validator) {
161
279
  const instance = this.pipeValidation(name, validator);
162
280
  return instance;
@@ -196,283 +314,571 @@ function customId(name, createFn) {
196
314
  return new ArcCustomId(name, createFn);
197
315
  }
198
316
 
199
- // context/query.ts
200
- class ArcQuery {
201
- lastResult;
202
- listener;
203
- }
317
+ // elements/object.ts
318
+ var objectValidator = typeValidatorBuilder("object");
204
319
 
205
- // collection/queries/abstract-collection-query.ts
206
- class ArcCollectionQuery extends ArcQuery {
207
- collection;
208
- bindedChangeHandler = this.changeHandler.bind(this);
209
- store;
210
- constructor(collection) {
211
- super();
212
- this.collection = collection;
213
- }
214
- async run(dataStorage, listener) {
215
- const store = dataStorage.getStore(this.collection.name);
216
- this.store = store;
217
- const result = await this.fetch(store);
218
- this.lastResult = result;
219
- if (listener)
220
- this.listener = listener;
221
- return result;
222
- }
223
- changeHandler(changes) {
224
- let resultChanged = false;
225
- for (const change of changes) {
226
- const response = this.onChange(change);
227
- if (response !== false) {
228
- this.lastResult = response;
229
- resultChanged = true;
320
+ class ArcObject extends ArcAbstract {
321
+ rawShape;
322
+ constructor(rawShape) {
323
+ super([
324
+ objectValidator,
325
+ {
326
+ name: "schema",
327
+ validator: (value) => {
328
+ const errors = Object.entries(this.rawShape).reduce((acc, [key, element]) => {
329
+ if (!element.validate) {
330
+ return acc;
331
+ }
332
+ acc[key] = element.validate(value[key]);
333
+ return acc;
334
+ }, {});
335
+ if (Object.values(errors).some((result) => !!result)) {
336
+ return errors;
337
+ }
338
+ return false;
339
+ }
230
340
  }
231
- }
232
- if (resultChanged)
233
- this.nextResult(this.lastResult);
234
- }
235
- unsubscribe() {
236
- this.store.unsubscribe(this.bindedChangeHandler);
341
+ ]);
342
+ this.rawShape = rawShape;
237
343
  }
238
- nextResult(result) {
239
- this.lastResult = result;
240
- this.listener?.(result);
344
+ parse(value) {
345
+ return Object.entries(this.rawShape).reduce((acc, [key, element]) => {
346
+ acc[key] = element.parse(value[key]);
347
+ return acc;
348
+ }, {});
241
349
  }
242
- }
243
-
244
- // collection/queries/abstract-many-items.ts
245
- class QueryCollectionResult {
246
- result;
247
- constructor(result) {
248
- this.result = result;
350
+ serialize(value) {
351
+ return Object.entries(value).reduce((acc, [key, value2]) => {
352
+ if (!this.rawShape[key]) {
353
+ acc[key] = value2;
354
+ } else {
355
+ acc[key] = this.rawShape[key].serialize(value2);
356
+ }
357
+ return acc;
358
+ }, {});
249
359
  }
250
- get(id2) {
251
- return id2 ? this.result.find((r) => r._id === id2) : undefined;
360
+ deserialize(value) {
361
+ return Object.fromEntries(Object.entries(this.rawShape).map(([key, element]) => [
362
+ key,
363
+ element.deserialize(value[key])
364
+ ]));
252
365
  }
253
- map(callbackfn) {
254
- return this.result.map(callbackfn);
366
+ deserializePath(path, value) {
367
+ if (path.length === 0) {
368
+ return this.deserialize(value);
369
+ }
370
+ const [key, ...restPath] = path;
371
+ const element = this.rawShape[key];
372
+ if (!element) {
373
+ console.warn(`No element found for key: ${key}`);
374
+ return value;
375
+ }
376
+ if (element instanceof ArcObject || element instanceof ArcArray) {
377
+ return element.deserializePath(restPath, value);
378
+ }
379
+ return element.deserialize(value);
255
380
  }
256
- toArray() {
257
- return this.result;
381
+ parsePartial(value) {
382
+ return Object.entries(value).reduce((acc, [key, value2]) => {
383
+ acc[key] = this.rawShape[key].parse(value2);
384
+ return acc;
385
+ }, {});
258
386
  }
259
- }
260
-
261
- class ArcManyItemsQuery extends ArcCollectionQuery {
262
- filterFn;
263
- sortFn;
264
- constructor(collection, filterFn, sortFn) {
265
- super(collection);
266
- this.filterFn = filterFn;
267
- this.sortFn = sortFn;
387
+ deserializePartial(value) {
388
+ return Object.entries(value).reduce((acc, [key, value2]) => {
389
+ acc[key] = this.rawShape[key].deserialize(value2);
390
+ return acc;
391
+ }, {});
268
392
  }
269
- onChange(change) {
270
- const lastResult = this.lastResult;
271
- const lastResultAsArray = lastResult?.toArray() || [];
272
- const index = lastResultAsArray.findIndex((e) => e._id === (change.type === "delete" ? change.id : change.id));
273
- const isInLastResult = index !== -1;
274
- const shouldBeInTheResult = change.type !== "delete" && this.checkItem(change.item);
275
- if (isInLastResult && shouldBeInTheResult)
276
- return this.createResult(lastResultAsArray.toSpliced(index, 1, change.item));
277
- else if (isInLastResult && (change.type === "delete" || !shouldBeInTheResult))
278
- return this.createResult(lastResultAsArray.toSpliced(index, 1));
279
- else if (!isInLastResult && shouldBeInTheResult)
280
- return this.createResult(lastResultAsArray.concat(change.item));
281
- return false;
393
+ serializePartial(value) {
394
+ return Object.entries(value).reduce((acc, [key, value2]) => {
395
+ acc[key] = this.rawShape[key].serialize(value2);
396
+ return acc;
397
+ }, {});
282
398
  }
283
- createResult(result) {
284
- if (this.sortFn)
285
- return new QueryCollectionResult(result.sort(this.sortFn));
286
- return new QueryCollectionResult(result);
399
+ pick(...keys) {
400
+ return new ArcObject(Object.fromEntries(keys.map((key) => [key, this.rawShape[key]])));
287
401
  }
288
- createFiltredResult(result) {
289
- if (this.filterFn)
290
- return this.createResult(result.filter(this.filterFn));
291
- return this.createResult(result);
402
+ omit(...keys) {
403
+ return new ArcObject(Object.fromEntries(Object.entries(this.rawShape).filter(([key]) => !keys.includes(key))));
292
404
  }
293
- checkItem(item) {
294
- if (this.filterFn)
295
- return this.filterFn(item);
296
- return true;
405
+ entries() {
406
+ return Object.entries(this.rawShape);
297
407
  }
298
408
  }
299
-
300
- // collection/queries/all-items.ts
301
- class ArcAllItemsQuery extends ArcManyItemsQuery {
302
- async fetch(store) {
303
- const results = await store.findAll(this.bindedChangeHandler);
304
- return this.createFiltredResult(results);
305
- }
409
+ function object(element) {
410
+ return new ArcObject(element);
306
411
  }
307
412
 
308
- // context/query-builders.ts
309
- class ArcQueryBuilder {
310
- }
413
+ // elements/array.ts
414
+ var arrayValidator = typeValidatorBuilder("array", Array.isArray);
311
415
 
312
- // collection/query-builders/abstract-many-items.ts
313
- function sortComparatorBuilder(comparator) {
314
- if (typeof comparator === "function") {
315
- return comparator;
316
- } else if (Array.isArray(comparator)) {
317
- return (a, b) => {
318
- for (const [key, order] of comparator) {
319
- if (a[key] < b[key])
320
- return order === "ASC" ? -1 : 1;
321
- if (a[key] > b[key])
322
- return order === "ASC" ? 1 : -1;
416
+ class ArcArray extends ArcAbstract {
417
+ parent;
418
+ constructor(parent) {
419
+ super([
420
+ arrayValidator,
421
+ {
422
+ name: "schema",
423
+ validator: (values) => {
424
+ const errors = values.reduce((acc, value, index) => {
425
+ const error = parent.validate(value);
426
+ if (error)
427
+ acc[index] = error;
428
+ return acc;
429
+ }, {});
430
+ if (Object.values(errors).some((result) => !!result)) {
431
+ return errors;
432
+ }
433
+ return false;
434
+ }
323
435
  }
324
- return 0;
325
- };
436
+ ]);
437
+ this.parent = parent;
326
438
  }
327
- throw new Error("Invalid comparator type");
328
- }
329
-
330
- class ArcManyItemsQueryBuilder extends ArcQueryBuilder {
331
- filterFn;
332
- sortFn;
333
- filter(callback) {
334
- this.filterFn = callback;
335
- return this;
439
+ minLength(min) {
440
+ return this.validation("minLength", (value) => {
441
+ if (value.length < min)
442
+ return {
443
+ currentLength: value.length,
444
+ minLength: min
445
+ };
446
+ });
336
447
  }
337
- sort(comparator) {
338
- this.sortFn = sortComparatorBuilder(comparator);
339
- return this;
448
+ maxLength(max) {
449
+ return this.validation("maxLength", (value) => {
450
+ if (value.length > max)
451
+ return {
452
+ currentLength: value.length,
453
+ maxLength: max
454
+ };
455
+ });
340
456
  }
341
- }
342
-
343
- // collection/query-builders/all-items.ts
344
- class ArcAllItemsQueryBuilder extends ArcManyItemsQueryBuilder {
345
- collection;
346
- constructor(collection) {
347
- super();
348
- this.collection = collection;
349
- if (collection.options.sort)
350
- this.sortFn = collection.options.sort;
457
+ length(number) {
458
+ return this.validation("length", (value) => {
459
+ if (value.length !== number) {
460
+ return {
461
+ currentLength: value.length,
462
+ length: number
463
+ };
464
+ }
465
+ });
351
466
  }
352
- toQuery() {
353
- return new ArcAllItemsQuery(this.collection, this.filterFn, this.sortFn);
467
+ nonEmpty() {
468
+ return this.validation("nonEmpty", (value) => {
469
+ if (value.length === 0)
470
+ return { msg: "array is empty" };
471
+ });
354
472
  }
355
- }
356
-
357
- // db/index-query.ts
358
- function indexQueryPredicate(item, query) {
359
- if (!("$gt" in query) && !("$gte" in query) && !("$lt" in query) && !("$lte" in query)) {
360
- return Object.entries(query).every(([key, value]) => item[key] === value);
361
- }
362
- if (query.$gt) {
363
- const isGreaterThan = Object.entries(query.$gt).every(([key, value]) => item[key] > value);
364
- if (!isGreaterThan)
365
- return false;
473
+ parse(value) {
474
+ return value.map((v) => this.parent.parse(v));
366
475
  }
367
- if (query.$gte) {
368
- const isGreaterThanOrEqual = Object.entries(query.$gte).every(([key, value]) => item[key] >= value);
369
- if (!isGreaterThanOrEqual)
370
- return false;
476
+ serialize(value) {
477
+ return value.map((v) => this.parent.serialize(v));
371
478
  }
372
- if (query.$lt) {
373
- const isLessThan = Object.entries(query.$lt).every(([key, value]) => item[key] < value);
374
- if (!isLessThan)
375
- return false;
479
+ deserialize(value) {
480
+ if (!Array.isArray(value))
481
+ return [];
482
+ return value.map((v) => this.parent.deserialize(v));
376
483
  }
377
- if (query.$lte) {
378
- const isLessThanOrEqual = Object.entries(query.$lte).every(([key, value]) => item[key] <= value);
379
- if (!isLessThanOrEqual)
380
- return false;
484
+ deserializePath(path, value) {
485
+ if (path.length === 0) {
486
+ return this.deserialize(value);
487
+ }
488
+ if (this.parent instanceof ArcObject || this.parent instanceof ArcArray) {
489
+ return this.parent.deserializePath(path, value);
490
+ }
491
+ return this.parent.deserialize(value);
381
492
  }
382
- return true;
383
- }
384
-
385
- // collection/queries/indexed.ts
386
- class ArcIndexedItemsQuery extends ArcManyItemsQuery {
387
- index;
388
- data;
389
- filterFn;
390
- sortFn;
391
- constructor(collection, index, data, filterFn, sortFn) {
392
- super(collection, filterFn, sortFn);
393
- this.index = index;
394
- this.data = data;
395
- this.filterFn = filterFn;
396
- this.sortFn = sortFn;
493
+ validation(name, validator) {
494
+ const instance = this.pipeValidation(name, validator);
495
+ return instance;
397
496
  }
398
- checkItem(item) {
399
- if (!super.checkItem(item))
400
- return false;
401
- return indexQueryPredicate(item, this.data);
497
+ }
498
+ function array(element) {
499
+ return new ArcArray(element);
500
+ }
501
+ // elements/boolean.ts
502
+ class ArcBoolean extends ArcPrimitive {
503
+ }
504
+ function boolean() {
505
+ return new ArcBoolean;
506
+ }
507
+ // elements/date.ts
508
+ var dateValidator = typeValidatorBuilder("Date", (value) => value instanceof Date);
509
+
510
+ class ArcDate extends ArcAbstract {
511
+ constructor() {
512
+ super([dateValidator]);
402
513
  }
403
- async fetch(store) {
404
- const results = await store.findByIndex(this.index, this.data, this.bindedChangeHandler);
405
- return this.createFiltredResult(results);
514
+ parse(value) {
515
+ return new Date(value);
516
+ }
517
+ serialize(value) {
518
+ return value.getTime();
519
+ }
520
+ deserialize(value) {
521
+ return new Date(value);
522
+ }
523
+ after(after) {
524
+ return this.validation("after", (value) => {
525
+ if (value <= after)
526
+ return { current: value, after };
527
+ });
528
+ }
529
+ before(before) {
530
+ return this.validation("before", (value) => {
531
+ if (value >= before)
532
+ return { current: value, before };
533
+ });
534
+ }
535
+ validation(name, validator) {
536
+ const instance = this.pipeValidation(name, validator);
537
+ return instance;
406
538
  }
407
539
  }
540
+ function date() {
541
+ return new ArcDate;
542
+ }
543
+ // elements/number.ts
544
+ var numberValidator = typeValidatorBuilder("number");
408
545
 
409
- // collection/query-builders/indexed.ts
410
- class ArcIndexedItemsQueryBuilder extends ArcManyItemsQueryBuilder {
411
- collection;
412
- index;
413
- data;
414
- constructor(collection, index, data) {
546
+ class ArcNumber extends ArcPrimitive {
547
+ constructor() {
548
+ super([numberValidator]);
549
+ }
550
+ min(min) {
551
+ return this.validation("min", (value) => {
552
+ if (value < min)
553
+ return { current: value, min };
554
+ });
555
+ }
556
+ max(max) {
557
+ return this.validation("max", (value) => {
558
+ if (value > max)
559
+ return { current: value, max };
560
+ });
561
+ }
562
+ validation(name, validator) {
563
+ const instance = this.pipeValidation(name, validator);
564
+ return instance;
565
+ }
566
+ }
567
+ function number() {
568
+ return new ArcNumber;
569
+ }
570
+ // elements/record.ts
571
+ class ArcRecord extends ArcAbstract {
572
+ key;
573
+ element;
574
+ constructor(key, element) {
575
+ super([
576
+ {
577
+ name: "schema",
578
+ validator: (value) => {
579
+ const errors = Object.entries(value).reduce((acc, [key2, element2]) => {
580
+ const error = this.element.validate(element2);
581
+ if (error) {
582
+ acc[key2] = error;
583
+ }
584
+ return acc;
585
+ }, {});
586
+ if (Object.entries(errors).some(([key2, element2]) => !!(key2 || element2))) {
587
+ return errors;
588
+ }
589
+ return false;
590
+ }
591
+ }
592
+ ]);
593
+ this.key = key;
594
+ this.element = element;
595
+ }
596
+ parse(value) {
597
+ if (!value)
598
+ return {};
599
+ return Object.entries(value).reduce((acc, [key, recordValue]) => {
600
+ acc[key] = this.element.parse(recordValue);
601
+ return acc;
602
+ }, {});
603
+ }
604
+ serialize(value) {
605
+ if (!value)
606
+ return {};
607
+ return Object.entries(value).reduce((acc, [key, recordValue]) => {
608
+ acc[key] = this.element.serialize(recordValue);
609
+ return acc;
610
+ }, {});
611
+ }
612
+ deserialize(value) {
613
+ if (!value)
614
+ return {};
615
+ return Object.entries(value).reduce((acc, [key, recordValue]) => {
616
+ acc[key] = this.element.deserialize(recordValue);
617
+ return acc;
618
+ }, {});
619
+ }
620
+ }
621
+ function record(key, element) {
622
+ return new ArcRecord(key, element);
623
+ }
624
+ // elements/string-enum.ts
625
+ class ArcStringEnum extends ArcAbstract {
626
+ values;
627
+ constructor(values) {
628
+ super([
629
+ {
630
+ name: "schema",
631
+ validator: (value) => {
632
+ if (this.values.includes(value))
633
+ return false;
634
+ return { expect: values, current: value };
635
+ }
636
+ }
637
+ ]);
638
+ this.values = values;
639
+ }
640
+ parse(value) {
641
+ return value;
642
+ }
643
+ serialize(value) {
644
+ return value;
645
+ }
646
+ deserialize(value) {
647
+ return value;
648
+ }
649
+ getEnumerators() {
650
+ return this.values;
651
+ }
652
+ }
653
+ function stringEnum(...values) {
654
+ return new ArcStringEnum(values);
655
+ }
656
+ // utils/arcObjectToStoreSchema.ts
657
+ function getSQLiteType(element) {
658
+ if (element instanceof ArcDate) {
659
+ return "TEXT";
660
+ }
661
+ if (element instanceof ArcArray || element instanceof ArcObject) {
662
+ return "TEXT";
663
+ }
664
+ if (element instanceof ArcBoolean) {
665
+ return "INTEGER";
666
+ }
667
+ if (element instanceof ArcNumber) {
668
+ return "NUMBER";
669
+ }
670
+ return "TEXT";
671
+ }
672
+ function arcObjectToStoreSchema(tableName, schema) {
673
+ const columns = schema.entries().map(([name, element]) => ({
674
+ name,
675
+ type: getSQLiteType(element),
676
+ isOptional: element instanceof ArcOptional
677
+ }));
678
+ columns.unshift({
679
+ name: "_id",
680
+ type: "TEXT",
681
+ isOptional: false
682
+ }, {
683
+ name: "deleted",
684
+ type: "INTEGER",
685
+ isOptional: false,
686
+ default: 0
687
+ }, {
688
+ name: "lastUpdate",
689
+ type: "TEXT",
690
+ isOptional: false
691
+ });
692
+ return {
693
+ tables: [
694
+ {
695
+ name: tableName,
696
+ columns,
697
+ primaryKey: "_id"
698
+ }
699
+ ]
700
+ };
701
+ }
702
+
703
+ // context/query.ts
704
+ class ArcQuery {
705
+ lastResult;
706
+ listeners = new Set;
707
+ subscribe(listener) {
708
+ this.listeners.add(listener);
709
+ }
710
+ unsubscribe(listener) {
711
+ this.listeners.delete(listener);
712
+ }
713
+ nextResult(result) {
714
+ this.lastResult = result;
715
+ this.listeners.forEach((listener) => listener(result));
716
+ }
717
+ }
718
+
719
+ // context/serializable-query.ts
720
+ class ArcSerializableQuery extends ArcQuery {
721
+ params;
722
+ static key;
723
+ constructor(params) {
415
724
  super();
725
+ this.params = params;
726
+ }
727
+ serialize() {
728
+ return {
729
+ key: this.constructor.key,
730
+ params: this.params
731
+ };
732
+ }
733
+ }
734
+
735
+ // collection/queries/abstract-collection-query.ts
736
+ class ArcCollectionQuery extends ArcSerializableQuery {
737
+ collection;
738
+ bindedChangeHandler = this.changeHandler.bind(this);
739
+ store;
740
+ constructor(collection, params) {
741
+ super(params);
416
742
  this.collection = collection;
417
- this.index = index;
418
- this.data = data;
419
- if (collection.options.sort)
420
- this.sortFn = collection.options.sort;
421
743
  }
422
- toQuery() {
423
- return new ArcIndexedItemsQuery(this.collection, this.index, this.data, this.filterFn, this.sortFn);
744
+ async run(dataStorage) {
745
+ const store = dataStorage.getStore(this.collection.name);
746
+ this.store = store;
747
+ const result = await this.fetch(store);
748
+ this.lastResult = result;
749
+ return result;
750
+ }
751
+ changeHandler(changes) {
752
+ let resultChanged = false;
753
+ for (const change of changes) {
754
+ const response = this.onChange(change);
755
+ if (response !== false) {
756
+ this.lastResult = response;
757
+ resultChanged = true;
758
+ }
759
+ }
760
+ if (resultChanged)
761
+ this.nextResult(this.lastResult);
762
+ }
763
+ }
764
+
765
+ // collection/queries/find.ts
766
+ class QueryCollectionResult {
767
+ result;
768
+ constructor(result) {
769
+ this.result = result;
770
+ }
771
+ get(id3) {
772
+ return id3 ? this.result.find((r) => r._id === id3) : undefined;
773
+ }
774
+ map(callbackfn) {
775
+ return this.result.map(callbackfn);
776
+ }
777
+ toArray() {
778
+ return this.result;
424
779
  }
425
780
  }
426
781
 
427
- // collection/queries/one-item.ts
428
- class ArcOneItemQuery extends ArcCollectionQuery {
429
- id2;
430
- constructor(collection, id2) {
431
- super(collection);
432
- this.id = id2;
782
+ class ArcFindQuery extends ArcCollectionQuery {
783
+ params;
784
+ constructor(collection, params) {
785
+ super(collection, params);
786
+ this.params = params;
787
+ }
788
+ async fetch(store) {
789
+ const results = await store.find(this.params, this.bindedChangeHandler);
790
+ return this.createResult(results);
791
+ }
792
+ checkItem(item) {
793
+ if (!this.params.where)
794
+ return true;
795
+ return Object.entries(this.params.where).every(([key, condition]) => {
796
+ const value = item[key];
797
+ if (typeof condition !== "object" || condition === null) {
798
+ return value === condition;
799
+ }
800
+ return Object.entries(condition).every(([operator, operatorValue]) => {
801
+ switch (operator) {
802
+ case "$eq":
803
+ return value === operatorValue;
804
+ case "$ne":
805
+ return value !== operatorValue;
806
+ case "$gt":
807
+ return typeof value === "number" && typeof operatorValue === "number" && value > operatorValue;
808
+ case "$gte":
809
+ return typeof value === "number" && typeof operatorValue === "number" && value >= operatorValue;
810
+ case "$lt":
811
+ return typeof value === "number" && typeof operatorValue === "number" && value < operatorValue;
812
+ case "$lte":
813
+ return typeof value === "number" && typeof operatorValue === "number" && value <= operatorValue;
814
+ case "$in":
815
+ return Array.isArray(operatorValue) && operatorValue.includes(value);
816
+ case "$nin":
817
+ return Array.isArray(operatorValue) && !operatorValue.includes(value);
818
+ case "$exists":
819
+ return typeof operatorValue === "boolean" ? operatorValue ? value !== undefined : value === undefined : true;
820
+ default:
821
+ return true;
822
+ }
823
+ });
824
+ });
433
825
  }
434
826
  onChange(change) {
435
- if (change.id !== this.id)
436
- return false;
437
- if (change.type === "delete")
438
- return null;
439
- if (change.type === "set")
440
- return change.item;
827
+ const lastResult = this.lastResult;
828
+ const lastResultAsArray = lastResult?.toArray() || [];
829
+ const index = lastResultAsArray.findIndex((e) => e._id === (change.type === "delete" ? change.id : change.id));
830
+ const isInLastResult = index !== -1;
831
+ const shouldBeInTheResult = change.type !== "delete" && this.checkItem(change.item);
832
+ if (isInLastResult && shouldBeInTheResult)
833
+ return this.createResult(lastResultAsArray.toSpliced(index, 1, change.item));
834
+ else if (isInLastResult && (change.type === "delete" || !shouldBeInTheResult))
835
+ return this.createResult(lastResultAsArray.toSpliced(index, 1));
836
+ else if (!isInLastResult && shouldBeInTheResult)
837
+ return this.createResult(lastResultAsArray.concat(change.item));
441
838
  return false;
442
839
  }
443
- async fetch(store) {
444
- const result = await store.findById(this.id, this.bindedChangeHandler);
445
- return result;
840
+ createResult(result) {
841
+ return new QueryCollectionResult(result);
446
842
  }
447
843
  }
448
844
 
449
- // collection/query-builders/one-item.ts
450
- class ArcOneItemQueryBuilder extends ArcQueryBuilder {
845
+ // collection/query-builders/find.ts
846
+ class ArcFindQueryBuilder {
451
847
  collection;
452
- id2;
453
- constructor(collection, id2) {
454
- super();
848
+ queryContext;
849
+ options;
850
+ constructor(collection, queryContext, options) {
455
851
  this.collection = collection;
456
- this.id = id2;
852
+ this.queryContext = queryContext;
853
+ this.options = options;
457
854
  }
458
855
  toQuery() {
459
- return new ArcOneItemQuery(this.collection, this.id);
856
+ return this.queryContext.cacheQuery(ArcFindQuery, [
857
+ this.collection,
858
+ this.options
859
+ ]);
860
+ }
861
+ run() {
862
+ return this.queryContext.runQuery(this.toQuery());
460
863
  }
461
864
  }
462
865
 
463
866
  // collection/collection.ts
464
- class ArcCollection extends ArcContextElement {
867
+ class ArcCollection extends ArcContextElementWithStore {
465
868
  name;
466
- id2;
869
+ id;
467
870
  schema;
468
871
  options;
469
- constructor(name, id2, schema, options) {
872
+ constructor(name, id3, schema, options) {
470
873
  super();
471
874
  this.name = name;
472
- this.id = id2;
875
+ this.id = id3;
473
876
  this.schema = schema;
474
877
  this.options = options;
475
878
  }
879
+ storeSchema() {
880
+ return arcObjectToStoreSchema(this.name, this.schema);
881
+ }
476
882
  serialize(data) {
477
883
  return {
478
884
  _id: this.id.serialize(data._id),
@@ -485,22 +891,22 @@ class ArcCollection extends ArcContextElement {
485
891
  ...this.schema.deserialize(data)
486
892
  };
487
893
  }
488
- queryBuilder() {
894
+ queryBuilder = (context) => {
489
895
  return {
490
- all: () => new ArcAllItemsQueryBuilder(this),
491
- one: (id2) => new ArcOneItemQueryBuilder(this, id2)
896
+ find: (options) => new ArcFindQueryBuilder(this, context, options || {})
492
897
  };
493
- }
494
- commandContext(dataStorage, publishEvent) {
898
+ };
899
+ commandContext = (dataStorage, publishEvent) => {
495
900
  const store = dataStorage.getStore(this.name);
496
901
  return {
497
902
  add: async (data) => {
498
903
  if (this.id instanceof ArcCustomId)
499
904
  throw new Error("Collection with custom id not support 'add' method");
500
- const id2 = this.id.generate();
905
+ const id3 = this.id.generate();
501
906
  const parsed = this.schema.parse(data);
502
907
  const body = {
503
- _id: id2,
908
+ _id: id3,
909
+ lastUpdate: new Date().toISOString(),
504
910
  ...parsed
505
911
  };
506
912
  await store.set(body);
@@ -508,16 +914,16 @@ class ArcCollection extends ArcContextElement {
508
914
  type: "set",
509
915
  to: body
510
916
  });
511
- return { id: id2 };
917
+ return { id: id3 };
512
918
  },
513
- remove: async (id2) => {
514
- await store.remove(id2);
919
+ remove: async (id3) => {
920
+ await store.remove(id3);
515
921
  return { success: true };
516
922
  },
517
- set: async (id2, data) => {
923
+ set: async (id3, data) => {
518
924
  const parsed = this.schema.parse(data);
519
925
  const body = {
520
- _id: id2,
926
+ _id: id3,
521
927
  ...parsed
522
928
  };
523
929
  await store.set(body);
@@ -527,15 +933,19 @@ class ArcCollection extends ArcContextElement {
527
933
  });
528
934
  return { success: true };
529
935
  },
530
- all: async () => {
531
- return store.findAll();
936
+ find: async (options) => {
937
+ return store.find(options);
532
938
  },
533
- one: async (id2) => {
534
- return store.findById(id2);
939
+ findOne: async (where) => {
940
+ const result = await store.find({
941
+ where,
942
+ limit: 1
943
+ });
944
+ return result[0];
535
945
  },
536
- modify: async (id2, data) => {
946
+ modify: async (id3, data) => {
537
947
  const deserialized = this.schema.serializePartial(data);
538
- const { from, to } = await store.modify(id2, deserialized);
948
+ const { from, to } = await store.modify(id3, deserialized);
539
949
  await publishEvent({
540
950
  type: "modify",
541
951
  changes: deserialized,
@@ -543,8 +953,8 @@ class ArcCollection extends ArcContextElement {
543
953
  to
544
954
  });
545
955
  },
546
- edit: async (id2, editCallback) => {
547
- const { from, to } = await store.mutate(id2, editCallback);
956
+ edit: async (id3, editCallback) => {
957
+ const { from, to } = await store.mutate(id3, editCallback);
548
958
  await publishEvent({
549
959
  type: "mutate",
550
960
  from,
@@ -552,118 +962,385 @@ class ArcCollection extends ArcContextElement {
552
962
  });
553
963
  }
554
964
  };
555
- }
556
- indexBy(indexes) {
557
- return new ArcIndexedCollection(this.name, this.id, this.schema, this.options, indexes);
558
- }
965
+ };
559
966
  }
560
-
561
- class ArcIndexedCollection extends ArcCollection {
562
- indexes;
563
- constructor(name, id2, schema, options, indexes) {
564
- super(name, id2, schema, options);
565
- this.indexes = indexes;
566
- }
567
- commandContext(dataStorage, publishEvent) {
568
- const superContext = super.commandContext(dataStorage, publishEvent);
569
- return new Proxy(superContext, {
570
- get: (target, name) => {
571
- if (name in target) {
572
- return target[name];
573
- }
574
- if (!(name in this.indexes)) {
575
- throw new Error(`Index "${name}" not found in collection "${this.name}"`);
576
- }
577
- return (data) => dataStorage.getStore(this.name).findByIndex(name, data);
578
- }
579
- });
967
+ function collection(name, id3, schema, options = {}) {
968
+ return new ArcCollection(name, id3, schema, options);
969
+ }
970
+ // command/command.ts
971
+ class ArcCommand extends ArcContextElement {
972
+ name;
973
+ _description;
974
+ _params;
975
+ _result;
976
+ _elements;
977
+ _handler;
978
+ constructor(name) {
979
+ super();
980
+ this.name = name;
580
981
  }
581
- queryBuilder() {
582
- const superQueryBuilder = super.queryBuilder();
583
- return new Proxy({}, {
584
- get: (target, name) => {
585
- if (name in superQueryBuilder)
586
- return superQueryBuilder[name];
587
- if (!(name in this.indexes)) {
588
- throw new Error(`Index "${name}" not found in collection "${this.name}"`);
589
- }
590
- return (data) => new ArcIndexedItemsQueryBuilder(this, name, data);
591
- }
592
- });
982
+ use(elements) {
983
+ const clone = this.clone();
984
+ clone._elements = elements;
985
+ return clone;
986
+ }
987
+ description(description) {
988
+ const clone = this.clone();
989
+ clone._description = description;
990
+ return clone;
991
+ }
992
+ withParams(schema) {
993
+ const clone = this.clone();
994
+ clone._params = schema instanceof ArcObject ? schema : object(schema);
995
+ return clone;
996
+ }
997
+ withResult(schema) {
998
+ const clone = this.clone();
999
+ clone._result = object(schema);
1000
+ return clone;
1001
+ }
1002
+ handle(handler) {
1003
+ const clone = this.clone();
1004
+ clone._handler = handler;
1005
+ return clone;
1006
+ }
1007
+ commandClient = (ctx) => {
1008
+ return Object.assign(async (params) => {
1009
+ if (this._handler)
1010
+ return this._handler?.(ctx, params);
1011
+ }, { params: this._params });
1012
+ };
1013
+ clone() {
1014
+ const clone = new ArcCommand(this.name);
1015
+ clone._description = this._description;
1016
+ clone._params = this._params;
1017
+ clone._result = this._result;
1018
+ clone._handler = this._handler;
1019
+ clone._elements = this._elements;
1020
+ return clone;
593
1021
  }
594
1022
  }
595
- function collection(name, id2, schema, options = {}) {
596
- return new ArcCollection(name, id2, schema, options);
1023
+ function command(name) {
1024
+ return new ArcCommand(name);
597
1025
  }
598
1026
  // context/context.ts
599
1027
  class ArcContext {
600
- version;
601
1028
  elements;
602
- commands;
603
- listeners;
604
- elementsMap;
605
- constructor(version, elements, commands, listeners) {
606
- this.version = version;
1029
+ eventListeners;
1030
+ constructor(elements) {
607
1031
  this.elements = elements;
608
- this.commands = commands;
609
- this.listeners = listeners;
610
- this.elementsMap = Object.fromEntries(elements.map((element) => [element.name, element]));
1032
+ this.eventListeners = new Map;
1033
+ elements.forEach((element) => {
1034
+ if (element.observer) {
1035
+ const handlers = element.observer();
1036
+ Object.entries(handlers).forEach(([alias, handler]) => {
1037
+ const listeners = this.eventListeners.get(alias) || [];
1038
+ listeners.push(handler);
1039
+ this.eventListeners.set(alias, listeners);
1040
+ });
1041
+ }
1042
+ });
1043
+ }
1044
+ pipe(newElements) {
1045
+ return new ArcContext([
1046
+ ...this.elements,
1047
+ ...newElements.filter(Boolean)
1048
+ ]);
611
1049
  }
612
- queryBuilder() {
1050
+ queryBuilder(queryContext) {
613
1051
  return new Proxy({}, {
614
1052
  get: (target, name) => {
615
- const element = this.elementsMap[name];
1053
+ const element = this.elements.find((element2) => element2.name === name);
616
1054
  if (!element) {
617
- throw new Error(`Collection "${name}" not found`);
1055
+ throw new Error(`Element "${String(name)}" not found`);
1056
+ }
1057
+ if (!element.queryBuilder) {
1058
+ throw new Error(`Element "${String(name)}" does not have a query builder`);
618
1059
  }
619
- return element.queryBuilder();
1060
+ return element.queryBuilder(queryContext);
620
1061
  }
621
1062
  });
622
1063
  }
623
- commandContext(client, dataStorage, publishEvent) {
1064
+ commandContext(client, dataStorage) {
624
1065
  return new Proxy({}, {
625
1066
  get: (target, name) => {
626
1067
  if (name === "$client") {
627
1068
  return client;
628
1069
  }
629
- const element = this.elementsMap[name];
630
- return element.commandContext(dataStorage, (event) => publishEvent({
631
- element: name,
632
- ...event
633
- }));
1070
+ const element = this.elements.find((element2) => element2.name === name);
1071
+ if (!element) {
1072
+ throw new Error(`Element "${String(name)}" not found`);
1073
+ }
1074
+ if (!element.commandContext) {
1075
+ throw new Error(`Element "${String(name)}" does not have a command context`);
1076
+ }
1077
+ return element.commandContext(dataStorage, async (event) => {
1078
+ const listeners = this.eventListeners.get(event.type) || [];
1079
+ await Promise.all(listeners.map((listener) => listener(event, dataStorage)));
1080
+ });
634
1081
  }
635
1082
  });
636
1083
  }
637
- commandsClient(client, dataStorage, catchErrorCallback) {
1084
+ commandsClient(client, queryContext, dataStorage, catchErrorCallback) {
638
1085
  return new Proxy({}, {
639
1086
  get: (_, name) => {
640
- if (name in this.commands) {
641
- return async (...args) => {
642
- const forkedDataStorage = dataStorage.fork();
643
- const commandContext = this.commandContext(client, forkedDataStorage, async (data) => {
644
- if (!this.listeners)
645
- return;
646
- await Promise.all(this.listeners?.map((listener) => listener(data, commandContext)));
647
- });
648
- try {
649
- const result = await this.commands[name](commandContext, ...args);
650
- await forkedDataStorage.merge();
651
- return result;
652
- } catch (error) {
653
- console.log("error", error);
654
- catchErrorCallback(error);
655
- return error;
656
- }
657
- };
1087
+ const element = this.elements.find((element2) => element2.name === name);
1088
+ if (!element) {
1089
+ throw new Error(`Element "${String(name)}" not found`);
1090
+ }
1091
+ if (!element.commandClient) {
1092
+ throw new Error(`Element "${String(name)}" does not have a command client`);
1093
+ }
1094
+ return async (arg) => {
1095
+ const forkedDataStorage = dataStorage.fork();
1096
+ const commandContext = this.commandContext(client, forkedDataStorage);
1097
+ try {
1098
+ const result = await element.commandClient(commandContext)(arg);
1099
+ await forkedDataStorage.merge();
1100
+ return result;
1101
+ } catch (error) {
1102
+ console.log("error", error);
1103
+ catchErrorCallback(error);
1104
+ return error;
1105
+ }
1106
+ };
1107
+ }
1108
+ });
1109
+ }
1110
+ }
1111
+ async function context(elementsPromise) {
1112
+ const elements = await Promise.all(elementsPromise.map(async (element) => {
1113
+ if (element instanceof Promise) {
1114
+ return (await element).default;
1115
+ }
1116
+ return element;
1117
+ })).then((elements2) => elements2.filter(Boolean));
1118
+ return new ArcContext(elements);
1119
+ }
1120
+ // context/event.ts
1121
+ var eventValidator = typeValidatorBuilder("object");
1122
+ var eventStoreSchema = {
1123
+ tables: [
1124
+ {
1125
+ name: "events",
1126
+ primaryKey: "id",
1127
+ columns: [
1128
+ {
1129
+ name: "id",
1130
+ type: "string"
1131
+ },
1132
+ {
1133
+ name: "type",
1134
+ type: "string"
1135
+ },
1136
+ {
1137
+ name: "payload",
1138
+ type: "object"
1139
+ },
1140
+ {
1141
+ name: "createdAt",
1142
+ type: "datetime"
658
1143
  }
659
- console.warn(`Command '${name}' not found in the context.`);
1144
+ ]
1145
+ }
1146
+ ]
1147
+ };
1148
+ var eventId = id("event");
1149
+
1150
+ class ArcEvent extends ArcContextElementWithStore {
1151
+ name;
1152
+ payload;
1153
+ storeSchema = () => eventStoreSchema;
1154
+ constructor(name, payload) {
1155
+ super();
1156
+ this.name = name;
1157
+ this.payload = payload;
1158
+ }
1159
+ commandContext = (dataStorage, publishEvent) => {
1160
+ return {
1161
+ emit: async (payload) => {
1162
+ const event = {
1163
+ id: eventId.generate(),
1164
+ type: this.name,
1165
+ payload,
1166
+ createdAt: new Date().toISOString()
1167
+ };
1168
+ await dataStorage.getStore("events").set(event);
1169
+ await publishEvent(event);
1170
+ }
1171
+ };
1172
+ };
1173
+ }
1174
+ function event(name, payload) {
1175
+ return new ArcEvent(name, payload ? new ArcObject(payload) : undefined);
1176
+ }
1177
+ // context/query-builder-context.ts
1178
+ class QueryBuilderContext {
1179
+ queryCache;
1180
+ dataStorage;
1181
+ usedQueries = new Set;
1182
+ constructor(queryCache, dataStorage) {
1183
+ this.queryCache = queryCache;
1184
+ this.dataStorage = dataStorage;
1185
+ }
1186
+ cacheQuery(QueryConstructor, args) {
1187
+ return new QueryConstructor(...args);
1188
+ }
1189
+ runQuery(query) {
1190
+ this.usedQueries.add(query);
1191
+ return query.run(this.dataStorage);
1192
+ }
1193
+ getUsedQueries() {
1194
+ const queries = Array.from(this.usedQueries);
1195
+ this.usedQueries.clear();
1196
+ return queries;
1197
+ }
1198
+ }
1199
+ // context/query-builders.ts
1200
+ class ArcQueryBuilder {
1201
+ queryContext;
1202
+ constructor(queryContext) {
1203
+ this.queryContext = queryContext;
1204
+ }
1205
+ run() {
1206
+ const query = this.toQuery();
1207
+ return this.queryContext.runQuery(query);
1208
+ }
1209
+ }
1210
+ // utils/murmur-hash.ts
1211
+ function murmurHash(key, seed = 0) {
1212
+ var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i;
1213
+ remainder = key.length & 3;
1214
+ bytes = key.length - remainder;
1215
+ h1 = seed;
1216
+ c1 = 3432918353;
1217
+ c2 = 461845907;
1218
+ i = 0;
1219
+ while (i < bytes) {
1220
+ k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
1221
+ ++i;
1222
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
1223
+ k1 = k1 << 15 | k1 >>> 17;
1224
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
1225
+ h1 ^= k1;
1226
+ h1 = h1 << 13 | h1 >>> 19;
1227
+ h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
1228
+ h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
1229
+ }
1230
+ k1 = 0;
1231
+ switch (remainder) {
1232
+ case 3:
1233
+ k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
1234
+ case 2:
1235
+ k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
1236
+ case 1:
1237
+ k1 ^= key.charCodeAt(i) & 255;
1238
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
1239
+ k1 = k1 << 15 | k1 >>> 17;
1240
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
1241
+ h1 ^= k1;
1242
+ }
1243
+ h1 ^= key.length;
1244
+ h1 ^= h1 >>> 16;
1245
+ h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
1246
+ h1 ^= h1 >>> 13;
1247
+ h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
1248
+ h1 ^= h1 >>> 16;
1249
+ return h1 >>> 0;
1250
+ }
1251
+
1252
+ // context/query-cache.ts
1253
+ class QueryCache {
1254
+ cache = new Map;
1255
+ getIndexHash(value) {
1256
+ if (typeof value === "number" || typeof value === "string" || typeof value === "function" || value === null || value === undefined) {
1257
+ return value;
1258
+ }
1259
+ return murmurHash(value);
1260
+ }
1261
+ set(index, query) {
1262
+ let current = this.cache;
1263
+ for (let i = 0;i < index.length - 1; i++) {
1264
+ const hashedIndex = this.getIndexHash(index[i]);
1265
+ if (!current.has(hashedIndex)) {
1266
+ current.set(hashedIndex, new Map);
1267
+ }
1268
+ current = current.get(hashedIndex);
1269
+ }
1270
+ const lastHashedIndex = this.getIndexHash(index[index.length - 1]);
1271
+ current.set(lastHashedIndex, query);
1272
+ }
1273
+ get(index) {
1274
+ let current = this.cache;
1275
+ for (let i = 0;i < index.length - 1; i++) {
1276
+ const hashedIndex = this.getIndexHash(index[i]);
1277
+ if (!current.has(hashedIndex)) {
660
1278
  return;
661
1279
  }
1280
+ current = current.get(hashedIndex);
1281
+ }
1282
+ const lastHashedIndex = this.getIndexHash(index[index.length - 1]);
1283
+ return current.get(lastHashedIndex);
1284
+ }
1285
+ debug() {
1286
+ return this.cache;
1287
+ }
1288
+ }
1289
+ // context/reactive-query.ts
1290
+ class ReactiveQuery extends ArcQuery {
1291
+ queryContext;
1292
+ queryBuilder;
1293
+ fn;
1294
+ queries = [];
1295
+ constructor(queryContext, queryBuilder, fn) {
1296
+ super();
1297
+ this.queryContext = queryContext;
1298
+ this.queryBuilder = queryBuilder;
1299
+ this.fn = fn;
1300
+ }
1301
+ run() {
1302
+ const promise = new Promise(async (resolve) => {
1303
+ const value = await this.runQuery();
1304
+ resolve(value);
1305
+ });
1306
+ return promise;
1307
+ }
1308
+ onChangeHandler = this.onChange.bind(this);
1309
+ async onChange() {
1310
+ const value = await this.runQuery();
1311
+ await this.nextResult(value);
1312
+ }
1313
+ async runQuery() {
1314
+ const value = await this.fn(this.queryBuilder);
1315
+ const queries = this.queryContext.getUsedQueries();
1316
+ this.queries.forEach((query) => {
1317
+ if (!queries.includes(query)) {
1318
+ query.unsubscribe(this.onChangeHandler);
1319
+ }
1320
+ });
1321
+ queries.forEach((query) => {
1322
+ if (!this.queries.includes(query)) {
1323
+ query.subscribe(this.onChangeHandler);
1324
+ }
662
1325
  });
1326
+ this.queries = queries;
1327
+ return value;
1328
+ }
1329
+ }
1330
+
1331
+ class ReactiveQueryBuilder {
1332
+ queryBuilder;
1333
+ fn;
1334
+ constructor(queryBuilder, fn) {
1335
+ this.queryBuilder = queryBuilder;
1336
+ this.fn = fn;
1337
+ }
1338
+ toQuery(context2) {
1339
+ return new ReactiveQuery(context2, this.queryBuilder, this.fn);
663
1340
  }
664
1341
  }
665
- function context(version, elements, commands, listeners) {
666
- return new ArcContext(version, elements, commands, listeners);
1342
+ function reactive(fn) {
1343
+ return (context2) => new ReactiveQueryBuilder(context2, fn);
667
1344
  }
668
1345
  // data-storage/data-storage.abstract.ts
669
1346
  class DataStorage {
@@ -717,30 +1394,31 @@ class StoreState {
717
1394
  };
718
1395
  await this.applyChanges([change]);
719
1396
  }
720
- async remove(id2) {
1397
+ async remove(id3) {
721
1398
  const change = {
722
1399
  type: "delete",
723
- id: id2
1400
+ id: id3
724
1401
  };
725
1402
  await this.applyChanges([change]);
726
1403
  }
727
- async modify(id2, data) {
1404
+ async modify(id3, data) {
728
1405
  const change = {
729
1406
  type: "modify",
730
- id: id2,
1407
+ id: id3,
731
1408
  data
732
1409
  };
733
1410
  const { from, to } = await this.applyChange(change);
734
1411
  return { from, to };
735
1412
  }
736
- async mutate(id2, editCallback) {
737
- const object = await this.findById(id2);
738
- const [draft, finalize] = create(object || {}, { enablePatches: true });
1413
+ async mutate(id3, editCallback) {
1414
+ const result = await this.find({ where: { _id: id3 } });
1415
+ const object3 = result[0];
1416
+ const [draft, finalize] = create(object3 || {}, { enablePatches: true });
739
1417
  await editCallback(draft);
740
1418
  const [_, patches] = finalize();
741
1419
  const change = {
742
1420
  type: "mutate",
743
- id: id2,
1421
+ id: id3,
744
1422
  patches
745
1423
  };
746
1424
  const { from, to } = await this.applyChange(change);
@@ -784,10 +1462,10 @@ class ForkedStoreState extends StoreState {
784
1462
  };
785
1463
  }
786
1464
  if (change.type === "delete") {
787
- const from = await this.findById(change.id);
1465
+ const from = await this.find({ where: { _id: change.id } }).then((results) => results[0] || null);
788
1466
  this.changedItems.set(change.id, null);
789
1467
  return {
790
- from: from || null,
1468
+ from,
791
1469
  to: null,
792
1470
  event: {
793
1471
  type: "delete",
@@ -797,7 +1475,9 @@ class ForkedStoreState extends StoreState {
797
1475
  };
798
1476
  }
799
1477
  if (change.type === "modify") {
800
- const existing = await this.findById(change.id);
1478
+ const existing = await this.find({
1479
+ where: { _id: change.id }
1480
+ }).then((results) => results[0]);
801
1481
  const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
802
1482
  const item = this.deserialize ? this.deserialize(updated) : updated;
803
1483
  this.changedItems.set(change.id, item);
@@ -812,7 +1492,9 @@ class ForkedStoreState extends StoreState {
812
1492
  };
813
1493
  }
814
1494
  if (change.type === "mutate") {
815
- const existing = await this.findById(change.id);
1495
+ const existing = await this.find({
1496
+ where: { _id: change.id }
1497
+ }).then((results) => results[0]);
816
1498
  const updated = apply(existing || {}, change.patches);
817
1499
  const item = this.deserialize ? this.deserialize(updated) : updated;
818
1500
  this.changedItems.set(change.id, item);
@@ -829,59 +1511,42 @@ class ForkedStoreState extends StoreState {
829
1511
  throw new Error("Unknown change type");
830
1512
  }
831
1513
  async applyChange(change) {
832
- const { event, from, to } = await this.applyChangeAndReturnEvent(change);
833
- this.notifyListeners([event]);
1514
+ const { event: event3, from, to } = await this.applyChangeAndReturnEvent(change);
1515
+ this.notifyListeners([event3]);
834
1516
  return { from, to };
835
1517
  }
836
1518
  async applyChanges(changes) {
837
1519
  const events = [];
838
1520
  for (const change of changes) {
839
- const { event } = await this.applyChangeAndReturnEvent(change);
840
- if (event)
841
- events.push(event);
1521
+ const { event: event3 } = await this.applyChangeAndReturnEvent(change);
1522
+ if (event3)
1523
+ events.push(event3);
842
1524
  }
843
1525
  if (events.length > 0) {
844
1526
  this.notifyListeners(events);
845
1527
  }
846
1528
  }
847
- async findById(id2, listener) {
848
- if (listener)
849
- this.listeners.set(listener, { callback: listener, id: id2 });
850
- if (this.changedItems.has(id2))
851
- return this.changedItems.get(id2);
852
- return await this.master.findById(id2);
853
- }
854
- async findByIndex(index, data, listener) {
855
- if (listener)
1529
+ async find(options, listener) {
1530
+ if (listener) {
856
1531
  this.listeners.set(listener, { callback: listener });
857
- const parentResult = await this.master.findByIndex(index, data);
1532
+ }
1533
+ const parentResults = await this.master.find(options);
858
1534
  const results = new Map;
859
- parentResult.forEach((item) => results.set(item._id, item));
860
- for (const [id2, changedItem] of this.changedItems) {
1535
+ parentResults.forEach((item) => results.set(item._id, item));
1536
+ for (const [id3, changedItem] of this.changedItems) {
861
1537
  if (changedItem === null) {
862
- results.delete(id2);
1538
+ results.delete(id3);
863
1539
  continue;
864
1540
  }
865
- const matches = Object.entries(data).every(([key, value]) => changedItem[key] === value);
1541
+ const matches = !options.where || Object.entries(options.where).every(([key, value]) => changedItem[key] === value);
866
1542
  if (matches) {
867
- results.set(id2, changedItem);
1543
+ results.set(id3, changedItem);
868
1544
  } else {
869
- results.delete(id2);
1545
+ results.delete(id3);
870
1546
  }
871
1547
  }
872
1548
  return Array.from(results.values());
873
1549
  }
874
- async findAll(listener) {
875
- if (listener)
876
- this.listeners.set(listener, { callback: listener });
877
- const parentResult = await this.master.findAll();
878
- return parentResult.map((item) => {
879
- const id2 = item._id;
880
- if (this.changedItems.has(id2))
881
- return this.changedItems.get(id2);
882
- return item;
883
- });
884
- }
885
1550
  }
886
1551
 
887
1552
  // data-storage/data-storage-forked.ts
@@ -920,8 +1585,6 @@ class ForkedDataStorage extends DataStorage {
920
1585
  // data-storage/store-state-master.ts
921
1586
  import { apply as apply2 } from "mutative";
922
1587
  class MasterStoreState extends StoreState {
923
- items = new Map;
924
- isComplete = false;
925
1588
  constructor(storeName, dataStorage, deserialize) {
926
1589
  super(storeName, dataStorage, deserialize);
927
1590
  }
@@ -929,7 +1592,6 @@ class MasterStoreState extends StoreState {
929
1592
  if (change.type === "set") {
930
1593
  await transaction.set(this.storeName, change.data);
931
1594
  const item = this.deserialize ? this.deserialize(change.data) : change.data;
932
- this.items.set(change.data._id, item);
933
1595
  return {
934
1596
  from: null,
935
1597
  to: item,
@@ -942,7 +1604,6 @@ class MasterStoreState extends StoreState {
942
1604
  }
943
1605
  if (change.type === "delete") {
944
1606
  await transaction.remove(this.storeName, change.id);
945
- this.items.set(change.id, null);
946
1607
  return {
947
1608
  from: null,
948
1609
  to: null,
@@ -954,11 +1615,10 @@ class MasterStoreState extends StoreState {
954
1615
  };
955
1616
  }
956
1617
  if (change.type === "modify") {
957
- const existing = await transaction.findById(this.storeName, change.id);
1618
+ const existing = await transaction.find(this.storeName, { where: { _id: change.id } }).then((results) => results[0]);
958
1619
  const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
959
1620
  await transaction.set(this.storeName, updated);
960
1621
  const item = this.deserialize ? this.deserialize(updated) : updated;
961
- this.items.set(change.id, item);
962
1622
  return {
963
1623
  from: null,
964
1624
  to: item,
@@ -970,11 +1630,10 @@ class MasterStoreState extends StoreState {
970
1630
  };
971
1631
  }
972
1632
  if (change.type === "mutate") {
973
- const existing = await transaction.findById(this.storeName, change.id);
974
- const updated = apply2(existing, change.patches);
1633
+ const existing = await transaction.find(this.storeName, { where: { _id: change.id } }).then((results) => results[0]);
1634
+ const updated = apply2(existing || {}, change.patches);
975
1635
  await transaction.set(this.storeName, updated);
976
1636
  const item = this.deserialize ? this.deserialize(updated) : updated;
977
- this.items.set(change.id, item);
978
1637
  return {
979
1638
  from: null,
980
1639
  to: item,
@@ -989,77 +1648,31 @@ class MasterStoreState extends StoreState {
989
1648
  }
990
1649
  async applyChange(change) {
991
1650
  const transaction = await this.dataStorage.getReadWriteTransaction();
992
- const { event, from, to } = await this.applyChangeAndReturnEvent(transaction, change);
993
- this.notifyListeners([event]);
1651
+ const { event: event3, from, to } = await this.applyChangeAndReturnEvent(transaction, change);
1652
+ await transaction.commit();
1653
+ this.notifyListeners([event3]);
994
1654
  return { from, to };
995
1655
  }
996
1656
  async applyChanges(changes) {
997
1657
  const transaction = await this.dataStorage.getReadWriteTransaction();
998
1658
  const events = [];
999
1659
  for (const change of changes) {
1000
- const { event } = await this.applyChangeAndReturnEvent(transaction, change);
1001
- if (event)
1002
- events.push(event);
1660
+ const { event: event3 } = await this.applyChangeAndReturnEvent(transaction, change);
1661
+ if (event3)
1662
+ events.push(event3);
1003
1663
  }
1004
1664
  await transaction.commit();
1005
1665
  if (events.length > 0) {
1006
1666
  this.notifyListeners(events);
1007
1667
  }
1008
1668
  }
1009
- async findById(id2, listener) {
1010
- if (!id2)
1011
- return;
1012
- if (listener)
1013
- this.listeners.set(listener, { callback: listener, id: id2 });
1014
- if (this.items.has(id2))
1015
- return this.items.get(id2);
1016
- const transaction = await this.dataStorage.getReadTransaction();
1017
- const result = await transaction.findById(this.storeName, id2);
1018
- const item = result && this.deserialize ? this.deserialize(result) : result;
1019
- if (!item)
1020
- return;
1021
- this.items.set(id2, item);
1022
- return item;
1023
- }
1024
- async findByIndex(index, data, listener) {
1025
- if (listener)
1669
+ async find(options, listener) {
1670
+ if (listener) {
1026
1671
  this.listeners.set(listener, { callback: listener });
1027
- if (this.isComplete) {
1028
- const results2 = Array.from(this.items.values()).filter((item) => {
1029
- if (!item)
1030
- return false;
1031
- return indexQueryPredicate(item, data);
1032
- });
1033
- return results2;
1034
1672
  }
1035
1673
  const transaction = await this.dataStorage.getReadTransaction();
1036
- const dbResults = await transaction.findByIndex(this.storeName, index, data);
1037
- const results = dbResults.map((item) => {
1038
- const id2 = item._id;
1039
- if (this.items.has(id2))
1040
- return this.items.get(id2);
1041
- const processedItem = this.deserialize ? this.deserialize(item) : item;
1042
- return processedItem;
1043
- });
1044
- return results;
1045
- }
1046
- async findAll(listener) {
1047
- if (listener)
1048
- this.listeners.set(listener, { callback: listener });
1049
- if (this.isComplete)
1050
- return Array.from(this.items.values()).filter((e) => !!e);
1051
- const transaction = await this.dataStorage.getReadTransaction();
1052
- const dbResults = await transaction.findAll(this.storeName);
1053
- const items = dbResults.map((item) => {
1054
- const id2 = item._id;
1055
- if (this.items.has(id2))
1056
- return this.items.get(id2);
1057
- const processedItem = this.deserialize ? this.deserialize(item) : item;
1058
- this.items.set(processedItem._id, processedItem);
1059
- return processedItem;
1060
- });
1061
- this.isComplete = true;
1062
- return items;
1674
+ const results = await transaction.find(this.storeName, options);
1675
+ return results.map((item) => this.deserialize ? this.deserialize(item) : item);
1063
1676
  }
1064
1677
  }
1065
1678
 
@@ -1083,250 +1696,376 @@ class MasterDataStorage extends DataStorage {
1083
1696
  }
1084
1697
  getStore(storeName) {
1085
1698
  if (!this.stores.has(storeName)) {
1086
- const contextElement = this.arcContext.elementsMap[storeName];
1699
+ const contextElement = this.arcContext.elements.find((element) => element.name === storeName);
1087
1700
  if (!contextElement)
1088
1701
  console.log(`Can't find ${storeName} as context element`);
1089
- this.stores.set(storeName, new MasterStoreState(storeName, this, contextElement && contextElement.deserialize ? (a) => contextElement.deserialize(a) : undefined));
1702
+ this.stores.set(storeName, new MasterStoreState(storeName, this, contextElement && "deserialize" in contextElement && typeof contextElement.deserialize === "function" ? (a) => contextElement.deserialize(a) : undefined));
1090
1703
  }
1091
1704
  return this.stores.get(storeName);
1092
1705
  }
1093
1706
  async applyChanges(changes) {
1094
1707
  return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
1095
1708
  }
1096
- applySerializedChanges(changes) {
1097
- return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applySerializedChanges(changes2)));
1098
- }
1099
- async commitChanges(changes) {
1100
- await Promise.all([
1101
- this.applyChanges(changes),
1102
- this.rtcAdapter.commitChanges(changes)
1103
- ]);
1104
- }
1105
- fork() {
1106
- return new ForkedDataStorage(this);
1107
- }
1108
- async sync(progressCallback) {
1109
- await this.rtcAdapter.sync(progressCallback);
1110
- }
1111
- }
1112
- // elements/object.ts
1113
- class ArcObject extends ArcAbstract {
1114
- rawShape;
1115
- constructor(rawShape) {
1116
- super();
1117
- this.rawShape = rawShape;
1118
- }
1119
- parse(value) {
1120
- return Object.entries(this.rawShape).reduce((acc, [key, element]) => {
1121
- acc[key] = element.parse(value[key]);
1122
- return acc;
1123
- }, {});
1124
- }
1125
- serialize(value) {
1126
- return Object.entries(value).reduce((acc, [key, value2]) => {
1127
- if (!this.rawShape[key]) {
1128
- acc[key] = value2;
1129
- } else {
1130
- acc[key] = this.rawShape[key].serialize(value2);
1131
- }
1132
- return acc;
1133
- }, {});
1134
- }
1135
- deserialize(value) {
1136
- return Object.fromEntries(Object.entries(this.rawShape).map(([key, element]) => [
1137
- key,
1138
- element.deserialize(value[key])
1139
- ]));
1140
- }
1141
- deserializePath(path, value) {
1142
- if (path.length === 0) {
1143
- return this.deserialize(value);
1144
- }
1145
- const [key, ...restPath] = path;
1146
- const element = this.rawShape[key];
1147
- if (!element) {
1148
- console.warn(`No element found for key: ${key}`);
1149
- return value;
1150
- }
1151
- if (element instanceof ArcObject || element instanceof ArcArray) {
1152
- return element.deserializePath(restPath, value);
1153
- }
1154
- return element.deserialize(value);
1155
- }
1156
- parsePartial(value) {
1157
- return Object.entries(value).reduce((acc, [key, value2]) => {
1158
- acc[key] = this.rawShape[key].parse(value2);
1159
- return acc;
1160
- }, {});
1709
+ applySerializedChanges(changes) {
1710
+ return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applySerializedChanges(changes2)));
1161
1711
  }
1162
- deserializePartial(value) {
1163
- return Object.entries(value).reduce((acc, [key, value2]) => {
1164
- acc[key] = this.rawShape[key].deserialize(value2);
1165
- return acc;
1166
- }, {});
1712
+ async commitChanges(changes) {
1713
+ await Promise.all([
1714
+ this.applyChanges(changes),
1715
+ this.rtcAdapter.commitChanges(changes)
1716
+ ]);
1167
1717
  }
1168
- serializePartial(value) {
1169
- return Object.entries(value).reduce((acc, [key, value2]) => {
1170
- acc[key] = this.rawShape[key].serialize(value2);
1171
- return acc;
1172
- }, {});
1718
+ fork() {
1719
+ return new ForkedDataStorage(this);
1173
1720
  }
1174
- pick(...keys) {
1175
- return new ArcObject(Object.fromEntries(keys.map((key) => [key, this.rawShape[key]])));
1721
+ async sync(progressCallback) {
1722
+ await this.rtcAdapter.sync(progressCallback);
1176
1723
  }
1177
- validate(value) {
1178
- console.log(this.rawShape);
1179
- return Object.entries(this.rawShape).reduce((acc, [key, element]) => {
1180
- if (!element.validate) {
1181
- return acc;
1724
+ }
1725
+ // db/sqliteAdapter.ts
1726
+ class SQLiteReadTransaction {
1727
+ db;
1728
+ tables;
1729
+ constructor(db, tables) {
1730
+ this.db = db;
1731
+ this.tables = tables;
1732
+ }
1733
+ getId(store, id3) {
1734
+ return id3;
1735
+ }
1736
+ buildWhereClause(where) {
1737
+ if (!where) {
1738
+ return { sql: "deleted != 1", params: [] };
1739
+ }
1740
+ const conditions = ["deleted != 1"];
1741
+ const params = [];
1742
+ Object.entries(where).forEach(([key, value]) => {
1743
+ if (typeof value === "object" && value !== null) {
1744
+ Object.entries(value).forEach(([operator, operand]) => {
1745
+ switch (operator) {
1746
+ case "$eq":
1747
+ case "$ne":
1748
+ case "$gt":
1749
+ case "$gte":
1750
+ case "$lt":
1751
+ case "$lte":
1752
+ conditions.push(`${key} ${this.getOperatorSymbol(operator)} ?`);
1753
+ params.push(operand);
1754
+ break;
1755
+ case "$in":
1756
+ case "$nin":
1757
+ if (Array.isArray(operand)) {
1758
+ conditions.push(`${key} ${operator === "$in" ? "IN" : "NOT IN"} (${operand.map(() => "?").join(", ")})`);
1759
+ params.push(...operand);
1760
+ }
1761
+ break;
1762
+ case "$exists":
1763
+ if (typeof operand === "boolean") {
1764
+ conditions.push(operand ? `${key} IS NOT NULL` : `${key} IS NULL`);
1765
+ }
1766
+ break;
1767
+ }
1768
+ });
1769
+ } else {
1770
+ conditions.push(`${key} = ?`);
1771
+ params.push(value);
1182
1772
  }
1183
- console.log(element);
1184
- acc[key] = element.validate(value[key]);
1185
- return acc;
1186
- }, {});
1773
+ });
1774
+ return {
1775
+ sql: conditions.join(" AND "),
1776
+ params
1777
+ };
1778
+ }
1779
+ getOperatorSymbol(operator) {
1780
+ const operators = {
1781
+ $eq: "=",
1782
+ $ne: "!=",
1783
+ $gt: ">",
1784
+ $gte: ">=",
1785
+ $lt: "<",
1786
+ $lte: "<="
1787
+ };
1788
+ return operators[operator] || "=";
1789
+ }
1790
+ buildOrderByClause(orderBy) {
1791
+ if (!orderBy)
1792
+ return "";
1793
+ const orderClauses = Object.entries(orderBy).map(([key, direction]) => `${key} ${direction.toUpperCase()}`).join(", ");
1794
+ return orderClauses ? `ORDER BY ${orderClauses}` : "";
1795
+ }
1796
+ async find(store, options) {
1797
+ const { where, limit, offset, orderBy } = options || {};
1798
+ const whereClause = this.buildWhereClause(where);
1799
+ const orderByClause = this.buildOrderByClause(orderBy);
1800
+ const query2 = `
1801
+ SELECT *
1802
+ FROM ${store}
1803
+ WHERE ${whereClause.sql}
1804
+ ${orderByClause}
1805
+ ${limit ? `LIMIT ${limit}` : ""}
1806
+ ${offset ? `OFFSET ${offset}` : ""}
1807
+ `;
1808
+ return await this.db.exec(query2, whereClause.params);
1187
1809
  }
1188
- }
1189
- function object(element) {
1190
- return new ArcObject(element);
1191
1810
  }
1192
1811
 
1193
- // elements/array.ts
1194
- class ArcArray extends ArcAbstract {
1195
- parent;
1196
- constructor(parent) {
1197
- super();
1198
- this.parent = parent;
1199
- }
1200
- parse(value) {
1201
- return value.map((v) => this.parent.parse(v));
1202
- }
1203
- serialize(value) {
1204
- return value.map((v) => this.parent.serialize(v));
1205
- }
1206
- deserialize(value) {
1207
- if (!Array.isArray(value))
1208
- return [];
1209
- return value.map((v) => this.parent.deserialize(v));
1812
+ class SQLiteReadWriteTransaction extends SQLiteReadTransaction {
1813
+ async remove(store, id3) {
1814
+ const table = this.tables.get(store);
1815
+ if (!table) {
1816
+ throw new Error(`Store ${store} not found`);
1817
+ }
1818
+ const query2 = `UPDATE ${store} SET deleted = 1, lastUpdate = ? WHERE ${table.primaryKey} = ?`;
1819
+ await this.db.exec(query2, [new Date().toISOString(), id3]);
1210
1820
  }
1211
- deserializePath(path, value) {
1212
- if (path.length === 0) {
1213
- return this.deserialize(value);
1821
+ async set(store, item) {
1822
+ const schema = this.tables.get(store);
1823
+ if (!schema) {
1824
+ throw new Error(`Store ${store} not found`);
1214
1825
  }
1215
- if (this.parent instanceof ArcObject || this.parent instanceof ArcArray) {
1216
- return this.parent.deserializePath(path, value);
1826
+ const now = new Date().toISOString();
1827
+ const columnNames = schema.columns.map((col) => col.name);
1828
+ const values = schema.columns.map((column) => {
1829
+ let value = item[column.name];
1830
+ if (value === undefined && column.default !== undefined) {
1831
+ value = column.default;
1832
+ }
1833
+ return this.serializeValue(value);
1834
+ });
1835
+ const placeholders = columnNames.map(() => "?").join(", ");
1836
+ const sql = `
1837
+ INSERT OR REPLACE INTO ${schema.name}
1838
+ (${columnNames.join(", ")})
1839
+ VALUES (${placeholders})
1840
+ `;
1841
+ await this.db.exec(sql, values);
1842
+ }
1843
+ async commit() {
1844
+ return Promise.resolve();
1845
+ }
1846
+ serializeValue(value) {
1847
+ if (value === null || value === undefined)
1848
+ return null;
1849
+ if (value instanceof Date) {
1850
+ return value.toISOString();
1217
1851
  }
1218
- return this.parent.deserialize(value);
1852
+ if (Array.isArray(value) || typeof value === "object") {
1853
+ return JSON.stringify(value);
1854
+ }
1855
+ return value;
1219
1856
  }
1220
1857
  }
1221
- function array(element) {
1222
- return new ArcArray(element);
1223
- }
1224
- // elements/boolean.ts
1225
- class ArcBoolean extends ArcPrimitive {
1226
- }
1227
- function boolean() {
1228
- return new ArcBoolean;
1229
- }
1230
- // elements/date.ts
1231
- class ArcDate extends ArcAbstract {
1232
- constructor() {
1233
- super();
1234
- }
1235
- parse(value) {
1236
- return new Date(value);
1237
- }
1238
- serialize(value) {
1239
- return value.getTime();
1858
+
1859
+ class SQLiteAdapter {
1860
+ db;
1861
+ context;
1862
+ tables = new Map;
1863
+ constructor(db, context3) {
1864
+ this.db = db;
1865
+ this.context = context3;
1866
+ this.context.elements.forEach((element) => {
1867
+ if ("storeSchema" in element && typeof element.storeSchema === "function") {
1868
+ element.storeSchema().tables.forEach((table) => {
1869
+ this.tables.set(table.name, table);
1870
+ });
1871
+ }
1872
+ });
1240
1873
  }
1241
- deserialize(value) {
1242
- return new Date(value);
1874
+ async initialize() {
1875
+ const stores = new Set;
1876
+ for (const element of this.context.elements) {
1877
+ if ("storeSchema" in element && typeof element.storeSchema === "function") {
1878
+ const schema = element.storeSchema();
1879
+ stores.add(schema);
1880
+ }
1881
+ }
1882
+ for (const schema of stores) {
1883
+ for (const table of schema.tables) {
1884
+ await this.createTableIfNotExists(table);
1885
+ }
1886
+ }
1243
1887
  }
1244
- }
1245
- function date() {
1246
- return new ArcDate;
1247
- }
1248
- // elements/number.ts
1249
- class ArcNumber extends ArcPrimitive {
1250
- min(min) {
1251
- return this.validation("min", (value) => {
1252
- if (value < min)
1253
- return { current: value, min };
1888
+ async createTableIfNotExists(table) {
1889
+ const columns = table.columns.map((column) => {
1890
+ const constraints = [];
1891
+ if (!column.isOptional) {
1892
+ constraints.push("NOT NULL");
1893
+ }
1894
+ if (column.default !== undefined) {
1895
+ constraints.push(`DEFAULT ${JSON.stringify(column.default)}`);
1896
+ }
1897
+ if (column.name === table.primaryKey) {
1898
+ constraints.push("PRIMARY KEY");
1899
+ }
1900
+ return `"${column.name}" ${column.type} ${constraints.join(" ")}`.trim();
1254
1901
  });
1902
+ const createTableSQL = `
1903
+ CREATE TABLE IF NOT EXISTS ${table.name} (
1904
+ ${columns.join(`,
1905
+ `)}
1906
+ )
1907
+ `;
1908
+ await this.db.exec(createTableSQL);
1255
1909
  }
1256
- max(max) {
1257
- return this.validation("max", (value) => {
1258
- if (value > max)
1259
- return { current: value, max };
1260
- });
1910
+ readWriteTransaction(stores) {
1911
+ return new SQLiteReadWriteTransaction(this.db, this.tables);
1261
1912
  }
1262
- validation(name, validator) {
1263
- const instance = this.pipeValidation(name, validator);
1264
- return instance;
1913
+ readTransaction(stores) {
1914
+ return new SQLiteReadTransaction(this.db, this.tables);
1265
1915
  }
1266
1916
  }
1267
- function number() {
1268
- return new ArcNumber;
1917
+ var createSQLiteAdapterFactory = (db) => {
1918
+ return async (context3) => {
1919
+ const adapter = new SQLiteAdapter(db, context3);
1920
+ await adapter.initialize();
1921
+ return adapter;
1922
+ };
1923
+ };
1924
+ // model/model.ts
1925
+ class ModelBase {
1269
1926
  }
1270
- // elements/record.ts
1271
- class ArcRecord extends ArcAbstract {
1272
- key;
1273
- element;
1274
- constructor(key, element) {
1927
+
1928
+ class Model extends ModelBase {
1929
+ context;
1930
+ dataStorage;
1931
+ client;
1932
+ catchErrorCallback;
1933
+ queryCache = new QueryCache;
1934
+ constructor(context3, dataStorage, client, catchErrorCallback) {
1275
1935
  super();
1276
- this.key = key;
1277
- this.element = element;
1936
+ this.context = context3;
1937
+ this.dataStorage = dataStorage;
1938
+ this.client = client;
1939
+ this.catchErrorCallback = catchErrorCallback;
1940
+ }
1941
+ async query(queryBuilderFn) {
1942
+ const queryContext = new QueryBuilderContext(this.queryCache, this.dataStorage);
1943
+ const queryBuilder = this.context.queryBuilder(queryContext);
1944
+ const query2 = queryBuilderFn(queryBuilder).toQuery(queryContext);
1945
+ return query2.run(this.dataStorage);
1946
+ }
1947
+ subscribe(queryBuilderFn, callback) {
1948
+ const queryContext = new QueryBuilderContext(this.queryCache, this.dataStorage);
1949
+ const queryBuilder = this.context.queryBuilder(queryContext);
1950
+ const query2 = queryBuilderFn(queryBuilder).toQuery(queryContext);
1951
+ query2.subscribe(callback);
1952
+ const runPromise = query2.run(this.dataStorage);
1953
+ runPromise.then((result) => {
1954
+ callback(result);
1955
+ });
1956
+ return {
1957
+ unsubscribe: () => {
1958
+ query2.unsubscribe(callback);
1959
+ },
1960
+ result: runPromise
1961
+ };
1278
1962
  }
1279
- parse(value) {
1280
- if (!value)
1281
- return {};
1282
- return Object.entries(value).reduce((acc, [key, recordValue]) => {
1283
- acc[key] = this.element.parse(recordValue);
1284
- return acc;
1285
- }, {});
1963
+ commands() {
1964
+ const queryContext = new QueryBuilderContext(this.queryCache, this.dataStorage);
1965
+ return this.context.commandsClient(this.client, queryContext, this.dataStorage, this.catchErrorCallback);
1286
1966
  }
1287
- serialize(value) {
1288
- if (!value)
1289
- return {};
1290
- return Object.entries(value).reduce((acc, [key, recordValue]) => {
1291
- acc[key] = this.element.serialize(recordValue);
1292
- return acc;
1293
- }, {});
1967
+ fork() {
1968
+ return new ForkedModel(this.context, this.dataStorage.fork(), this.client, this.catchErrorCallback);
1294
1969
  }
1295
- deserialize(value) {
1296
- if (!value)
1297
- return {};
1298
- return Object.entries(value).reduce((acc, [key, recordValue]) => {
1299
- acc[key] = this.element.deserialize(recordValue);
1300
- return acc;
1301
- }, {});
1970
+ get $debug() {
1971
+ return {};
1302
1972
  }
1303
1973
  }
1304
- function record(key, element) {
1305
- return new ArcRecord(key, element);
1974
+
1975
+ class ForkedModel extends Model {
1976
+ constructor(context3, dataStorage, client, catchErrorCallback) {
1977
+ super(context3, dataStorage, client, catchErrorCallback);
1978
+ }
1979
+ merge() {}
1306
1980
  }
1307
- // elements/string-enum.ts
1308
- class ArcStringEnum extends ArcAbstract {
1309
- values;
1310
- constructor(values) {
1981
+
1982
+ class RemoteModelClient extends ModelBase {
1983
+ context;
1984
+ apiBaseUrl;
1985
+ client;
1986
+ catchErrorCallback;
1987
+ constructor(context3, apiBaseUrl, client, catchErrorCallback) {
1311
1988
  super();
1312
- this.values = values;
1313
- }
1314
- parse(value) {
1315
- return value;
1316
- }
1317
- serialize(value) {
1318
- return value;
1989
+ this.context = context3;
1990
+ this.apiBaseUrl = apiBaseUrl;
1991
+ this.client = client;
1992
+ this.catchErrorCallback = catchErrorCallback;
1993
+ }
1994
+ async query(queryBuilderFn) {
1995
+ const queryTracking = {
1996
+ element: null,
1997
+ queryType: null,
1998
+ params: null
1999
+ };
2000
+ const queryContext = new QueryBuilderContext(new QueryCache, null);
2001
+ const originalQueryBuilder = this.context.queryBuilder(queryContext);
2002
+ const queryBuilderProxy = new Proxy(originalQueryBuilder, {
2003
+ get: (target, prop) => {
2004
+ queryTracking.element = prop;
2005
+ const originalElement = Reflect.get(target, prop);
2006
+ return new Proxy(originalElement, {
2007
+ get: (elementTarget, methodProp) => {
2008
+ queryTracking.queryType = methodProp;
2009
+ const originalMethod = Reflect.get(elementTarget, methodProp);
2010
+ return (...args) => {
2011
+ queryTracking.params = args;
2012
+ return originalMethod(...args);
2013
+ };
2014
+ }
2015
+ });
2016
+ }
2017
+ });
2018
+ const query2 = queryBuilderFn(queryBuilderProxy).toQuery(queryContext);
2019
+ const response = await fetch(`${this.apiBaseUrl}/query`, {
2020
+ method: "POST",
2021
+ headers: { "Content-Type": "application/json" },
2022
+ body: JSON.stringify({
2023
+ query: {
2024
+ element: queryTracking.element,
2025
+ queryType: queryTracking.queryType,
2026
+ params: queryTracking.params
2027
+ }
2028
+ })
2029
+ });
2030
+ if (!response.ok) {
2031
+ throw new Error(`Query failed: ${response.statusText}`);
2032
+ }
2033
+ const { result } = await response.json();
2034
+ return result;
1319
2035
  }
1320
- deserialize(value) {
1321
- return value;
2036
+ subscribe(queryBuilderFn, callback) {
2037
+ const result = this.query(queryBuilderFn);
2038
+ result.then((initialResult) => {
2039
+ callback(initialResult);
2040
+ }).catch(this.catchErrorCallback);
2041
+ return {
2042
+ unsubscribe: () => {},
2043
+ result
2044
+ };
1322
2045
  }
1323
- getEnumerators() {
1324
- return this.values;
2046
+ commands() {
2047
+ const commandsProxy = new Proxy({}, {
2048
+ get: (target, prop) => {
2049
+ const element = this.context.elements.find((e) => e.name === prop);
2050
+ if (!element) {
2051
+ throw new Error(`Command ${String(prop)} not found`);
2052
+ }
2053
+ return Object.assign(async (argument) => {
2054
+ const response = await fetch(`${this.apiBaseUrl}/command/${String(prop)}`, {
2055
+ method: "POST",
2056
+ headers: { "Content-Type": "application/json" },
2057
+ body: JSON.stringify(argument)
2058
+ });
2059
+ if (!response.ok) {
2060
+ throw new Error(`Command ${String(prop)} failed: ${response.statusText}`);
2061
+ }
2062
+ return response.json();
2063
+ }, { params: element._params });
2064
+ }
2065
+ });
2066
+ return commandsProxy;
1325
2067
  }
1326
2068
  }
1327
- function stringEnum(...values) {
1328
- return new ArcStringEnum(values);
1329
- }
1330
2069
  // rtc/client.ts
1331
2070
  class RTCClient {
1332
2071
  storage;
@@ -1350,41 +2089,9 @@ class RTCClient {
1350
2089
  }
1351
2090
  async performSync() {
1352
2091
  this.connectWebSocket();
1353
- const arcState = await this.storage.getStore("state").findById("$arc", (a) => a);
1354
- const response = await fetch(`/ws/sync?lastSync=${arcState?.lastSyncDate || ""}`, {
1355
- method: "GET",
1356
- headers: {
1357
- "Content-Type": "application/json",
1358
- Authorization: `Bearer ${this.token}`
1359
- }
1360
- });
1361
- if (!response.ok) {
1362
- throw new Error("Sync failed");
1363
- }
1364
- const { results, syncDate } = await response.json();
1365
- const pendingStoreChanges = [];
1366
- const transaction = await this.storage.getReadWriteTransaction();
1367
- for (const { store, items } of results) {
1368
- this.syncProgressCallback?.({ store, size: items.length });
1369
- for (const item of items) {
1370
- if (item.deleted) {
1371
- await transaction.remove(store, item._id);
1372
- } else {
1373
- await transaction.set(store, item);
1374
- }
1375
- }
1376
- }
1377
- await transaction.commit();
1378
- const stateStorage = this.storage.getStore("state");
1379
- await stateStorage.applyChanges([
1380
- {
1381
- type: "set",
1382
- data: { _id: "$arc", lastSyncDate: syncDate }
1383
- }
1384
- ]);
1385
2092
  }
1386
2093
  async connectWebSocket() {
1387
- this._socket = new WebSocket(`wss://${window.location.host}/ws?token=${this.token}`);
2094
+ this._socket = new WebSocket(`wss://${window.location.host}/api/ws?token=${this.token}`);
1388
2095
  this.openSocket = new Promise((resolve) => {
1389
2096
  this._socket.addEventListener("open", () => {
1390
2097
  this.reconnectAttempts = 0;
@@ -1434,138 +2141,160 @@ class RTCClient {
1434
2141
  var rtcClientFactory = (token) => (storage) => {
1435
2142
  return new RTCClient(storage, token);
1436
2143
  };
1437
- // state/query.ts
1438
- class ArcStateQuery extends ArcQuery {
1439
- state;
1440
- bindedChangeHandler = this.changeHandler.bind(this);
1441
- store;
1442
- constructor(state) {
1443
- super();
1444
- this.state = state;
1445
- }
1446
- async run(dataStorage, listener) {
1447
- this.store = dataStorage.getStore("state");
1448
- const result = await this.store.findById(this.state.name, this.bindedChangeHandler);
1449
- this.lastResult = this.state.deserialize(result);
1450
- if (listener)
1451
- this.listener = listener;
1452
- return this.lastResult;
1453
- }
1454
- onChange(change) {
1455
- if (change.type === "set")
1456
- return change.item;
1457
- return false;
1458
- }
1459
- changeHandler(changes) {
1460
- for (const change of changes) {
1461
- const response = this.onChange(change);
1462
- if (response !== false)
1463
- this.lastResult = this.state.deserialize(response);
1464
- }
1465
- if (this.lastResult)
1466
- this.nextResult(this.lastResult);
1467
- }
1468
- unsubscribe() {
1469
- this.store.unsubscribe(this.bindedChangeHandler);
1470
- }
1471
- nextResult(result) {
1472
- this.lastResult = result;
1473
- this.listener?.(result);
1474
- }
1475
- }
1476
-
1477
- // state/query-builder.ts
1478
- class ArcStateQueryBuilder extends ArcQueryBuilder {
1479
- state;
1480
- constructor(state) {
1481
- super();
1482
- this.state = state;
1483
- }
1484
- toQuery() {
1485
- return new ArcStateQuery(this.state);
1486
- }
1487
- }
1488
-
1489
- // state/state.ts
1490
- class ArcState extends ArcContextElement {
2144
+ // view/view.ts
2145
+ class ArcView extends ArcContextElementWithStore {
1491
2146
  name;
2147
+ id;
1492
2148
  schema;
1493
- constructor(name, schema) {
2149
+ _description;
2150
+ _elements;
2151
+ _handler;
2152
+ constructor(name, id3, schema) {
1494
2153
  super();
1495
2154
  this.name = name;
2155
+ this.id = id3;
1496
2156
  this.schema = schema;
1497
2157
  }
1498
- serialize(data) {
2158
+ storeSchema = () => {
2159
+ return arcObjectToStoreSchema(this.name, this.schema);
2160
+ };
2161
+ use(elements) {
2162
+ const clone = this.clone();
2163
+ clone._elements = elements;
2164
+ return clone;
2165
+ }
2166
+ description(description) {
2167
+ const clone = this.clone();
2168
+ clone._description = description;
2169
+ return clone;
2170
+ }
2171
+ handle(handler) {
2172
+ const clone = this.clone();
2173
+ clone._handler = handler;
2174
+ return clone;
2175
+ }
2176
+ queryBuilder = (context3) => {
1499
2177
  return {
1500
- ...this.schema.serialize(data),
1501
- _id: this.name
2178
+ find: (options) => {
2179
+ throw new Error("Not implemented");
2180
+ }
1502
2181
  };
1503
- }
1504
- deserialize(data) {
1505
- return this.schema.deserialize(data || {});
1506
- }
1507
- queryBuilder() {
1508
- return new ArcStateQueryBuilder(this);
1509
- }
1510
- commandContext(dataStorage, publishEvent) {
1511
- const store = dataStorage.getStore("state");
2182
+ };
2183
+ commandContext = (dataStorage, publishEvent) => {
2184
+ const store = dataStorage.getStore(this.name);
1512
2185
  return {
1513
- get: async () => {
1514
- return store.findById(this.name);
2186
+ find: async (options) => {
2187
+ return store.find(options);
1515
2188
  },
1516
- modify: async (data) => {
1517
- const serialized = this.serialize(data);
1518
- const { from, to } = await store.modify(this.name, serialized);
1519
- await publishEvent({
1520
- type: "modify",
1521
- changes: data,
1522
- from,
1523
- to
2189
+ findOne: async (where) => {
2190
+ const result = await store.find({
2191
+ where,
2192
+ limit: 1
1524
2193
  });
1525
- },
1526
- edit: async (editCallback) => {
1527
- const { from, to } = await store.mutate(this.name, editCallback);
2194
+ return result[0];
1528
2195
  }
1529
2196
  };
2197
+ };
2198
+ observer = () => {
2199
+ return Object.entries(this._handler ?? {}).reduce((acc, [key, value]) => {
2200
+ acc[key] = (event3, dataStorage) => {
2201
+ const store = dataStorage.getStore(this.name);
2202
+ const ctx = {
2203
+ remove: async (id3) => {
2204
+ await store.remove(id3);
2205
+ return { success: true };
2206
+ },
2207
+ set: async (id3, data) => {
2208
+ const parsed = this.schema.parse(data);
2209
+ const body = {
2210
+ _id: id3,
2211
+ lastUpdate: new Date().toISOString(),
2212
+ ...parsed
2213
+ };
2214
+ await store.set(body);
2215
+ return { success: true };
2216
+ },
2217
+ find: async (options) => {
2218
+ return store.find(options);
2219
+ },
2220
+ findOne: async (where) => {
2221
+ const result = await store.find({
2222
+ where,
2223
+ limit: 1
2224
+ });
2225
+ return result[0];
2226
+ },
2227
+ modify: async (id3, data) => {
2228
+ const deserialized = this.schema.serializePartial(data);
2229
+ const { from, to } = await store.modify(id3, {
2230
+ ...deserialized,
2231
+ lastUpdate: new Date().toISOString()
2232
+ });
2233
+ }
2234
+ };
2235
+ value(ctx, event3);
2236
+ };
2237
+ return acc;
2238
+ }, {});
2239
+ };
2240
+ clone() {
2241
+ const clone = new ArcView(this.name, this.id, this.schema);
2242
+ clone._description = this._description;
2243
+ clone._elements = this._elements;
2244
+ clone._handler = this._handler;
2245
+ return clone;
1530
2246
  }
1531
2247
  }
1532
- function state(name, schema) {
1533
- return new ArcState(name, schema);
2248
+ function view(name, id3, schema) {
2249
+ return new ArcView(name, id3, schema);
1534
2250
  }
1535
2251
  export {
2252
+ view,
1536
2253
  stringEnum,
1537
2254
  string,
1538
- state,
1539
2255
  rtcClientFactory,
1540
2256
  record,
2257
+ reactive,
1541
2258
  object,
1542
2259
  number,
1543
2260
  id,
2261
+ event,
1544
2262
  date,
1545
2263
  customId,
2264
+ createSQLiteAdapterFactory,
1546
2265
  context,
2266
+ command,
1547
2267
  collection,
1548
2268
  boolean,
1549
2269
  array,
1550
2270
  StoreState,
2271
+ SQLiteAdapter,
2272
+ RemoteModelClient,
2273
+ QueryCache,
2274
+ QueryBuilderContext,
2275
+ ModelBase,
2276
+ Model,
1551
2277
  MasterStoreState,
1552
2278
  MasterDataStorage,
1553
2279
  ForkedStoreState,
2280
+ ForkedModel,
1554
2281
  ForkedDataStorage,
1555
2282
  DataStorage,
2283
+ ArcView,
1556
2284
  ArcStringEnum,
1557
2285
  ArcString,
1558
- ArcState,
1559
2286
  ArcRecord,
1560
2287
  ArcQueryBuilder,
1561
2288
  ArcQuery,
1562
2289
  ArcOptional,
1563
2290
  ArcObject,
1564
2291
  ArcNumber,
1565
- ArcIndexedCollection,
1566
2292
  ArcId,
2293
+ ArcEvent,
1567
2294
  ArcDate,
1568
2295
  ArcCustomId,
2296
+ ArcContext,
2297
+ ArcCommand,
1569
2298
  ArcCollectionQuery,
1570
2299
  ArcCollection,
1571
2300
  ArcBranded,