cabloy 5.1.59 → 5.1.61

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 (149) 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/references/follow-up-checklist.md +1 -0
  4. package/.claude/skills/cabloy-contract-loop/SKILL.md +103 -14
  5. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +126 -12
  6. package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +148 -0
  7. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +49 -13
  8. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +11 -0
  9. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +2 -0
  10. package/.claude/skills/cabloy-module-removal/SKILL.md +144 -0
  11. package/.claude/skills/cabloy-resource-field-update/SKILL.md +274 -0
  12. package/.claude/skills/cabloy-resource-field-update/evals/evals.json +53 -0
  13. package/.claude/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +102 -0
  14. package/.claude/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +120 -0
  15. package/.claude/skills/cabloy-resource-field-update/references/follow-up-checklist.md +80 -0
  16. package/.claude/skills/cabloy-resource-field-update/references/verification-checklist.md +97 -0
  17. package/.claude/skills/cabloy-zova-source-reading/SKILL.md +221 -0
  18. package/.claude/skills/cabloy-zova-source-reading/references/analysis-modes.md +91 -0
  19. package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +117 -0
  20. package/.github/workflows/docs-pages.yml +2 -0
  21. package/.github/workflows/vona-cov-pg.yml +2 -0
  22. package/.github/workflows/vona-test-crud.yml +4 -2
  23. package/.github/workflows/vona-test-mysql.yml +2 -0
  24. package/.github/workflows/vona-test-pg.yml +2 -0
  25. package/.github/workflows/vona-test-sqlite3.yml +2 -0
  26. package/.github/workflows/vona-tsc.yml +2 -0
  27. package/.github/workflows/zova-ui.yml +2 -0
  28. package/.gitignore +0 -4
  29. package/CHANGELOG.md +52 -0
  30. package/CLAUDE.md +12 -0
  31. package/README.md +15 -0
  32. package/cabloy-docs/.vitepress/config.mjs +89 -0
  33. package/cabloy-docs/ai/class-placement-rule.md +2 -0
  34. package/cabloy-docs/ai/cli-to-skill-map.md +14 -0
  35. package/cabloy-docs/ai/docs-skills-rules-mapping.md +14 -0
  36. package/cabloy-docs/ai/future-skill-roadmap.md +27 -9
  37. package/cabloy-docs/ai/introduction.md +1 -0
  38. package/cabloy-docs/ai/playbook-backend-module.md +6 -0
  39. package/cabloy-docs/ai/playbook-module-removal.md +164 -0
  40. package/cabloy-docs/ai/skills.md +11 -0
  41. package/cabloy-docs/backend/bean-scene-authoring.md +350 -0
  42. package/cabloy-docs/backend/cli.md +26 -1
  43. package/cabloy-docs/backend/dto-guide.md +6 -0
  44. package/cabloy-docs/backend/entity-guide.md +18 -0
  45. package/cabloy-docs/backend/foundation.md +28 -3
  46. package/cabloy-docs/backend/introduction.md +10 -0
  47. package/cabloy-docs/backend/serialization-guide.md +10 -0
  48. package/cabloy-docs/backend/service-guide.md +2 -0
  49. package/cabloy-docs/backend/status-guide.md +271 -0
  50. package/cabloy-docs/backend/websocket-call-flow.md +435 -0
  51. package/cabloy-docs/backend/websocket-guide.md +455 -0
  52. package/cabloy-docs/backend/websocket-protocol-guide.md +381 -0
  53. package/cabloy-docs/backend/websocket-usage-guide.md +356 -0
  54. package/cabloy-docs/frontend/api-guide.md +2 -0
  55. package/cabloy-docs/frontend/bean-scene-authoring.md +374 -0
  56. package/cabloy-docs/frontend/behavior-guide.md +449 -0
  57. package/cabloy-docs/frontend/cli.md +24 -0
  58. package/cabloy-docs/frontend/command-scene-authoring.md +495 -0
  59. package/cabloy-docs/frontend/design-principles.md +6 -0
  60. package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
  61. package/cabloy-docs/frontend/form-guide.md +795 -0
  62. package/cabloy-docs/frontend/foundation.md +29 -0
  63. package/cabloy-docs/frontend/introduction.md +17 -1
  64. package/cabloy-docs/frontend/ioc-and-beans.md +16 -9
  65. package/cabloy-docs/frontend/mock-guide.md +1 -0
  66. package/cabloy-docs/frontend/model-architecture.md +252 -39
  67. package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
  68. package/cabloy-docs/frontend/model-resource-cookbook.md +505 -0
  69. package/cabloy-docs/frontend/model-resource-owner-pattern.md +382 -0
  70. package/cabloy-docs/frontend/model-resource-usage-guide.md +318 -0
  71. package/cabloy-docs/frontend/model-state-guide.md +366 -13
  72. package/cabloy-docs/frontend/openapi-sdk-guide.md +5 -2
  73. package/cabloy-docs/frontend/page-guide.md +6 -0
  74. package/cabloy-docs/frontend/quickstart.md +4 -0
  75. package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
  76. package/cabloy-docs/frontend/router-tabs-admin-web-comparison.md +206 -0
  77. package/cabloy-docs/frontend/router-tabs-introduction.md +106 -0
  78. package/cabloy-docs/frontend/router-tabs-mechanism.md +469 -0
  79. package/cabloy-docs/frontend/router-tabs-overview.md +227 -0
  80. package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +343 -0
  81. package/cabloy-docs/frontend/server-data.md +2 -0
  82. package/cabloy-docs/frontend/ssr-architecture-overview.md +211 -0
  83. package/cabloy-docs/frontend/ssr-build-deploy-guide.md +308 -0
  84. package/cabloy-docs/frontend/ssr-review-checklist.md +184 -0
  85. package/cabloy-docs/frontend/ssr-troubleshooting-guide.md +301 -0
  86. package/cabloy-docs/frontend/zova-form-source-reading-map.md +295 -0
  87. package/cabloy-docs/frontend/zova-form-under-the-hood.md +556 -0
  88. package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
  89. package/cabloy-docs/frontend/zova-source-reading-map.md +327 -0
  90. package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
  91. package/cabloy-docs/fullstack/contract-loop-playbook.md +350 -0
  92. package/cabloy-docs/fullstack/framework-performance.md +3 -3
  93. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +44 -1
  94. package/cabloy-docs/fullstack/introduction.md +40 -0
  95. package/cabloy-docs/fullstack/openapi-to-sdk.md +19 -9
  96. package/cabloy-docs/fullstack/quickstart.md +7 -1
  97. package/cabloy-docs/fullstack/tutorial-1-first-module.md +111 -0
  98. package/cabloy-docs/fullstack/tutorial-2-first-crud.md +122 -0
  99. package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +131 -0
  100. package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +144 -0
  101. package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +146 -0
  102. package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +170 -0
  103. package/cabloy-docs/fullstack/tutorials-overview.md +192 -0
  104. package/cabloy-docs/index.md +4 -3
  105. package/cabloy-docs/reference/bean-scene-boilerplates.md +75 -0
  106. package/cabloy-docs/reference/cli-reference.md +2 -0
  107. package/package.json +7 -2
  108. package/scripts/initTestData.ts +25 -0
  109. package/scripts/upgrade.ts +17 -2
  110. package/vona/packages-cli/cabloy-cli/package.json +2 -2
  111. package/vona/packages-cli/cli/package.json +1 -1
  112. package/vona/packages-cli/cli-set-api/package.json +1 -1
  113. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.module.ts +4 -0
  114. package/vona/packages-vona/vona/package.json +1 -1
  115. package/vona/pnpm-lock.yaml +226 -1091
  116. package/vona/pnpm-workspace.yaml +0 -1
  117. package/vona/src/suite-vendor/a-vona/modules/a-core/assets/static/img/vona.svg +1 -1
  118. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  119. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  120. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +1 -1
  121. package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +2 -2
  122. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  123. package/zova/package.original.json +1 -1
  124. package/zova/packages-cli/cli/package.json +3 -3
  125. package/zova/packages-cli/cli-set-front/cli/templates/init/icon/boilerplate/icons/default/zova.svg +1 -1
  126. package/zova/packages-cli/cli-set-front/cli/templates/openapi/config/boilerplate/module/openapi.config.ts +6 -1
  127. package/zova/packages-cli/cli-set-front/package.json +3 -3
  128. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +4 -0
  129. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
  130. package/zova/packages-cli/cli-set-front/src/lib/command/create.bean.ts +5 -1
  131. package/zova/packages-utils/zova-vite/package.json +2 -2
  132. package/zova/packages-zova/zova/package.json +2 -2
  133. package/zova/pnpm-lock.yaml +282 -1311
  134. package/zova/pnpm-workspace.yaml +0 -1
  135. package/zova/src/suite/a-home/modules/home-icon/icons/social/cabloy.svg +1 -1
  136. package/zova/src/suite/a-home/modules/home-icon/icons/social/vona.svg +1 -1
  137. package/zova/src/suite/a-home/modules/home-icon/icons/social/zova.svg +1 -1
  138. package/zova/src/suite/a-home/modules/home-icon/src/.metadata/icons/groups/social.svg +3 -3
  139. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +9 -0
  140. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  141. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +66 -16
  142. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  143. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
  144. package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +60 -18
  145. package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  146. package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableCell/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  147. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  148. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  149. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -0,0 +1,556 @@
1
+ # Zova Form Under the Hood
2
+
3
+ This guide explains the source-level runtime path behind Zova Form.
4
+
5
+ Use this page together with:
6
+
7
+ - [Form Guide](/frontend/form-guide)
8
+ - [Zova Form Source Reading Map](/frontend/zova-form-source-reading-map)
9
+ - [Zova Reactivity Under the Hood](/frontend/zova-reactivity-under-the-hood)
10
+ - [Behavior Guide](/frontend/behavior-guide)
11
+ - [API Schema Guide](/frontend/api-schema-guide)
12
+
13
+ Use this page after [Form Guide](/frontend/form-guide) when you want to move from the public authoring surface to the internal cooperation among form controllers, field controllers, schema metadata, provider config, behaviors, and CRUD integration.
14
+
15
+ If your next question is not “how does this runtime work?” but “which files should I read next?”, continue with [Zova Form Source Reading Map](/frontend/zova-form-source-reading-map).
16
+
17
+ > [!TIP]
18
+ > **Zova Form docs path**
19
+ > 1. **[Form Guide](/frontend/form-guide)** — learn the public authoring surface
20
+ > 2. **[Zova Form Under the Hood](/frontend/zova-form-under-the-hood)** — learn how the runtime pieces cooperate
21
+ > 3. **[Zova Form Source Reading Map](/frontend/zova-form-source-reading-map)** — learn which files to read next
22
+ >
23
+ > **You are here:** step 2.
24
+ > **Previous page:** [Form Guide](/frontend/form-guide).
25
+ > **Next recommended page:** [Zova Form Source Reading Map](/frontend/zova-form-source-reading-map).
26
+
27
+ ## Why this page exists
28
+
29
+ The public form guide already explains the authoring surface:
30
+
31
+ - `ZForm`
32
+ - `ZFormFieldPreset`
33
+ - `ZFormField`
34
+ - `ZFormFieldBlank`
35
+ - `formMeta`
36
+ - `formProvider`
37
+
38
+ The source-reading map already explains where to look when you need a targeted code path.
39
+
40
+ What many contributors and AI workflows still want next is the implementation bridge:
41
+
42
+ - where the TanStack form instance is created
43
+ - where one field becomes a TanStack field binding
44
+ - how schema metadata becomes field props
45
+ - how layout, provider config, and behaviors merge into final rendering
46
+ - how validation and server errors flow back into the form state
47
+ - how CRUD pages feed resource-driven schema and data into `ZForm`
48
+
49
+ This page is that bridge.
50
+
51
+ ## The shortest accurate runtime model
52
+
53
+ For a typical Zova form, the shortest accurate model is:
54
+
55
+ 1. the `ZForm` wrapper creates a form controller bean through the normal Zova controller path
56
+ 2. the form controller creates a TanStack form instance through Zova’s `$useForm(...)` wrapper
57
+ 3. the form controller computes provider config, schema, Zod schema, and rendered properties
58
+ 4. if the form body is not manually overridden, the form render bean turns schema properties into field children
59
+ 5. each field controller creates its own TanStack field binding with `useField(...)`
60
+ 6. field props merge from schema metadata, field props, layout options, provider config, and readonly rules
61
+ 7. provider behaviors wrap the field render path before the final renderer is invoked
62
+ 8. submit and validation flow through TanStack and Zod, then Zova normalizes invalid-submit and 422 server errors back into form state
63
+ 9. resource-driven CRUD pages feed `formMeta`, `formSchema`, `formData`, and `formProvider` into the same runtime
64
+
65
+ That is why Zova Form is not only a thin wrapper around TanStack Form. The business-facing runtime surface is still Zova-native.
66
+
67
+ ## A concrete source specimen
68
+
69
+ A small public example that shows several form patterns clearly is:
70
+
71
+ ```text
72
+ zova/src/suite/a-demo/modules/demo-basic/src/page/toolOne/render.tsx
73
+ ```
74
+
75
+ That specimen is useful because it shows both:
76
+
77
+ - schema-driven rendering
78
+ - manual field rendering through `ZFormField`
79
+
80
+ A more business-facing specimen is:
81
+
82
+ ```text
83
+ zova/src/suite/a-home/modules/home-login/src/page/login/render.tsx
84
+ ```
85
+
86
+ That page shows:
87
+
88
+ - preset-based field rendering
89
+ - a provider-level layout behavior override
90
+ - a blank row used for action controls
91
+
92
+ The rest of this page explains how those public authoring shapes become real runtime behavior.
93
+
94
+ ## The core source-reading path
95
+
96
+ When you want to trace the full mechanism, read these files in order:
97
+
98
+ 1. `zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx`
99
+ 2. `zova/src/suite-vendor/a-zova/modules/a-form/src/lib/beanControllerFormBase.ts`
100
+ 3. `zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/render.tsx`
101
+ 4. `zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx`
102
+ 5. `zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/render.tsx`
103
+ 6. `zova/src/suite-vendor/a-zova/modules/a-openapi/src/lib/schema.ts`
104
+ 7. `zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx`
105
+
106
+ A compact role map is:
107
+
108
+ - `form/controller.tsx` owns form runtime creation, schema state, submit flow, and error normalization
109
+ - `beanControllerFormBase.ts` shows the Zova wrapper around TanStack `useForm(...)`
110
+ - `form/render.tsx` shows automatic schema-driven field iteration and form-level submit wiring
111
+ - `formField/controller.tsx` owns field runtime creation, props merge, validation setup, and behavior selection
112
+ - `formField/render.tsx` shows the final behavior-wrapped render handoff
113
+ - `schema.ts` shows schema-property loading and Zod conversion
114
+ - `blockPageEntry/controller.tsx` shows how a resource-driven CRUD page feeds schema and data into `ZForm`
115
+
116
+ ## Step-by-step runtime path
117
+
118
+ ### 1. `ZForm` creates the form controller bean
119
+
120
+ The public wrapper enters the normal Zova controller path through the generated metadata wrapper:
121
+
122
+ ```text
123
+ zova/src/suite-vendor/a-zova/modules/a-form/src/.metadata/component/form.ts
124
+ ```
125
+
126
+ That wrapper calls `useController(...)`, which means the form runtime begins as a controller bean, not as a page-local ad hoc object.
127
+
128
+ A practical reading takeaway is:
129
+
130
+ - **the visible wrapper component is thin**
131
+ - **the controller bean is the real runtime owner**
132
+
133
+ ## 2. The form controller creates the TanStack form bridge
134
+
135
+ The main runtime owner is:
136
+
137
+ ```text
138
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx
139
+ ```
140
+
141
+ Inside `ControllerForm.__init__()` the controller:
142
+
143
+ - registers itself as `$$form`
144
+ - creates the form instance with `_createForm()`
145
+ - creates `formState` with `useStore(this.form.store, ...)`
146
+ - computes `formProvider`
147
+ - computes `schema`
148
+ - computes `zodSchema`
149
+ - computes rendered `properties`
150
+ - creates the field CEL environment
151
+ - creates `zovaJsx`
152
+ - watches incoming `data` and resets the form when it changes
153
+
154
+ This is one of the most important source-level facts about Zova Form.
155
+
156
+ The form controller is not only coordinating submit. It is the central bridge among:
157
+
158
+ - TanStack form state
159
+ - schema-driven field metadata
160
+ - provider-driven renderer lookup
161
+ - Zova field render context
162
+
163
+ ## 3. Why `$useForm(...)` exists
164
+
165
+ The shared wrapper lives in:
166
+
167
+ ```text
168
+ zova/src/suite-vendor/a-zova/modules/a-form/src/lib/beanControllerFormBase.ts
169
+ ```
170
+
171
+ and the page-controller variant lives in:
172
+
173
+ ```text
174
+ zova/src/suite-vendor/a-zova/modules/a-form/src/lib/beanControllerPageFormBase.ts
175
+ ```
176
+
177
+ The important runtime detail is that `$useForm(...)` wraps TanStack `useForm(...)` like this:
178
+
179
+ - run it inside `ctx.util.instanceScope(...)`
180
+ - then `markRaw(...)` the returned TanStack object
181
+
182
+ That matters because:
183
+
184
+ - Zova wants the controller bean to stay the business-facing reactive host
185
+ - the underlying TanStack object still needs to be created in the right Zova instance scope
186
+ - the raw TanStack API should not itself become the main reactive authoring object
187
+
188
+ A practical reading takeaway is:
189
+
190
+ - **Zova does not replace TanStack Form**
191
+ - **Zova relocates the business-facing ownership into controller beans**
192
+
193
+ ## 4. How schema becomes rendered fields
194
+
195
+ The form controller computes two related surfaces:
196
+
197
+ - `zodSchema`
198
+ - `properties`
199
+
200
+ The relevant source files are:
201
+
202
+ ```text
203
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx
204
+ zova/src/suite-vendor/a-zova/modules/a-openapi/src/lib/schema.ts
205
+ ```
206
+
207
+ The important runtime path is:
208
+
209
+ 1. the form receives `schema`
210
+ 2. `_getZodSchema()` either reuses `props.zodSchema` or converts the schema with `schemaToZodSchema(...)`
211
+ 3. `loadSchemaProperties(...)` resolves fields for the current schema scene
212
+ 4. each property carries field-level metadata such as render, order, and scene-specific `rest` overrides
213
+
214
+ `loadSchemaProperties(...)` is especially important because it does more than list object keys.
215
+
216
+ It also:
217
+
218
+ - resolves `$ref`
219
+ - applies scene-specific metadata overlays such as `form`, `form-view`, `form-create`, and `filter`
220
+ - sorts fields by `rest.order`
221
+
222
+ A practical reading takeaway is:
223
+
224
+ - **schema is not only validation truth**
225
+ - **schema also drives ordering, render metadata, and scene-specific field behavior**
226
+
227
+ ## 5. The form controller creates the field render context
228
+
229
+ Still inside `form/controller.tsx`, the form controller prepares the field runtime support used later by every field:
230
+
231
+ - `getFieldValue(...)`
232
+ - `setFieldValue(...)`
233
+ - `getFieldProperty(...)`
234
+ - `getFieldZodSchema(...)`
235
+ - `getFieldScope(...)`
236
+ - `getFieldJsxRenderContext(...)`
237
+ - `getFieldComponentPropsTop(...)`
238
+
239
+ These methods matter because they separate responsibilities clearly:
240
+
241
+ - the form controller owns cross-field knowledge
242
+ - the field controller owns one field’s runtime binding
243
+
244
+ This is why a field can ask the parent form for:
245
+
246
+ - its current value
247
+ - its schema property metadata
248
+ - its field-level Zod schema
249
+ - the JSX/CEL scope used for rendering expressions
250
+
251
+ ## 6. One field becomes a TanStack field binding
252
+
253
+ The field runtime owner is:
254
+
255
+ ```text
256
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx
257
+ ```
258
+
259
+ Inside `ControllerFormField.__init__()` the field controller:
260
+
261
+ - verifies it is inside a form
262
+ - registers itself as `$$formField`
263
+ - creates the field with `_createField()`
264
+ - computes `propsBucket`
265
+ - watches schema-property changes and updates the TanStack field options
266
+ - initializes the behavior holder
267
+
268
+ The key bridge is `_createField()`:
269
+
270
+ - call `useField(options as any)`
271
+ - `markRaw(...)` the field object
272
+ - create reactive `fieldState` with `useStore(field.api.store, ...)`
273
+
274
+ This is the field-level equivalent of the form controller’s TanStack bridge.
275
+
276
+ A practical reading takeaway is:
277
+
278
+ - **the form owns the cross-field runtime**
279
+ - **each field controller owns one field’s TanStack binding and render context**
280
+
281
+ ## 7. How one field is configured
282
+
283
+ The field controller builds its runtime configuration mainly through:
284
+
285
+ - `_getPropsBucket()`
286
+ - `_getFormFieldOptions()`
287
+ - `_getFormFieldOptionsValidators()`
288
+
289
+ ### `_getPropsBucket()`
290
+
291
+ This is one of the most important methods in the entire module.
292
+
293
+ Its job is to merge the final field-facing props from several sources:
294
+
295
+ 1. default field render assumptions
296
+ 2. local field props
297
+ 3. top-level schema-derived props from the parent form
298
+ 4. computed layout options
299
+ 5. computed renderer options
300
+ 6. readonly normalization
301
+ 7. final render-provider resolution
302
+
303
+ That means the final field render is not decided by one layer only.
304
+
305
+ It is the result of several layers cooperating.
306
+
307
+ ### `_getFormFieldOptions()`
308
+
309
+ This method builds the TanStack field options by combining:
310
+
311
+ - current form value
312
+ - default value from system options or schema property defaults
313
+ - form reference
314
+ - validators
315
+
316
+ ### `_getFormFieldOptionsValidators()`
317
+
318
+ This method chooses the validation surface for `onDynamic`, `onBlur`, and `onChange`.
319
+
320
+ Its important behavior is:
321
+
322
+ - if a validator flag is `true`, use the field’s Zod schema
323
+ - if a validator is an explicit Zod validator, use that
324
+ - if no field-specific validator is given, default dynamic validation can still be enabled
325
+
326
+ A practical reading takeaway is:
327
+
328
+ - **field validation is not hard-coded in one place**
329
+ - **it is derived from either explicit field options or the field’s schema-driven Zod contract**
330
+
331
+ ## 8. The prop/provider/behavior merge pipeline
332
+
333
+ The most useful durable mental model for field rendering is:
334
+
335
+ ```text
336
+ schema/rest + field props + layout + provider config -> behavior wrapping -> final renderer
337
+ ```
338
+
339
+ The relevant sources are:
340
+
341
+ ```text
342
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx
343
+ zova/src/suite/cabloy-basic/modules/basic-adapter/src/config/config.ts
344
+ zova/src/suite/cabloy-basic/modules/basic-form/src/bean/behavior.formField.ts
345
+ zova/src/suite/cabloy-basic/modules/basic-form/src/bean/behavior.formFieldLayout.tsx
346
+ ```
347
+
348
+ ### Provider defaults
349
+
350
+ In Cabloy Basic, the default provider config maps:
351
+
352
+ - `FormField` -> `basic-form:formField`
353
+ - `FormFieldLayout` -> `basic-form:formFieldLayout`
354
+ - `Input` -> `basic-input:formFieldInput`
355
+
356
+ That means the field runtime is provider-driven even before a page overrides anything.
357
+
358
+ ### Behavior merge
359
+
360
+ `_getFieldBehaviors()` merges:
361
+
362
+ - explicit field `behaviors`
363
+ - provider-level `FormField`
364
+ - provider-level `FormFieldLayout`
365
+
366
+ Then `RenderFormField.render()` passes rendering through:
367
+
368
+ - `$$beanBehaviorsHolder.render(...)`
369
+
370
+ In the Basic defaults:
371
+
372
+ - `BehaviorFormField` is a pass-through behavior
373
+ - `BehaviorFormFieldLayout` decides inline vs block layout and renders validation errors in the wrapper
374
+
375
+ A practical reading takeaway is:
376
+
377
+ - **field rendering is provider-driven and behavior-wrapped**
378
+ - **`a-form` does not hard-code one final Basic UI layout by itself**
379
+
380
+ ## 9. Render flow for form and field
381
+
382
+ The form render bean lives in:
383
+
384
+ ```text
385
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/render.tsx
386
+ ```
387
+
388
+ The field render bean lives in:
389
+
390
+ ```text
391
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/render.tsx
392
+ ```
393
+
394
+ ### Form render path
395
+
396
+ `RenderForm` does three important jobs:
397
+
398
+ - iterate schema properties when the form body is not manually overridden
399
+ - create structural slots like header/body/footer/wrapper
400
+ - wire native form submit to `submit()` unless `onFormSubmit` is supplied
401
+
402
+ That means automatic schema-driven rendering is not happening magically in the wrapper component. It is happening in the render bean.
403
+
404
+ ### Field render path
405
+
406
+ `RenderFormField` does two important jobs:
407
+
408
+ - pass the field render context through the behavior pipeline
409
+ - if no custom slot is given, call `$$form.zovaJsx.render(...)`
410
+
411
+ That means the final renderer is reached only after:
412
+
413
+ - field controller preparation
414
+ - props merge
415
+ - behavior wrapping
416
+
417
+ ## 10. Validation and server error round-trip
418
+
419
+ The main submit and error path lives in:
420
+
421
+ ```text
422
+ zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx
423
+ ```
424
+
425
+ The short version is:
426
+
427
+ - `submit()` delegates to `this.form.handleSubmit(...)`
428
+ - `_createForm()` wires `onSubmitInvalid` and `onSubmit`
429
+ - `onSubmit` calls user `onSubmitData`
430
+ - if the backend returns a 422 validation error, Zova normalizes it back into TanStack field/form error state
431
+ - other errors can flow to `onShowError`
432
+
433
+ ### Why 422 handling matters
434
+
435
+ Without this step, server validation would stay outside the form runtime and feel disconnected from field state.
436
+
437
+ Instead, `_handleError422(...)` parses the server payload and pushes normalized errors back into TanStack’s error maps.
438
+
439
+ That is one of the strongest reasons the module feels like a real form runtime rather than only a submit helper.
440
+
441
+ A practical reading takeaway is:
442
+
443
+ - **Zova does not treat server validation as an unrelated external concern**
444
+ - **it feeds server validation back into the same field/form state model**
445
+
446
+ ## 11. CRUD and filter integration path
447
+
448
+ Zova Form is also used as part of Cabloy Basic’s resource-driven page runtime.
449
+
450
+ The strongest source specimens are:
451
+
452
+ ```text
453
+ zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx
454
+ zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockForm/controller.tsx
455
+ zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockFilter/controller.tsx
456
+ zova/src/suite-vendor/a-zova/modules/a-form/src/lib/utils.ts
457
+ ```
458
+
459
+ ### Resource entry page path
460
+
461
+ `blockPageEntry` computes:
462
+
463
+ - `formMeta`
464
+ - `formProvider`
465
+ - `formSchema`
466
+ - `formData`
467
+
468
+ from the resource model.
469
+
470
+ Then `blockForm` passes those into `ZForm`.
471
+
472
+ So in resource CRUD pages, `ZForm` is not expected to discover business data by itself. The page/resource layer prepares the form inputs first.
473
+
474
+ ### Filter-form path
475
+
476
+ `blockFilter` shows the lighter filter branch:
477
+
478
+ - `formMeta = { formMode: 'edit' }`
479
+ - `schemaScene="filter"`
480
+ - inline field layout
481
+ - reset and submit reuse the same form runtime
482
+
483
+ This is a useful reminder that the same form module supports more than create/edit/view pages.
484
+
485
+ ## 12. Type contracts worth knowing
486
+
487
+ If you want the compact type surface, do not skip these files:
488
+
489
+ ```text
490
+ zova/src/suite-vendor/a-zova/modules/a-form/src/types/form.ts
491
+ zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts
492
+ ```
493
+
494
+ The most useful contracts to notice are:
495
+
496
+ - `TypeForm`
497
+ - `TypeFormField`
498
+ - `TypeFormOnSubmitData`
499
+ - `TypeFormOnSubmitInvalid`
500
+ - `TypeFormOnShowError`
501
+ - `IFormFieldRenderContext`
502
+ - `IJsxRenderContextFormField`
503
+ - `constFieldProps`
504
+
505
+ These types show where the runtime contracts are formalized for:
506
+
507
+ - submit payloads
508
+ - field render context
509
+ - form events
510
+ - field-level slot signatures
511
+
512
+ ## 13. Compact call-flow sketch
513
+
514
+ When in doubt, use this short call flow:
515
+
516
+ 1. `ZForm` wrapper enters the normal Zova controller path
517
+ 2. `ControllerForm.__init__()` creates the TanStack form bridge
518
+ 3. form controller computes provider/schema/Zod/properties
519
+ 4. `RenderForm` either auto-renders schema fields or uses custom slots
520
+ 5. each `ControllerFormField` creates a TanStack `useField(...)` binding
521
+ 6. field props merge from schema metadata, field props, layout, provider config, and readonly rules
522
+ 7. `RenderFormField` sends the field through the behavior pipeline
523
+ 8. final field rendering reaches `zovaJsx.render(...)` or a custom slot
524
+ 9. submit flows through TanStack, then Zova normalizes invalid-submit and server-side validation back into form state
525
+ 10. resource CRUD pages prepare `formMeta`, `formSchema`, `formData`, and `formProvider` before entering the same runtime
526
+
527
+ That is the shortest end-to-end explanation of how the module cooperates.
528
+
529
+ ## Final takeaway
530
+
531
+ Zova Form is not just TanStack Form plus JSX wrappers.
532
+
533
+ It moves form ownership into:
534
+
535
+ - Zova controller beans
536
+ - schema metadata
537
+ - provider-driven renderer lookup
538
+ - behavior-based field wrapping
539
+ - resource-driven CRUD integration
540
+
541
+ TanStack Form and Zod are still important underlying engines, but the business-facing runtime model is Zova-native.
542
+
543
+ ## Verification checklist
544
+
545
+ When documenting or changing this area, verify in this order:
546
+
547
+ 1. confirm the runtime claims against the current `a-form` source
548
+ 2. confirm the Basic provider defaults still match current `basic-adapter` and `basic-form` wiring
549
+ 3. confirm CRUD integration claims still match `blockPageEntry`, `blockForm`, and `blockFilter`
550
+ 4. build the docs site:
551
+
552
+ ```bash
553
+ npm run docs:build
554
+ ```
555
+
556
+ 5. verify the page is reachable from the frontend sidebar and related form docs