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,10 +1,14 @@
|
|
|
1
1
|
# Backend OpenAPI to Frontend SDK
|
|
2
2
|
|
|
3
|
-
This page
|
|
3
|
+
This page is the **forward chain** deep dive for Cabloy’s bidirectional contract loop.
|
|
4
4
|
|
|
5
5
|
## Why this path matters
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
In the bidirectional [Contract Loop Playbook](/fullstack/contract-loop-playbook), this page covers the **forward chain**:
|
|
8
|
+
|
|
9
|
+
> [!NOTE]
|
|
10
|
+
> The fullstack tutorial series intentionally uses a standalone `demo-student` sandbox so readers can experiment without colliding with the repo's real suite-owned `a-training/training-student` implementation.
|
|
11
|
+
> This guide focuses on the current repo implementation as its forward-chain specimen.
|
|
8
12
|
|
|
9
13
|
1. Vona emits backend API metadata through Swagger/OpenAPI
|
|
10
14
|
2. Zova consumes that metadata to generate frontend SDKs and schema-aware helpers
|
|
@@ -12,7 +16,7 @@ Cabloy’s fullstack productivity depends heavily on a contract loop:
|
|
|
12
16
|
|
|
13
17
|
This is one of the strongest AI-leverage paths in the repo because it reduces duplicated type work and keeps backend/frontend coordination closer to source truth.
|
|
14
18
|
|
|
15
|
-
## The
|
|
19
|
+
## The forward chain in practical terms
|
|
16
20
|
|
|
17
21
|
A useful split is:
|
|
18
22
|
|
|
@@ -20,7 +24,11 @@ A useful split is:
|
|
|
20
24
|
- fullstack docs define the bridge from emitted contract to generated SDK
|
|
21
25
|
- frontend docs define the consumption side of the generated contract
|
|
22
26
|
|
|
23
|
-
That means this page is the
|
|
27
|
+
That means this page is the forward-chain bridge page, not the backend authoring page and not the frontend usage page.
|
|
28
|
+
|
|
29
|
+
If the changed source is actually a frontend-owned resource that backend consumers later depend on, switch to the reverse-chain guide: [Frontend Metadata Back to Backend](/fullstack/frontend-metadata-to-backend).
|
|
30
|
+
|
|
31
|
+
If your real question is how one backend-owned row action becomes a visible frontend table action through metadata, page blocks, `tableCell` resources, and optionally generated API/model layers, continue with [Backend Metadata to Frontend Table Actions](/fullstack/backend-metadata-to-frontend-table-actions).
|
|
24
32
|
|
|
25
33
|
## Backend side: Vona emits the contract
|
|
26
34
|
|
|
@@ -37,6 +45,7 @@ For the deeper backend perspective, see:
|
|
|
37
45
|
- [OpenAPI Guide](/backend/openapi-guide)
|
|
38
46
|
- [Validation Guide](/backend/validation-guide)
|
|
39
47
|
- [DTO Infer and Generation](/backend/dto-infer-generation)
|
|
48
|
+
- [Backend Resource/Module Contract Chain](/backend/backend-resource-module-contract-chain)
|
|
40
49
|
|
|
41
50
|
## Frontend side: Zova consumes the contract
|
|
42
51
|
|
|
@@ -54,6 +63,65 @@ For the deeper frontend perspective, see:
|
|
|
54
63
|
- [API Schema Guide](/frontend/api-schema-guide)
|
|
55
64
|
- [SDK Guide](/frontend/sdk-guide)
|
|
56
65
|
|
|
66
|
+
## Source-to-consumer chain
|
|
67
|
+
|
|
68
|
+
If you want the shortest accurate mental model, use this forward chain:
|
|
69
|
+
|
|
70
|
+
1. backend controller signatures define request and response entry surfaces
|
|
71
|
+
2. backend DTO and entity fields shape named and shared contract structure
|
|
72
|
+
3. validation rules and `v` helpers refine the machine-readable contract
|
|
73
|
+
4. Vona emits OpenAPI output from those backend declarations
|
|
74
|
+
5. Zova OpenAPI config decides which generated contract slice belongs to which frontend module
|
|
75
|
+
6. frontend generation produces SDK and rest/schema-related contract output
|
|
76
|
+
7. frontend code consumes the generated contract through:
|
|
77
|
+
- generated SDK methods
|
|
78
|
+
- schema-driven helpers
|
|
79
|
+
- `$sdk` and `$apiSchema`-adjacent runtime surfaces
|
|
80
|
+
- thin model facades and existing resource-owner consumers when the API belongs to an existing resource
|
|
81
|
+
|
|
82
|
+
That means this bridge is not only “generate the SDK.”
|
|
83
|
+
|
|
84
|
+
It is the whole path that moves backend-authored truth into frontend-usable contract material.
|
|
85
|
+
|
|
86
|
+
## Which page owns which question?
|
|
87
|
+
|
|
88
|
+
Use this split to avoid reading the wrong layer too deeply.
|
|
89
|
+
|
|
90
|
+
### Backend authoring semantics
|
|
91
|
+
|
|
92
|
+
Use these when the real question is how the backend contract is authored:
|
|
93
|
+
|
|
94
|
+
- [Controller Guide](/backend/controller-guide)
|
|
95
|
+
- [DTO Guide](/backend/dto-guide)
|
|
96
|
+
- [DTO Infer and Generation](/backend/dto-infer-generation)
|
|
97
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
98
|
+
- [Backend Resource/Module Contract Chain](/backend/backend-resource-module-contract-chain)
|
|
99
|
+
|
|
100
|
+
### Forward-chain bridge and regeneration workflow
|
|
101
|
+
|
|
102
|
+
Use **this page** when the real question is:
|
|
103
|
+
|
|
104
|
+
- how backend-authored truth crosses the stack boundary
|
|
105
|
+
- which generation steps to run
|
|
106
|
+
- where module ownership and regeneration decisions belong
|
|
107
|
+
- how to keep frontend follow-up thin after regeneration
|
|
108
|
+
|
|
109
|
+
### Frontend generation and usage setup
|
|
110
|
+
|
|
111
|
+
Use these when the generated contract has already crossed the boundary and you are configuring or consuming it in Zova:
|
|
112
|
+
|
|
113
|
+
- [OpenAPI SDK Guide](/frontend/openapi-sdk-guide)
|
|
114
|
+
- [API Schema Guide](/frontend/api-schema-guide)
|
|
115
|
+
- [SDK Guide](/frontend/sdk-guide)
|
|
116
|
+
|
|
117
|
+
### Frontend runtime and deeper consumption internals
|
|
118
|
+
|
|
119
|
+
Use these when the real question is how generated contract material is consumed inside Zova runtime layers:
|
|
120
|
+
|
|
121
|
+
- [A-OpenAPI Under the Hood](/frontend/a-openapi-under-the-hood)
|
|
122
|
+
- [ModelResource Internals Deep Dive](/frontend/model-resource-internals-deep-dive)
|
|
123
|
+
- [Rest Resource Source Reading Map](/frontend/rest-resource-source-reading-map)
|
|
124
|
+
|
|
57
125
|
## Cabloy Basic workflow
|
|
58
126
|
|
|
59
127
|
In the current public monorepo, Basic-specific Zova flavors include:
|
|
@@ -64,29 +132,74 @@ In the current public monorepo, Basic-specific Zova flavors include:
|
|
|
64
132
|
Representative frontend-side contract-generation commands include:
|
|
65
133
|
|
|
66
134
|
```bash
|
|
67
|
-
npm run zova :openapi:config
|
|
68
|
-
npm run zova :openapi:generate
|
|
135
|
+
npm run zova :openapi:config training-student
|
|
136
|
+
npm run zova :openapi:generate training-student
|
|
69
137
|
cd zova && npm run build:rest:cabloyBasicAdmin
|
|
70
138
|
cd zova && npm run build:rest:cabloyBasicWeb
|
|
71
139
|
```
|
|
72
140
|
|
|
73
|
-
A practical
|
|
141
|
+
A practical forward-chain sequence is:
|
|
74
142
|
|
|
75
143
|
1. author or change the backend contract
|
|
76
144
|
2. emit or inspect backend OpenAPI output
|
|
77
|
-
3.
|
|
78
|
-
4.
|
|
79
|
-
5.
|
|
80
|
-
6.
|
|
145
|
+
3. if the frontend generator reads from a local Swagger endpoint, start the backend service first so the endpoint is reachable — in this repo, `npm run dev` is the normal path and exposes Swagger at `http://localhost:7102/swagger/json?version=V31`
|
|
146
|
+
4. configure frontend module ownership if needed
|
|
147
|
+
5. generate module-level OpenAPI SDK output
|
|
148
|
+
6. run the rest build for the active flavor when needed
|
|
149
|
+
7. consume the generated contract from frontend code instead of re-declaring it manually
|
|
150
|
+
8. keep frontend follow-up thin by wrapping generated consumers with semantic facades instead of re-declaring the contract
|
|
151
|
+
9. when the custom API still belongs to an existing resource, reuse the existing resource-owner instead of creating a competing cache owner
|
|
81
152
|
|
|
82
153
|
A practical responsibility split is:
|
|
83
154
|
|
|
84
155
|
- project-level OpenAPI config decides where the backend Swagger/OpenAPI source comes from
|
|
85
156
|
- module-level OpenAPI config decides which generated contract slice belongs to which frontend module
|
|
157
|
+
- module-level ownership should be declared explicitly with `operations.match` or `operations.ignore`
|
|
158
|
+
|
|
159
|
+
If both `operations.match` and `operations.ignore` are empty, frontend SDK generation should fail fast instead of generating a large unrelated contract surface for the module. That fail-fast behavior helps both developers and AI agents notice the missing ownership boundary immediately and repair the config before the wrong SDK slice is generated.
|
|
86
160
|
|
|
87
161
|
A practical regeneration rule is:
|
|
88
162
|
|
|
89
163
|
- if the backend contract changed, prefer regenerating the SDK/rest layer before hand-editing frontend request code
|
|
164
|
+
- if `npm run zova :openapi:generate ...` fails because the local Swagger source is unavailable, first start the backend service and confirm `http://localhost:7102/swagger/json?version=V31` is reachable before treating generation as broken
|
|
165
|
+
- if the generated consumer path is already correct, but frontend behavior still looks stale, stop patching generated files and diagnose consumer drift or local dependency drift instead
|
|
166
|
+
|
|
167
|
+
## `training-student` as a compact forward-chain specimen
|
|
168
|
+
|
|
169
|
+
A compact specimen helps make the bridge more concrete.
|
|
170
|
+
|
|
171
|
+
A practical `training-student` forward chain looks like this:
|
|
172
|
+
|
|
173
|
+
1. backend contract truth changes in places such as:
|
|
174
|
+
- `controller/student.ts`
|
|
175
|
+
- `entity/student.tsx`
|
|
176
|
+
- `dto/studentCreate.tsx`
|
|
177
|
+
- `dto/studentUpdate.tsx`
|
|
178
|
+
- `dto/studentView.tsx`
|
|
179
|
+
- `dto/studentSelectReq.tsx`
|
|
180
|
+
2. backend OpenAPI output changes because those controller/DTO/entity/validation surfaces changed
|
|
181
|
+
3. frontend OpenAPI generation refreshes the module-owned consumer slice
|
|
182
|
+
4. flavor-specific rest output is rebuilt when the workflow depends on generated rest output
|
|
183
|
+
5. frontend code consumes the generated result through module-owned SDK/schema surfaces, then keeps follow-up thin with semantic wrappers or existing resource owners
|
|
184
|
+
|
|
185
|
+
This is the main point of the forward chain:
|
|
186
|
+
|
|
187
|
+
> backend contract truth moves first, generated handoff moves second, frontend consumers stay thin and downstream.
|
|
188
|
+
|
|
189
|
+
## Thin frontend follow-up after generation
|
|
190
|
+
|
|
191
|
+
After the generated contract crosses the boundary, the best frontend move is usually **not** to recreate the contract by hand.
|
|
192
|
+
|
|
193
|
+
A practical split is:
|
|
194
|
+
|
|
195
|
+
- use generated SDKs when the module already follows the OpenAPI-generated API-service path
|
|
196
|
+
- use schema-driven helpers when the workflow is contract/schema oriented
|
|
197
|
+
- use thin model facades when the UI needs business semantics over generated APIs
|
|
198
|
+
- reuse the existing resource-owner when the custom API still belongs to the same resource
|
|
199
|
+
|
|
200
|
+
That last point matters especially for resource-driven pages.
|
|
201
|
+
|
|
202
|
+
If the endpoint still belongs to an existing business resource, prefer keeping `ModelResource` or the existing resource-owner story as the stable state owner rather than introducing a competing second owner.
|
|
90
203
|
|
|
91
204
|
## Cabloy Start workflow
|
|
92
205
|
|
|
@@ -103,6 +216,17 @@ Before documenting or automating this path for Start, confirm:
|
|
|
103
216
|
2. the Start repo’s `package.json`
|
|
104
217
|
3. the exact frontend flavor names and generated output paths
|
|
105
218
|
|
|
219
|
+
## Where to read next
|
|
220
|
+
|
|
221
|
+
- If your next question is still on the backend authoring side, continue with [OpenAPI Guide](/backend/openapi-guide), [Backend Contract Emission Specimen](/backend/backend-contract-emission-specimen), [Backend Contract Emission Output Inspection](/backend/backend-contract-emission-output-inspection), [DTO Guide](/backend/dto-guide), [DTO Infer and Generation](/backend/dto-infer-generation), and [Backend Resource/Module Contract Chain](/backend/backend-resource-module-contract-chain).
|
|
222
|
+
- If your next question is about frontend SDK setup and module ownership, continue with [OpenAPI SDK Guide](/frontend/openapi-sdk-guide).
|
|
223
|
+
- If your next question is about what generated contract consumption looks like in one practical frontend path, continue with [Generated Contract Consumption Specimen](/frontend/generated-contract-consumption-specimen), then choose [Generated Contract Consumption: List Branch](/frontend/generated-contract-consumption-list-branch) or [Generated Contract Consumption: Entry Branch](/frontend/generated-contract-consumption-entry-branch) as needed.
|
|
224
|
+
- If your next question becomes one mixed Student row-action thread spanning backend metadata, generated contract follow-up, and frontend action resources, continue with [Backend Metadata to Frontend Table Actions Source Reading Map](/fullstack/backend-metadata-to-frontend-table-actions-source-reading-map).
|
|
225
|
+
- If your next question is about schema-driven frontend consumption, continue with [API Schema Guide](/frontend/api-schema-guide).
|
|
226
|
+
- If your next question is about the lower-level frontend runtime under generated OpenAPI/schema usage, continue with [A-OpenAPI Under the Hood](/frontend/a-openapi-under-the-hood).
|
|
227
|
+
- If your next question is about resource-owner or model-level consumption after regeneration, continue with [ModelResource Internals Deep Dive](/frontend/model-resource-internals-deep-dive) and [Rest Resource Source Reading Map](/frontend/rest-resource-source-reading-map).
|
|
228
|
+
- If the problem is actually about deciding which direction the contract loop is moving, return to [Contract Loop Playbook](/fullstack/contract-loop-playbook).
|
|
229
|
+
|
|
106
230
|
## Implementation checks for backend-to-frontend contract changes
|
|
107
231
|
|
|
108
232
|
When changing a backend API contract, ask:
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# Suites and Modules
|
|
2
|
+
|
|
3
|
+
This guide explains how to think about suites and modules in the current Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
Use it when you need to answer these questions clearly:
|
|
6
|
+
|
|
7
|
+
1. what a suite is
|
|
8
|
+
2. when to create a suite instead of only a module
|
|
9
|
+
3. how suite naming works
|
|
10
|
+
4. where suite-owned modules should live
|
|
11
|
+
5. which CLI workflows should create the structure
|
|
12
|
+
|
|
13
|
+
## Why suites exist
|
|
14
|
+
|
|
15
|
+
As a project evolves, business capabilities do not usually grow as one isolated feature at a time.
|
|
16
|
+
|
|
17
|
+
In real business scenarios, one business domain often requires multiple related modules that evolve together. A training domain, for example, may later grow into modules for:
|
|
18
|
+
|
|
19
|
+
- training-student
|
|
20
|
+
- training-course
|
|
21
|
+
- training-record
|
|
22
|
+
- training-attendance
|
|
23
|
+
- training-certificate
|
|
24
|
+
|
|
25
|
+
Because of that, the default architectural decision should usually start from a **suite** rather than from an isolated standalone module.
|
|
26
|
+
|
|
27
|
+
A suite is the business-level composition boundary for a domain. A module is the feature-level implementation boundary inside that domain.
|
|
28
|
+
|
|
29
|
+
A practical mental model is:
|
|
30
|
+
|
|
31
|
+
- use a **suite** for the business domain
|
|
32
|
+
- use **modules** for the concrete capabilities inside that domain
|
|
33
|
+
|
|
34
|
+
## Suite and module roles
|
|
35
|
+
|
|
36
|
+
The two units serve different jobs.
|
|
37
|
+
|
|
38
|
+
### Suite
|
|
39
|
+
|
|
40
|
+
A suite groups related modules into one larger business scenario or architectural area.
|
|
41
|
+
|
|
42
|
+
That grouping matters because it gives the domain:
|
|
43
|
+
|
|
44
|
+
- a stable ownership boundary
|
|
45
|
+
- a clear place for future module growth
|
|
46
|
+
- consistent source-tree organization
|
|
47
|
+
- a shared naming anchor across backend and frontend
|
|
48
|
+
|
|
49
|
+
### Module
|
|
50
|
+
|
|
51
|
+
A module is the concrete implementation unit for one feature area.
|
|
52
|
+
|
|
53
|
+
That usually means a module owns the code for things such as:
|
|
54
|
+
|
|
55
|
+
- backend controllers, services, entities, DTOs, and models
|
|
56
|
+
- frontend pages, components, APIs, models, and metadata
|
|
57
|
+
- module-local config, locale, and other scoped resources
|
|
58
|
+
|
|
59
|
+
A useful rule is:
|
|
60
|
+
|
|
61
|
+
- the **suite** answers "which business domain does this belong to?"
|
|
62
|
+
- the **module** answers "which capability inside that domain owns this work?"
|
|
63
|
+
|
|
64
|
+
## Recommended decision path
|
|
65
|
+
|
|
66
|
+
In the current Cabloy monorepo, the preferred decision path is:
|
|
67
|
+
|
|
68
|
+
1. identify the business domain
|
|
69
|
+
2. create a suite for that domain
|
|
70
|
+
3. create one or more modules inside the suite
|
|
71
|
+
4. continue feature growth inside those suite-owned modules
|
|
72
|
+
|
|
73
|
+
In other words, for real business work, **suite-first** is usually the best choice.
|
|
74
|
+
|
|
75
|
+
### When suite-first is the default
|
|
76
|
+
|
|
77
|
+
Create a suite first when:
|
|
78
|
+
|
|
79
|
+
- the work belongs to a real business domain
|
|
80
|
+
- the domain is expected to grow beyond one small feature
|
|
81
|
+
- backend and frontend will both evolve around the same domain
|
|
82
|
+
- you want to avoid later structural migration from standalone modules into a domain boundary
|
|
83
|
+
|
|
84
|
+
In practice, this is the normal path for long-lived product work.
|
|
85
|
+
|
|
86
|
+
### When a standalone module is still acceptable
|
|
87
|
+
|
|
88
|
+
A standalone module can still be acceptable for cases such as:
|
|
89
|
+
|
|
90
|
+
- very small experiments
|
|
91
|
+
- disposable demos
|
|
92
|
+
- isolated utilities that are intentionally not the start of a larger domain
|
|
93
|
+
- short tutorials where introducing a domain suite would add noise
|
|
94
|
+
|
|
95
|
+
But this should be the exception, not the default path for real business architecture.
|
|
96
|
+
|
|
97
|
+
## Naming
|
|
98
|
+
|
|
99
|
+
Suite naming follows the same high-level model on both sides:
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
Vona: FullName = vona-suite-{providerId}-{suiteName}
|
|
103
|
+
Zova: FullName = zova-suite-{providerId}-{suiteName}
|
|
104
|
+
ShortName = {providerId}-{suiteName}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Important suiteName rule
|
|
108
|
+
|
|
109
|
+
In this repository, `suiteName` must follow this rule:
|
|
110
|
+
|
|
111
|
+
- `suiteName` must use lowercase English letters only
|
|
112
|
+
- `suiteName` must not contain another `-`
|
|
113
|
+
|
|
114
|
+
This rule matters because the `-` already separates `{providerId}` and `{suiteName}` in the short name.
|
|
115
|
+
|
|
116
|
+
So the supported shape is:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
{providerId}-{suiteName}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
not:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
{providerId}-{part1-part2}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Examples
|
|
129
|
+
|
|
130
|
+
Representative examples from the current repo include:
|
|
131
|
+
|
|
132
|
+
- `a-home`
|
|
133
|
+
- `a-demo`
|
|
134
|
+
- `cabloy-basic`
|
|
135
|
+
|
|
136
|
+
These can be read as:
|
|
137
|
+
|
|
138
|
+
- `a-home` -> providerId: `a`, suiteName: `home`
|
|
139
|
+
- `a-demo` -> providerId: `a`, suiteName: `demo`
|
|
140
|
+
- `cabloy-basic` -> providerId: `cabloy`, suiteName: `basic`
|
|
141
|
+
|
|
142
|
+
For a training-oriented suite, the valid short name is:
|
|
143
|
+
|
|
144
|
+
- `a-training`
|
|
145
|
+
|
|
146
|
+
where:
|
|
147
|
+
|
|
148
|
+
- providerId: `a`
|
|
149
|
+
- suiteName: `training`
|
|
150
|
+
|
|
151
|
+
A practical rule is:
|
|
152
|
+
|
|
153
|
+
- keep `suiteName` simple, lowercase, and single-segment
|
|
154
|
+
- do not add another `-` inside `suiteName`
|
|
155
|
+
- if you need more semantic detail, express it through module names inside the suite rather than by making the suite name longer
|
|
156
|
+
|
|
157
|
+
## Supported directory pattern
|
|
158
|
+
|
|
159
|
+
To keep the code style consistent and reduce cognitive overhead, this repository supports only one suite layout for normal authoring work:
|
|
160
|
+
|
|
161
|
+
- **suite-contained modules**
|
|
162
|
+
|
|
163
|
+
That means when a suite exists, its modules belong under that suite.
|
|
164
|
+
|
|
165
|
+
### Backend pattern
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
vona/src/suite/<suite>/modules/<module>/
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Frontend pattern
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
zova/src/suite/<suite>/modules/<module>/
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Example
|
|
178
|
+
|
|
179
|
+
```text
|
|
180
|
+
vona/src/suite/a-training/
|
|
181
|
+
├── modules/
|
|
182
|
+
│ ├── training-student/
|
|
183
|
+
│ ├── training-course/
|
|
184
|
+
│ └── training-record/
|
|
185
|
+
└── package.json
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
zova/src/suite/a-training/
|
|
190
|
+
├── modules/
|
|
191
|
+
│ ├── training-student/
|
|
192
|
+
│ ├── training-course/
|
|
193
|
+
│ └── training-record/
|
|
194
|
+
└── package.json
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Unsupported pattern for normal project authoring
|
|
198
|
+
|
|
199
|
+
For consistency, do not treat a suite as a loose composition package that only depends on standalone modules located elsewhere.
|
|
200
|
+
|
|
201
|
+
In other words, do not use a suite as a separate conceptual wrapper while keeping its real modules outside the suite tree.
|
|
202
|
+
|
|
203
|
+
Use the suite as the real ownership boundary, and keep the suite-owned modules physically inside:
|
|
204
|
+
|
|
205
|
+
- `vona/src/suite/<suite>/modules/`
|
|
206
|
+
- `zova/src/suite/<suite>/modules/`
|
|
207
|
+
|
|
208
|
+
This keeps the source tree easier to read and avoids extra mental branching about whether a module is only logically related to a suite or actually owned by it.
|
|
209
|
+
|
|
210
|
+
## CLI-first workflow
|
|
211
|
+
|
|
212
|
+
Do not scaffold suite/module structure manually when the CLI already supports it.
|
|
213
|
+
|
|
214
|
+
Use the framework CLI first, then make only the minimal follow-up edits that the task still needs.
|
|
215
|
+
|
|
216
|
+
### Create a backend suite
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npm run vona :create:suite suiteName
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Create a frontend suite
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npm run zova :create:suite suiteName
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Create a backend module inside a suite
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm run vona :create:module moduleName -- --suite=suiteName
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Create a frontend module inside a suite
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npm run zova :create:module moduleName -- --suite=suiteName
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
A practical fullstack rule is:
|
|
241
|
+
|
|
242
|
+
- use `npm run vona` to create the backend side of the domain
|
|
243
|
+
- use `npm run zova` to create the frontend side of the domain
|
|
244
|
+
- for a real business domain, create the suite first on both sides, then create the suite-owned modules
|
|
245
|
+
|
|
246
|
+
## Recommended workflow for real business domains
|
|
247
|
+
|
|
248
|
+
A practical suite-first workflow is:
|
|
249
|
+
|
|
250
|
+
1. decide the domain boundary
|
|
251
|
+
2. choose a valid suite short name
|
|
252
|
+
3. create the suite in Vona
|
|
253
|
+
4. create the suite in Zova
|
|
254
|
+
5. create the first backend and frontend modules inside that suite
|
|
255
|
+
6. continue all later domain growth inside the same suite
|
|
256
|
+
|
|
257
|
+
For example, for a training domain:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
npm run vona :create:suite a-training
|
|
261
|
+
npm run zova :create:suite a-training
|
|
262
|
+
|
|
263
|
+
npm run vona :create:module training-student -- --suite=a-training
|
|
264
|
+
npm run zova :create:module training-student -- --suite=a-training
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Later domain growth can continue with modules such as:
|
|
268
|
+
|
|
269
|
+
- training-course
|
|
270
|
+
- training-record
|
|
271
|
+
- training-attendance
|
|
272
|
+
|
|
273
|
+
This keeps the domain boundary stable while the capabilities inside it expand.
|
|
274
|
+
|
|
275
|
+
## How to choose between a suite and only a module
|
|
276
|
+
|
|
277
|
+
Use this rule:
|
|
278
|
+
|
|
279
|
+
### Choose a suite first when
|
|
280
|
+
|
|
281
|
+
- the work belongs to a real domain
|
|
282
|
+
- more related modules are likely
|
|
283
|
+
- the feature will grow across backend and frontend
|
|
284
|
+
- you want the structure to remain stable as the domain expands
|
|
285
|
+
|
|
286
|
+
### Choose only a standalone module when
|
|
287
|
+
|
|
288
|
+
- the work is intentionally isolated
|
|
289
|
+
- the scope is very small
|
|
290
|
+
- the code is exploratory or disposable
|
|
291
|
+
- creating a domain suite would add more ceremony than value
|
|
292
|
+
|
|
293
|
+
For most real business scenarios, the correct answer is to create the suite first.
|
|
294
|
+
|
|
295
|
+
## Relationship to repo structure
|
|
296
|
+
|
|
297
|
+
This guide should be read together with:
|
|
298
|
+
|
|
299
|
+
- [Package Map](/reference/package-map)
|
|
300
|
+
- [Backend Directory Structure](/reference/backend-directory-structure)
|
|
301
|
+
- [Frontend Directory Structure](/reference/frontend-directory-structure)
|
|
302
|
+
- [Backend CLI](/backend/cli)
|
|
303
|
+
- [Frontend CLI](/frontend/cli)
|
|
304
|
+
- [Fullstack CLI](/fullstack/cli)
|
|
305
|
+
|
|
306
|
+
A practical split is:
|
|
307
|
+
|
|
308
|
+
- this page explains the decision model for suites and modules
|
|
309
|
+
- the reference pages explain where those units live in the repo
|
|
310
|
+
- the CLI pages explain how to generate them correctly
|
|
311
|
+
|
|
312
|
+
## Verification
|
|
313
|
+
|
|
314
|
+
After creating or restructuring suites and modules, verify with the narrowest useful checks first.
|
|
315
|
+
|
|
316
|
+
Typical checks include:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
npm run vona :
|
|
320
|
+
npm run zova :
|
|
321
|
+
|
|
322
|
+
npm run deps:vona
|
|
323
|
+
npm run deps:zova
|
|
324
|
+
|
|
325
|
+
npm run tsc
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
If the change affects broader cross-stack output, also use the relevant build flow from the repo root.
|
|
329
|
+
|
|
330
|
+
The key rule is:
|
|
331
|
+
|
|
332
|
+
- verify that the suite and module were created in the intended structural location
|
|
333
|
+
- verify that later commands and dependency refresh flows still recognize that structure
|
|
@@ -52,6 +52,8 @@ Usage notes:
|
|
|
52
52
|
- use `npm run vona :create:module` for the backend module boundary
|
|
53
53
|
- use `npm run zova :create:module` for the frontend module boundary
|
|
54
54
|
- use an empty `--suite=` when you want an independent module rather than a suite-owned module
|
|
55
|
+
- this tutorial intentionally uses a standalone `demo-student` sandbox so readers can experiment without colliding with the repo's real `a-training/training-student` example
|
|
56
|
+
- for the normal suite-first domain decision path, see [Suites and Modules](/fullstack/suites-and-modules)
|
|
55
57
|
- rerun `npm run dev` after module creation so the local workflow picks up the new modules cleanly
|
|
56
58
|
|
|
57
59
|
## Generated or affected files
|
|
@@ -82,6 +84,7 @@ At this stage, the key idea is ownership, not business logic yet.
|
|
|
82
84
|
- the backend module root is where the Student resource, entity, DTOs, controller, tests, and backend metadata will live later
|
|
83
85
|
- the frontend module root is where generated OpenAPI output, model helpers, render resources, and frontend metadata will live later
|
|
84
86
|
- the frontend `.metadata` entrypoint is part of how the module exposes its local registration surface
|
|
87
|
+
- because this tutorial path is intentionally standalone, you can compare its generated result against the repo's real suite-owned `a-training/training-student` implementation without overwriting it
|
|
85
88
|
|
|
86
89
|
A good beginner rule is: do not rush into editing business logic until you can explain which module roots were created and why they will own the next tutorials.
|
|
87
90
|
|
|
@@ -27,6 +27,10 @@ Once the module exists, this is the next useful step because the prompt can driv
|
|
|
27
27
|
|
|
28
28
|
That keeps the conversation focused on the generated business thread rather than on repetitive scaffolding details.
|
|
29
29
|
|
|
30
|
+
> [!NOTE]
|
|
31
|
+
> This tutorial continues the standalone `demo-student` sandbox from Tutorial 1.
|
|
32
|
+
> That sandbox is intentional: it lets you run the full tutorial flow without colliding with the repo's real suite-owned `a-training/training-student` implementation.
|
|
33
|
+
|
|
30
34
|
## CLI commands to inspect/use
|
|
31
35
|
|
|
32
36
|
Inspect the CRUD family first:
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
<Badge type="info" text="Basic" />
|
|
4
4
|
|
|
5
|
-
In this tutorial, one prompt lets AI show the reverse
|
|
5
|
+
In this tutorial, one prompt lets AI show the **reverse chain** of Cabloy’s fullstack contract loop: backend field metadata can reference frontend render resources.
|
|
6
6
|
|
|
7
7
|
You start with the simplest path first: reuse the existing built-in rendering resources for the `level` field.
|
|
8
8
|
|
|
9
|
+
> [!NOTE]
|
|
10
|
+
> This tutorial still uses the standalone `demo-student` sandbox introduced in Tutorial 1.
|
|
11
|
+
> Keep that sandbox separate from the repo's real suite-owned `a-training/training-student` example so you can experiment and compare the two paths side by side.
|
|
12
|
+
|
|
9
13
|
## Goal
|
|
10
14
|
|
|
11
15
|
By the end of this tutorial, you will understand:
|
|
@@ -19,7 +23,7 @@ By the end of this tutorial, you will understand:
|
|
|
19
23
|
Give AI a prompt like this:
|
|
20
24
|
|
|
21
25
|
```text
|
|
22
|
-
Please add a level field to the Student resource. It should be a number field with these enum values:
|
|
26
|
+
Please add a level field to the Student resource. It should be a required number field with these enum values:
|
|
23
27
|
|
|
24
28
|
- 1: beginner
|
|
25
29
|
- 2: intermediate
|