@statezero/core 0.2.50 → 0.2.52

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 (171) hide show
  1. package/dist/adaptors/vue/components/StateZeroDebugPanel.js +489 -471
  2. package/dist/adaptors/vue/reactivity.d.ts +1 -0
  3. package/dist/adaptors/vue/reactivity.js +17 -5
  4. package/dist/cli/commands/syncActions.js +33 -1
  5. package/dist/cli/commands/syncModels.js +44 -3
  6. package/dist/filtering/localFiltering.js +4 -4
  7. package/dist/flavours/django/errors.d.ts +12 -0
  8. package/dist/flavours/django/errors.js +20 -0
  9. package/dist/flavours/django/f.js +16 -15
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.js +2 -2
  12. package/dist/models/backend1/django_app/author.d.ts +284 -0
  13. package/dist/models/backend1/django_app/author.js +69 -0
  14. package/dist/models/backend1/django_app/author.schema.json +281 -0
  15. package/dist/models/backend1/django_app/book.d.ts +262 -0
  16. package/dist/models/backend1/django_app/book.js +71 -0
  17. package/dist/models/backend1/django_app/book.schema.json +254 -0
  18. package/dist/models/backend1/django_app/composeditem.d.ts +140 -0
  19. package/dist/models/backend1/django_app/composeditem.js +69 -0
  20. package/dist/models/backend1/django_app/composeditem.schema.json +122 -0
  21. package/dist/models/backend1/django_app/comprehensivemodel.schema.json +3 -3
  22. package/dist/models/backend1/django_app/dailyrate.schema.json +7 -7
  23. package/dist/models/backend1/django_app/deepmodellevel1.schema.json +1 -1
  24. package/dist/models/backend1/django_app/dummymodel.schema.json +3 -3
  25. package/dist/models/backend1/django_app/errortestcompoundunique.d.ts +124 -0
  26. package/dist/models/backend1/django_app/errortestcompoundunique.js +69 -0
  27. package/dist/models/backend1/django_app/errortestcompoundunique.schema.json +106 -0
  28. package/dist/models/backend1/django_app/errortestonetoonemodel.d.ts +118 -0
  29. package/dist/models/backend1/django_app/errortestonetoonemodel.js +71 -0
  30. package/dist/models/backend1/django_app/errortestonetoonemodel.schema.json +90 -0
  31. package/dist/models/backend1/django_app/errortestparent.d.ts +92 -0
  32. package/dist/models/backend1/django_app/errortestparent.js +69 -0
  33. package/dist/models/backend1/django_app/errortestparent.schema.json +70 -0
  34. package/dist/models/backend1/django_app/errortestprotectedchild.d.ts +118 -0
  35. package/dist/models/backend1/django_app/errortestprotectedchild.js +71 -0
  36. package/dist/models/backend1/django_app/errortestprotectedchild.schema.json +94 -0
  37. package/dist/models/backend1/django_app/errortestuniquemodel.d.ts +108 -0
  38. package/dist/models/backend1/django_app/errortestuniquemodel.js +69 -0
  39. package/dist/models/backend1/django_app/errortestuniquemodel.schema.json +88 -0
  40. package/dist/models/backend1/django_app/excludeditem.d.ts +124 -0
  41. package/dist/models/backend1/django_app/excludeditem.js +69 -0
  42. package/dist/models/backend1/django_app/excludeditem.schema.json +105 -0
  43. package/dist/models/backend1/django_app/hfchild.d.ts +118 -0
  44. package/dist/models/backend1/django_app/hfchild.js +71 -0
  45. package/dist/models/backend1/django_app/hfchild.schema.json +94 -0
  46. package/dist/models/backend1/django_app/hfparent.d.ts +124 -0
  47. package/dist/models/backend1/django_app/hfparent.js +69 -0
  48. package/dist/models/backend1/django_app/hfparent.schema.json +105 -0
  49. package/dist/models/backend1/django_app/index.js +19 -0
  50. package/dist/models/backend1/django_app/m2mdepthtestlevel1.schema.json +3 -3
  51. package/dist/models/backend1/django_app/m2mdepthtestlevel2.schema.json +3 -3
  52. package/dist/models/backend1/django_app/m2mdepthtestlevel3.schema.json +5 -5
  53. package/dist/models/backend1/django_app/modelwithrestrictedfields.schema.json +2 -2
  54. package/dist/models/backend1/django_app/nodeleteitem.d.ts +124 -0
  55. package/dist/models/backend1/django_app/nodeleteitem.js +69 -0
  56. package/dist/models/backend1/django_app/nodeleteitem.schema.json +105 -0
  57. package/dist/models/backend1/django_app/objectlevelitem.d.ts +124 -0
  58. package/dist/models/backend1/django_app/objectlevelitem.js +69 -0
  59. package/dist/models/backend1/django_app/objectlevelitem.schema.json +105 -0
  60. package/dist/models/backend1/django_app/order.schema.json +7 -7
  61. package/dist/models/backend1/django_app/orderitem.schema.json +5 -5
  62. package/dist/models/backend1/django_app/product.schema.json +11 -11
  63. package/dist/models/backend1/django_app/productcategory.schema.json +2 -2
  64. package/dist/models/backend1/django_app/rateplan.schema.json +2 -2
  65. package/dist/models/backend1/django_app/readonlyitem.d.ts +124 -0
  66. package/dist/models/backend1/django_app/readonlyitem.js +69 -0
  67. package/dist/models/backend1/django_app/readonlyitem.schema.json +105 -0
  68. package/dist/models/backend1/django_app/restrictedcreateitem.d.ts +124 -0
  69. package/dist/models/backend1/django_app/restrictedcreateitem.js +69 -0
  70. package/dist/models/backend1/django_app/restrictedcreateitem.schema.json +105 -0
  71. package/dist/models/backend1/django_app/restrictededititem.d.ts +124 -0
  72. package/dist/models/backend1/django_app/restrictededititem.js +69 -0
  73. package/dist/models/backend1/django_app/restrictededititem.schema.json +105 -0
  74. package/dist/models/backend1/django_app/restrictedfieldrelatedmodel.schema.json +1 -1
  75. package/dist/models/backend1/django_app/rowfiltereditem.d.ts +124 -0
  76. package/dist/models/backend1/django_app/rowfiltereditem.js +69 -0
  77. package/dist/models/backend1/django_app/rowfiltereditem.schema.json +105 -0
  78. package/dist/models/backend1/django_app/tag.d.ts +554 -0
  79. package/dist/models/backend1/django_app/tag.js +71 -0
  80. package/dist/models/backend1/django_app/tag.schema.json +541 -0
  81. package/dist/models/backend1/django_app/updateonlyitem.d.ts +108 -0
  82. package/dist/models/backend1/django_app/updateonlyitem.js +69 -0
  83. package/dist/models/backend1/django_app/updateonlyitem.schema.json +88 -0
  84. package/dist/models/default/django_app/author.d.ts +284 -0
  85. package/dist/models/default/django_app/author.js +69 -0
  86. package/dist/models/default/django_app/author.schema.json +281 -0
  87. package/dist/models/default/django_app/book.d.ts +262 -0
  88. package/dist/models/default/django_app/book.js +71 -0
  89. package/dist/models/default/django_app/book.schema.json +254 -0
  90. package/dist/models/default/django_app/composeditem.d.ts +140 -0
  91. package/dist/models/default/django_app/composeditem.js +69 -0
  92. package/dist/models/default/django_app/composeditem.schema.json +122 -0
  93. package/dist/models/default/django_app/comprehensivemodel.schema.json +3 -3
  94. package/dist/models/default/django_app/dailyrate.schema.json +7 -7
  95. package/dist/models/default/django_app/deepmodellevel1.d.ts +1 -13
  96. package/dist/models/default/django_app/deepmodellevel1.schema.json +2 -14
  97. package/dist/models/default/django_app/deepmodellevel2.d.ts +1 -13
  98. package/dist/models/default/django_app/deepmodellevel2.schema.json +1 -13
  99. package/dist/models/default/django_app/deepmodellevel3.d.ts +1 -13
  100. package/dist/models/default/django_app/deepmodellevel3.schema.json +1 -13
  101. package/dist/models/default/django_app/dummymodel.d.ts +1 -13
  102. package/dist/models/default/django_app/dummymodel.schema.json +4 -16
  103. package/dist/models/default/django_app/dummyrelatedmodel.d.ts +1 -13
  104. package/dist/models/default/django_app/dummyrelatedmodel.schema.json +1 -13
  105. package/dist/models/default/django_app/errortestcompoundunique.d.ts +124 -0
  106. package/dist/models/default/django_app/errortestcompoundunique.js +69 -0
  107. package/dist/models/default/django_app/errortestcompoundunique.schema.json +106 -0
  108. package/dist/models/default/django_app/errortestonetoonemodel.d.ts +118 -0
  109. package/dist/models/default/django_app/errortestonetoonemodel.js +71 -0
  110. package/dist/models/default/django_app/errortestonetoonemodel.schema.json +90 -0
  111. package/dist/models/default/django_app/errortestparent.d.ts +92 -0
  112. package/dist/models/default/django_app/errortestparent.js +69 -0
  113. package/dist/models/default/django_app/errortestparent.schema.json +70 -0
  114. package/dist/models/default/django_app/errortestprotectedchild.d.ts +118 -0
  115. package/dist/models/default/django_app/errortestprotectedchild.js +71 -0
  116. package/dist/models/default/django_app/errortestprotectedchild.schema.json +94 -0
  117. package/dist/models/default/django_app/errortestuniquemodel.d.ts +108 -0
  118. package/dist/models/default/django_app/errortestuniquemodel.js +69 -0
  119. package/dist/models/default/django_app/errortestuniquemodel.schema.json +88 -0
  120. package/dist/models/default/django_app/excludeditem.d.ts +124 -0
  121. package/dist/models/default/django_app/excludeditem.js +69 -0
  122. package/dist/models/default/django_app/excludeditem.schema.json +105 -0
  123. package/dist/models/default/django_app/filetest.d.ts +1 -13
  124. package/dist/models/default/django_app/filetest.schema.json +1 -13
  125. package/dist/models/default/django_app/hfchild.d.ts +118 -0
  126. package/dist/models/default/django_app/hfchild.js +71 -0
  127. package/dist/models/default/django_app/hfchild.schema.json +94 -0
  128. package/dist/models/default/django_app/hfparent.d.ts +124 -0
  129. package/dist/models/default/django_app/hfparent.js +69 -0
  130. package/dist/models/default/django_app/hfparent.schema.json +105 -0
  131. package/dist/models/default/django_app/index.js +19 -0
  132. package/dist/models/default/django_app/m2mdepthtestlevel1.schema.json +3 -3
  133. package/dist/models/default/django_app/m2mdepthtestlevel2.schema.json +3 -3
  134. package/dist/models/default/django_app/m2mdepthtestlevel3.schema.json +5 -5
  135. package/dist/models/default/django_app/modelwithrestrictedfields.schema.json +2 -2
  136. package/dist/models/default/django_app/nodeleteitem.d.ts +124 -0
  137. package/dist/models/default/django_app/nodeleteitem.js +69 -0
  138. package/dist/models/default/django_app/nodeleteitem.schema.json +105 -0
  139. package/dist/models/default/django_app/objectlevelitem.d.ts +124 -0
  140. package/dist/models/default/django_app/objectlevelitem.js +69 -0
  141. package/dist/models/default/django_app/objectlevelitem.schema.json +105 -0
  142. package/dist/models/default/django_app/order.schema.json +7 -7
  143. package/dist/models/default/django_app/orderitem.schema.json +5 -5
  144. package/dist/models/default/django_app/product.schema.json +11 -11
  145. package/dist/models/default/django_app/productcategory.schema.json +2 -2
  146. package/dist/models/default/django_app/rateplan.schema.json +2 -2
  147. package/dist/models/default/django_app/readonlyitem.d.ts +124 -0
  148. package/dist/models/default/django_app/readonlyitem.js +69 -0
  149. package/dist/models/default/django_app/readonlyitem.schema.json +105 -0
  150. package/dist/models/default/django_app/restrictedcreateitem.d.ts +124 -0
  151. package/dist/models/default/django_app/restrictedcreateitem.js +69 -0
  152. package/dist/models/default/django_app/restrictedcreateitem.schema.json +105 -0
  153. package/dist/models/default/django_app/restrictededititem.d.ts +124 -0
  154. package/dist/models/default/django_app/restrictededititem.js +69 -0
  155. package/dist/models/default/django_app/restrictededititem.schema.json +105 -0
  156. package/dist/models/default/django_app/restrictedfieldrelatedmodel.schema.json +1 -1
  157. package/dist/models/default/django_app/rowfiltereditem.d.ts +124 -0
  158. package/dist/models/default/django_app/rowfiltereditem.js +69 -0
  159. package/dist/models/default/django_app/rowfiltereditem.schema.json +105 -0
  160. package/dist/models/default/django_app/tag.d.ts +554 -0
  161. package/dist/models/default/django_app/tag.js +71 -0
  162. package/dist/models/default/django_app/tag.schema.json +541 -0
  163. package/dist/models/default/django_app/updateonlyitem.d.ts +108 -0
  164. package/dist/models/default/django_app/updateonlyitem.js +69 -0
  165. package/dist/models/default/django_app/updateonlyitem.schema.json +88 -0
  166. package/dist/schemaIntegrity.d.ts +14 -0
  167. package/dist/schemaIntegrity.js +29 -0
  168. package/dist/setup.js +6 -0
  169. package/dist/syncEngine/stores/operationEventHandlers.js +10 -8
  170. package/dist/syncEngine/stores/querysetStore.js +9 -0
  171. package/package.json +1 -1
@@ -0,0 +1,69 @@
1
+ /**
2
+ * This file was auto-generated. Do not make direct changes to the file.
3
+ */
4
+ import { Model, Manager, QuerySet, getModelClass } from '../../../../src';
5
+ import { wrapReactiveModel } from '../../../../src';
6
+ import schemaData from './updateonlyitem.schema.json';
7
+ /**
8
+ * Model-specific QuerySet implementation
9
+ */
10
+ export class UpdateOnlyItemQuerySet extends QuerySet {
11
+ }
12
+ /**
13
+ * Model-specific Manager implementation
14
+ */
15
+ export class UpdateOnlyItemManager extends Manager {
16
+ constructor(ModelClass) {
17
+ super(ModelClass, UpdateOnlyItemQuerySet);
18
+ }
19
+ newQuerySet() {
20
+ return new UpdateOnlyItemQuerySet(this.ModelClass);
21
+ }
22
+ }
23
+ /**
24
+ * Implementation of the UpdateOnlyItem model
25
+ */
26
+ export class UpdateOnlyItem extends Model {
27
+ constructor(data) {
28
+ UpdateOnlyItem.validateFields(data);
29
+ super(data);
30
+ // Define getters and setters for all fields
31
+ this._defineProperties();
32
+ return wrapReactiveModel(this);
33
+ }
34
+ /**
35
+ * Define property getters and setters for all model fields
36
+ * @private
37
+ */
38
+ _defineProperties() {
39
+ // For each field, define a property that gets/sets from internal storage
40
+ UpdateOnlyItem.fields.forEach(field => {
41
+ Object.defineProperty(this, field, {
42
+ get: function () {
43
+ return this.getField(field);
44
+ },
45
+ set: function (value) {
46
+ this.setField(field, value);
47
+ },
48
+ enumerable: true, // Make sure fields are enumerable for serialization
49
+ configurable: true
50
+ });
51
+ });
52
+ // Add a special read-only getter for the repr field
53
+ Object.defineProperty(this, 'repr', {
54
+ get: function () {
55
+ return this.getField('repr');
56
+ },
57
+ enumerable: true, // Make sure repr is enumerable
58
+ configurable: true
59
+ });
60
+ }
61
+ }
62
+ // Bind this model to its backend
63
+ UpdateOnlyItem.configKey = 'default';
64
+ UpdateOnlyItem.modelName = 'django_app.updateonlyitem';
65
+ UpdateOnlyItem.primaryKeyField = 'id';
66
+ UpdateOnlyItem.objects = new UpdateOnlyItemManager(UpdateOnlyItem);
67
+ UpdateOnlyItem.fields = ['id', 'name', 'value'];
68
+ UpdateOnlyItem.schema = schemaData;
69
+ UpdateOnlyItem.relationshipFields = new Map([]);
@@ -0,0 +1,88 @@
1
+ {
2
+ "model_name": "django_app.updateonlyitem",
3
+ "title": "Update Only Item",
4
+ "class_name": "UpdateOnlyItem",
5
+ "plural_title": "Update Only Items",
6
+ "primary_key_field": "id",
7
+ "filterable_fields": [
8
+ "value",
9
+ "id",
10
+ "name"
11
+ ],
12
+ "searchable_fields": [
13
+ "name"
14
+ ],
15
+ "ordering_fields": [
16
+ "value",
17
+ "name"
18
+ ],
19
+ "properties": {
20
+ "id": {
21
+ "type": "integer",
22
+ "title": "Id",
23
+ "required": true,
24
+ "description": null,
25
+ "nullable": false,
26
+ "format": "id",
27
+ "max_length": null,
28
+ "choices": null,
29
+ "default": null,
30
+ "validators": [],
31
+ "max_digits": null,
32
+ "decimal_places": null,
33
+ "read_only": true,
34
+ "ref": null
35
+ },
36
+ "name": {
37
+ "type": "string",
38
+ "title": "Name",
39
+ "required": true,
40
+ "description": null,
41
+ "nullable": false,
42
+ "format": null,
43
+ "max_length": 100,
44
+ "choices": null,
45
+ "default": null,
46
+ "validators": [],
47
+ "max_digits": null,
48
+ "decimal_places": null,
49
+ "read_only": false,
50
+ "ref": null
51
+ },
52
+ "value": {
53
+ "type": "integer",
54
+ "title": "Value",
55
+ "required": false,
56
+ "description": null,
57
+ "nullable": false,
58
+ "format": null,
59
+ "max_length": null,
60
+ "choices": null,
61
+ "default": 0,
62
+ "validators": [],
63
+ "max_digits": null,
64
+ "decimal_places": null,
65
+ "read_only": false,
66
+ "ref": null
67
+ }
68
+ },
69
+ "relationships": {},
70
+ "default_ordering": null,
71
+ "definitions": {
72
+ "MoneyField": {
73
+ "type": "object",
74
+ "properties": {
75
+ "amount": {
76
+ "type": "number"
77
+ },
78
+ "currency": {
79
+ "type": "string"
80
+ }
81
+ }
82
+ }
83
+ },
84
+ "datetime_format": "iso-8601",
85
+ "date_format": "iso-8601",
86
+ "time_format": "iso-8601",
87
+ "display": null
88
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Background check that compares stored schema checksums (from sync time)
3
+ * against the current checksums returned by the backend.
4
+ *
5
+ * Warns via console if schemas have drifted. Silently skips on network error.
6
+ *
7
+ * @param {Object.<string, Object>} backendConfigs - Backend configuration map from configInstance
8
+ * @param {Object.<string, string>} checksums - Map of backend key to checksum from sync time
9
+ */
10
+ export function checkSchemaIntegrity(backendConfigs: {
11
+ [x: string]: Object;
12
+ }, checksums: {
13
+ [x: string]: string;
14
+ }): Promise<void>;
@@ -0,0 +1,29 @@
1
+ import axios from "axios";
2
+ /**
3
+ * Background check that compares stored schema checksums (from sync time)
4
+ * against the current checksums returned by the backend.
5
+ *
6
+ * Warns via console if schemas have drifted. Silently skips on network error.
7
+ *
8
+ * @param {Object.<string, Object>} backendConfigs - Backend configuration map from configInstance
9
+ * @param {Object.<string, string>} checksums - Map of backend key to checksum from sync time
10
+ */
11
+ export async function checkSchemaIntegrity(backendConfigs, checksums) {
12
+ for (const [backendKey, expectedChecksum] of Object.entries(checksums)) {
13
+ const backend = backendConfigs[backendKey];
14
+ if (!backend)
15
+ continue;
16
+ try {
17
+ const headers = backend.getAuthHeaders ? backend.getAuthHeaders() : {};
18
+ const response = await axios.get(`${backend.API_URL}/models/`, { headers });
19
+ const currentChecksum = response.headers['x-statezero-schema-checksum'];
20
+ if (currentChecksum && currentChecksum !== expectedChecksum) {
21
+ console.warn(`[StateZero] Schema drift detected for backend '${backendKey}'. ` +
22
+ `Run 'npx statezero sync' to update your generated types.`);
23
+ }
24
+ }
25
+ catch {
26
+ // Silently skip — this is a non-blocking background check
27
+ }
28
+ }
29
+ }
package/dist/setup.js CHANGED
@@ -5,6 +5,7 @@ import { initEventHandler } from "./syncEngine/stores/operationEventHandlers.js"
5
5
  import { querysetStoreRegistry } from "./syncEngine/registries/querysetStoreRegistry.js";
6
6
  import { modelStoreRegistry } from "./syncEngine/registries/modelStoreRegistry.js";
7
7
  import { metricRegistry } from "./syncEngine/registries/metricRegistry.js";
8
+ import { checkSchemaIntegrity } from "./schemaIntegrity.js";
8
9
  /**
9
10
  * Initialize StateZero with the provided configuration
10
11
  *
@@ -30,4 +31,9 @@ export function setupStateZero(config, getModelClass, adapters) {
30
31
  metricRegistry,
31
32
  };
32
33
  }
34
+ // Background schema freshness check (fire-and-forget)
35
+ if (getModelClass.SYNC_CHECKSUMS) {
36
+ const cfg = configInstance.getConfig();
37
+ checkSchemaIntegrity(cfg.backendConfigs, getModelClass.SYNC_CHECKSUMS);
38
+ }
33
39
  }
@@ -203,7 +203,7 @@ function routeCreateOperation(operation, applyAction) {
203
203
  *
204
204
  * @param {Operation} operation - The UPDATE operation
205
205
  */
206
- function routeUpdateOperation(operation) {
206
+ function routeUpdateOperation(operation, applyAction) {
207
207
  const modelClass = operation.queryset.ModelClass;
208
208
  // frozenInstances is already serialized with proper FK structure
209
209
  const beforeInstances = operation.frozenInstances;
@@ -230,6 +230,8 @@ function routeUpdateOperation(operation) {
230
230
  return;
231
231
  }
232
232
  // Item matched before OR matches after, no offset - definitely affected
233
+ // Apply the operation so the queryset can add/remove PKs from its candidate set
234
+ applyAction(store);
233
235
  operationRegistry.setQuerysetState(operation.operationId, semanticKey, createMembershipState(true, false));
234
236
  });
235
237
  }
@@ -243,7 +245,7 @@ function routeUpdateOperation(operation) {
243
245
  *
244
246
  * @param {Operation} operation - The DELETE operation
245
247
  */
246
- function routeDeleteOperation(operation) {
248
+ function routeDeleteOperation(operation, applyAction) {
247
249
  const modelClass = operation.queryset.ModelClass;
248
250
  // frozenInstances is already serialized with proper FK structure
249
251
  const beforeInstances = operation.frozenInstances;
@@ -267,6 +269,7 @@ function routeDeleteOperation(operation) {
267
269
  return;
268
270
  }
269
271
  // Item matched before, no offset - definitely affected
272
+ applyAction(store);
270
273
  operationRegistry.setQuerysetState(operation.operationId, semanticKey, createMembershipState(true, false));
271
274
  });
272
275
  }
@@ -339,15 +342,14 @@ function processQuerysetStores(operation, actionType) {
339
342
  return;
340
343
  case Type.UPDATE:
341
344
  case Type.UPDATE_INSTANCE:
342
- // Track membership for sync optimization
343
- // Check both before (frozenInstances) and after (instances) state
344
- routeUpdateOperation(operation);
345
+ // Route update to affected querysets so items can move between filtered sets
346
+ // (e.g., an item changing name from 'beta' to 'alpha' needs to appear in the alpha queryset)
347
+ routeUpdateOperation(operation, applyAction);
345
348
  return;
346
349
  case Type.DELETE:
347
350
  case Type.DELETE_INSTANCE:
348
- // Track membership for sync optimization
349
- // Check before state only (item being deleted)
350
- routeDeleteOperation(operation);
351
+ // Add delete to matching queryset stores for optimistic removal
352
+ routeDeleteOperation(operation, applyAction);
351
353
  return;
352
354
  case Type.CHECKPOINT:
353
355
  // Model store handles the change, querysets re-render via local filtering
@@ -125,6 +125,10 @@ export class QuerysetStore {
125
125
  }
126
126
  async setGroundTruth(groundTruthPks) {
127
127
  this.groundTruthPks = Array.isArray(groundTruthPks) ? groundTruthPks : [];
128
+ if (this.groundTruthPks.length > 500) {
129
+ const limit = this.queryset?._serializerOptions?.limit;
130
+ console.warn(`[statezero] ⚠️ ${this.modelClass.modelName} (${this.queryset.semanticKey}) received ${this.groundTruthPks.length} items${limit ? ` (limit: ${limit})` : ' with NO limit'}. Live querysets re-render on every change — at this size, this WILL cause UI freezes on mobile. Add .fetch({ limit }) or use narrower filters.`);
131
+ }
128
132
  this.lastSync = Date.now();
129
133
  this._emitRenderEvent();
130
134
  }
@@ -269,8 +273,13 @@ export class QuerysetStore {
269
273
  currentPks.add(pk);
270
274
  break;
271
275
  case Type.CHECKPOINT:
276
+ break;
272
277
  case Type.UPDATE:
273
278
  case Type.UPDATE_INSTANCE:
279
+ // Add PKs as candidates so items can move into this queryset
280
+ // when an update makes them match the filter.
281
+ // _getValidatedAndFilteredPks will filter out non-matching items.
282
+ currentPks.add(pk);
274
283
  break;
275
284
  case Type.DELETE:
276
285
  case Type.DELETE_INSTANCE:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.2.50",
3
+ "version": "0.2.52",
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",