@statezero/core 0.1.2 → 0.1.3-9.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.
- package/LICENSE +3 -2
- package/dist/cli/commands/sync.d.ts +6 -0
- package/dist/cli/commands/sync.js +30 -0
- package/dist/cli/commands/syncActions.d.ts +46 -0
- package/dist/cli/commands/syncActions.js +623 -0
- package/dist/cli/commands/syncModels.js +17 -35
- package/dist/cli/index.js +18 -10
- package/dist/config.d.ts +5 -0
- package/dist/config.js +40 -10
- package/dist/flavours/django/dates.js +3 -3
- package/dist/flavours/django/files.d.ts +8 -7
- package/dist/flavours/django/files.js +36 -2
- package/dist/flavours/django/model.d.ts +15 -0
- package/dist/flavours/django/model.js +143 -24
- package/dist/setup.js +11 -0
- package/dist/syncEngine/registries/metricRegistry.d.ts +5 -0
- package/dist/syncEngine/registries/metricRegistry.js +8 -0
- package/dist/syncEngine/registries/querysetStoreGraph.d.ts +21 -0
- package/dist/syncEngine/registries/querysetStoreGraph.js +95 -0
- package/dist/syncEngine/registries/querysetStoreRegistry.d.ts +14 -0
- package/dist/syncEngine/registries/querysetStoreRegistry.js +64 -16
- package/dist/syncEngine/stores/modelStore.d.ts +3 -0
- package/dist/syncEngine/stores/modelStore.js +76 -41
- package/dist/syncEngine/stores/querysetStore.d.ts +19 -0
- package/dist/syncEngine/stores/querysetStore.js +133 -18
- package/dist/syncEngine/sync.d.ts +5 -0
- package/dist/syncEngine/sync.js +61 -5
- package/package.json +126 -123
- package/readme.md +1 -1
package/dist/syncEngine/sync.js
CHANGED
|
@@ -58,6 +58,7 @@ export class SyncManager {
|
|
|
58
58
|
// Map of querysets to keep synced
|
|
59
59
|
this.followAllQuerysets = true;
|
|
60
60
|
this.followedQuerysets = new Map();
|
|
61
|
+
this.periodicSyncTimer = null;
|
|
61
62
|
}
|
|
62
63
|
/**
|
|
63
64
|
* Initialize event handlers for all event receivers
|
|
@@ -74,13 +75,68 @@ export class SyncManager {
|
|
|
74
75
|
receiver.addModelEventHandler(this.handleEvent.bind(this));
|
|
75
76
|
}
|
|
76
77
|
});
|
|
78
|
+
this.startPeriodicSync();
|
|
79
|
+
}
|
|
80
|
+
startPeriodicSync() {
|
|
81
|
+
if (this.periodicSyncTimer)
|
|
82
|
+
return;
|
|
83
|
+
try {
|
|
84
|
+
const config = getConfig();
|
|
85
|
+
const intervalSeconds = config.periodicSyncIntervalSeconds;
|
|
86
|
+
// If null or undefined, don't start periodic sync
|
|
87
|
+
if (!intervalSeconds) {
|
|
88
|
+
console.log("[SyncManager] Periodic sync disabled (set to null)");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const intervalMs = intervalSeconds * 1000;
|
|
92
|
+
this.periodicSyncTimer = setInterval(() => {
|
|
93
|
+
this.syncStaleQuerysets();
|
|
94
|
+
}, intervalMs);
|
|
95
|
+
console.log(`[SyncManager] Periodic sync started: ${intervalSeconds}s intervals`);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
// If no config, don't start periodic sync by default
|
|
99
|
+
console.log("[SyncManager] No config found, periodic sync disabled by default");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
syncStaleQuerysets() {
|
|
103
|
+
let syncedCount = 0;
|
|
104
|
+
// Sync all followed querysets - keep it simple
|
|
105
|
+
const querysetRegistry = this.registries.get("QuerysetStoreRegistry");
|
|
106
|
+
if (querysetRegistry) {
|
|
107
|
+
for (const [semanticKey, store] of querysetRegistry._stores.entries()) {
|
|
108
|
+
// Only sync if this store is actually being followed
|
|
109
|
+
const isFollowed = this.isStoreFollowed(querysetRegistry, semanticKey);
|
|
110
|
+
if (this.followAllQuerysets || isFollowed) {
|
|
111
|
+
store.sync();
|
|
112
|
+
syncedCount++;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (syncedCount > 0) {
|
|
117
|
+
console.log(`[SyncManager] Periodic sync: ${syncedCount} stores synced`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
isStoreFollowed(registry, semanticKey) {
|
|
121
|
+
const followingQuerysets = registry.followingQuerysets.get(semanticKey);
|
|
122
|
+
if (!followingQuerysets)
|
|
123
|
+
return false;
|
|
124
|
+
return [...followingQuerysets].some((queryset) => {
|
|
125
|
+
return this.isQuerysetFollowed(queryset);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
cleanup() {
|
|
129
|
+
if (this.periodicSyncTimer) {
|
|
130
|
+
clearInterval(this.periodicSyncTimer);
|
|
131
|
+
this.periodicSyncTimer = null;
|
|
132
|
+
}
|
|
77
133
|
}
|
|
78
134
|
followModel(registry, modelClass) {
|
|
79
135
|
const models = this.followedModels.get(registry) || new Set();
|
|
80
136
|
this.followedModels.set(registry, models);
|
|
81
137
|
if (models.has(modelClass))
|
|
82
138
|
return;
|
|
83
|
-
const alreadyFollowed = [...this.followedModels.values()].some(set => set.has(modelClass));
|
|
139
|
+
const alreadyFollowed = [...this.followedModels.values()].some((set) => set.has(modelClass));
|
|
84
140
|
models.add(modelClass);
|
|
85
141
|
if (!alreadyFollowed) {
|
|
86
142
|
getEventReceiver(modelClass.configKey)?.subscribe(modelClass.modelName, this.handleEvent);
|
|
@@ -91,7 +147,7 @@ export class SyncManager {
|
|
|
91
147
|
if (!models)
|
|
92
148
|
return;
|
|
93
149
|
models.delete(modelClass);
|
|
94
|
-
const stillFollowed = [...this.followedModels.values()].some(set => set.has(modelClass));
|
|
150
|
+
const stillFollowed = [...this.followedModels.values()].some((set) => set.has(modelClass));
|
|
95
151
|
if (!stillFollowed) {
|
|
96
152
|
getEventReceiver(modelClass.configKey)?.unsubscribe(modelClass.modelName, this.handleEvent);
|
|
97
153
|
}
|
|
@@ -104,10 +160,10 @@ export class SyncManager {
|
|
|
104
160
|
this.registries.delete(registry.constructor.name);
|
|
105
161
|
}
|
|
106
162
|
isQuerysetFollowed(queryset) {
|
|
163
|
+
const activeSemanticKeys = new Set([...this.followedQuerysets].map((qs) => qs.semanticKey));
|
|
107
164
|
let current = queryset;
|
|
108
|
-
// All followed querysets and their descendents get updated
|
|
109
165
|
while (current) {
|
|
110
|
-
if (
|
|
166
|
+
if (activeSemanticKeys.has(current.semanticKey)) {
|
|
111
167
|
return true;
|
|
112
168
|
}
|
|
113
169
|
current = current.__parent;
|
|
@@ -127,7 +183,7 @@ export class SyncManager {
|
|
|
127
183
|
const followingQuerysets = registry.followingQuerysets.get(semanticKey);
|
|
128
184
|
if (followingQuerysets) {
|
|
129
185
|
// Use some() to break early when we find a match
|
|
130
|
-
const shouldSync = [...followingQuerysets].some(queryset => {
|
|
186
|
+
const shouldSync = [...followingQuerysets].some((queryset) => {
|
|
131
187
|
return this.isQuerysetFollowed(queryset);
|
|
132
188
|
});
|
|
133
189
|
if (shouldSync) {
|
package/package.json
CHANGED
|
@@ -1,123 +1,126 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@statezero/core",
|
|
3
|
-
"version": "0.1.2",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"description": "The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate",
|
|
7
|
-
"main": "dist/index.js",
|
|
8
|
-
"types": "dist/index.d.ts",
|
|
9
|
-
"bin": {
|
|
10
|
-
"statezero": "dist/cli/index.js"
|
|
11
|
-
},
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"import": "./dist/index.js",
|
|
15
|
-
"require": "./dist/index.js"
|
|
16
|
-
},
|
|
17
|
-
"./cli": {
|
|
18
|
-
"import": "./dist/cli/index.js",
|
|
19
|
-
"require": "./dist/cli/index.js"
|
|
20
|
-
},
|
|
21
|
-
"./react": {
|
|
22
|
-
"import": "./dist/react-entry.js",
|
|
23
|
-
"require": "./dist/react-entry.js"
|
|
24
|
-
},
|
|
25
|
-
"./vue": {
|
|
26
|
-
"import": "./dist/vue-entry.js",
|
|
27
|
-
"require": "./dist/vue-entry.js"
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"test": "vitest run --config=vitest.base.config.ts",
|
|
32
|
-
"test:e2e": "vitest run --config=vitest.sequential.config.ts tests/e2e",
|
|
33
|
-
"generate:test-apps": "ts-node scripts/generate-test-apps.js",
|
|
34
|
-
"test:adaptors": "playwright test tests/adaptors",
|
|
35
|
-
"test:coverage": "vitest run --coverage",
|
|
36
|
-
"build": "tsc",
|
|
37
|
-
"parse-queries": "node scripts/perfect-query-parser.js",
|
|
38
|
-
"sync
|
|
39
|
-
"sync
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
"@
|
|
102
|
-
"@types/
|
|
103
|
-
"@types/
|
|
104
|
-
"@
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
},
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
},
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
}
|
|
123
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@statezero/core",
|
|
3
|
+
"version": "0.1.39.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"description": "The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"statezero": "dist/cli/index.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./cli": {
|
|
18
|
+
"import": "./dist/cli/index.js",
|
|
19
|
+
"require": "./dist/cli/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./react": {
|
|
22
|
+
"import": "./dist/react-entry.js",
|
|
23
|
+
"require": "./dist/react-entry.js"
|
|
24
|
+
},
|
|
25
|
+
"./vue": {
|
|
26
|
+
"import": "./dist/vue-entry.js",
|
|
27
|
+
"require": "./dist/vue-entry.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"test": "vitest run --config=vitest.base.config.ts",
|
|
32
|
+
"test:e2e": "vitest run --config=vitest.sequential.config.ts tests/e2e",
|
|
33
|
+
"generate:test-apps": "ts-node scripts/generate-test-apps.js",
|
|
34
|
+
"test:adaptors": "playwright test tests/adaptors",
|
|
35
|
+
"test:coverage": "vitest run --coverage",
|
|
36
|
+
"build": "tsc",
|
|
37
|
+
"parse-queries": "node scripts/perfect-query-parser.js",
|
|
38
|
+
"sync": "node src/cli/index.js sync",
|
|
39
|
+
"sync:dev": "npx cross-env NODE_ENV=test npm run sync",
|
|
40
|
+
"sync-models": "node src/cli/index.js sync-models",
|
|
41
|
+
"sync-models:dev": "npx cross-env NODE_ENV=test npm run sync-models",
|
|
42
|
+
"sync-actions": "node src/cli/index.js sync-actions",
|
|
43
|
+
"sync-actions:dev": "npx cross-env NODE_ENV=test npm run sync-actions",
|
|
44
|
+
"clean": "npx rimraf dist",
|
|
45
|
+
"prepare": "npm run clean && npm run build",
|
|
46
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"typescript",
|
|
50
|
+
"orm",
|
|
51
|
+
"backend",
|
|
52
|
+
"frontend",
|
|
53
|
+
"database",
|
|
54
|
+
"sql",
|
|
55
|
+
"django",
|
|
56
|
+
"sqlalchemy",
|
|
57
|
+
"react",
|
|
58
|
+
"vue",
|
|
59
|
+
"svelte"
|
|
60
|
+
],
|
|
61
|
+
"author": "Robert Herring <robert.herring@resipilot.com>",
|
|
62
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
63
|
+
"repository": {
|
|
64
|
+
"type": "git",
|
|
65
|
+
"url": "git+https://github.com/state-zero/statezero-client.git"
|
|
66
|
+
},
|
|
67
|
+
"files": [
|
|
68
|
+
"dist",
|
|
69
|
+
"LICENSE",
|
|
70
|
+
"README.md"
|
|
71
|
+
],
|
|
72
|
+
"homepage": "https://www.statezero.dev",
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"axios": "^1.7.9",
|
|
75
|
+
"cli-progress": "^3.12.0",
|
|
76
|
+
"cosmiconfig": "^9.0.0",
|
|
77
|
+
"cosmiconfig-typescript-loader": "^6.1.0",
|
|
78
|
+
"date-fns": "^4.1.0",
|
|
79
|
+
"dotenv": "^16.4.7",
|
|
80
|
+
"fs-extra": "^11.3.0",
|
|
81
|
+
"graphlib": "^2.1.8",
|
|
82
|
+
"handlebars": "^4.7.8",
|
|
83
|
+
"idb": "^8.0.2",
|
|
84
|
+
"inquirer": "^12.4.2",
|
|
85
|
+
"lodash-es": "^4.17.21",
|
|
86
|
+
"luxon": "^3.6.1",
|
|
87
|
+
"mathjs": "^14.4.0",
|
|
88
|
+
"mitt": "^3.0.1",
|
|
89
|
+
"object-hash": "^3.0.0",
|
|
90
|
+
"openapi-typescript": "^6.7.1",
|
|
91
|
+
"p-queue": "^8.1.0",
|
|
92
|
+
"pusher-js": "^8.4.0",
|
|
93
|
+
"rfdc": "^1.4.1",
|
|
94
|
+
"sift": "^17.1.3",
|
|
95
|
+
"superjson": "^2.2.2",
|
|
96
|
+
"uuid": "^11.1.0",
|
|
97
|
+
"yargs": "^17.7.2",
|
|
98
|
+
"zod": "^3.24.2"
|
|
99
|
+
},
|
|
100
|
+
"devDependencies": {
|
|
101
|
+
"@playwright/test": "^1.50.1",
|
|
102
|
+
"@types/cli-progress": "^3.11.6",
|
|
103
|
+
"@types/lodash-es": "^4.17.12",
|
|
104
|
+
"@types/node": "^22.13.1",
|
|
105
|
+
"@types/react": "^18.3.18",
|
|
106
|
+
"@types/yargs": "^17.0.32",
|
|
107
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
108
|
+
"fake-indexeddb": "^6.0.0",
|
|
109
|
+
"fast-glob": "^3.3.3",
|
|
110
|
+
"react": "^18.2.0",
|
|
111
|
+
"rimraf": "^5.0.5",
|
|
112
|
+
"ts-node": "^10.9.2",
|
|
113
|
+
"typescript": "^5.7.3",
|
|
114
|
+
"vitest": "^3.0.5",
|
|
115
|
+
"vue": "^3.2.0"
|
|
116
|
+
},
|
|
117
|
+
"publishConfig": {
|
|
118
|
+
"access": "public"
|
|
119
|
+
},
|
|
120
|
+
"bugs": {
|
|
121
|
+
"url": "https://github.com/state-zero/statezero-client/issues"
|
|
122
|
+
},
|
|
123
|
+
"directories": {
|
|
124
|
+
"test": "tests"
|
|
125
|
+
}
|
|
126
|
+
}
|