@statezero/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/adaptors/react/composables.d.ts +1 -0
  2. package/dist/adaptors/react/composables.js +4 -0
  3. package/dist/adaptors/react/index.d.ts +1 -0
  4. package/dist/adaptors/react/index.js +1 -0
  5. package/dist/adaptors/vue/composables.d.ts +2 -0
  6. package/dist/adaptors/vue/composables.js +36 -0
  7. package/dist/adaptors/vue/index.d.ts +2 -0
  8. package/dist/adaptors/vue/index.js +2 -0
  9. package/dist/adaptors/vue/reactivity.d.ts +18 -0
  10. package/dist/adaptors/vue/reactivity.js +125 -0
  11. package/dist/cli/commands/syncModels.d.ts +132 -0
  12. package/dist/cli/commands/syncModels.js +1040 -0
  13. package/dist/cli/configFileLoader.d.ts +10 -0
  14. package/dist/cli/configFileLoader.js +85 -0
  15. package/dist/cli/index.d.ts +2 -0
  16. package/dist/cli/index.js +14 -0
  17. package/dist/config.d.ts +52 -0
  18. package/dist/config.js +242 -0
  19. package/dist/core/eventReceivers.d.ts +179 -0
  20. package/dist/core/eventReceivers.js +210 -0
  21. package/dist/core/utils.d.ts +8 -0
  22. package/dist/core/utils.js +62 -0
  23. package/dist/filtering/localFiltering.d.ts +116 -0
  24. package/dist/filtering/localFiltering.js +834 -0
  25. package/dist/flavours/django/dates.d.ts +33 -0
  26. package/dist/flavours/django/dates.js +99 -0
  27. package/dist/flavours/django/errors.d.ts +138 -0
  28. package/dist/flavours/django/errors.js +187 -0
  29. package/dist/flavours/django/f.d.ts +6 -0
  30. package/dist/flavours/django/f.js +91 -0
  31. package/dist/flavours/django/files.d.ts +76 -0
  32. package/dist/flavours/django/files.js +338 -0
  33. package/dist/flavours/django/makeApiCall.d.ts +20 -0
  34. package/dist/flavours/django/makeApiCall.js +169 -0
  35. package/dist/flavours/django/manager.d.ts +197 -0
  36. package/dist/flavours/django/manager.js +222 -0
  37. package/dist/flavours/django/model.d.ts +112 -0
  38. package/dist/flavours/django/model.js +253 -0
  39. package/dist/flavours/django/operationFactory.d.ts +65 -0
  40. package/dist/flavours/django/operationFactory.js +216 -0
  41. package/dist/flavours/django/q.d.ts +70 -0
  42. package/dist/flavours/django/q.js +43 -0
  43. package/dist/flavours/django/queryExecutor.d.ts +131 -0
  44. package/dist/flavours/django/queryExecutor.js +468 -0
  45. package/dist/flavours/django/querySet.d.ts +412 -0
  46. package/dist/flavours/django/querySet.js +601 -0
  47. package/dist/flavours/django/tempPk.d.ts +19 -0
  48. package/dist/flavours/django/tempPk.js +48 -0
  49. package/dist/flavours/django/utils.d.ts +19 -0
  50. package/dist/flavours/django/utils.js +29 -0
  51. package/dist/index.d.ts +38 -0
  52. package/dist/index.js +38 -0
  53. package/dist/react-entry.d.ts +2 -0
  54. package/dist/react-entry.js +2 -0
  55. package/dist/reactiveAdaptor.d.ts +24 -0
  56. package/dist/reactiveAdaptor.js +38 -0
  57. package/dist/setup.d.ts +15 -0
  58. package/dist/setup.js +22 -0
  59. package/dist/syncEngine/cache/cache.d.ts +75 -0
  60. package/dist/syncEngine/cache/cache.js +341 -0
  61. package/dist/syncEngine/metrics/metricOptCalcs.d.ts +79 -0
  62. package/dist/syncEngine/metrics/metricOptCalcs.js +284 -0
  63. package/dist/syncEngine/registries/metricRegistry.d.ts +53 -0
  64. package/dist/syncEngine/registries/metricRegistry.js +162 -0
  65. package/dist/syncEngine/registries/modelStoreRegistry.d.ts +11 -0
  66. package/dist/syncEngine/registries/modelStoreRegistry.js +56 -0
  67. package/dist/syncEngine/registries/querysetStoreRegistry.d.ts +55 -0
  68. package/dist/syncEngine/registries/querysetStoreRegistry.js +244 -0
  69. package/dist/syncEngine/stores/metricStore.d.ts +55 -0
  70. package/dist/syncEngine/stores/metricStore.js +222 -0
  71. package/dist/syncEngine/stores/modelStore.d.ts +40 -0
  72. package/dist/syncEngine/stores/modelStore.js +405 -0
  73. package/dist/syncEngine/stores/operation.d.ts +99 -0
  74. package/dist/syncEngine/stores/operation.js +224 -0
  75. package/dist/syncEngine/stores/operationEventHandlers.d.ts +8 -0
  76. package/dist/syncEngine/stores/operationEventHandlers.js +239 -0
  77. package/dist/syncEngine/stores/querysetStore.d.ts +32 -0
  78. package/dist/syncEngine/stores/querysetStore.js +200 -0
  79. package/dist/syncEngine/stores/reactivity.d.ts +3 -0
  80. package/dist/syncEngine/stores/reactivity.js +4 -0
  81. package/dist/syncEngine/stores/utils.d.ts +14 -0
  82. package/dist/syncEngine/stores/utils.js +32 -0
  83. package/dist/syncEngine/sync.d.ts +32 -0
  84. package/dist/syncEngine/sync.js +169 -0
  85. package/dist/vue-entry.d.ts +6 -0
  86. package/dist/vue-entry.js +2 -0
  87. package/license.md +116 -0
  88. package/package.json +123 -0
  89. package/readme.md +222 -0
@@ -0,0 +1,224 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _Operation__instances, _Operation__frozenInstances;
13
+ import { MAX, v7 as uuidv7 } from "uuid";
14
+ import { isNil } from 'lodash-es';
15
+ import mitt from 'mitt';
16
+ import { tempPkMap } from "../../flavours/django/tempPk";
17
+ export const operationEvents = mitt();
18
+ export const Status = {
19
+ CREATED: 'operation:created',
20
+ UPDATED: 'operation:updated',
21
+ CONFIRMED: 'operation:confirmed',
22
+ REJECTED: 'operation:rejected',
23
+ CLEAR: 'clear:all',
24
+ MUTATED: 'operation:mutated'
25
+ };
26
+ export const Type = {
27
+ CREATE: 'create',
28
+ UPDATE: 'update',
29
+ DELETE: 'delete',
30
+ UPDATE_INSTANCE: 'update_instance',
31
+ DELETE_INSTANCE: 'delete_instance',
32
+ GET_OR_CREATE: 'get_or_create',
33
+ UPDATE_OR_CREATE: 'update_or_create',
34
+ CHECKPOINT: 'checkpoint',
35
+ // Aggregation operations
36
+ COUNT: 'count',
37
+ MIN: 'min',
38
+ MAX: 'max',
39
+ AVG: 'avg',
40
+ SUM: 'sum',
41
+ AGGREGATE: 'aggregate',
42
+ };
43
+ export class Operation {
44
+ constructor(data, restore = false) {
45
+ _Operation__instances.set(this, void 0);
46
+ _Operation__frozenInstances.set(this, void 0);
47
+ if (!data || typeof data !== 'object') {
48
+ throw new Error("Operation constructor requires a data object.");
49
+ }
50
+ if (!data.type) {
51
+ throw new Error("Operation data must include a 'type'.");
52
+ }
53
+ if (!data.instances) {
54
+ throw new Error("Operation data must include 'instances'.");
55
+ }
56
+ this.operationId = data.operationId || `op_${uuidv7()}`;
57
+ this.type = data.type;
58
+ this.status = data.status || Status.CREATED;
59
+ this.queryset = data.queryset;
60
+ this.args = data.args;
61
+ this.doNotPropagate = data.doNotPropagate || false;
62
+ let ModelClass = this.queryset.ModelClass;
63
+ let instances = data.instances;
64
+ // guarantee instances is an array
65
+ if (!isNil(instances)) {
66
+ instances = Array.isArray(data.instances) ? data.instances : [data.instances];
67
+ }
68
+ // coerce to object format if its not already
69
+ let pkField = ModelClass.primaryKeyField;
70
+ if (instances.some(instance => isNil(instance) || typeof instance !== 'object' || !(pkField in instance))) {
71
+ throw new Error(`All operation instances must be objects with the '${pkField}' field`);
72
+ }
73
+ __classPrivateFieldSet(this, _Operation__instances, instances, "f");
74
+ __classPrivateFieldSet(this, _Operation__frozenInstances, instances.map(i => ModelClass.fromPk(i[ModelClass.primaryKeyField]).serialize()), "f");
75
+ this.timestamp = data.timestamp || Date.now();
76
+ if (restore)
77
+ return;
78
+ operationRegistry.register(this);
79
+ // Emit operation created event with the entire operation
80
+ operationEvents.emit(Status.CREATED, this);
81
+ }
82
+ /**
83
+ * Getter for instances that replaces any temporary PKs with real PKs
84
+ */
85
+ get instances() {
86
+ if (tempPkMap.size === 0)
87
+ return __classPrivateFieldGet(this, _Operation__instances, "f");
88
+ const ModelClass = this.queryset.ModelClass;
89
+ const pkField = ModelClass.primaryKeyField;
90
+ return __classPrivateFieldGet(this, _Operation__instances, "f").map(instance => {
91
+ const pk = instance[pkField];
92
+ if (typeof pk === 'string' && tempPkMap.has(pk.replace(/[{}]/g, ''))) {
93
+ // Return a new instance with the real PK
94
+ return {
95
+ ...instance,
96
+ [pkField]: tempPkMap.get(pk.replace(/[{}]/g, ''))
97
+ };
98
+ }
99
+ return instance;
100
+ });
101
+ }
102
+ /**
103
+ * Setter for instances
104
+ */
105
+ set instances(value) {
106
+ __classPrivateFieldSet(this, _Operation__instances, Array.isArray(value) ? value : [value], "f");
107
+ }
108
+ /**
109
+ * Getter for frozenInstances that replaces any temporary PKs with real PKs
110
+ */
111
+ get frozenInstances() {
112
+ if (tempPkMap.size === 0)
113
+ return __classPrivateFieldGet(this, _Operation__frozenInstances, "f");
114
+ const ModelClass = this.queryset.ModelClass;
115
+ const pkField = ModelClass.primaryKeyField;
116
+ return __classPrivateFieldGet(this, _Operation__frozenInstances, "f").map(instance => {
117
+ const pk = instance[pkField];
118
+ if (typeof pk === 'string' && tempPkMap.has(pk.replace(/[{}]/g, ''))) {
119
+ // Return a new instance with the real PK
120
+ return {
121
+ ...instance,
122
+ [pkField]: tempPkMap.get(pk.replace(/[{}]/g, ''))
123
+ };
124
+ }
125
+ return instance;
126
+ });
127
+ }
128
+ /**
129
+ * Setter for frozenInstances
130
+ */
131
+ set frozenInstances(value) {
132
+ __classPrivateFieldSet(this, _Operation__frozenInstances, Array.isArray(value) ? value : [value], "f");
133
+ }
134
+ /**
135
+ * Get primary keys of all instances in this operation
136
+ * Returns primary keys as simple values (not objects)
137
+ */
138
+ get instancePks() {
139
+ const pkField = this.queryset.ModelClass.primaryKeyField;
140
+ return this.instances.map(instance => instance[pkField]);
141
+ }
142
+ /**
143
+ * Update this operation's status and emit an event
144
+ * @param {string} status - New status ('confirmed', 'rejected', etc.)
145
+ * @param {Array|Object|null} [instances=null] - New instances for the operation
146
+ */
147
+ updateStatus(status, instances = null) {
148
+ this.status = status;
149
+ this.timestamp = Date.now();
150
+ if (instances !== null) {
151
+ this.instances = Array.isArray(instances) ? instances : [instances];
152
+ }
153
+ operationEvents.emit(status, this);
154
+ }
155
+ /**
156
+ * Updates this operation with new data and emits the appropriate event
157
+ * @param {Object} newData - New data to update the operation with
158
+ * @returns {Operation} - Returns this operation instance for chaining
159
+ */
160
+ mutate(newData) {
161
+ // Ensure instances is always an array
162
+ if (newData.instances && !Array.isArray(newData.instances)) {
163
+ newData.instances = [newData.instances];
164
+ }
165
+ // Use Object.assign to update all properties at once
166
+ Object.assign(this, newData);
167
+ // Update timestamp
168
+ this.timestamp = Date.now();
169
+ // Emit the mutated event with the updated operation
170
+ operationEvents.emit(Status.MUTATED, this);
171
+ return this;
172
+ }
173
+ }
174
+ _Operation__instances = new WeakMap(), _Operation__frozenInstances = new WeakMap();
175
+ class OperationRegistry {
176
+ constructor() {
177
+ this._operations = new Map();
178
+ }
179
+ /**
180
+ * Registers a pre-constructed Operation instance in the registry.
181
+ * Ensures the operationId is unique within the registry.
182
+ * Throws an Error if the operationId already exists.
183
+ *
184
+ * @param {Operation} operation - The fully instantiated Operation object to register.
185
+ * @throws {Error} If the input is not a valid operation object or if an operation with the same operationId already exists.
186
+ */
187
+ register(operation) {
188
+ if (!(operation instanceof Operation)) {
189
+ throw new Error("OperationRegistry.register requires an Operation object.");
190
+ }
191
+ // Ensure the ID is unique before registering
192
+ if (this._operations.has(operation.operationId)) {
193
+ // Throw an error if the ID is already used.
194
+ console.warn(`OperationId ${operation.operationId} is already used, overriding existing operation!`);
195
+ }
196
+ // Register the provided operation object
197
+ this._operations.set(operation.operationId, operation);
198
+ }
199
+ /**
200
+ * Retrieves an operation by its ID.
201
+ * @param {string} operationId - The ID of the operation.
202
+ * @returns {Operation | undefined} The operation instance or undefined if not found.
203
+ */
204
+ get(operationId) {
205
+ return this._operations.get(operationId);
206
+ }
207
+ /**
208
+ * Checks if an operation with the given ID exists in the registry.
209
+ * @param {string} operationId - The ID of the operation to check.
210
+ * @returns {boolean} True if the operation exists, false otherwise.
211
+ */
212
+ has(operationId) {
213
+ return this._operations.has(operationId);
214
+ }
215
+ /**
216
+ * Clears all operations from the registry.
217
+ */
218
+ clear() {
219
+ console.log("OperationRegistry: Clearing all operations.");
220
+ this._operations.clear();
221
+ operationEvents.emit(Status.CLEAR);
222
+ }
223
+ }
224
+ export const operationRegistry = new OperationRegistry();
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Initialize the operation event handler system by setting up event listeners
3
+ */
4
+ export function initEventHandler(): void;
5
+ /**
6
+ * Clean up by removing all event listeners
7
+ */
8
+ export function cleanupEventHandler(): void;
@@ -0,0 +1,239 @@
1
+ import { operationEvents, Status, Type } from './operation.js';
2
+ import { modelStoreRegistry } from '../registries/modelStoreRegistry.js';
3
+ import { querysetStoreRegistry } from '../registries/querysetStoreRegistry.js';
4
+ import { metricRegistry } from '../registries/metricRegistry.js';
5
+ import { getFingerprint } from './utils.js';
6
+ import { QuerySet } from '../../flavours/django/querySet.js';
7
+ import { isEqual, isNil } from 'lodash-es';
8
+ import hash from 'object-hash';
9
+ /**
10
+ * Returns querysets that have the same nodes as any ancestor of the specific queryset
11
+ * @param {QuerySet} queryset
12
+ * @returns {Map<QuerySet, Store>}
13
+ */
14
+ function relatedQuerysets(queryset) {
15
+ // Collect ancestor nodes for comparison
16
+ let ancestorNodes = [];
17
+ let current = queryset;
18
+ while (current) {
19
+ ancestorNodes.push(current.nodes);
20
+ current = current.__parent;
21
+ }
22
+ const modelClass = queryset.ModelClass;
23
+ const result = new Map();
24
+ Array.from(querysetStoreRegistry._stores.entries()).forEach(([queryset, store]) => {
25
+ if (store.modelClass !== modelClass)
26
+ return;
27
+ try {
28
+ if (ancestorNodes.some(nodes => isEqual(nodes, store.queryset.nodes))) {
29
+ result.set(store.queryset, store);
30
+ }
31
+ }
32
+ catch (e) {
33
+ console.warn('Error comparing nodes for related querysets', e);
34
+ }
35
+ });
36
+ return result;
37
+ }
38
+ /**
39
+ * Returns querysets that contain any of the specified instances
40
+ * @param {Operation} operation - The operation containing instances to check
41
+ * @returns {Map<QuerySet, Store>}
42
+ */
43
+ function querysetsContainingInstances(operation) {
44
+ const ModelClass = operation.queryset.ModelClass;
45
+ const pkField = ModelClass.primaryKeyField;
46
+ const instancePks = new Set(operation.instances
47
+ .filter(instance => instance && typeof instance === 'object' && pkField in instance)
48
+ .map(instance => instance[pkField]));
49
+ if (instancePks.size === 0) {
50
+ return new Map();
51
+ }
52
+ const result = new Map();
53
+ Array.from(querysetStoreRegistry._stores.entries()).forEach(([queryset, store]) => {
54
+ if (store.modelClass !== ModelClass)
55
+ return;
56
+ try {
57
+ // Check if this queryset contains any of the instances
58
+ const renderedPks = new Set(store.render(false)); // Get without optimistic updates
59
+ const hasIntersection = [...instancePks].some(pk => renderedPks.has(pk));
60
+ if (hasIntersection) {
61
+ result.set(store.queryset, store);
62
+ }
63
+ }
64
+ catch (e) {
65
+ console.warn('Error checking queryset for instances', e);
66
+ }
67
+ });
68
+ return result;
69
+ }
70
+ /**
71
+ * Process an operation in the model store
72
+ *
73
+ * @param {Operation} operation - The operation to process
74
+ * @param {string} actionType - The action to perform ('add', 'update', 'confirm', 'reject')
75
+ */
76
+ function processModelStore(operation, actionType) {
77
+ const ModelClass = operation.queryset.ModelClass;
78
+ const modelStore = modelStoreRegistry.getStore(ModelClass);
79
+ if (!modelStore)
80
+ return;
81
+ switch (actionType) {
82
+ case 'add':
83
+ modelStore.addOperation(operation);
84
+ break;
85
+ case 'update':
86
+ modelStore.updateOperation(operation);
87
+ break;
88
+ case 'confirm':
89
+ modelStore.confirm(operation);
90
+ break;
91
+ case 'reject':
92
+ modelStore.reject(operation);
93
+ break;
94
+ }
95
+ }
96
+ /**
97
+ * Process an operation in the queryset stores based on operation type
98
+ * Uses different routing strategies based on the operation type
99
+ *
100
+ * @param {Operation} operation - The operation to process
101
+ * @param {string} actionType - The action to perform ('add', 'update', 'confirm', 'reject')
102
+ */
103
+ function processQuerysetStores(operation, actionType) {
104
+ const ModelClass = operation.queryset.ModelClass;
105
+ const queryset = operation.queryset;
106
+ // Apply the appropriate action to a single queryset store
107
+ const applyAction = (store) => {
108
+ switch (actionType) {
109
+ case 'add':
110
+ store.addOperation(operation);
111
+ break;
112
+ case 'update':
113
+ store.updateOperation(operation);
114
+ break;
115
+ case 'confirm':
116
+ store.confirm(operation);
117
+ break;
118
+ case 'reject':
119
+ store.reject(operation);
120
+ break;
121
+ }
122
+ };
123
+ let querysetStoreMap;
124
+ // Different routing strategies based on operation type
125
+ switch (operation.type) {
126
+ case Type.CREATE:
127
+ case Type.GET_OR_CREATE:
128
+ case Type.UPDATE_OR_CREATE:
129
+ // For creates, route to related querysets (they might want to include the new item)
130
+ querysetStoreMap = relatedQuerysets(queryset);
131
+ break;
132
+ case Type.UPDATE:
133
+ case Type.UPDATE_INSTANCE:
134
+ case Type.DELETE:
135
+ case Type.DELETE_INSTANCE:
136
+ // For updates and deletes, only route to querysets that actually contain the instances
137
+ querysetStoreMap = querysetsContainingInstances(operation);
138
+ break;
139
+ case Type.CHECKPOINT:
140
+ // For checkpoints, route to querysets that contain the instances
141
+ querysetStoreMap = querysetsContainingInstances(operation);
142
+ break;
143
+ default:
144
+ // For other operation types, use the existing related querysets logic
145
+ querysetStoreMap = relatedQuerysets(queryset);
146
+ break;
147
+ }
148
+ Array.from(querysetStoreMap.values()).forEach(applyAction);
149
+ }
150
+ /**
151
+ * Process an operation in the metric stores based on operation type
152
+ *
153
+ * @param {Operation} operation - The operation to process
154
+ * @param {string} actionType - The action to perform ('add', 'update', 'confirm', 'reject')
155
+ */
156
+ function processMetricStores(operation, actionType) {
157
+ const queryset = operation.queryset;
158
+ const ModelClass = queryset.ModelClass;
159
+ // For metrics, we can use a similar strategy but might be more conservative
160
+ // and always use related querysets since metrics are aggregations
161
+ const allQuerysets = Array.from(relatedQuerysets(queryset).keys());
162
+ let allMetricStores = new Set();
163
+ allQuerysets.forEach(qs => {
164
+ const stores = metricRegistry.getAllStoresForQueryset(qs);
165
+ if (stores && stores.length > 0) {
166
+ stores.forEach(store => allMetricStores.add(store));
167
+ }
168
+ });
169
+ if (!allMetricStores || allMetricStores.size === 0) {
170
+ return;
171
+ }
172
+ // Apply the action to each matching metric store
173
+ allMetricStores.forEach(store => {
174
+ switch (actionType) {
175
+ case 'add':
176
+ store.addOperation(operation);
177
+ break;
178
+ case 'update':
179
+ store.updateOperation(operation);
180
+ break;
181
+ case 'confirm':
182
+ store.confirm(operation);
183
+ break;
184
+ case 'reject':
185
+ store.reject(operation);
186
+ break;
187
+ }
188
+ });
189
+ }
190
+ /**
191
+ * Common processing logic for operations, handling validation and routing
192
+ * to the appropriate store processors
193
+ *
194
+ * @param {Operation} operation - The operation to process
195
+ * @param {string} actionType - The action to perform ('add', 'update', 'confirm', 'reject')
196
+ */
197
+ function processOperation(operation, actionType) {
198
+ if (!operation || !operation.queryset || !operation.queryset.ModelClass) {
199
+ console.warn(`Received invalid operation in processOperation (${actionType})`, operation);
200
+ return;
201
+ }
202
+ if (operation.doNotPropagate) {
203
+ return;
204
+ }
205
+ // Process model store first
206
+ processModelStore(operation, actionType);
207
+ // Then process queryset stores with improved routing
208
+ processQuerysetStores(operation, actionType);
209
+ // Finally process metric stores
210
+ processMetricStores(operation, actionType);
211
+ }
212
+ // Define handlers as named arrow functions at the top level
213
+ const handleOperationCreated = operation => processOperation(operation, 'add');
214
+ const handleOperationUpdated = operation => processOperation(operation, 'update');
215
+ const handleOperationMutated = operation => processOperation(operation, 'update');
216
+ const handleOperationConfirmed = operation => processOperation(operation, 'confirm');
217
+ const handleOperationRejected = operation => processOperation(operation, 'reject');
218
+ /**
219
+ * Initialize the operation event handler system by setting up event listeners
220
+ */
221
+ export function initEventHandler() {
222
+ operationEvents.on(Status.CREATED, handleOperationCreated);
223
+ operationEvents.on(Status.UPDATED, handleOperationUpdated);
224
+ operationEvents.on(Status.CONFIRMED, handleOperationConfirmed);
225
+ operationEvents.on(Status.REJECTED, handleOperationRejected);
226
+ operationEvents.on(Status.MUTATED, handleOperationMutated);
227
+ console.log('Operation event handler initialized');
228
+ }
229
+ /**
230
+ * Clean up by removing all event listeners
231
+ */
232
+ export function cleanupEventHandler() {
233
+ operationEvents.off(Status.CREATED, handleOperationCreated);
234
+ operationEvents.off(Status.UPDATED, handleOperationUpdated);
235
+ operationEvents.off(Status.CONFIRMED, handleOperationConfirmed);
236
+ operationEvents.off(Status.REJECTED, handleOperationRejected);
237
+ operationEvents.off(Status.MUTATED, handleOperationMutated);
238
+ console.log('Operation event handler cleaned up');
239
+ }
@@ -0,0 +1,32 @@
1
+ export class QuerysetStore {
2
+ constructor(modelClass: any, fetchFn: any, queryset: any, initialGroundTruthPks?: null, initialOperations?: null, options?: {});
3
+ modelClass: any;
4
+ fetchFn: any;
5
+ queryset: any;
6
+ operationsMap: Map<any, any>;
7
+ groundTruthPks: never[];
8
+ isSyncing: boolean;
9
+ pruneThreshold: any;
10
+ qsCache: Cache;
11
+ get cacheKey(): any;
12
+ onHydrated(hydratedData: any): void;
13
+ setCache(result: any): void;
14
+ clearCache(): void;
15
+ get operations(): any[];
16
+ get pkField(): any;
17
+ get groundTruthSet(): Set<never>;
18
+ _emitRenderEvent(): void;
19
+ addOperation(operation: any): Promise<void>;
20
+ updateOperation(operation: any): Promise<true | undefined>;
21
+ confirm(operation: any): Promise<void>;
22
+ reject(operation: any): Promise<void>;
23
+ setGroundTruth(groundTruthPks: any): Promise<void>;
24
+ setOperations(operations: any): Promise<void>;
25
+ getTrimmedOperations(): any[];
26
+ getInflightOperations(): any[];
27
+ prune(): void;
28
+ render(optimistic?: boolean, fromCache?: boolean): any[];
29
+ applyOperation(operation: any, currentPks: any): any;
30
+ sync(): Promise<void>;
31
+ }
32
+ import { Cache } from '../cache/cache.js';