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.
Files changed (232) hide show
  1. package/.claude/hooks/contract-loop-gate.ts +296 -0
  2. package/.claude/settings.json +16 -0
  3. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +2 -0
  4. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
  5. package/.claude/skills/cabloy-contract-loop/SKILL.md +89 -16
  6. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +102 -14
  7. package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +4 -0
  8. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +32 -14
  9. package/.claude/skills/cabloy-domain-planning/SKILL.md +212 -0
  10. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +13 -0
  11. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
  12. package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
  13. package/.claude/skills/cabloy-resource-field-update/SKILL.md +7 -0
  14. package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
  15. package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
  16. package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
  17. package/CHANGELOG.md +64 -0
  18. package/CLAUDE.md +11 -0
  19. package/cabloy-docs/.vitepress/config.mjs +197 -5
  20. package/cabloy-docs/ai/cli-to-skill-map.md +7 -0
  21. package/cabloy-docs/ai/docs-skills-rules-mapping.md +22 -0
  22. package/cabloy-docs/ai/future-skill-roadmap.md +12 -7
  23. package/cabloy-docs/ai/introduction.md +1 -0
  24. package/cabloy-docs/ai/playbook-backend-module.md +6 -0
  25. package/cabloy-docs/ai/playbook-module-removal.md +164 -0
  26. package/cabloy-docs/ai/skills.md +12 -0
  27. package/cabloy-docs/backend/backend-contract-emission-output-inspection.md +189 -0
  28. package/cabloy-docs/backend/backend-contract-emission-source-reading-map.md +160 -0
  29. package/cabloy-docs/backend/backend-contract-emission-specimen.md +170 -0
  30. package/cabloy-docs/backend/backend-resource-module-contract-chain.md +323 -0
  31. package/cabloy-docs/backend/backend-source-reading-debug-checklist.md +173 -0
  32. package/cabloy-docs/backend/backend-source-reading-roadmap.md +129 -0
  33. package/cabloy-docs/backend/backend-source-reading-verify-playbook.md +166 -0
  34. package/cabloy-docs/backend/bean-scene-authoring.md +4 -4
  35. package/cabloy-docs/backend/broadcast-guide.md +3 -3
  36. package/cabloy-docs/backend/cli.md +20 -11
  37. package/cabloy-docs/backend/config-guide.md +4 -4
  38. package/cabloy-docs/backend/controller-aop-guide.md +10 -10
  39. package/cabloy-docs/backend/controller-guide.md +12 -2
  40. package/cabloy-docs/backend/crud-workflow.md +7 -3
  41. package/cabloy-docs/backend/dto-guide.md +18 -2
  42. package/cabloy-docs/backend/dto-infer-generation.md +201 -25
  43. package/cabloy-docs/backend/election-guide.md +2 -2
  44. package/cabloy-docs/backend/entity-guide.md +30 -3
  45. package/cabloy-docs/backend/error-guide.md +3 -3
  46. package/cabloy-docs/backend/event-guide.md +4 -4
  47. package/cabloy-docs/backend/external-aop-guide.md +2 -2
  48. package/cabloy-docs/backend/field-indexes.md +9 -3
  49. package/cabloy-docs/backend/foundation.md +8 -8
  50. package/cabloy-docs/backend/i18n-guide.md +6 -6
  51. package/cabloy-docs/backend/internal-aop-guide.md +2 -2
  52. package/cabloy-docs/backend/introduction.md +15 -0
  53. package/cabloy-docs/backend/migration-and-changes.md +3 -3
  54. package/cabloy-docs/backend/model-guide.md +16 -6
  55. package/cabloy-docs/backend/openapi-guide.md +3 -0
  56. package/cabloy-docs/backend/queue-guide.md +3 -3
  57. package/cabloy-docs/backend/redlock-guide.md +2 -2
  58. package/cabloy-docs/backend/schedule-guide.md +2 -2
  59. package/cabloy-docs/backend/scripts.md +8 -0
  60. package/cabloy-docs/backend/serialization-guide.md +12 -2
  61. package/cabloy-docs/backend/service-guide.md +18 -9
  62. package/cabloy-docs/backend/startup-guide.md +5 -5
  63. package/cabloy-docs/backend/status-guide.md +271 -0
  64. package/cabloy-docs/backend/unit-testing.md +3 -3
  65. package/cabloy-docs/backend/vona-source-reading-map.md +157 -0
  66. package/cabloy-docs/backend/websocket-protocol-guide.md +5 -5
  67. package/cabloy-docs/backend/websocket-usage-guide.md +15 -8
  68. package/cabloy-docs/frontend/a-model-under-the-hood.md +281 -0
  69. package/cabloy-docs/frontend/a-openapi-under-the-hood.md +248 -0
  70. package/cabloy-docs/frontend/a-router-guide.md +307 -0
  71. package/cabloy-docs/frontend/api-guide.md +6 -4
  72. package/cabloy-docs/frontend/api-schema-guide.md +1 -0
  73. package/cabloy-docs/frontend/app-startup-guide.md +7 -4
  74. package/cabloy-docs/frontend/bean-scene-authoring.md +3 -1
  75. package/cabloy-docs/frontend/behavior-guide.md +16 -16
  76. package/cabloy-docs/frontend/cli.md +14 -2
  77. package/cabloy-docs/frontend/command-scene-authoring.md +504 -0
  78. package/cabloy-docs/frontend/component-guide.md +5 -5
  79. package/cabloy-docs/frontend/component-props-guide.md +1 -1
  80. package/cabloy-docs/frontend/component-v-model-guide.md +2 -2
  81. package/cabloy-docs/frontend/design-principles.md +6 -0
  82. package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
  83. package/cabloy-docs/frontend/filter-query-select-data-flow-guide.md +260 -0
  84. package/cabloy-docs/frontend/form-guide.md +786 -0
  85. package/cabloy-docs/frontend/form-scene-to-page-meta-guide.md +303 -0
  86. package/cabloy-docs/frontend/foundation.md +33 -0
  87. package/cabloy-docs/frontend/frontend-source-reading-roadmap.md +249 -0
  88. package/cabloy-docs/frontend/generated-contract-consumption-debug-checklist.md +190 -0
  89. package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +205 -0
  90. package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +157 -0
  91. package/cabloy-docs/frontend/generated-contract-consumption-specimen.md +203 -0
  92. package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +189 -0
  93. package/cabloy-docs/frontend/generic-component-guide.md +1 -1
  94. package/cabloy-docs/frontend/introduction.md +38 -5
  95. package/cabloy-docs/frontend/ioc-and-beans.md +6 -0
  96. package/cabloy-docs/frontend/mock-guide.md +1 -0
  97. package/cabloy-docs/frontend/model-architecture.md +288 -39
  98. package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
  99. package/cabloy-docs/frontend/model-resource-cookbook.md +508 -0
  100. package/cabloy-docs/frontend/model-resource-internals-deep-dive.md +238 -0
  101. package/cabloy-docs/frontend/model-resource-owner-pattern.md +402 -0
  102. package/cabloy-docs/frontend/model-resource-usage-guide.md +334 -0
  103. package/cabloy-docs/frontend/model-state-guide.md +371 -15
  104. package/cabloy-docs/frontend/module-scope.md +8 -8
  105. package/cabloy-docs/frontend/modules-and-suites.md +2 -1
  106. package/cabloy-docs/frontend/navigation-guards-guide.md +7 -0
  107. package/cabloy-docs/frontend/openapi-sdk-guide.md +17 -6
  108. package/cabloy-docs/frontend/page-guide.md +15 -9
  109. package/cabloy-docs/frontend/page-meta-guide.md +466 -0
  110. package/cabloy-docs/frontend/page-params-guide.md +3 -3
  111. package/cabloy-docs/frontend/page-query-guide.md +2 -2
  112. package/cabloy-docs/frontend/page-route-guide.md +6 -0
  113. package/cabloy-docs/frontend/permission-formscene-action-visibility-guide.md +263 -0
  114. package/cabloy-docs/frontend/quickstart.md +18 -2
  115. package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
  116. package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +271 -0
  117. package/cabloy-docs/frontend/resource-list-page-deep-dive.md +279 -0
  118. package/cabloy-docs/frontend/rest-resource-source-reading-map.md +522 -0
  119. package/cabloy-docs/frontend/rest-resource-under-the-hood.md +622 -0
  120. package/cabloy-docs/frontend/root-behaviors-guide.md +282 -0
  121. package/cabloy-docs/frontend/route-alias-guide.md +6 -0
  122. package/cabloy-docs/frontend/router-stack-guide.md +229 -0
  123. package/cabloy-docs/frontend/router-tabs-introduction.md +26 -3
  124. package/cabloy-docs/frontend/router-tabs-layout-integration.md +367 -0
  125. package/cabloy-docs/frontend/router-tabs-mechanism.md +6 -0
  126. package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +7 -0
  127. package/cabloy-docs/frontend/router-tabs-vs-stack.md +167 -0
  128. package/cabloy-docs/frontend/router-view-hosts-guide.md +450 -0
  129. package/cabloy-docs/frontend/server-data.md +4 -1
  130. package/cabloy-docs/frontend/system-startup-guide.md +2 -2
  131. package/cabloy-docs/frontend/table-action-visibility-permission-flow-guide.md +263 -0
  132. package/cabloy-docs/frontend/table-cell-cookbook.md +568 -0
  133. package/cabloy-docs/frontend/table-guide.md +373 -0
  134. package/cabloy-docs/frontend/table-resource-crud-cookbook.md +496 -0
  135. package/cabloy-docs/frontend/zova-app-guide.md +251 -0
  136. package/cabloy-docs/frontend/zova-form-source-reading-map.md +293 -0
  137. package/cabloy-docs/frontend/zova-form-under-the-hood.md +561 -0
  138. package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
  139. package/cabloy-docs/frontend/zova-router-under-the-hood.md +561 -0
  140. package/cabloy-docs/frontend/zova-source-reading-map.md +421 -0
  141. package/cabloy-docs/frontend/zova-table-controller-render-supplement.md +225 -0
  142. package/cabloy-docs/frontend/zova-table-source-reading-map.md +317 -0
  143. package/cabloy-docs/frontend/zova-table-under-the-hood.md +532 -0
  144. package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
  145. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-debug-checklist.md +245 -0
  146. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-source-reading-map.md +139 -0
  147. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-verify-playbook.md +248 -0
  148. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions.md +511 -0
  149. package/cabloy-docs/fullstack/contract-loop-playbook.md +356 -0
  150. package/cabloy-docs/fullstack/edition-collaboration-differences.md +6 -0
  151. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +199 -23
  152. package/cabloy-docs/fullstack/introduction.md +15 -1
  153. package/cabloy-docs/fullstack/openapi-to-sdk.md +135 -11
  154. package/cabloy-docs/fullstack/suites-and-modules.md +333 -0
  155. package/cabloy-docs/fullstack/tutorial-1-first-module.md +3 -0
  156. package/cabloy-docs/fullstack/tutorial-2-first-crud.md +4 -0
  157. package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +6 -2
  158. package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +60 -23
  159. package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +14 -7
  160. package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +6 -0
  161. package/cabloy-docs/fullstack/tutorials-overview.md +17 -4
  162. package/cabloy-docs/reference/bean-scene-boilerplates.md +15 -13
  163. package/cabloy-docs/reference/package-map.md +4 -3
  164. package/package.json +2 -1
  165. package/scripts/init.ts +2 -18
  166. package/scripts/initTestData.ts +25 -0
  167. package/scripts/upgrade.ts +17 -2
  168. package/vona/pnpm-lock.yaml +48 -194
  169. package/vona/src/suite/a-training/modules/training-student/package.json +53 -0
  170. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +400 -0
  171. package/vona/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +18 -0
  172. package/vona/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  173. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.index.ts +12 -0
  174. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +21 -0
  175. package/vona/src/suite/a-training/modules/training-student/src/bean/ssrMenu.student.ts +29 -0
  176. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +15 -0
  177. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +15 -0
  178. package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +74 -0
  179. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +28 -0
  180. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +44 -0
  181. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectRes.tsx +11 -0
  182. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +45 -0
  183. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +42 -0
  184. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +28 -0
  185. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +25 -0
  186. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +84 -0
  187. package/vona/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  188. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +10 -0
  189. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +57 -0
  190. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +173 -0
  191. package/vona/src/suite/a-training/modules/training-student/tsconfig.build.json +11 -0
  192. package/vona/src/suite/a-training/modules/training-student/tsconfig.json +7 -0
  193. package/vona/src/suite/a-training/package.json +12 -0
  194. package/vona/src/suite/a-training/tsconfig.base.json +4 -0
  195. package/vona/src/suite/a-training/tsconfig.json +10 -0
  196. package/zova/packages-cli/cli/package.json +2 -2
  197. package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
  198. package/zova/packages-cli/cli-set-front/package.json +1 -1
  199. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
  200. package/zova/packages-zova/zova/package.json +2 -2
  201. package/zova/pnpm-lock.yaml +416 -690
  202. package/zova/src/suite/a-training/modules/training-student/cli/openapi.config.ts +9 -0
  203. package/zova/src/suite/a-training/modules/training-student/package.json +52 -0
  204. package/zova/src/suite/a-training/modules/training-student/src/.metadata/component/formFieldLevel.ts +31 -0
  205. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +258 -0
  206. package/zova/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +7 -0
  207. package/zova/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  208. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/baseURL.ts +5 -0
  209. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/index.ts +3 -0
  210. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +196 -0
  211. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +4146 -0
  212. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +151 -0
  213. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +43 -0
  214. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +51 -0
  215. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +56 -0
  216. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.level.tsx +63 -0
  217. package/zova/src/suite/a-training/modules/training-student/src/component/formFieldLevel/controller.tsx +117 -0
  218. package/zova/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +9 -0
  219. package/zova/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +9 -0
  220. package/zova/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  221. package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +42 -0
  222. package/zova/src/suite/a-training/modules/training-student/tsconfig.build.json +13 -0
  223. package/zova/src/suite/a-training/modules/training-student/tsconfig.json +5 -0
  224. package/zova/src/suite/a-training/package.json +12 -0
  225. package/zova/src/suite/a-training/tsconfig.base.json +4 -0
  226. package/zova/src/suite/a-training/tsconfig.json +4 -0
  227. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +29 -7
  228. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +34 -11
  229. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  230. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +3 -3
  231. package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/tableCell.ts +1 -1
  232. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -1,28 +1,50 @@
1
1
  # Model State Guide
2
2
 
3
- This guide explains how model-based server-data state works in Zova within the Cabloy monorepo.
3
+ This guide explains how to author and consume model-managed state in Zova within the Cabloy monorepo.
4
4
 
5
- ## Why the model layer exists
5
+ Read [Model Architecture](/frontend/model-architecture) first if you want the broader architectural role of Model.
6
6
 
7
- Zova uses model-based state management on top of API access so remote data can participate in a more unified caching and usage model.
7
+ If you specifically want the scalable resource-facade pattern, continue with [Model Resource Owner Pattern](/frontend/model-resource-owner-pattern).
8
8
 
9
- This improves runtime performance and developer experience by building on top of TanStack Query rather than exposing only raw request flows.
9
+ If you want the generic lower-level model runtime beneath these helper families, continue with [A-Model Under the Hood](/frontend/a-model-under-the-hood).
10
+
11
+ If you want to understand how that owner pattern expands into the whole `rest-resource` module runtime, continue with [Rest Resource Under the Hood](/frontend/rest-resource-under-the-hood), then [Rest Resource Source Reading Map](/frontend/rest-resource-source-reading-map).
12
+
13
+ If you want to apply that pattern in your own module with a more uniform two-usage model, continue with [Using `ModelResource` in Your Module](/frontend/model-resource-usage-guide).
14
+
15
+ ## Why the model-state layer exists
16
+
17
+ Zova uses model-based state management so cached remote data and several local state categories can participate in one broader model system.
18
+
19
+ This improves runtime performance and developer experience by building on top of TanStack Query while keeping the developer-facing surface aligned with Zova beans.
20
+
21
+ The key point is that model state is not limited to server data.
22
+
23
+ Current `a-model` source supports a broader state family that includes:
24
+
25
+ - remote/query-style state
26
+ - in-memory state
27
+ - local-storage state
28
+ - cookie-backed state
29
+ - async persisted db state
10
30
 
11
31
  ## Create a model
12
32
 
13
- Example: create a model named `menu` in module `demo-student`.
33
+ Example: create a model named `menu` in module `training-student`.
14
34
 
15
35
  ```bash
16
- npm run zova :create:bean model menu -- --module=demo-student
36
+ npm run zova :create:bean model menu -- --module=training-student
17
37
  ```
18
38
 
19
- ## Model definition
39
+ ## Basic model definition
20
40
 
21
41
  Representative pattern:
22
42
 
23
43
  ```typescript
44
+ import { BeanModelBase, Model } from 'zova-module-a-model';
45
+
24
46
  @Model()
25
- export class ModelMenu {
47
+ export class ModelMenu extends BeanModelBase {
26
48
  retrieveMenus() {
27
49
  return this.$useStateData({
28
50
  queryKey: ['retrieveMenus'],
@@ -36,11 +58,11 @@ export class ModelMenu {
36
58
  }
37
59
  ```
38
60
 
39
- This pattern is important because it shows that model logic is not just local state. It is also the place where cached remote data becomes a reusable abstraction.
61
+ This pattern matters because it shows that model logic is the place where cached remote data becomes a reusable abstraction.
40
62
 
41
63
  ## Using a model
42
64
 
43
- Representative pattern:
65
+ Representative consumption pattern:
44
66
 
45
67
  ```typescript
46
68
  @Use()
@@ -53,18 +75,352 @@ protected render() {
53
75
  }
54
76
  ```
55
77
 
78
+ The important point is architectural:
79
+
80
+ - the page/controller consumes the model
81
+ - the model owns the reusable data access and cache behavior
82
+
83
+ ## The main helper families
84
+
85
+ The current source organizes model state around these helper families.
86
+
87
+ ### 1. `$useStateData(...)`
88
+
89
+ Use this for cached remote data or other query-style state where the caller wants the full query object.
90
+
91
+ Representative characteristics from current source:
92
+
93
+ - it delegates to `$useQuery(...)`
94
+ - it memoizes the query wrapper by prefixed query key
95
+ - it auto-calls `suspense()` on first creation unless disabled by metadata
96
+ - it is the main bridge from model methods to query-style UI state
97
+
98
+ Representative example:
99
+
100
+ ```typescript
101
+ findAll() {
102
+ return this.$useStateData({
103
+ queryKey: ['list'],
104
+ queryFn: async () => {
105
+ return this.scope.api.todo.findAll();
106
+ },
107
+ });
108
+ }
109
+ ```
110
+
111
+ ## 2. `$useMutationData(...)`
112
+
113
+ Use this for model-owned mutation state.
114
+
115
+ Current-source behavior includes:
116
+
117
+ - `mutationKey` is required
118
+ - the key is automatically prefixed with model identity
119
+ - the mutation wrapper is memoized by prefixed key
120
+ - default error handling is attached unless disabled
121
+
122
+ Representative example:
123
+
124
+ ```typescript
125
+ create() {
126
+ return this.$useMutationData({
127
+ mutationKey: ['create'],
128
+ mutationFn: async body => {
129
+ return this.scope.api.todo.create(body);
130
+ },
131
+ onSuccess: () => {
132
+ this.$invalidateQueries({ queryKey: ['list'] });
133
+ },
134
+ });
135
+ }
136
+ ```
137
+
138
+ The pattern to notice is that the model owns both the mutation and the follow-up cache invalidation policy.
139
+
140
+ ## 3. `$useStateMem(...)`
141
+
142
+ Use this when the state should stay only in memory.
143
+
144
+ Current-source characteristics:
145
+
146
+ - no persistence
147
+ - `enabled: false`
148
+ - `staleTime: Infinity`
149
+ - still uses model-owned query cache semantics under the hood
150
+
151
+ This is useful when you want model ownership and query-key identity without local persistence.
152
+
153
+ ## 4. `$useStateLocal(...)`
154
+
155
+ Use this when the model state should persist in local storage.
156
+
157
+ Current-source characteristics:
158
+
159
+ - sync local storage persistence
160
+ - simplified storage keys by default
161
+ - `enabled: false`
162
+ - `staleTime: Infinity`
163
+ - state still flows through model-owned query cache first
164
+
165
+ A useful mental model is:
166
+
167
+ > local-storage state in Zova Model is not a separate store system. It is model-owned query state with a local-storage persister.
168
+
169
+ ## 5. `$useStateCookie(...)`
170
+
171
+ Use this when the model state should persist in cookies.
172
+
173
+ Current-source characteristics:
174
+
175
+ - sync cookie persistence
176
+ - cookie-type coercion support such as `boolean`, `number`, `date`, or `string`
177
+ - simplified storage keys by default
178
+ - still uses model-owned query cache semantics
179
+
180
+ This is particularly relevant for state that must participate in request-aware or SSR-adjacent flows.
181
+
182
+ ## 6. `$useStateDb(...)`
183
+
184
+ Use this when the model state should persist asynchronously in db-style client storage.
185
+
186
+ Current-source characteristics:
187
+
188
+ - async persistence through `localforage`
189
+ - `enabled: false`
190
+ - `staleTime: Infinity`
191
+ - explicit `ssr.dehydrate = false`
192
+ - getters may need async restore flow before data is available
193
+
194
+ This is useful for larger persisted client state that should outlive a page session without being stored in cookies or plain local storage.
195
+
196
+ ## 7. `$useStateComputed(...)`
197
+
198
+ Use this when the model should expose derived state that is still model-key-oriented but computed locally.
199
+
200
+ Current-source characteristics:
201
+
202
+ - it prefixes the query key
203
+ - it memoizes the computed value by the hashed prefixed key
204
+ - it uses `$computed(...)` rather than TanStack Query fetching
205
+
206
+ ## Query keys are model-owned, not global strings
207
+
208
+ One of the most important model-state behaviors is automatic key prefixing.
209
+
210
+ When a model uses:
211
+
212
+ ```typescript
213
+ queryKey: ['list'];
214
+ ```
215
+
216
+ that logical key is prefixed internally with model identity, and with selector when selector mode is enabled.
217
+
218
+ That means model code can use short business-facing keys while still getting namespace isolation.
219
+
220
+ ## Persistence and restore behavior
221
+
222
+ Current source treats persistence as part of the model-state runtime.
223
+
224
+ Representative behaviors include:
225
+
226
+ - persisted data can be restored back into query state
227
+ - expired or busted persisted entries are removed automatically
228
+ - `defaultData` can initialize the cache when no restored value exists
229
+ - setting persisted state to `undefined` removes the persisted record
230
+
231
+ This is why model helpers are better understood as state-runtime helpers, not only convenience wrappers.
232
+
233
+ ## SSR-sensitive state choices
234
+
235
+ Model state choices can affect SSR behavior.
236
+
237
+ Current-source behaviors to remember:
238
+
239
+ - query state can be dehydrated on server and hydrated on client
240
+ - mutations are not dehydrated
241
+ - `db` state is explicitly not dehydrated
242
+ - server cannot use local-storage or db persistence backends
243
+ - cookie state is special because cookie access can still exist through the app cookie surface
244
+
245
+ Practical implication:
246
+
247
+ - do not assume every persisted model state behaves the same during SSR
248
+ - choose `mem`, `local`, `cookie`, `db`, or `data` based on ownership and hydration requirements, not only convenience
249
+
250
+ ## Real examples to read
251
+
252
+ ### Minimal query and mutation model
253
+
254
+ Read:
255
+
256
+ - `zova/src/suite/a-demo/modules/demo-todo/src/model/todo.ts`
257
+
258
+ This file shows:
259
+
260
+ - extending `BeanModelBase`
261
+ - `@Model()` authoring
262
+ - query-style state through `$useStateData(...)`
263
+ - mutation-style state through `$useMutationData(...)`
264
+ - cache invalidation inside the model
265
+
266
+ ### Selector-enabled cache-oriented model
267
+
268
+ Read:
269
+
270
+ - `zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts`
271
+
272
+ This file shows:
273
+
274
+ - `@Model({ enableSelector: true, ... })`
275
+ - richer model initialization in `__init__`
276
+ - mixed use of `$useStateMem(...)` and `$useStateDb(...)`
277
+ - model-owned tab state with cache and persistence decisions
278
+
279
+ ### SSR-sensitive auth model
280
+
281
+ Read:
282
+
283
+ - `zova/src/suite/a-home/modules/home-passport/src/model/passport.ts`
284
+
285
+ This file shows:
286
+
287
+ - mixing `mem`, `local`, and `cookie` state in one model
288
+ - SSR-aware state choices
289
+ - model ownership of auth-related cached state and mutation flows
290
+
291
+ ### Generic resource-owner model
292
+
293
+ Read:
294
+
295
+ - `zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts`
296
+
297
+ This file is especially important because it shows a higher-level infrastructure pattern rather than a small feature model.
298
+
299
+ It demonstrates that a model can act as a **resource owner facade** for CRUD-oriented business modules.
300
+
301
+ What this example shows:
302
+
303
+ - `@Model({ enableSelector: true })` uses selector to isolate one model instance per resource name
304
+ - `__init__(resource)` bootstraps resource metadata and resolves `resourceApi` before normal query usage
305
+ - `$computed(...)` can expose permissions, form provider, and schema surfaces as model-owned derived state
306
+ - `$useStateData(...)` drives select/view queries
307
+ - `$useMutationData(...)` is wrapped by reusable `create`, `update`, `delete`, and `mutationItem` helpers
308
+ - invalidation policy is centralized so list and item caches stay coherent after mutations
309
+ - model methods can combine `$fetch`, `$sdk`, OpenAPI schema helpers, and form-oriented helpers behind one reusable boundary
310
+
311
+ This is one of the best examples for understanding how Zova Model scales from simple data queries to reusable domain infrastructure.
312
+
313
+ If your next question is not only about the model class but about how generic routes, page shells, schema-driven blocks, and downstream CRUD blocks cooperate around that owner, continue with [Rest Resource Under the Hood](/frontend/rest-resource-under-the-hood).
314
+
315
+ #### Why `enableSelector` matters here
316
+
317
+ This model is not meant to represent only one concrete resource forever.
318
+
319
+ It is a reusable generic model class that can serve many resources.
320
+
321
+ That is why `enableSelector` is essential.
322
+
323
+ The model passes `resource` into `super.__init__(resource)`, so the resource name becomes the selector identity for that model instance.
324
+
325
+ At runtime, model query keys are therefore prefixed not only by the bean full name but also by the selected resource.
326
+
327
+ That means two consumers can both use logical keys such as:
328
+
329
+ ```typescript
330
+ ['select', '', hashkey(query)][('item', id, 'view')];
331
+ ```
332
+
333
+ without colliding with each other, because the effective cache identity is separated by resource selector.
334
+
335
+ A practical reading takeaway is:
336
+
337
+ > selector turns one generic `ModelResource` implementation into many isolated resource-specific runtime instances.
338
+
339
+ #### Why this is a resource owner, not only a CRUD helper
340
+
341
+ A plain CRUD helper usually forwards requests.
342
+
343
+ `ModelResource` does more than that.
344
+
345
+ It owns several resource-level concerns together:
346
+
347
+ - bootstrap of resource metadata through `$QueryAutoLoad(...)`
348
+ - resolution of the final `resourceApi`
349
+ - permissions lookup
350
+ - OpenAPI schema access for view/create/update/select
351
+ - form integration such as submit mutation choice and default form data
352
+ - query and mutation cache invalidation rules
353
+
354
+ That is why this model is better understood as a **resource owner facade**.
355
+
356
+ In application code, prefer consuming that existing owner directly or adding a thin facade over it, while the lower-level `$fetch` and `$sdk` details stay inside the owner boundary.
357
+
358
+ #### How the cache-key design works
359
+
360
+ The cache-key design in this file is also worth reading carefully.
361
+
362
+ It separates three levels of identity:
363
+
364
+ - `keySelect(actionPath, query)` → list/query-level state
365
+ - `keyItemRoot(id)` → all state owned by one row id
366
+ - `keyItem(id, action)` → one concrete row action such as `view` or `update`
367
+
368
+ Representative shapes are:
369
+
370
+ ```typescript
371
+ ['select', actionPath ?? '', hashkey(query)][('item', id)][('item', id, action)];
372
+ ```
373
+
374
+ This makes the invalidation strategy much clearer:
375
+
376
+ - create invalidates the select-level list cache
377
+ - update/delete invalidate the select-level list cache and the item root for that row
378
+ - item-specific queries such as `view(id)` live under the item branch
379
+
380
+ The practical benefit is that the model does not scatter cache policy across pages.
381
+
382
+ Instead, the model itself defines how list-level and row-level state stay coherent after mutations.
383
+
384
+ #### Why this example is a strong source-reading specimen
385
+
386
+ If `demo-todo` shows the minimal pattern for model queries and mutations, `rest-resource` shows the scalable pattern.
387
+
388
+ Use it when you want to understand how Zova Model can support:
389
+
390
+ - generic reusable business infrastructure
391
+ - selector-isolated model instances
392
+ - unified resource schema and permission ownership
393
+ - form-oriented integration on top of query state
394
+ - centralized invalidation semantics for larger UI systems
395
+
56
396
  ## Relationship to the server-data ladder
57
397
 
58
- In the new docs, think about the layers like this:
398
+ Think about the layers like this:
59
399
 
60
400
  - `$fetch` → direct request access
61
401
  - `$api` → business-oriented service methods
62
- - `Model` → cached, reusable, UI-friendly remote state
402
+ - `Model` → cached, reusable, persistence-aware state
63
403
 
64
404
  That makes the model layer one of the most important bridges between backend contracts and frontend rendering.
65
405
 
66
- ## Implementation checks for model-based state changes
406
+ ## Practical design checks
407
+
408
+ When adding frontend state, avoid jumping straight to ad hoc request logic or generic store habits.
409
+
410
+ Instead ask:
411
+
412
+ 1. should this state live in an existing model?
413
+ 2. should it be `data`, `mem`, `local`, `cookie`, or `db` state?
414
+ 3. should the model own invalidation or refetch behavior?
415
+ 4. does persistence or SSR change the right helper choice?
416
+ 5. should the page/controller consume a model instead of owning this state directly?
417
+
418
+ That usually produces cleaner, more Cabloy-native code.
419
+
420
+ ## Final takeaway
421
+
422
+ The most important usage insight is simple:
67
423
 
68
- When you see repeated frontend data usage, caching concerns, or UI state that depends on remote data, ask whether the right abstraction is a model instead of a direct API call in the page.
424
+ > In Zova, model state is not only “fetch some data”. It is a unified model-owned runtime for query state, local state, persistence, invalidation, and SSR-aware reuse.
69
425
 
70
- That usually leads to cleaner SSR behavior, cleaner reuse, and a more Cabloy-native structure.
426
+ Once that is clear, the helper family in `a-model` reads as one coherent system instead of several unrelated APIs.
@@ -40,11 +40,11 @@ These categories make module resources discoverable and consistently organized.
40
40
  Representative CLI entrypoints include:
41
41
 
42
42
  ```bash
43
- npm run zova :init:config demo-student
44
- npm run zova :init:constant demo-student
45
- npm run zova :init:locale demo-student
46
- npm run zova :init:error demo-student
47
- npm run zova :create:bean api test -- --module=demo-student
43
+ npm run zova :init:config training-student
44
+ npm run zova :init:constant training-student
45
+ npm run zova :init:locale training-student
46
+ npm run zova :init:error training-student
47
+ npm run zova :create:bean api test -- --module=training-student
48
48
  ```
49
49
 
50
50
  This matters because scope is not just a read surface. It is the organized destination for resources generated or initialized through the standard Zova workflow.
@@ -119,14 +119,14 @@ Representative pattern:
119
119
 
120
120
  ```typescript
121
121
  @UseScope()
122
- $$scopeDemoStudent: ScopeModuleDemoStudent;
122
+ $$scopeTrainingStudent: ScopeModuleTrainingStudent;
123
123
  ```
124
124
 
125
125
  A common follow-up access pattern is:
126
126
 
127
127
  ```typescript
128
- const res = await this.$$scopeDemoStudent.api.test.echo();
129
- console.log(this.$$scopeDemoStudent.locale.HelloWorld());
128
+ const res = await this.$$scopeTrainingStudent.api.test.echo();
129
+ console.log(this.$$scopeTrainingStudent.locale.HelloWorld());
130
130
  ```
131
131
 
132
132
  This allows one module to consume another module’s scoped resources explicitly without flattening everything into one shared global namespace.
@@ -129,7 +129,7 @@ Representative patterns include:
129
129
 
130
130
  ```json
131
131
  {
132
- "name": "zova-module-demo-student",
132
+ "name": "zova-module-training-student",
133
133
  "zovaModule": {
134
134
  "dependencies": {
135
135
  "a-zova": "5.0.0"
@@ -160,6 +160,7 @@ This reinforces that modules are not merely folders. They are explicit package,
160
160
 
161
161
  Read this together with:
162
162
 
163
+ - [Suites and Modules](/fullstack/suites-and-modules) for the cross-stack suite-first decision path in the monorepo
163
164
  - [IoC and Beans](/frontend/ioc-and-beans)
164
165
  - [Module Scope](/frontend/module-scope)
165
166
  - [Frontend Scripts](/frontend/scripts)
@@ -66,3 +66,10 @@ When changing auth-sensitive routing behavior, ask:
66
66
  4. should redirects happen at the routing-policy layer rather than being hardcoded into page logic?
67
67
 
68
68
  That produces cleaner and more framework-native navigation behavior.
69
+
70
+ ## Where to read next
71
+
72
+ - If you want the broader route-record surface first, continue with [Page Route Guide](/frontend/page-route-guide).
73
+ - If the guard decision depends on route metadata or task-level shell state, continue with [Page Meta Guide](/frontend/page-meta-guide).
74
+ - If the guard behavior is really part of a larger SSR decision path, continue with [SSR Architecture Overview](/frontend/ssr-architecture-overview).
75
+ - If you want the deeper routing runtime after the public policy surface is clear, descend into [Zova Router Under the Hood](/frontend/zova-router-under-the-hood).
@@ -20,22 +20,29 @@ For the bridge view, also see [Backend OpenAPI to Frontend SDK](/fullstack/opena
20
20
 
21
21
  For the broader frontend contract-consumption ladder, also see [Server Data](/frontend/server-data), [API Schema Guide](/frontend/api-schema-guide), and [SDK Guide](/frontend/sdk-guide).
22
22
 
23
+ If your next question is how the lower-level OpenAPI/schema runtime works under `$sdk`, continue with [A-OpenAPI Under the Hood](/frontend/a-openapi-under-the-hood).
24
+
25
+ If your next question is how generated contract material becomes schema-driven frontend behavior or resource-owner consumption, continue with [API Schema Guide](/frontend/api-schema-guide) and [ModelResource Internals Deep Dive](/frontend/model-resource-internals-deep-dive).
26
+
23
27
  ## Initialize OpenAPI config
24
28
 
25
- Example: initialize OpenAPI config for module `demo-student`.
29
+ Example: initialize OpenAPI config for module `training-student`.
26
30
 
27
31
  ```bash
28
- npm run zova :openapi:config demo-student
32
+ npm run zova :openapi:config training-student
29
33
  ```
30
34
 
31
35
  ## Module-level config
32
36
 
33
- Each module can control which backend operations belong to it.
37
+ Each module must explicitly declare which backend operations belong to it.
34
38
 
35
39
  Representative idea:
36
40
 
37
- - configure matching rules in the module OpenAPI config
41
+ - configure `operations.match` or `operations.ignore` in the module OpenAPI config
38
42
  - keep API ownership aligned with the module boundary
43
+ - avoid generating large amounts of unrelated SDK output for the current module
44
+
45
+ If both `operations.match` and `operations.ignore` are left empty, `:openapi:generate` should fail fast and ask you to define one of them explicitly. This fail-fast feedback helps both developers and AI agents notice the missing ownership rule immediately and correct it before unrelated SDK output is generated.
39
46
 
40
47
  This modular split matters because Cabloy does not treat the frontend as one flat API client surface.
41
48
 
@@ -50,10 +57,10 @@ Representative use case:
50
57
 
51
58
  ## Generate the SDK
52
59
 
53
- Example: generate OpenAPI-based frontend services for module `demo-student`.
60
+ Example: generate OpenAPI-based frontend services for module `training-student`.
54
61
 
55
62
  ```bash
56
- npm run zova :openapi:generate demo-student
63
+ npm run zova :openapi:generate training-student
57
64
  ```
58
65
 
59
66
  ## Build the rest-contract output
@@ -90,6 +97,10 @@ If the backend contract itself changes, first inspect or update the backend cont
90
97
 
91
98
  Then return to this page for the frontend regeneration step.
92
99
 
100
+ If your next question is what that generated contract looks like when it is actually consumed in a practical frontend path, continue with [Generated Contract Consumption Specimen](/frontend/generated-contract-consumption-specimen).
101
+
102
+ If you then want a proof-oriented or symptom-first companion for the consumer-side path, continue with [Generated Contract Consumption Verify Playbook](/frontend/generated-contract-consumption-verify-playbook) and [Generated Contract Consumption Debug Checklist](/frontend/generated-contract-consumption-debug-checklist).
103
+
93
104
  ## Implementation checks for SDK regeneration decisions
94
105
 
95
106
  When evaluating a request that depends on backend contracts, ask:
@@ -17,10 +17,10 @@ That combination is one of the clearest examples of Zova’s overall design phil
17
17
 
18
18
  ## Create a page
19
19
 
20
- Example: create a page named `counter` in module `demo-student`.
20
+ Example: create a page named `counter` in module `training-student`.
21
21
 
22
22
  ```bash
23
- npm run zova :create:page counter -- --module=demo-student
23
+ npm run zova :create:page counter -- --module=training-student
24
24
  ```
25
25
 
26
26
  ## Route path generation
@@ -29,9 +29,9 @@ Zova automatically derives the page path from the module and page names.
29
29
 
30
30
  Representative example:
31
31
 
32
- - module: `demo-student`
32
+ - module: `training-student`
33
33
  - page: `counter`
34
- - generated page path: `/demo/student/counter`
34
+ - generated page path: `/training/student/counter`
35
35
 
36
36
  This matters because the framework already has conventions for route structure. AI should reuse those conventions rather than inventing unrelated paths.
37
37
 
@@ -123,7 +123,7 @@ A typical first step is keeping the page controller responsible for state while
123
123
  #### Create the first render bean
124
124
 
125
125
  ```bash
126
- npm run zova :refactor:firstRender page/counter -- --module=demo-student
126
+ npm run zova :refactor:firstRender page/counter -- --module=training-student
127
127
  ```
128
128
 
129
129
  Representative render bean shape:
@@ -146,7 +146,7 @@ class RenderPageCounter extends BeanRenderBase {
146
146
  #### Create the first style bean
147
147
 
148
148
  ```bash
149
- npm run zova :refactor:firstStyle page/counter -- --module=demo-student
149
+ npm run zova :refactor:firstStyle page/counter -- --module=training-student
150
150
  ```
151
151
 
152
152
  Representative style bean shape:
@@ -177,19 +177,19 @@ Representative refactors include:
177
177
  #### Create another render bean
178
178
 
179
179
  ```bash
180
- npm run zova :refactor:anotherRender page/counter another -- --module=demo-student
180
+ npm run zova :refactor:anotherRender page/counter another -- --module=training-student
181
181
  ```
182
182
 
183
183
  #### Create another style bean
184
184
 
185
185
  ```bash
186
- npm run zova :refactor:anotherStyle page/counter another -- --module=demo-student
186
+ npm run zova :refactor:anotherStyle page/counter another -- --module=training-student
187
187
  ```
188
188
 
189
189
  #### Create a service bean for state management
190
190
 
191
191
  ```bash
192
- npm run zova :create:bean service page/counter/counter -- --module=demo-student
192
+ npm run zova :create:bean service page/counter/counter -- --module=training-student
193
193
  ```
194
194
 
195
195
  Representative service bean shape:
@@ -215,6 +215,12 @@ These refactors are supported by Zova CLI commands rather than requiring a fully
215
215
 
216
216
  When generating or editing a Zova page, preserve the page/controller mental model instead of rewriting the code into a generic Vue single-file-component pattern.
217
217
 
218
+ If you want a stronger reading bridge from Vue habits into page-controller source code, also read:
219
+
220
+ - [Reading Zova for Vue Developers](/frontend/reading-zova-for-vue-developers)
221
+ - [Zova Reactivity Under the Hood](/frontend/zova-reactivity-under-the-hood)
222
+ - [Zova Source Reading Map](/frontend/zova-source-reading-map)
223
+
218
224
  A better default is:
219
225
 
220
226
  1. use the Zova page generator