@statezero/core 0.1.82 → 0.1.84

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.
@@ -163,6 +163,16 @@ export class QuerysetStoreRegistry {
163
163
  this.addFollowingQueryset(semanticKey, queryset);
164
164
  return this._stores.get(semanticKey);
165
165
  }
166
+ // Check if any parent in the chain has a temp store with the same semantic key
167
+ // This ensures that materialized querysets (created via fetch/create/etc) share
168
+ // the same store as their parent queryset when they have the same semantic key
169
+ let current = queryset.__parent;
170
+ while (current) {
171
+ if (this._tempStores.has(current) && current.semanticKey === semanticKey) {
172
+ return this._tempStores.get(current);
173
+ }
174
+ current = current.__parent;
175
+ }
166
176
  // Create a new temporary store
167
177
  const fetchQueryset = async ({ ast, modelClass }) => {
168
178
  // Directly assemble the request and call the API to avoid recursive logic from the
@@ -37,6 +37,7 @@ function relatedQuerysets(queryset) {
37
37
  }
38
38
  /**
39
39
  * Process an operation in the model store
40
+ * Only processes if the model store doesn't already have the operation.
40
41
  *
41
42
  * @param {Operation} operation - The operation to process
42
43
  * @param {string} actionType - The action to perform ('add', 'update', 'confirm', 'reject')
@@ -46,6 +47,10 @@ function processModelStore(operation, actionType) {
46
47
  const modelStore = modelStoreRegistry.getStore(ModelClass);
47
48
  if (!modelStore)
48
49
  return;
50
+ // Skip if the model store already has this operation
51
+ if (modelStore.operationsMap.has(operation.operationId)) {
52
+ return;
53
+ }
49
54
  switch (actionType) {
50
55
  case 'add':
51
56
  modelStore.addOperation(operation);
@@ -113,7 +118,12 @@ function processQuerysetStores(operation, actionType) {
113
118
  querysetStoreMap = relatedQuerysets(queryset);
114
119
  break;
115
120
  }
116
- Array.from(querysetStoreMap.values()).forEach(applyAction);
121
+ // Filter to only stores that DON'T already have this operation
122
+ const storesToRoute = Array.from(querysetStoreMap.values()).filter(store => {
123
+ return !store.operationsMap.has(operation.operationId);
124
+ });
125
+ // Route only to stores that don't have the operation yet
126
+ storesToRoute.forEach(applyAction);
117
127
  }
118
128
  /**
119
129
  * Process an operation in the metric stores based on operation type
@@ -46,7 +46,19 @@ export class SyncManager {
46
46
  this.processMetrics(payload);
47
47
  }
48
48
  if (isLocalOperation) {
49
- return;
49
+ // Check if any stores for this model class DON'T have the operation yet
50
+ const modelStore = modelStoreRegistry.getStore(payload.modelClass);
51
+ const querysetStores = querysetStoreRegistry.getAllStoresForModel(payload.modelClass);
52
+ // If model store and all queryset stores already have the operation, skip
53
+ // Note: getStore() always returns a store (creates if needed)
54
+ // and operationsMap is always initialized in constructors
55
+ const modelStoreHasIt = modelStore.operationsMap.has(payload.operation_id);
56
+ const allQuerysetStoresHaveIt = querysetStores.length === 0 ||
57
+ querysetStores.every(store => store.operationsMap.has(payload.operation_id));
58
+ if (modelStoreHasIt && allQuerysetStoresHaveIt) {
59
+ return; // All stores already have it, no need to process
60
+ }
61
+ // Otherwise, continue to process for stores that don't have it yet
50
62
  }
51
63
  // Add to batch for queryset/model processing
52
64
  const key = `${event.model}::${event.configKey}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.1.82",
3
+ "version": "0.1.84",
4
4
  "type": "module",
5
5
  "module": "ESNext",
6
6
  "description": "The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate",