cabloy 5.1.60 → 5.1.62
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/.claude/hooks/contract-loop-gate.ts +296 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/cabloy-backend-scaffold/SKILL.md +2 -0
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
- package/.claude/skills/cabloy-contract-loop/SKILL.md +89 -16
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +102 -14
- package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +4 -0
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +32 -14
- package/.claude/skills/cabloy-domain-planning/SKILL.md +212 -0
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +13 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
- package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
- package/.claude/skills/cabloy-resource-field-update/SKILL.md +7 -0
- package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
- package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
- package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
- package/CHANGELOG.md +64 -0
- package/CLAUDE.md +11 -0
- package/cabloy-docs/.vitepress/config.mjs +197 -5
- package/cabloy-docs/ai/cli-to-skill-map.md +7 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +22 -0
- package/cabloy-docs/ai/future-skill-roadmap.md +12 -7
- package/cabloy-docs/ai/introduction.md +1 -0
- package/cabloy-docs/ai/playbook-backend-module.md +6 -0
- package/cabloy-docs/ai/playbook-module-removal.md +164 -0
- package/cabloy-docs/ai/skills.md +12 -0
- package/cabloy-docs/backend/backend-contract-emission-output-inspection.md +189 -0
- package/cabloy-docs/backend/backend-contract-emission-source-reading-map.md +160 -0
- package/cabloy-docs/backend/backend-contract-emission-specimen.md +170 -0
- package/cabloy-docs/backend/backend-resource-module-contract-chain.md +323 -0
- package/cabloy-docs/backend/backend-source-reading-debug-checklist.md +173 -0
- package/cabloy-docs/backend/backend-source-reading-roadmap.md +129 -0
- package/cabloy-docs/backend/backend-source-reading-verify-playbook.md +166 -0
- package/cabloy-docs/backend/bean-scene-authoring.md +4 -4
- package/cabloy-docs/backend/broadcast-guide.md +3 -3
- package/cabloy-docs/backend/cli.md +20 -11
- package/cabloy-docs/backend/config-guide.md +4 -4
- package/cabloy-docs/backend/controller-aop-guide.md +10 -10
- package/cabloy-docs/backend/controller-guide.md +12 -2
- package/cabloy-docs/backend/crud-workflow.md +7 -3
- package/cabloy-docs/backend/dto-guide.md +18 -2
- package/cabloy-docs/backend/dto-infer-generation.md +201 -25
- package/cabloy-docs/backend/election-guide.md +2 -2
- package/cabloy-docs/backend/entity-guide.md +30 -3
- package/cabloy-docs/backend/error-guide.md +3 -3
- package/cabloy-docs/backend/event-guide.md +4 -4
- package/cabloy-docs/backend/external-aop-guide.md +2 -2
- package/cabloy-docs/backend/field-indexes.md +9 -3
- package/cabloy-docs/backend/foundation.md +8 -8
- package/cabloy-docs/backend/i18n-guide.md +6 -6
- package/cabloy-docs/backend/internal-aop-guide.md +2 -2
- package/cabloy-docs/backend/introduction.md +15 -0
- package/cabloy-docs/backend/migration-and-changes.md +3 -3
- package/cabloy-docs/backend/model-guide.md +16 -6
- package/cabloy-docs/backend/openapi-guide.md +3 -0
- package/cabloy-docs/backend/queue-guide.md +3 -3
- package/cabloy-docs/backend/redlock-guide.md +2 -2
- package/cabloy-docs/backend/schedule-guide.md +2 -2
- package/cabloy-docs/backend/scripts.md +8 -0
- package/cabloy-docs/backend/serialization-guide.md +12 -2
- package/cabloy-docs/backend/service-guide.md +18 -9
- package/cabloy-docs/backend/startup-guide.md +5 -5
- package/cabloy-docs/backend/status-guide.md +271 -0
- package/cabloy-docs/backend/unit-testing.md +3 -3
- package/cabloy-docs/backend/vona-source-reading-map.md +157 -0
- package/cabloy-docs/backend/websocket-protocol-guide.md +5 -5
- package/cabloy-docs/backend/websocket-usage-guide.md +15 -8
- package/cabloy-docs/frontend/a-model-under-the-hood.md +281 -0
- package/cabloy-docs/frontend/a-openapi-under-the-hood.md +248 -0
- package/cabloy-docs/frontend/a-router-guide.md +307 -0
- package/cabloy-docs/frontend/api-guide.md +6 -4
- package/cabloy-docs/frontend/api-schema-guide.md +1 -0
- package/cabloy-docs/frontend/app-startup-guide.md +7 -4
- package/cabloy-docs/frontend/bean-scene-authoring.md +3 -1
- package/cabloy-docs/frontend/behavior-guide.md +16 -16
- package/cabloy-docs/frontend/cli.md +14 -2
- package/cabloy-docs/frontend/command-scene-authoring.md +504 -0
- package/cabloy-docs/frontend/component-guide.md +5 -5
- package/cabloy-docs/frontend/component-props-guide.md +1 -1
- package/cabloy-docs/frontend/component-v-model-guide.md +2 -2
- package/cabloy-docs/frontend/design-principles.md +6 -0
- package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
- package/cabloy-docs/frontend/filter-query-select-data-flow-guide.md +260 -0
- package/cabloy-docs/frontend/form-guide.md +786 -0
- package/cabloy-docs/frontend/form-scene-to-page-meta-guide.md +303 -0
- package/cabloy-docs/frontend/foundation.md +33 -0
- package/cabloy-docs/frontend/frontend-source-reading-roadmap.md +249 -0
- package/cabloy-docs/frontend/generated-contract-consumption-debug-checklist.md +190 -0
- package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +205 -0
- package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +157 -0
- package/cabloy-docs/frontend/generated-contract-consumption-specimen.md +203 -0
- package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +189 -0
- package/cabloy-docs/frontend/generic-component-guide.md +1 -1
- package/cabloy-docs/frontend/introduction.md +38 -5
- package/cabloy-docs/frontend/ioc-and-beans.md +6 -0
- package/cabloy-docs/frontend/mock-guide.md +1 -0
- package/cabloy-docs/frontend/model-architecture.md +288 -39
- package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
- package/cabloy-docs/frontend/model-resource-cookbook.md +508 -0
- package/cabloy-docs/frontend/model-resource-internals-deep-dive.md +238 -0
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +402 -0
- package/cabloy-docs/frontend/model-resource-usage-guide.md +334 -0
- package/cabloy-docs/frontend/model-state-guide.md +371 -15
- package/cabloy-docs/frontend/module-scope.md +8 -8
- package/cabloy-docs/frontend/modules-and-suites.md +2 -1
- package/cabloy-docs/frontend/navigation-guards-guide.md +7 -0
- package/cabloy-docs/frontend/openapi-sdk-guide.md +17 -6
- package/cabloy-docs/frontend/page-guide.md +15 -9
- package/cabloy-docs/frontend/page-meta-guide.md +466 -0
- package/cabloy-docs/frontend/page-params-guide.md +3 -3
- package/cabloy-docs/frontend/page-query-guide.md +2 -2
- package/cabloy-docs/frontend/page-route-guide.md +6 -0
- package/cabloy-docs/frontend/permission-formscene-action-visibility-guide.md +263 -0
- package/cabloy-docs/frontend/quickstart.md +18 -2
- package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
- package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +271 -0
- package/cabloy-docs/frontend/resource-list-page-deep-dive.md +279 -0
- package/cabloy-docs/frontend/rest-resource-source-reading-map.md +522 -0
- package/cabloy-docs/frontend/rest-resource-under-the-hood.md +622 -0
- package/cabloy-docs/frontend/root-behaviors-guide.md +282 -0
- package/cabloy-docs/frontend/route-alias-guide.md +6 -0
- package/cabloy-docs/frontend/router-stack-guide.md +229 -0
- package/cabloy-docs/frontend/router-tabs-introduction.md +26 -3
- package/cabloy-docs/frontend/router-tabs-layout-integration.md +367 -0
- package/cabloy-docs/frontend/router-tabs-mechanism.md +6 -0
- package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +7 -0
- package/cabloy-docs/frontend/router-tabs-vs-stack.md +167 -0
- package/cabloy-docs/frontend/router-view-hosts-guide.md +450 -0
- package/cabloy-docs/frontend/server-data.md +4 -1
- package/cabloy-docs/frontend/system-startup-guide.md +2 -2
- package/cabloy-docs/frontend/table-action-visibility-permission-flow-guide.md +263 -0
- package/cabloy-docs/frontend/table-cell-cookbook.md +568 -0
- package/cabloy-docs/frontend/table-guide.md +373 -0
- package/cabloy-docs/frontend/table-resource-crud-cookbook.md +496 -0
- package/cabloy-docs/frontend/zova-app-guide.md +251 -0
- package/cabloy-docs/frontend/zova-form-source-reading-map.md +293 -0
- package/cabloy-docs/frontend/zova-form-under-the-hood.md +561 -0
- package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
- package/cabloy-docs/frontend/zova-router-under-the-hood.md +561 -0
- package/cabloy-docs/frontend/zova-source-reading-map.md +421 -0
- package/cabloy-docs/frontend/zova-table-controller-render-supplement.md +225 -0
- package/cabloy-docs/frontend/zova-table-source-reading-map.md +317 -0
- package/cabloy-docs/frontend/zova-table-under-the-hood.md +532 -0
- package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
- package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-debug-checklist.md +245 -0
- package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-source-reading-map.md +139 -0
- package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-verify-playbook.md +248 -0
- package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions.md +511 -0
- package/cabloy-docs/fullstack/contract-loop-playbook.md +356 -0
- package/cabloy-docs/fullstack/edition-collaboration-differences.md +6 -0
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +199 -23
- package/cabloy-docs/fullstack/introduction.md +15 -1
- package/cabloy-docs/fullstack/openapi-to-sdk.md +135 -11
- package/cabloy-docs/fullstack/suites-and-modules.md +333 -0
- package/cabloy-docs/fullstack/tutorial-1-first-module.md +3 -0
- package/cabloy-docs/fullstack/tutorial-2-first-crud.md +4 -0
- package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +6 -2
- package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +60 -23
- package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +14 -7
- package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +6 -0
- package/cabloy-docs/fullstack/tutorials-overview.md +17 -4
- package/cabloy-docs/reference/bean-scene-boilerplates.md +15 -13
- package/cabloy-docs/reference/package-map.md +4 -3
- package/package.json +2 -1
- package/scripts/init.ts +2 -18
- package/scripts/initTestData.ts +25 -0
- package/scripts/upgrade.ts +17 -2
- package/vona/pnpm-lock.yaml +48 -194
- package/vona/src/suite/a-training/modules/training-student/package.json +53 -0
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +400 -0
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +18 -0
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/bean/meta.index.ts +12 -0
- package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +21 -0
- package/vona/src/suite/a-training/modules/training-student/src/bean/ssrMenu.student.ts +29 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +15 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +15 -0
- package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +74 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +28 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +44 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectRes.tsx +11 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +45 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +42 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +28 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +25 -0
- package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +84 -0
- package/vona/src/suite/a-training/modules/training-student/src/index.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +10 -0
- package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +57 -0
- package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +173 -0
- package/vona/src/suite/a-training/modules/training-student/tsconfig.build.json +11 -0
- package/vona/src/suite/a-training/modules/training-student/tsconfig.json +7 -0
- package/vona/src/suite/a-training/package.json +12 -0
- package/vona/src/suite/a-training/tsconfig.base.json +4 -0
- package/vona/src/suite/a-training/tsconfig.json +10 -0
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
- package/zova/packages-cli/cli-set-front/package.json +1 -1
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +416 -690
- package/zova/src/suite/a-training/modules/training-student/cli/openapi.config.ts +9 -0
- package/zova/src/suite/a-training/modules/training-student/package.json +52 -0
- package/zova/src/suite/a-training/modules/training-student/src/.metadata/component/formFieldLevel.ts +31 -0
- package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +258 -0
- package/zova/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +196 -0
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +4146 -0
- package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +151 -0
- package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +43 -0
- package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +51 -0
- package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +56 -0
- package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.level.tsx +63 -0
- package/zova/src/suite/a-training/modules/training-student/src/component/formFieldLevel/controller.tsx +117 -0
- package/zova/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +9 -0
- package/zova/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +9 -0
- package/zova/src/suite/a-training/modules/training-student/src/index.ts +2 -0
- package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +42 -0
- package/zova/src/suite/a-training/modules/training-student/tsconfig.build.json +13 -0
- package/zova/src/suite/a-training/modules/training-student/tsconfig.json +5 -0
- package/zova/src/suite/a-training/package.json +12 -0
- package/zova/src/suite/a-training/tsconfig.base.json +4 -0
- package/zova/src/suite/a-training/tsconfig.json +4 -0
- package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +29 -7
- package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +34 -11
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +3 -3
- package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/tableCell.ts +1 -1
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
|
@@ -1,78 +1,318 @@
|
|
|
1
1
|
# Model Architecture
|
|
2
2
|
|
|
3
|
-
This guide explains the
|
|
3
|
+
This guide explains the architecture of Zova Model in the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
It focuses on the Zova-native role of Model first, then connects that role to the current `a-model` source implementation.
|
|
4
6
|
|
|
5
7
|
## Why Zova models matter
|
|
6
8
|
|
|
7
|
-
Zova uses a unified `Model` mechanism to manage several kinds of
|
|
9
|
+
Zova uses a unified `Model` mechanism to manage several kinds of frontend state that other stacks often split across unrelated tools.
|
|
8
10
|
|
|
9
11
|
This is one of the most important architectural ideas in Zova.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
The key point is not only caching remote data.
|
|
14
|
+
|
|
15
|
+
The deeper point is that Zova gives state a dedicated bean-oriented home with:
|
|
16
|
+
|
|
17
|
+
- framework-managed identity
|
|
18
|
+
- query-key namespacing
|
|
19
|
+
- persistence options
|
|
20
|
+
- SSR-aware hydration behavior
|
|
21
|
+
- reuse across pages, components, and services
|
|
22
|
+
|
|
23
|
+
## Zova-native role of a model
|
|
24
|
+
|
|
25
|
+
A Zova model is a **model bean**.
|
|
26
|
+
|
|
27
|
+
It is not only a generic Vue composable and it is not only a thin request wrapper.
|
|
12
28
|
|
|
13
|
-
|
|
29
|
+
Its architectural job is to own data that benefits from broader lifecycle and reuse behavior, especially when that data is:
|
|
14
30
|
|
|
15
|
-
- asynchronous data
|
|
16
|
-
- local
|
|
17
|
-
- cookie data
|
|
18
|
-
- in-memory data
|
|
31
|
+
- asynchronous server data
|
|
32
|
+
- local-storage data
|
|
33
|
+
- cookie-backed data
|
|
34
|
+
- in-memory cache-oriented data
|
|
35
|
+
- persistence-aware state that should survive page transitions or refreshes
|
|
19
36
|
|
|
20
|
-
In
|
|
37
|
+
In practice, a model often sits above `$api` and below page rendering:
|
|
38
|
+
|
|
39
|
+
- `$fetch` handles transport-oriented access
|
|
40
|
+
- `$api` handles business-oriented service methods
|
|
41
|
+
- `Model` handles cached, reusable, UI-friendly state ownership
|
|
42
|
+
|
|
43
|
+
Read together with [Server Data](/frontend/server-data) when deciding which abstraction layer a feature should use.
|
|
44
|
+
|
|
45
|
+
If your next question is how the generic lower-level model runtime works beneath these abstractions, continue with [A-Model Under the Hood](/frontend/a-model-under-the-hood).
|
|
21
46
|
|
|
22
47
|
## Relationship to TanStack Query
|
|
23
48
|
|
|
24
|
-
One
|
|
49
|
+
One current-source fact is explicit: Zova Model is built on top of TanStack Query.
|
|
50
|
+
|
|
51
|
+
That matters because Zova is not replacing TanStack Query with a separate state engine.
|
|
52
|
+
|
|
53
|
+
Instead, Zova wraps TanStack Query inside a model-bean architecture so that:
|
|
54
|
+
|
|
55
|
+
- query and mutation APIs fit naturally into the bean system
|
|
56
|
+
- sync and async state categories can use one broader model surface
|
|
57
|
+
- persistence and SSR behavior are expressed in one place
|
|
58
|
+
- model identity becomes part of cache identity
|
|
25
59
|
|
|
26
|
-
|
|
60
|
+
## Public authoring surface
|
|
27
61
|
|
|
28
|
-
|
|
62
|
+
Representative model definition:
|
|
29
63
|
|
|
30
|
-
|
|
64
|
+
```typescript
|
|
65
|
+
import { Model } from 'zova';
|
|
66
|
+
import { BeanModelBase } from 'zova-module-a-model';
|
|
67
|
+
|
|
68
|
+
@Model()
|
|
69
|
+
export class ModelTodo extends BeanModelBase {}
|
|
70
|
+
```
|
|
31
71
|
|
|
32
|
-
|
|
72
|
+
At source level, `@Model()` is a bean decorator factory:
|
|
33
73
|
|
|
34
|
-
|
|
74
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/lib/model.ts`
|
|
35
75
|
|
|
36
|
-
|
|
76
|
+
That file shows that a model is registered on the `model` onion/scene rather than being a special-case standalone mechanism.
|
|
37
77
|
|
|
38
|
-
|
|
78
|
+
### A practical thin-facade example
|
|
39
79
|
|
|
40
|
-
|
|
80
|
+
This subsection is the first layer of a small source-reading chain around same-resource model facades.
|
|
41
81
|
|
|
42
|
-
|
|
82
|
+
Use the three related pages in this order when your question is specifically about a same-resource custom facade:
|
|
43
83
|
|
|
44
|
-
|
|
84
|
+
1. this page for the broader role of Zova Model
|
|
85
|
+
2. [Generated Contract Consumption: Entry Branch](/frontend/generated-contract-consumption-entry-branch) for the consumer-side handoff into the owner
|
|
86
|
+
3. [ModelResource Internals Deep Dive](/frontend/model-resource-internals-deep-dive) for the owner internals that make that handoff work
|
|
45
87
|
|
|
46
|
-
|
|
88
|
+
A current example of a model staying intentionally thin is:
|
|
47
89
|
|
|
48
|
-
|
|
90
|
+
- `zova/src/suite/a-training/modules/training-student/src/model/student.ts`
|
|
49
91
|
|
|
50
|
-
|
|
92
|
+
That file is useful for one specific architectural point:
|
|
51
93
|
|
|
52
|
-
|
|
94
|
+
- `ModelResource` remains the stable resource owner
|
|
95
|
+
- the module model adds resource-specific methods such as `summary(id)` and `deleteForce(id)`
|
|
96
|
+
- those methods still delegate to owner-level helpers such as `queryItem(...)` and `mutationItem(...)`
|
|
53
97
|
|
|
54
|
-
|
|
98
|
+
A compact source-reading path for this pattern is:
|
|
55
99
|
|
|
56
|
-
|
|
100
|
+
1. `zova/src/suite/a-training/modules/training-student/src/model/student.ts`
|
|
101
|
+
2. `zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts`
|
|
102
|
+
3. `zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/entry/controller.tsx`
|
|
57
103
|
|
|
58
|
-
|
|
104
|
+
This is a good pattern when custom frontend behavior still belongs to the same resource and should continue to participate in resource-owned query, mutation, and form semantics.
|
|
59
105
|
|
|
60
|
-
|
|
106
|
+
For the entry-branch consumer path that uses this owner-preserving pattern, continue with [Generated Contract Consumption: Entry Branch](/frontend/generated-contract-consumption-entry-branch).
|
|
107
|
+
For the deeper owner internals behind `queryItem(...)`, `mutationItem(...)`, and form-derived helpers, continue with [ModelResource Internals Deep Dive](/frontend/model-resource-internals-deep-dive).
|
|
61
108
|
|
|
62
|
-
|
|
109
|
+
It is not the whole story of Zova Model.
|
|
110
|
+
It is a narrow example of resource-owner-preserving facade design inside the broader model architecture.
|
|
63
111
|
|
|
64
|
-
##
|
|
112
|
+
## The core architectural idea
|
|
65
113
|
|
|
66
|
-
|
|
114
|
+
The most important current-source insight is this:
|
|
67
115
|
|
|
68
|
-
|
|
69
|
-
import { Model } from 'zova';
|
|
70
|
-
import { BeanModelBase } from 'zova-module-a-model';
|
|
116
|
+
> Zova unifies remote state and several local state categories around query-cache semantics, then exposes that system through model beans.
|
|
71
117
|
|
|
72
|
-
|
|
73
|
-
|
|
118
|
+
That is why model APIs look broader than a normal “data fetching helper”.
|
|
119
|
+
|
|
120
|
+
Even local, cookie, db, and mem state are expressed through model helpers that still participate in model-owned keying, restore, invalidation, and SSR rules.
|
|
121
|
+
|
|
122
|
+
## Five state families in the current model layer
|
|
123
|
+
|
|
124
|
+
The `a-model` source exposes five main state families through `BeanModelBase` helpers:
|
|
125
|
+
|
|
126
|
+
- `data` → remote/query-style state through `$useStateData(...)`
|
|
127
|
+
- `mem` → in-memory state through `$useStateMem(...)`
|
|
128
|
+
- `local` → local-storage state through `$useStateLocal(...)`
|
|
129
|
+
- `cookie` → cookie-backed state through `$useStateCookie(...)`
|
|
130
|
+
- `db` → async persisted state through `$useStateDb(...)`
|
|
131
|
+
|
|
132
|
+
This is why Zova Model is better understood as a **unified model-state layer** rather than only a remote-data wrapper.
|
|
133
|
+
|
|
134
|
+
## How the runtime is assembled
|
|
135
|
+
|
|
136
|
+
A compact source-confirmed runtime path is:
|
|
137
|
+
|
|
138
|
+
1. `@Model()` registers the class as a model bean
|
|
139
|
+
2. the `a-model` module monkey bootstraps a shared `QueryClient`
|
|
140
|
+
3. the monkey injects `$queryClient` onto bean instances
|
|
141
|
+
4. `BeanModelBase` composes query, mutation, state, and persistence helpers
|
|
142
|
+
5. helper calls automatically prefix query keys with model identity
|
|
143
|
+
6. persistence and SSR behavior are applied from model metadata and module config
|
|
144
|
+
|
|
145
|
+
### 1. `@Model()` registers a model bean
|
|
146
|
+
|
|
147
|
+
Source:
|
|
148
|
+
|
|
149
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/lib/model.ts`
|
|
150
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/types/model.ts`
|
|
151
|
+
|
|
152
|
+
These files confirm that:
|
|
153
|
+
|
|
154
|
+
- models are bean-based
|
|
155
|
+
- the scene/onion name is `model`
|
|
156
|
+
- model decorator options currently include `enableSelector?: boolean`
|
|
157
|
+
|
|
158
|
+
### 2. The module bootstraps a shared query client
|
|
159
|
+
|
|
160
|
+
Source:
|
|
161
|
+
|
|
162
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/monkey.ts`
|
|
163
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/service/storage.ts`
|
|
164
|
+
|
|
165
|
+
These files show that the module:
|
|
166
|
+
|
|
167
|
+
- creates a `QueryClient`
|
|
168
|
+
- installs `VueQueryPlugin`
|
|
169
|
+
- injects `$queryClient` onto bean instances
|
|
170
|
+
- owns SSR dehydrate/hydrate behavior for query state
|
|
171
|
+
|
|
172
|
+
This is important because model code does not manually construct its own query client.
|
|
173
|
+
|
|
174
|
+
## `BeanModelBase` is a composed capability stack
|
|
175
|
+
|
|
176
|
+
`BeanModelBase` is a reusable base, not just an empty convenience class.
|
|
177
|
+
|
|
178
|
+
Representative source path:
|
|
179
|
+
|
|
180
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.modelBase.ts`
|
|
181
|
+
- `zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/`
|
|
182
|
+
|
|
183
|
+
The current source composes a layered model base that provides:
|
|
184
|
+
|
|
185
|
+
- query helpers
|
|
186
|
+
- mutation helpers
|
|
187
|
+
- state helpers
|
|
188
|
+
- persistence helpers
|
|
189
|
+
- cookie/local/db adapters
|
|
190
|
+
- selector-aware key prefixing
|
|
191
|
+
|
|
192
|
+
For source reading, the most important files are:
|
|
193
|
+
|
|
194
|
+
- `bean.model.useQuery.ts`
|
|
195
|
+
- `bean.model.useMutation.ts`
|
|
196
|
+
- `bean.model.useState.ts`
|
|
197
|
+
- `bean.model.query.ts`
|
|
198
|
+
- `bean.model.persister.ts`
|
|
199
|
+
|
|
200
|
+
## Automatic namespacing and selector-aware identity
|
|
201
|
+
|
|
202
|
+
One of the most important source-level behaviors is automatic key prefixing.
|
|
203
|
+
|
|
204
|
+
Model helpers do not only use the caller-provided `queryKey`.
|
|
205
|
+
|
|
206
|
+
They first prefix it with the model bean identity, and when `enableSelector` is enabled they also prefix it with the selector value.
|
|
207
|
+
|
|
208
|
+
That means a logical user key such as:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
['list'];
|
|
74
212
|
```
|
|
75
213
|
|
|
214
|
+
becomes model-owned cache identity rather than a globally ambiguous key.
|
|
215
|
+
|
|
216
|
+
This is one reason model state can scale more safely across larger apps.
|
|
217
|
+
|
|
218
|
+
## Persistence architecture
|
|
219
|
+
|
|
220
|
+
The current model layer supports several persistence strategies:
|
|
221
|
+
|
|
222
|
+
- `mem` → no persistence
|
|
223
|
+
- `local` → sync local storage
|
|
224
|
+
- `cookie` → sync cookie storage
|
|
225
|
+
- `db` → async persisted storage through `localforage`
|
|
226
|
+
|
|
227
|
+
Representative source files:
|
|
228
|
+
|
|
229
|
+
- `bean.model.useState.ts`
|
|
230
|
+
- `bean.model.persister.ts`
|
|
231
|
+
- `bean.model.local.ts`
|
|
232
|
+
- `bean.model.cookie.ts`
|
|
233
|
+
- `common/cookieWrapper.ts`
|
|
234
|
+
|
|
235
|
+
A key design detail is that persistence is treated as an extension of model-owned query state rather than as a separate unrelated subsystem.
|
|
236
|
+
|
|
237
|
+
## SSR behavior
|
|
238
|
+
|
|
239
|
+
Zova Model is SSR-aware.
|
|
240
|
+
|
|
241
|
+
Important current-source behavior includes:
|
|
242
|
+
|
|
243
|
+
- server render dehydrates query state into SSR deferred state
|
|
244
|
+
- client pre-hydration hydrates that query state back into the client query client
|
|
245
|
+
- mutations are not dehydrated
|
|
246
|
+
- sync persisted state such as `local` and `cookie` is not treated the same way as dehydrated async query state
|
|
247
|
+
- `db` state is explicitly marked not to dehydrate
|
|
248
|
+
|
|
249
|
+
Representative source files:
|
|
250
|
+
|
|
251
|
+
- `service/storage.ts`
|
|
252
|
+
- `config/config.ts`
|
|
253
|
+
- `types/query.ts`
|
|
254
|
+
- `bean.model.useQuery.ts`
|
|
255
|
+
- `bean.model.useState.ts`
|
|
256
|
+
|
|
257
|
+
This matters because a model choice can affect hydration behavior, not only local developer ergonomics.
|
|
258
|
+
|
|
259
|
+
## When state should live in a model
|
|
260
|
+
|
|
261
|
+
A model is usually a good fit when one or more of these are true:
|
|
262
|
+
|
|
263
|
+
- multiple pages or components need the same data
|
|
264
|
+
- remote data should be cached and invalidated consistently
|
|
265
|
+
- the state has persistence value across route changes or reloads
|
|
266
|
+
- SSR and hydration behavior matter
|
|
267
|
+
- the data should have a dedicated owner separate from one page controller
|
|
268
|
+
|
|
269
|
+
A model is often **not** the first choice when:
|
|
270
|
+
|
|
271
|
+
- the state is purely page-local and short-lived
|
|
272
|
+
- the data has no reuse value outside one controller
|
|
273
|
+
- plain controller fields already express the intent clearly
|
|
274
|
+
|
|
275
|
+
That is why Zova asks a different first question than many Vue stacks.
|
|
276
|
+
|
|
277
|
+
Instead of asking only “should this be a store?”, it is often better to ask:
|
|
278
|
+
|
|
279
|
+
1. which bean should own this data?
|
|
280
|
+
2. does the data need model-level caching or persistence?
|
|
281
|
+
3. does SSR or reuse make a model the right boundary?
|
|
282
|
+
|
|
283
|
+
## Source-reading path for Model
|
|
284
|
+
|
|
285
|
+
If you want the shortest accurate path from public docs into current source, use this order:
|
|
286
|
+
|
|
287
|
+
1. this page
|
|
288
|
+
2. [Model State Guide](/frontend/model-state-guide)
|
|
289
|
+
3. [Model Resource Owner Pattern](/frontend/model-resource-owner-pattern)
|
|
290
|
+
4. [Zova Source Reading Map](/frontend/zova-source-reading-map)
|
|
291
|
+
5. `zova/src/suite/a-demo/modules/demo-todo/src/model/todo.ts`
|
|
292
|
+
6. `zova/src/suite-vendor/a-zova/modules/a-model/src/lib/model.ts`
|
|
293
|
+
7. `zova/src/suite-vendor/a-zova/modules/a-model/src/monkey.ts`
|
|
294
|
+
8. `zova/src/suite-vendor/a-zova/modules/a-model/src/service/storage.ts`
|
|
295
|
+
9. `zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useState.ts`
|
|
296
|
+
10. `zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.persister.ts`
|
|
297
|
+
|
|
298
|
+
Use representative real models next when you want a richer case:
|
|
299
|
+
|
|
300
|
+
- `zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts`
|
|
301
|
+
- `zova/src/suite/a-home/modules/home-passport/src/model/passport.ts`
|
|
302
|
+
- `zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts`
|
|
303
|
+
|
|
304
|
+
The `rest-resource` model is especially important because it shows that Zova Model is not only for small feature-local caching.
|
|
305
|
+
|
|
306
|
+
It also supports **generic infrastructure models** that:
|
|
307
|
+
|
|
308
|
+
- use `enableSelector` to isolate one model instance per resource
|
|
309
|
+
- bootstrap resource metadata before normal state usage
|
|
310
|
+
- combine `$fetch`, `$sdk`, and model state in one reusable resource owner
|
|
311
|
+
- expose schema, permissions, form helpers, and CRUD query/mutation flows through one model boundary
|
|
312
|
+
- centralize invalidation rules for list and item-level resource state
|
|
313
|
+
|
|
314
|
+
That example is a good reading target when you want to understand how Zova Model can become a reusable full-feature resource facade instead of only a thin data wrapper.
|
|
315
|
+
|
|
76
316
|
## Practical implications for frontend state design
|
|
77
317
|
|
|
78
318
|
When asked to add frontend state, do not immediately assume a generic Vue/Pinia-style answer.
|
|
@@ -80,8 +320,17 @@ When asked to add frontend state, do not immediately assume a generic Vue/Pinia-
|
|
|
80
320
|
A better default is to ask:
|
|
81
321
|
|
|
82
322
|
1. is this state already a good fit for a Zova model?
|
|
83
|
-
2. is the data async
|
|
84
|
-
3.
|
|
85
|
-
4.
|
|
323
|
+
2. is the data async, mem, local, cookie, or db-oriented?
|
|
324
|
+
3. do caching, invalidation, or persistence matter?
|
|
325
|
+
4. does SSR or hydration make the model layer especially valuable here?
|
|
326
|
+
5. is there already a model bean that should own this state instead of adding a new ad hoc state container?
|
|
86
327
|
|
|
87
328
|
That keeps the code aligned with Zova’s actual architecture.
|
|
329
|
+
|
|
330
|
+
## Final takeaway
|
|
331
|
+
|
|
332
|
+
The most important architectural insight is simple:
|
|
333
|
+
|
|
334
|
+
> Zova Model is a model-bean layer built on top of TanStack Query that unifies async data, local persistence, cookie state, db persistence, and in-memory state behind one model-owned runtime.
|
|
335
|
+
|
|
336
|
+
Once that clicks, the model APIs stop looking like isolated helpers and start reading as one coherent state architecture.
|