@statezero/core 0.2.42 → 0.2.43
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.
|
@@ -32,6 +32,9 @@ export function useQueryset(querysetFactory) {
|
|
|
32
32
|
updateSyncManager();
|
|
33
33
|
lastQueryset = queryset;
|
|
34
34
|
}
|
|
35
|
+
// Access __version to establish Vue dependency tracking for watch()
|
|
36
|
+
// This makes the computed re-evaluate when queryset data changes
|
|
37
|
+
const _ = result?.__version;
|
|
35
38
|
return result;
|
|
36
39
|
});
|
|
37
40
|
}
|
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vue Reactivity Adapters for StateZero
|
|
3
|
+
*
|
|
4
|
+
* This module bridges StateZero's event-based reactivity (mitt) with Vue's reactivity system.
|
|
5
|
+
*
|
|
6
|
+
* ## How It Works
|
|
7
|
+
*
|
|
8
|
+
* StateZero emits events via mitt when data changes. These adapters:
|
|
9
|
+
* 1. Wrap data in Vue's reactive() or ref()
|
|
10
|
+
* 2. Listen for mitt events
|
|
11
|
+
* 3. Update the reactive wrapper when events fire
|
|
12
|
+
*
|
|
13
|
+
* ## Queryset Reactivity
|
|
14
|
+
*
|
|
15
|
+
* Querysets are wrapped as **stable reactive arrays**. The same object reference is
|
|
16
|
+
* maintained across updates - data is mutated in place via splice/push. This is
|
|
17
|
+
* intentional:
|
|
18
|
+
*
|
|
19
|
+
* - Templates automatically re-render (Vue tracks array mutations)
|
|
20
|
+
* - Object identity stays stable (no stale references in UI code)
|
|
21
|
+
* - Cached wrappers are reused for the same queryset
|
|
22
|
+
*
|
|
23
|
+
* ### Watching Querysets
|
|
24
|
+
*
|
|
25
|
+
* Because the object reference is stable, Vue's shallow watch won't detect changes.
|
|
26
|
+
* Use one of these patterns:
|
|
27
|
+
*
|
|
28
|
+
* ```js
|
|
29
|
+
* const messages = useQueryset(() => baseQs.value.fetch())
|
|
30
|
+
*
|
|
31
|
+
* // Option 1: Deep watch (recommended)
|
|
32
|
+
* watch(messages, (newMessages) => {
|
|
33
|
+
* scrollToBottom()
|
|
34
|
+
* }, { deep: true })
|
|
35
|
+
*
|
|
36
|
+
* // Option 2: Watch a derived value
|
|
37
|
+
* watch(() => messages.value.length, (newLen) => {
|
|
38
|
+
* scrollToBottom()
|
|
39
|
+
* })
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* ### The __version Mechanism
|
|
43
|
+
*
|
|
44
|
+
* Each queryset wrapper has a `__version` counter that increments on every update.
|
|
45
|
+
* The `useQueryset` composable accesses this to establish Vue dependency tracking,
|
|
46
|
+
* ensuring the computed re-evaluates when data changes. This makes `{ deep: true }`
|
|
47
|
+
* watches work correctly.
|
|
48
|
+
*
|
|
49
|
+
* ## Model Reactivity
|
|
50
|
+
*
|
|
51
|
+
* Models use a similar `__version` / `touch()` mechanism. When a model is updated,
|
|
52
|
+
* `touch()` increments the version, triggering Vue to re-render dependent components.
|
|
53
|
+
*/
|
|
1
54
|
import { reactive, ref, nextTick } from "vue";
|
|
2
55
|
import { modelEventEmitter, querysetEventEmitter, metricEventEmitter } from "../../syncEngine/stores/reactivity.js";
|
|
3
56
|
import { initEventHandler } from "../../syncEngine/stores/operationEventHandlers.js";
|
|
@@ -66,6 +119,7 @@ export function QuerySetAdaptor(liveQuerySet, reactivityFn = reactive) {
|
|
|
66
119
|
// Make the queryset reactive using the specified function
|
|
67
120
|
const wrapper = reactivityFn([...liveQuerySet]);
|
|
68
121
|
wrapper.original = liveQuerySet;
|
|
122
|
+
wrapper.__version = 0;
|
|
69
123
|
const eventName = `${configKey}::${modelName}::queryset::render`;
|
|
70
124
|
// Handler bumps version to trigger Vue reactivity when this queryset updates
|
|
71
125
|
const renderHandler = (eventData) => {
|
|
@@ -77,6 +131,8 @@ export function QuerySetAdaptor(liveQuerySet, reactivityFn = reactive) {
|
|
|
77
131
|
wrapper.splice(0, wrapper.length);
|
|
78
132
|
wrapper.push(...liveQuerySet);
|
|
79
133
|
}
|
|
134
|
+
// Bump version so computed/watch can track changes
|
|
135
|
+
wrapper.__version++;
|
|
80
136
|
}
|
|
81
137
|
};
|
|
82
138
|
// Subscribe to queryset events indefinitely
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statezero/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.43",
|
|
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",
|
|
@@ -115,8 +115,10 @@
|
|
|
115
115
|
"@types/yargs": "^17.0.32",
|
|
116
116
|
"@vitejs/plugin-vue": "^6.0.4",
|
|
117
117
|
"@vitest/coverage-v8": "^3.0.5",
|
|
118
|
+
"@vue/test-utils": "^2.4.6",
|
|
118
119
|
"fake-indexeddb": "^6.0.0",
|
|
119
120
|
"fast-glob": "^3.3.3",
|
|
121
|
+
"happy-dom": "^20.5.0",
|
|
120
122
|
"react": "^18.2.0",
|
|
121
123
|
"rimraf": "^5.0.5",
|
|
122
124
|
"ts-node": "^10.9.2",
|