cabloy 5.1.72 → 5.1.74
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/skills/cabloy-backend-scaffold/SKILL.md +3 -1
- package/.claude/skills/cabloy-master-detail/SKILL.md +198 -0
- package/.claude/skills/cabloy-workflow/SKILL.md +3 -1
- package/.gitignore +0 -2
- package/CHANGELOG.md +38 -0
- package/cabloy-docs/.vitepress/config.mjs +5 -0
- package/cabloy-docs/backend/dto-guide.md +1 -1
- package/cabloy-docs/backend/dto-infer-generation.md +38 -0
- package/cabloy-docs/backend/master-detail-source-reading-map.md +260 -0
- package/cabloy-docs/backend/master-detail-workflow.md +174 -23
- package/cabloy-docs/backend/relations-guide.md +4 -0
- package/lint-staged.config.mjs +0 -1
- package/oxfmt.config.ts +0 -1
- package/oxlint.config.ts +0 -1
- package/package.json +2 -2
- package/scripts/init.ts +29 -2
- package/vona/oxfmt.config.ts +0 -1
- package/vona/oxlint.config.ts +0 -1
- package/vona/packages-cli/cabloy-cli/package.json +1 -1
- package/vona/packages-cli/cabloy-cli/src/lib/local.common.ts +3 -3
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.build.ts +2 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.buildModule.ts +2 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +1 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.deps.ts +10 -23
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.metadata.ts +1 -1
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/patches/zova-core@5.1.61.patch +57 -0
- package/vona/pnpm-lock.yaml +278 -332
- package/vona/pnpm-workspace.yaml +4 -0
- package/vona/src/suite/a-training/modules/training-record/src/dto/recordCreate.tsx +1 -1
- package/vona/src/suite/a-training/modules/training-record/src/dto/recordUpdate.tsx +1 -1
- package/vona/src/suite/a-training/modules/training-record/src/entity/record.tsx +2 -52
- package/vona/src/suite/a-training/modules/training-record/src/index.ts +1 -0
- package/vona/src/suite/a-training/modules/training-record/src/lib/index.ts +2 -0
- package/vona/src/suite/a-training/modules/training-record/src/lib/onEffectForAverageScore.tsx +29 -0
- package/vona/src/suite/a-training/modules/training-record/src/lib/onEffectForTrainingRecordSubjects.tsx +26 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx +2 -1
- package/vona/src/suite/cabloy-basic/modules/basic-siteadmin/package.json +1 -2
- package/vona/src/suite/cabloy-basic/modules/basic-siteweb/package.json +1 -2
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +2 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/env/.env.cabloyBasicAdmin +1 -1
- package/zova/env/.env.cabloyBasicWeb +1 -1
- package/zova/oxfmt.config.ts +0 -1
- package/zova/oxlint.config.ts +0 -1
- package/zova/packages-cli/cli/package.json +3 -3
- package/zova/packages-cli/cli-set-front/package.json +2 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +47 -47
- package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.tabs.tsx +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cabloy-backend-scaffold
|
|
3
|
-
description:
|
|
3
|
+
description: This skill should be used when the user needs the Vona backend scaffold/extend path in this Cabloy repo, especially to choose the right `npm run vona` generator or CRUD command and the required backend follow-up after generation. Trigger most strongly on backend requests involving modules, beans, controllers, services, models, entities, DTOs, CRUD, meta.version, field indexes, validation, or backend tests. Do not use it for frontend-first Zova work, stale generated consumer diagnosis, workflow-routing questions, or master-detail / nested-detail aggregation workflows that belong in `cabloy-master-detail`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Cabloy Backend Scaffold
|
|
@@ -40,6 +40,8 @@ If the user is still deciding a new business-domain boundary or suite/module nam
|
|
|
40
40
|
|
|
41
41
|
If the task is really a broad cross-stack workflow, consider whether the root `cabloy-workflow` skill is the better primary router.
|
|
42
42
|
|
|
43
|
+
If the request is not ordinary standalone backend scaffolding but a parent-owned detail aggregation workflow, such as master-detail, nested-detail, aggregate-only detail, standalone-capable detail, or `:tools:masterDetail`, prefer the dedicated `cabloy-master-detail` skill first.
|
|
44
|
+
|
|
43
45
|
## Step 2: Start from Vona CLI and repo entrypoints
|
|
44
46
|
|
|
45
47
|
Inspect these surfaces before proposing implementation:
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cabloy-master-detail
|
|
3
|
+
description: This skill should be used when the main Cabloy task is parent-owned detail aggregation: master-detail or nested-detail backend scaffolding, choosing aggregate-owned vs standalone-capable detail mode, running `:tools:masterDetail`, or preserving nested detail DTO naming and placement rules. Prefer it when the core problem is detail aggregation rather than ordinary standalone CRUD scaffolding or cross-stack contract drift.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cabloy Master-Detail
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants to add, extend, analyze, or preserve a Cabloy master-detail or nested-detail backend workflow.
|
|
9
|
+
|
|
10
|
+
Read the public [Master-Detail Workflow](../../../cabloy-docs/backend/master-detail-workflow.md) for the canonical operational explanation and [Master-Detail Source Reading Map](../../../cabloy-docs/backend/master-detail-source-reading-map.md) for the current source evidence. This skill is the thinner orchestration layer: it should classify the detail shape, choose the generator-first path, preserve the naming and placement invariants, and finish with the right verification path.
|
|
11
|
+
|
|
12
|
+
## Goals
|
|
13
|
+
|
|
14
|
+
1. detect whether the active repository is Cabloy Basic or Cabloy Start
|
|
15
|
+
2. classify the request as first-level master-detail, recursive nested-detail, aggregate-only detail, standalone-capable detail, or docs/source-reading only
|
|
16
|
+
3. prefer `npm run vona :tools:masterDetail` over manual scaffolding when the task is really generator-oriented
|
|
17
|
+
4. preserve nested detail DTO naming and placement invariants
|
|
18
|
+
5. keep aggregate vs standalone detail mode explicit
|
|
19
|
+
6. finish with verification guidance that matches the actual detail shape
|
|
20
|
+
|
|
21
|
+
## Step 1: Detect repo, edition, and task shape
|
|
22
|
+
|
|
23
|
+
Check the repository root for these marker files:
|
|
24
|
+
|
|
25
|
+
- `__CABLOY_BASIC__`
|
|
26
|
+
- `__CABLOY_START__`
|
|
27
|
+
|
|
28
|
+
Interpretation:
|
|
29
|
+
|
|
30
|
+
- `__CABLOY_BASIC__` present → this is Cabloy Basic
|
|
31
|
+
- `__CABLOY_START__` present → this is Cabloy Start
|
|
32
|
+
- neither present → inspect nearby scripts and ask before making edition-specific assumptions
|
|
33
|
+
|
|
34
|
+
Then classify the request into one of these entry shapes.
|
|
35
|
+
|
|
36
|
+
### Shape A: first-level master-detail
|
|
37
|
+
|
|
38
|
+
Use this shape when the user wants a master resource to own one detail collection, such as:
|
|
39
|
+
|
|
40
|
+
- `student -> trainingRecords`
|
|
41
|
+
- parent resource plus one nested child collection
|
|
42
|
+
|
|
43
|
+
### Shape B: recursive nested-detail
|
|
44
|
+
|
|
45
|
+
Use this shape when a detail resource itself becomes the immediate parent of another detail collection, such as:
|
|
46
|
+
|
|
47
|
+
- `student -> trainingRecords -> trainingRecordSubjects`
|
|
48
|
+
|
|
49
|
+
Treat this as the same master-detail pattern repeated one level lower, not as an unrelated mechanism.
|
|
50
|
+
|
|
51
|
+
### Shape C: aggregate-only detail
|
|
52
|
+
|
|
53
|
+
Use this shape when the detail should remain owned by the aggregate and should not keep a standalone controller/service/DTO resource surface in source.
|
|
54
|
+
|
|
55
|
+
### Shape D: standalone-capable detail
|
|
56
|
+
|
|
57
|
+
Use this shape when the detail must still participate in nested editing but also keep its own ordinary standalone resource surface.
|
|
58
|
+
|
|
59
|
+
### Shape E: docs or source-reading only
|
|
60
|
+
|
|
61
|
+
Use this shape when the user is not changing the scaffold but wants explanation, diagnosis, or source-reading guidance. In that case, anchor the answer in the two public master-detail docs instead of pretending the next step is generation.
|
|
62
|
+
|
|
63
|
+
## Step 2: Start from shared entrypoints and the generator
|
|
64
|
+
|
|
65
|
+
Inspect these surfaces before proposing implementation:
|
|
66
|
+
|
|
67
|
+
- the repository `package.json`
|
|
68
|
+
- `npm run vona`
|
|
69
|
+
- `vona/packages-cli/cli-set-api/src/lib/command/tools.masterDetail.ts`
|
|
70
|
+
- `vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts`
|
|
71
|
+
- the two public master-detail docs
|
|
72
|
+
|
|
73
|
+
If the task is scaffold or generator oriented, prefer the generator path first.
|
|
74
|
+
|
|
75
|
+
Typical command shape:
|
|
76
|
+
|
|
77
|
+
- `npm run vona :tools:masterDetail resourceName -- [--module=] [--detailModule=] [--detailResourceName=] [--relationName=] [--fk=] [--detailMode=aggregate|standalone]`
|
|
78
|
+
|
|
79
|
+
Important rule:
|
|
80
|
+
|
|
81
|
+
- use canonical module relative names such as `training-student` and `training-record`
|
|
82
|
+
- do not substitute package names for module names
|
|
83
|
+
|
|
84
|
+
## Step 3: Preserve the current nested detail invariants
|
|
85
|
+
|
|
86
|
+
### Nested detail DTO naming
|
|
87
|
+
|
|
88
|
+
Keep nested detail DTOs on the `detail*` prefix so their role remains explicit.
|
|
89
|
+
|
|
90
|
+
Representative examples:
|
|
91
|
+
|
|
92
|
+
- `detailRecordBase`
|
|
93
|
+
- `detailRecordMutate`
|
|
94
|
+
- `detailRecordResItem`
|
|
95
|
+
- `detailRecordView`
|
|
96
|
+
- `detailRecordSubjectBase`
|
|
97
|
+
- `detailRecordSubjectMutate`
|
|
98
|
+
- `detailRecordSubjectResItem`
|
|
99
|
+
- `detailRecordSubjectView`
|
|
100
|
+
|
|
101
|
+
Do not rewrite these into ordinary child-resource CRUD names when the DTOs are really describing nested detail editing under a parent.
|
|
102
|
+
|
|
103
|
+
### Nested detail DTO placement
|
|
104
|
+
|
|
105
|
+
Keep nested detail DTOs beside the immediate parent DTOs that consume them.
|
|
106
|
+
|
|
107
|
+
That means:
|
|
108
|
+
|
|
109
|
+
- first-level detail DTOs live with the master DTOs
|
|
110
|
+
- second-level detail DTOs live with the first-level parent DTOs
|
|
111
|
+
- deeper levels repeat the same immediate-parent rule recursively
|
|
112
|
+
|
|
113
|
+
Do not move nested detail DTOs into the child module just because the child may also have its own standalone resource surface.
|
|
114
|
+
|
|
115
|
+
## Step 4: Distinguish aggregate vs standalone mode deliberately
|
|
116
|
+
|
|
117
|
+
### Aggregate mode
|
|
118
|
+
|
|
119
|
+
Use `--detailMode=aggregate` when the detail should remain aggregate-owned only.
|
|
120
|
+
|
|
121
|
+
Preserve the source-backed rule:
|
|
122
|
+
|
|
123
|
+
- aggregate mode removes or disallows standalone controller/service/DTO resource surfaces as appropriate
|
|
124
|
+
|
|
125
|
+
### Standalone mode
|
|
126
|
+
|
|
127
|
+
Use `--detailMode=standalone` when the detail must also keep its own ordinary resource surface.
|
|
128
|
+
|
|
129
|
+
Preserve the source-backed rule:
|
|
130
|
+
|
|
131
|
+
- standalone mode still uses nested `detail*` DTOs in the parent-owned editing flow
|
|
132
|
+
- standalone child CRUD in the child module can keep its ordinary resource DTO names
|
|
133
|
+
|
|
134
|
+
## Step 5: Inspect the specimen modules before manual follow-up edits
|
|
135
|
+
|
|
136
|
+
Use the current specimen chain as the strongest current reference path:
|
|
137
|
+
|
|
138
|
+
- `training-student`
|
|
139
|
+
- `training-record`
|
|
140
|
+
- `training-recordsubject`
|
|
141
|
+
|
|
142
|
+
Especially inspect:
|
|
143
|
+
|
|
144
|
+
- parent model relation wiring
|
|
145
|
+
- parent service include lifecycle
|
|
146
|
+
- parent create/update/view DTOs
|
|
147
|
+
- sibling nested detail DTO files
|
|
148
|
+
- child entity FK support
|
|
149
|
+
- generated `.metadata/index.ts` exports
|
|
150
|
+
|
|
151
|
+
Important rule:
|
|
152
|
+
|
|
153
|
+
- do not start from hand-patching DTO placement or relation semantics until the generator path and specimen shape have been checked first
|
|
154
|
+
|
|
155
|
+
## Step 6: Keep fullstack boundaries explicit
|
|
156
|
+
|
|
157
|
+
This skill is primarily for backend detail aggregation.
|
|
158
|
+
|
|
159
|
+
If the task later becomes a backend/frontend contract synchronization or stale generated consumer problem, the root `cabloy-contract-loop` skill may become the better primary workflow.
|
|
160
|
+
|
|
161
|
+
Use this skill first when the core problem is still:
|
|
162
|
+
|
|
163
|
+
- parent-owned detail aggregation
|
|
164
|
+
- nested detail recursion
|
|
165
|
+
- generator choice
|
|
166
|
+
- aggregate vs standalone detail mode
|
|
167
|
+
- nested detail DTO naming or placement in a scaffolding context
|
|
168
|
+
|
|
169
|
+
## Step 7: Verification guidance
|
|
170
|
+
|
|
171
|
+
Always finish with verification that matches the detail shape.
|
|
172
|
+
|
|
173
|
+
Typical checks include:
|
|
174
|
+
|
|
175
|
+
- confirm the parent model contains the expected `hasMany` relation
|
|
176
|
+
- confirm parent service create/view/update/delete includes the nested detail relation
|
|
177
|
+
- confirm parent create/update/view DTOs consume the nested detail DTOs
|
|
178
|
+
- confirm nested detail DTO names still follow the `detail*` pattern
|
|
179
|
+
- confirm nested detail DTOs are placed with the immediate parent DTOs that consume them
|
|
180
|
+
- confirm the recursive immediate-parent rule still holds for deeper nesting
|
|
181
|
+
- confirm the detail entity contains the FK field when expected
|
|
182
|
+
- confirm detail schema/index support is present
|
|
183
|
+
- confirm both modules’ `.metadata/index.ts` outputs reflect the expected nested detail DTOs
|
|
184
|
+
- if standalone mode applies, confirm the detail module still exposes its standalone resource surface
|
|
185
|
+
- if this workflow changes `meta.version.ts`, run `npm run test` so the test database is reinitialized and schema/data consistency issues surface early
|
|
186
|
+
|
|
187
|
+
## Response pattern
|
|
188
|
+
|
|
189
|
+
When helpful, structure the response around these points:
|
|
190
|
+
|
|
191
|
+
1. detected edition
|
|
192
|
+
2. detected detail shape
|
|
193
|
+
3. recommended generator-first path
|
|
194
|
+
4. aggregate vs standalone decision
|
|
195
|
+
5. nested DTO naming and placement reminders
|
|
196
|
+
6. verification steps
|
|
197
|
+
|
|
198
|
+
Keep the response practical. The value of this skill is to route master-detail requests into the correct generator-first workflow while preserving the recursive ownership rules encoded by the current source.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cabloy-workflow
|
|
3
|
-
description:
|
|
3
|
+
description: This skill should be used when the main Cabloy problem is workflow routing before implementation: deciding between Vona backend scaffolding, Zova frontend scaffolding, contract-loop work, or docs/AI-enablement homes such as cabloy-docs, .docs-internal, CLAUDE.md, commands, or skills, including cases where Cabloy Basic vs Cabloy Start assumptions affect that routing. Trigger on requests to route, classify, choose a workflow, choose an edition-specific path, or decide where Cabloy guidance should live. Do not use it once the task is already clearly a backend scaffold, frontend scaffold, or contract-loop job.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Cabloy Workflow
|
|
@@ -176,6 +176,8 @@ Use `.claude/skills/` for:
|
|
|
176
176
|
- CLI-first orchestration paths
|
|
177
177
|
- future bundled references or deterministic helper scripts
|
|
178
178
|
|
|
179
|
+
When the request is specifically about master-detail or nested-detail aggregate scaffolding, aggregate-owned detail resources, `:tools:masterDetail`, or nested detail DTO naming/placement in a scaffolding context, route to the dedicated `cabloy-master-detail` skill instead of treating it as generic backend scaffolding.
|
|
180
|
+
|
|
179
181
|
### Class-placement questions
|
|
180
182
|
|
|
181
183
|
When the request is about whether a backend base class belongs in `src/lib`, `src/service`, or the global bean shorthand surface, apply the A / B1 / B2 rule.
|
package/.gitignore
CHANGED
|
@@ -72,6 +72,4 @@ vona/docker-compose.yml
|
|
|
72
72
|
!/zova/packages-utils/quasar-app-extension-zova/dist
|
|
73
73
|
|
|
74
74
|
vona/src/suite/cabloy-basic/modules/basic-siteadmin/assets/site
|
|
75
|
-
vona/src/suite/cabloy-basic/modules/basic-siteadmin/zovaRest
|
|
76
75
|
vona/src/suite/cabloy-basic/modules/basic-siteweb/assets/site
|
|
77
|
-
vona/src/suite/cabloy-basic/modules/basic-siteweb/zovaRest
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.1.74
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Update related functionality and project components.
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- Alias MariaDB drivers correctly in the Vona build.
|
|
12
|
+
- Reorder initialization to bootstrap Zova REST before other startup steps.
|
|
13
|
+
- Seed Vona Zova REST dependencies before running the initial install.
|
|
14
|
+
|
|
15
|
+
### Improvements
|
|
16
|
+
|
|
17
|
+
- Align Zova REST workspace naming.
|
|
18
|
+
- Streamline the Zova REST workspace flow.
|
|
19
|
+
|
|
20
|
+
## 5.1.73
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
- Export the training record entity.
|
|
25
|
+
- Update exposed functionality and related behavior.
|
|
26
|
+
|
|
27
|
+
### Bug Fixes
|
|
28
|
+
|
|
29
|
+
- Expand the `zova-core` type patch in `vona`.
|
|
30
|
+
- Patch `zova-core` type augmentation in `vona`.
|
|
31
|
+
- Watch `.tsx` file changes correctly in dev `nodemon`.
|
|
32
|
+
|
|
33
|
+
### Improvements
|
|
34
|
+
|
|
35
|
+
- Move the average score effect into the shared library.
|
|
36
|
+
- Move the training record subject effect into the shared library.
|
|
37
|
+
- Clarify `dtoClass` usage in DTO inference and master-detail documentation.
|
|
38
|
+
- Add master-detail guidance and skill routing documentation.
|
|
39
|
+
- Update tab rendering behavior.
|
|
40
|
+
|
|
3
41
|
## 5.1.72
|
|
4
42
|
|
|
5
43
|
### Features
|
|
@@ -266,6 +266,11 @@ export default defineConfig({
|
|
|
266
266
|
{ text: 'ORM Mutation Guide', link: '/backend/orm-mutation-guide' },
|
|
267
267
|
{ text: 'ORM Aggregate and Group Guide', link: '/backend/orm-aggregate-group-guide' },
|
|
268
268
|
{ text: 'Relations Guide', link: '/backend/relations-guide' },
|
|
269
|
+
{ text: 'Master-Detail Workflow', link: '/backend/master-detail-workflow' },
|
|
270
|
+
{
|
|
271
|
+
text: 'Master-Detail Source Reading Map',
|
|
272
|
+
link: '/backend/master-detail-source-reading-map',
|
|
273
|
+
},
|
|
269
274
|
{ text: 'Transaction Guide', link: '/backend/transaction-guide' },
|
|
270
275
|
],
|
|
271
276
|
},
|
|
@@ -148,7 +148,7 @@ A practical split is:
|
|
|
148
148
|
- use inferred DTOs when the contract closely follows model structure or query shape
|
|
149
149
|
- wrap inferred DTOs in a named DTO class when reuse or discoverability becomes more important
|
|
150
150
|
|
|
151
|
-
For the inference side, see [DTO Infer and Generation](/backend/dto-infer-generation).
|
|
151
|
+
Advanced inferred DTO shaping can also stay named and reusable through helper options such as `dtoClass`, especially for relation-aware contracts and nested DTO surfaces. For the inference side, see [DTO Infer and Generation](/backend/dto-infer-generation).
|
|
152
152
|
|
|
153
153
|
## Relationship to ORM and controller contracts
|
|
154
154
|
|
|
@@ -239,6 +239,44 @@ A practical rule is:
|
|
|
239
239
|
- keep inference inline when one action needs one contract shape only once
|
|
240
240
|
- wrap the inferred DTO into a named DTO class when the same relation-aware shape becomes part of a reusable public contract
|
|
241
241
|
|
|
242
|
+
## Use `dtoClass` to shape inferred fields
|
|
243
|
+
|
|
244
|
+
When inferred DTOs should still follow a reusable named field surface, pass `dtoClass` to the helper options.
|
|
245
|
+
|
|
246
|
+
This is useful when:
|
|
247
|
+
|
|
248
|
+
- the inferred DTO should reuse a DTO class instead of exposing the full model field surface
|
|
249
|
+
- a nested relation needs its own mutate/view contract class
|
|
250
|
+
- a master-detail contract should stay relation-aware while the allowed fields remain curated and discoverable by name
|
|
251
|
+
|
|
252
|
+
A practical rule is:
|
|
253
|
+
|
|
254
|
+
- use `dtoClass` when the shaping should be reusable and named
|
|
255
|
+
- use `columns` when the narrowing is simple and only needed once
|
|
256
|
+
|
|
257
|
+
Representative specimen from `training-student`:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
export class DtoDetailRecordMutate extends $Dto.mutate(() => ModelRecord, {
|
|
261
|
+
dtoClass: DtoDetailRecordBase,
|
|
262
|
+
include: { trainingRecordSubjects: { dtoClass: DtoDetailRecordSubjectMutate } },
|
|
263
|
+
}) {}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
This pattern keeps model-aware and relation-aware inference, but takes the field truth from the provided DTO classes.
|
|
267
|
+
|
|
268
|
+
In a master-detail flow, this usually means:
|
|
269
|
+
|
|
270
|
+
- a base detail DTO such as `DtoDetailRecordBase` defines the reusable field surface for the owned detail
|
|
271
|
+
- a parent contract such as `DtoStudentCreate` or `DtoStudentUpdate` includes the detail through `include: { trainingRecords: { dtoClass: DtoDetailRecordMutate } }`
|
|
272
|
+
- a nested detail can repeat the same rule one level lower, such as `trainingRecordSubjects: { dtoClass: DtoDetailRecordSubjectMutate }`
|
|
273
|
+
|
|
274
|
+
That separation is useful because the parent DTO keeps the aggregate relation wiring, while the detail DTO family owns which detail fields are actually exposed for create, update, or view.
|
|
275
|
+
|
|
276
|
+
The nested relation case matters because `dtoClass` can also be applied inside `include`, not only at the top level.
|
|
277
|
+
|
|
278
|
+
The test suite also shows the behavioral difference from a one-off `columns` selection: a relation-level `dtoClass` can act like a reusable named field subset instead of repeating inline column lists.
|
|
279
|
+
|
|
242
280
|
## Aggregate and group DTO inference
|
|
243
281
|
|
|
244
282
|
Summary-oriented ORM queries often benefit from inferred DTOs because the result shape is driven by `aggrs`, `groups`, and relation configuration.
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Master-Detail Source Reading Map
|
|
2
|
+
|
|
3
|
+
This page is a practical source-reading companion for one narrow backend question:
|
|
4
|
+
|
|
5
|
+
> if my question is no longer “how do I use the master-detail workflow?” but “which files prove the current master-detail, nested-detail, and standalone-capable detail behavior?”, where should I read first, and in what order?
|
|
6
|
+
|
|
7
|
+
Use this page together with:
|
|
8
|
+
|
|
9
|
+
- [Master-Detail Workflow](/backend/master-detail-workflow)
|
|
10
|
+
- [Relations Guide](/backend/relations-guide)
|
|
11
|
+
- [Backend Resource/Module Contract Chain](/backend/backend-resource-module-contract-chain)
|
|
12
|
+
- [Contract Loop Playbook](/fullstack/contract-loop-playbook)
|
|
13
|
+
|
|
14
|
+
> [!TIP]
|
|
15
|
+
> **Master-detail reading path**
|
|
16
|
+
>
|
|
17
|
+
> 1. **[Master-Detail Workflow](/backend/master-detail-workflow)** — understand the public workflow and DTO rules
|
|
18
|
+
> 2. **[Master-Detail Source Reading Map](/backend/master-detail-source-reading-map)** — trace the generator and specimen evidence
|
|
19
|
+
>
|
|
20
|
+
> **You are here:** step 2.
|
|
21
|
+
|
|
22
|
+
## Why this page exists
|
|
23
|
+
|
|
24
|
+
The current public docs already explain the basic master-detail workflow.
|
|
25
|
+
|
|
26
|
+
What was still missing was one file-order map that proves the current implementation across:
|
|
27
|
+
|
|
28
|
+
- generator behavior
|
|
29
|
+
- first-level master-detail specimen
|
|
30
|
+
- second-level nested-detail specimen
|
|
31
|
+
- the boundary between aggregate-owned detail DTOs and standalone child-resource surfaces
|
|
32
|
+
|
|
33
|
+
This page fills that gap.
|
|
34
|
+
|
|
35
|
+
It is a source-order map for the current implementation, not another broad CRUD or relation concept page.
|
|
36
|
+
|
|
37
|
+
## How to use this page
|
|
38
|
+
|
|
39
|
+
Use this rule of thumb:
|
|
40
|
+
|
|
41
|
+
1. start with the workflow page first
|
|
42
|
+
2. read the generator entrypoints to understand what the scaffold promises
|
|
43
|
+
3. read the specimen files in parent-to-child order
|
|
44
|
+
4. stop once the behavior is clear instead of rereading the whole suite
|
|
45
|
+
5. hand off to fullstack contract-loop docs only when the question becomes frontend generation or consumer drift
|
|
46
|
+
|
|
47
|
+
## The shortest accurate mental model
|
|
48
|
+
|
|
49
|
+
A practical master-detail implementation path looks like this:
|
|
50
|
+
|
|
51
|
+
1. `:tools:masterDetail` receives the master/detail module and resource arguments
|
|
52
|
+
2. the generator normalizes detail DTO names, relation names, FK names, and detail mode
|
|
53
|
+
3. the generator ensures the detail module/resource shape exists
|
|
54
|
+
4. it patches the detail entity/meta side
|
|
55
|
+
5. it renders nested detail DTOs into the parent DTO folder
|
|
56
|
+
6. it patches the master model/service/DTO/locales
|
|
57
|
+
7. it refreshes metadata for both the detail module and the master module
|
|
58
|
+
8. the specimen modules then demonstrate how the same pattern can repeat recursively for nested-detail
|
|
59
|
+
|
|
60
|
+
That means the source-reading branch is not only “follow one CRUD module.”
|
|
61
|
+
|
|
62
|
+
It starts from the generator, then confirms the shape in real specimen modules.
|
|
63
|
+
|
|
64
|
+
## Generator entrypoints
|
|
65
|
+
|
|
66
|
+
Start here:
|
|
67
|
+
|
|
68
|
+
1. `vona/packages-cli/cli-set-api/src/lib/command/tools.masterDetail.ts`
|
|
69
|
+
2. `vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts`
|
|
70
|
+
|
|
71
|
+
Read the command definition first when the question is:
|
|
72
|
+
|
|
73
|
+
- what CLI shape is officially supported?
|
|
74
|
+
- what arguments are part of the public workflow?
|
|
75
|
+
|
|
76
|
+
Read `cli.tools.masterDetail.ts` first when the question is:
|
|
77
|
+
|
|
78
|
+
- how are `detailMode`, relation names, FK names, and detail DTO names normalized?
|
|
79
|
+
- what exactly gets scaffolded or patched?
|
|
80
|
+
- how does the generator distinguish aggregate-only detail from standalone-capable detail?
|
|
81
|
+
|
|
82
|
+
## What `cli.tools.masterDetail.ts` actually patches
|
|
83
|
+
|
|
84
|
+
The main execution path is:
|
|
85
|
+
|
|
86
|
+
1. `_prepareArgv`
|
|
87
|
+
2. `_ensureDetailModule`
|
|
88
|
+
3. `_ensureDetailResourceShape`
|
|
89
|
+
4. `_patchDetailModule`
|
|
90
|
+
5. `_renderMasterDetailDtos`
|
|
91
|
+
6. `_patchMasterModule`
|
|
92
|
+
7. `_refreshMetadata`
|
|
93
|
+
|
|
94
|
+
A practical reading of the responsibilities is:
|
|
95
|
+
|
|
96
|
+
- `_prepareArgv`
|
|
97
|
+
- defaults and validates `detailMode`
|
|
98
|
+
- derives `relationName`, `fk`, and the nested detail DTO names
|
|
99
|
+
- confirms the `detail*` naming convention comes from the generator itself
|
|
100
|
+
- `_ensureDetailResourceShape`
|
|
101
|
+
- ensures the detail resource core exists
|
|
102
|
+
- branches into aggregate vs standalone handling
|
|
103
|
+
- `_handleAggregateDetailMode`
|
|
104
|
+
- refuses to silently collapse an existing standalone detail surface into aggregate-only mode
|
|
105
|
+
- removes generated standalone controller/service/DTO files when aggregate-only shape is intended
|
|
106
|
+
- `_handleStandaloneDetailMode`
|
|
107
|
+
- requires the standalone detail surface to remain present
|
|
108
|
+
- `_patchDetailModule`
|
|
109
|
+
- adds the FK field and schema/index support on the detail side
|
|
110
|
+
- `_renderMasterDetailDtos`
|
|
111
|
+
- emits `detail*` DTO files into the master module `src/dto` folder
|
|
112
|
+
- `_patchMasterDto`
|
|
113
|
+
- patches `Create` / `Update` / `View` DTOs so the parent DTOs consume the sibling nested detail DTOs
|
|
114
|
+
- emits the current `include: { relationName: { dtoClass: DtoDetail... } }` wiring pattern instead of inlining long relation column lists in every parent DTO
|
|
115
|
+
- `_refreshMetadata`
|
|
116
|
+
- regenerates `.metadata/index.ts` for both modules so the nested detail DTOs appear in generated contract surfaces
|
|
117
|
+
|
|
118
|
+
## First-level specimen: `training-student -> training-record`
|
|
119
|
+
|
|
120
|
+
Use this order:
|
|
121
|
+
|
|
122
|
+
1. `vona/src/suite/a-training/modules/training-student/src/model/student.ts`
|
|
123
|
+
2. `vona/src/suite/a-training/modules/training-student/src/service/student.ts`
|
|
124
|
+
3. `vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx`
|
|
125
|
+
4. `vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx`
|
|
126
|
+
5. `vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx`
|
|
127
|
+
6. `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx`
|
|
128
|
+
7. `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordMutate.tsx`
|
|
129
|
+
8. `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordResItem.tsx`
|
|
130
|
+
9. `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordView.tsx`
|
|
131
|
+
10. `vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts`
|
|
132
|
+
11. `vona/src/suite/a-training/modules/training-record/src/entity/record.tsx`
|
|
133
|
+
|
|
134
|
+
What this sequence clarifies:
|
|
135
|
+
|
|
136
|
+
- `student.ts` shows the `hasMany('training-record:record', 'studentId', ...)` ownership relation
|
|
137
|
+
- `service/student.ts` shows the nested include lifecycle for create/view/update/delete
|
|
138
|
+
- `studentCreate.tsx`, `studentUpdate.tsx`, and `studentView.tsx` show the parent DTOs consuming sibling nested detail DTOs through `dtoClass`-based `include` wiring
|
|
139
|
+
- `detailRecordBase.tsx` shows the reusable detail field surface that the mutate/view/res-item DTO family can build on
|
|
140
|
+
- `detailRecordMutate.tsx` and `detailRecordView.tsx` show that first-level nested detail DTOs can also repeat the same `dtoClass` pattern for deeper nested relations
|
|
141
|
+
- `detailRecord*.tsx` shows the `detail*` naming convention for first-level nested detail DTOs
|
|
142
|
+
- `.metadata/index.ts` confirms those nested detail DTOs are part of the generated contract registry
|
|
143
|
+
- `entity/record.tsx` shows the detail-side FK persistence field that closes the aggregate thread
|
|
144
|
+
|
|
145
|
+
## Second-level specimen: `training-record -> training-recordsubject`
|
|
146
|
+
|
|
147
|
+
Use this order:
|
|
148
|
+
|
|
149
|
+
1. `vona/src/suite/a-training/modules/training-record/src/model/record.ts`
|
|
150
|
+
2. `vona/src/suite/a-training/modules/training-record/src/service/record.ts`
|
|
151
|
+
3. `vona/src/suite/a-training/modules/training-record/src/dto/recordCreate.tsx`
|
|
152
|
+
4. `vona/src/suite/a-training/modules/training-record/src/dto/recordUpdate.tsx`
|
|
153
|
+
5. `vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx`
|
|
154
|
+
6. `vona/src/suite/a-training/modules/training-record/src/dto/detailRecordSubjectBase.tsx`
|
|
155
|
+
7. `vona/src/suite/a-training/modules/training-record/src/dto/detailRecordSubjectMutate.tsx`
|
|
156
|
+
8. `vona/src/suite/a-training/modules/training-record/src/dto/detailRecordSubjectResItem.tsx`
|
|
157
|
+
9. `vona/src/suite/a-training/modules/training-record/src/dto/detailRecordSubjectView.tsx`
|
|
158
|
+
10. `vona/src/suite/a-training/modules/training-record/src/.metadata/index.ts`
|
|
159
|
+
|
|
160
|
+
What this sequence clarifies:
|
|
161
|
+
|
|
162
|
+
- `record.ts` shows that `record` is itself a parent through `trainingRecordSubjects: $relation.hasMany(...)`
|
|
163
|
+
- `service/record.ts` shows the include lifecycle for the second-level nested detail collection
|
|
164
|
+
- `recordCreate.tsx`, `recordUpdate.tsx`, and `recordView.tsx` show the immediate parent consuming sibling `detailRecordSubject*` DTOs through the same `dtoClass`-based include pattern
|
|
165
|
+
- `detailRecordSubject*.tsx` proves the recursive `detail*` naming rule
|
|
166
|
+
- `.metadata/index.ts` confirms second-level nested detail DTOs are also exported into generated contract surfaces
|
|
167
|
+
|
|
168
|
+
The key point is that this is not a separate mechanism.
|
|
169
|
+
|
|
170
|
+
It is the same master-detail pattern repeated one level lower.
|
|
171
|
+
|
|
172
|
+
## Standalone child surface vs nested detail surface
|
|
173
|
+
|
|
174
|
+
This is the boundary most worth reading carefully.
|
|
175
|
+
|
|
176
|
+
The `training-record` module proves that a detail can keep its own standalone resource surface while still participating as a nested detail under `student`.
|
|
177
|
+
|
|
178
|
+
Read these files for the standalone-capable detail surface:
|
|
179
|
+
|
|
180
|
+
- `vona/src/suite/a-training/modules/training-record/src/service/record.ts`
|
|
181
|
+
- `vona/src/suite/a-training/modules/training-record/src/dto/recordCreate.tsx`
|
|
182
|
+
- `vona/src/suite/a-training/modules/training-record/src/dto/recordUpdate.tsx`
|
|
183
|
+
- `vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx`
|
|
184
|
+
|
|
185
|
+
Then compare that with the nested detail DTOs that live in the parent module:
|
|
186
|
+
|
|
187
|
+
- `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx`
|
|
188
|
+
- `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordMutate.tsx`
|
|
189
|
+
- `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordResItem.tsx`
|
|
190
|
+
- `vona/src/suite/a-training/modules/training-student/src/dto/detailRecordView.tsx`
|
|
191
|
+
|
|
192
|
+
That comparison shows the intended split:
|
|
193
|
+
|
|
194
|
+
- nested detail DTOs use `detail*` names in the parent module because they describe the child in its parent-owned detail role
|
|
195
|
+
- standalone child CRUD uses ordinary resource DTO names in the child module because it describes the child as its own resource surface
|
|
196
|
+
|
|
197
|
+
For `training-recordsubject`, the current source tree also helps prove the aggregate-only boundary.
|
|
198
|
+
|
|
199
|
+
Observed source state:
|
|
200
|
+
|
|
201
|
+
- `vona/src/suite/a-training/modules/training-recordsubject/src/` currently contains entity/model/meta files
|
|
202
|
+
- it does **not** currently contain `src/controller/`, `src/service/`, or `src/dto/`
|
|
203
|
+
- the compiled `dist/` tree still contains prior standalone declarations such as `dist/dto/subjectCreate.d.ts`
|
|
204
|
+
|
|
205
|
+
A practical interpretation is:
|
|
206
|
+
|
|
207
|
+
- source-level authoring for `training-recordsubject` is currently aggregate-oriented
|
|
208
|
+
- nested second-level detail authoring lives in the parent `training-record` module through `detailRecordSubject*`
|
|
209
|
+
- compiled artifacts alone should not be treated as the canonical source of truth when the source tree shows the current aggregate-only shape
|
|
210
|
+
|
|
211
|
+
## Frontend/runtime touchpoints
|
|
212
|
+
|
|
213
|
+
If your next question becomes “how does this nested detail DTO shape connect to actual detail UI/runtime behavior?”, read these areas next:
|
|
214
|
+
|
|
215
|
+
- `zova/src/suite/cabloy-basic/modules/basic-details/`
|
|
216
|
+
- `zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/detail/`
|
|
217
|
+
|
|
218
|
+
Use them to confirm:
|
|
219
|
+
|
|
220
|
+
- nested detail fields are rendered through `basic-details`
|
|
221
|
+
- detail lists/rows/actions have a concrete runtime contract
|
|
222
|
+
- the backend DTO and metadata shape feeds a real frontend detail workflow rather than remaining only a backend convention
|
|
223
|
+
|
|
224
|
+
## Suggested reading order for future source analysis
|
|
225
|
+
|
|
226
|
+
Use this order when you want the shortest reliable path:
|
|
227
|
+
|
|
228
|
+
1. `vona/packages-cli/cli-set-api/src/lib/command/tools.masterDetail.ts`
|
|
229
|
+
2. `vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts`
|
|
230
|
+
3. `vona/src/suite/a-training/modules/training-student/src/model/student.ts`
|
|
231
|
+
4. `vona/src/suite/a-training/modules/training-student/src/service/student.ts`
|
|
232
|
+
5. `vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx`
|
|
233
|
+
6. `vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx`
|
|
234
|
+
7. `vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx`
|
|
235
|
+
8. `vona/src/suite/a-training/modules/training-record/src/model/record.ts`
|
|
236
|
+
9. `vona/src/suite/a-training/modules/training-record/src/service/record.ts`
|
|
237
|
+
10. `vona/src/suite/a-training/modules/training-record/src/dto/recordCreate.tsx`
|
|
238
|
+
11. `vona/src/suite/a-training/modules/training-record/src/dto/recordUpdate.tsx`
|
|
239
|
+
12. `vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx`
|
|
240
|
+
13. both module `.metadata/index.ts` files
|
|
241
|
+
14. frontend `basic-details` and `a-openapi` detail runtime types if the question crosses into UI/runtime behavior
|
|
242
|
+
|
|
243
|
+
## Where to read next
|
|
244
|
+
|
|
245
|
+
- If you need the public workflow and naming/placement rules, return to [Master-Detail Workflow](/backend/master-detail-workflow).
|
|
246
|
+
- If you need broader ORM relation semantics, continue with [Relations Guide](/backend/relations-guide).
|
|
247
|
+
- If you want one concrete backend module wiring page before returning to detail-specific reading, continue with [Backend Resource/Module Contract Chain](/backend/backend-resource-module-contract-chain).
|
|
248
|
+
- If the next question becomes frontend consumer generation or backend/frontend drift, continue with [Contract Loop Playbook](/fullstack/contract-loop-playbook).
|
|
249
|
+
|
|
250
|
+
## Final takeaway
|
|
251
|
+
|
|
252
|
+
The cleanest way to read the current master-detail implementation is not to stay only at the workflow level and not to read every file in the suite.
|
|
253
|
+
|
|
254
|
+
Start from the CLI entrypoint, confirm what the generator promises, trace the first-level specimen, then trace the recursive second-level specimen.
|
|
255
|
+
|
|
256
|
+
That path is enough to prove the three current capabilities:
|
|
257
|
+
|
|
258
|
+
- master-detail
|
|
259
|
+
- nested-detail
|
|
260
|
+
- a detail resource that can remain aggregate-owned only or also keep its own standalone resource surface
|