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.
- package/.claude/hooks/contract-loop-gate.ts +296 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -0
- package/.claude/skills/cabloy-contract-loop/SKILL.md +103 -14
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +126 -12
- package/.claude/skills/cabloy-contract-loop/references/resource-custom-state-pattern.md +148 -0
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +49 -13
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +11 -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 +274 -0
- package/.claude/skills/cabloy-resource-field-update/evals/evals.json +53 -0
- package/.claude/skills/cabloy-resource-field-update/references/custom-renderer-demo-checklist.md +102 -0
- package/.claude/skills/cabloy-resource-field-update/references/field-update-decision-tree.md +120 -0
- package/.claude/skills/cabloy-resource-field-update/references/follow-up-checklist.md +80 -0
- package/.claude/skills/cabloy-resource-field-update/references/verification-checklist.md +97 -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/.github/workflows/docs-pages.yml +2 -0
- package/.github/workflows/vona-cov-pg.yml +2 -0
- package/.github/workflows/vona-test-crud.yml +4 -2
- package/.github/workflows/vona-test-mysql.yml +2 -0
- package/.github/workflows/vona-test-pg.yml +2 -0
- package/.github/workflows/vona-test-sqlite3.yml +2 -0
- package/.github/workflows/vona-tsc.yml +2 -0
- package/.github/workflows/zova-ui.yml +2 -0
- package/.gitignore +0 -4
- package/CHANGELOG.md +52 -0
- package/CLAUDE.md +12 -0
- package/README.md +15 -0
- package/cabloy-docs/.vitepress/config.mjs +89 -0
- package/cabloy-docs/ai/class-placement-rule.md +2 -0
- package/cabloy-docs/ai/cli-to-skill-map.md +14 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +14 -0
- package/cabloy-docs/ai/future-skill-roadmap.md +27 -9
- 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 +11 -0
- package/cabloy-docs/backend/bean-scene-authoring.md +350 -0
- package/cabloy-docs/backend/cli.md +26 -1
- package/cabloy-docs/backend/dto-guide.md +6 -0
- package/cabloy-docs/backend/entity-guide.md +18 -0
- package/cabloy-docs/backend/foundation.md +28 -3
- package/cabloy-docs/backend/introduction.md +10 -0
- package/cabloy-docs/backend/serialization-guide.md +10 -0
- package/cabloy-docs/backend/service-guide.md +2 -0
- package/cabloy-docs/backend/status-guide.md +271 -0
- package/cabloy-docs/backend/websocket-call-flow.md +435 -0
- package/cabloy-docs/backend/websocket-guide.md +455 -0
- package/cabloy-docs/backend/websocket-protocol-guide.md +381 -0
- package/cabloy-docs/backend/websocket-usage-guide.md +356 -0
- package/cabloy-docs/frontend/api-guide.md +2 -0
- package/cabloy-docs/frontend/bean-scene-authoring.md +374 -0
- package/cabloy-docs/frontend/behavior-guide.md +449 -0
- package/cabloy-docs/frontend/cli.md +24 -0
- package/cabloy-docs/frontend/command-scene-authoring.md +495 -0
- package/cabloy-docs/frontend/design-principles.md +6 -0
- package/cabloy-docs/frontend/fetch-interceptor-guide.md +440 -0
- package/cabloy-docs/frontend/form-guide.md +795 -0
- package/cabloy-docs/frontend/foundation.md +29 -0
- package/cabloy-docs/frontend/introduction.md +17 -1
- package/cabloy-docs/frontend/ioc-and-beans.md +16 -9
- package/cabloy-docs/frontend/mock-guide.md +1 -0
- package/cabloy-docs/frontend/model-architecture.md +252 -39
- package/cabloy-docs/frontend/model-resource-best-practices.md +379 -0
- package/cabloy-docs/frontend/model-resource-cookbook.md +505 -0
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +382 -0
- package/cabloy-docs/frontend/model-resource-usage-guide.md +318 -0
- package/cabloy-docs/frontend/model-state-guide.md +366 -13
- package/cabloy-docs/frontend/openapi-sdk-guide.md +5 -2
- package/cabloy-docs/frontend/page-guide.md +6 -0
- package/cabloy-docs/frontend/quickstart.md +4 -0
- package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +266 -0
- package/cabloy-docs/frontend/router-tabs-admin-web-comparison.md +206 -0
- package/cabloy-docs/frontend/router-tabs-introduction.md +106 -0
- package/cabloy-docs/frontend/router-tabs-mechanism.md +469 -0
- package/cabloy-docs/frontend/router-tabs-overview.md +227 -0
- package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +343 -0
- package/cabloy-docs/frontend/server-data.md +2 -0
- package/cabloy-docs/frontend/ssr-architecture-overview.md +211 -0
- package/cabloy-docs/frontend/ssr-build-deploy-guide.md +308 -0
- package/cabloy-docs/frontend/ssr-review-checklist.md +184 -0
- package/cabloy-docs/frontend/ssr-troubleshooting-guide.md +301 -0
- package/cabloy-docs/frontend/zova-form-source-reading-map.md +295 -0
- package/cabloy-docs/frontend/zova-form-under-the-hood.md +556 -0
- package/cabloy-docs/frontend/zova-reactivity-under-the-hood.md +320 -0
- package/cabloy-docs/frontend/zova-source-reading-map.md +327 -0
- package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +308 -0
- package/cabloy-docs/fullstack/contract-loop-playbook.md +350 -0
- package/cabloy-docs/fullstack/framework-performance.md +3 -3
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +44 -1
- package/cabloy-docs/fullstack/introduction.md +40 -0
- package/cabloy-docs/fullstack/openapi-to-sdk.md +19 -9
- package/cabloy-docs/fullstack/quickstart.md +7 -1
- package/cabloy-docs/fullstack/tutorial-1-first-module.md +111 -0
- package/cabloy-docs/fullstack/tutorial-2-first-crud.md +122 -0
- package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +131 -0
- package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +144 -0
- package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +146 -0
- package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +170 -0
- package/cabloy-docs/fullstack/tutorials-overview.md +192 -0
- package/cabloy-docs/index.md +4 -3
- package/cabloy-docs/reference/bean-scene-boilerplates.md +75 -0
- package/cabloy-docs/reference/cli-reference.md +2 -0
- package/package.json +7 -2
- package/scripts/initTestData.ts +25 -0
- package/scripts/upgrade.ts +17 -2
- package/vona/packages-cli/cabloy-cli/package.json +2 -2
- 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.create.module.ts +4 -0
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/pnpm-lock.yaml +226 -1091
- package/vona/pnpm-workspace.yaml +0 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/assets/static/img/vona.svg +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +2 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +3 -3
- package/zova/packages-cli/cli-set-front/cli/templates/init/icon/boilerplate/icons/default/zova.svg +1 -1
- 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 +3 -3
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +4 -0
- package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +34 -4
- package/zova/packages-cli/cli-set-front/src/lib/command/create.bean.ts +5 -1
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +282 -1311
- package/zova/pnpm-workspace.yaml +0 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/cabloy.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/vona.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/icons/social/zova.svg +1 -1
- package/zova/src/suite/a-home/modules/home-icon/src/.metadata/icons/groups/social.svg +3 -3
- package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +9 -0
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +66 -16
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +60 -18
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/cli/tableCell/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +4 -4
|
@@ -10,18 +10,21 @@ A roadmap helps convert that documented knowledge into a focused set of high-val
|
|
|
10
10
|
|
|
11
11
|
## What already exists
|
|
12
12
|
|
|
13
|
-
Current root
|
|
13
|
+
Current root skills include:
|
|
14
14
|
|
|
15
15
|
- `cabloy-workflow`
|
|
16
|
+
- `cabloy-contract-loop`
|
|
17
|
+
- `cabloy-resource-field-update`
|
|
18
|
+
- `cabloy-module-removal`
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
Their current roles are:
|
|
18
21
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
22
|
+
- `cabloy-workflow` → broad workflow selection, edition detection, CLI-first routing, and verification framing
|
|
23
|
+
- `cabloy-contract-loop` → backend/frontend contract regeneration, reverse-chain handling, and drift diagnosis
|
|
24
|
+
- `cabloy-resource-field-update` → existing backend resource-field changes with `fileVersion` and renderer-aware follow-up
|
|
25
|
+
- `cabloy-module-removal` → backend/frontend/fullstack module deletion order, generated-runtime cleanup, and verification
|
|
23
26
|
|
|
24
|
-
This is a
|
|
27
|
+
This is now a stronger foundation skill set, but it still leaves several useful workflow families for future specialization.
|
|
25
28
|
|
|
26
29
|
## Recommended next skill families
|
|
27
30
|
|
|
@@ -67,7 +70,22 @@ Primary dependencies:
|
|
|
67
70
|
- Zova OpenAPI SDK and server-data docs
|
|
68
71
|
- fullstack collaboration docs
|
|
69
72
|
|
|
70
|
-
### 4.
|
|
73
|
+
### 4. Resource field update skill
|
|
74
|
+
|
|
75
|
+
Purpose:
|
|
76
|
+
|
|
77
|
+
- handle updates to fields on existing backend resources
|
|
78
|
+
- force the right `fileVersion` decision for new persisted fields
|
|
79
|
+
- branch correctly between shared renderer reuse and custom renderer demo follow-up
|
|
80
|
+
- verify entity, locale, migration, test, metadata, build, and dependency-sync implications
|
|
81
|
+
|
|
82
|
+
Primary dependencies:
|
|
83
|
+
|
|
84
|
+
- Vona entity / migration / DTO workflow knowledge
|
|
85
|
+
- Zova metadata/build flows when renderer follow-up is involved
|
|
86
|
+
- the backend resource field workflow note in `.docs-internal/`
|
|
87
|
+
|
|
88
|
+
### 5. Metadata refresh skill
|
|
71
89
|
|
|
72
90
|
Purpose:
|
|
73
91
|
|
|
@@ -81,7 +99,7 @@ Primary dependencies:
|
|
|
81
99
|
- CLI-to-skill mapping
|
|
82
100
|
- edition detection docs
|
|
83
101
|
|
|
84
|
-
###
|
|
102
|
+
### 6. Distributed backend workflow skill
|
|
85
103
|
|
|
86
104
|
Purpose:
|
|
87
105
|
|
|
@@ -75,6 +75,7 @@ Use this path when the task is about implementing or reviewing Cabloy code with
|
|
|
75
75
|
- [Playbook: Backend Module](/ai/playbook-backend-module)
|
|
76
76
|
- [Playbook: Frontend Page](/ai/playbook-frontend-page)
|
|
77
77
|
- [Playbook: Contract Regeneration](/ai/playbook-contract-regeneration)
|
|
78
|
+
- [Playbook: Module Removal](/ai/playbook-module-removal)
|
|
78
79
|
- [Playbook: Metadata Refresh](/ai/playbook-metadata-refresh)
|
|
79
80
|
|
|
80
81
|
### Verification and roadmap path
|
|
@@ -66,6 +66,12 @@ Depending on the feature, extend the generated code with the right framework-lev
|
|
|
66
66
|
- migration and changes
|
|
67
67
|
- field indexes
|
|
68
68
|
|
|
69
|
+
When refining entity or DTO fields that use `@Api.field(...)`, apply this framework-specific guardrail:
|
|
70
|
+
|
|
71
|
+
- if you include an explicit zod schema such as `z.number().int().min(1)`, place it as the **last argument**
|
|
72
|
+
- keep helper metadata such as `v.xxx(...)` and `ZovaRender.xxx(...)` before the zod schema
|
|
73
|
+
- otherwise helpers written after the zod schema may stop taking effect
|
|
74
|
+
|
|
69
75
|
Relevant docs:
|
|
70
76
|
|
|
71
77
|
- [Controller Guide](/backend/controller-guide)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Playbook: Remove a Cabloy Module
|
|
2
|
+
|
|
3
|
+
This playbook turns Cabloy module deletion into a repeatable AI-friendly workflow.
|
|
4
|
+
|
|
5
|
+
## When to use this playbook
|
|
6
|
+
|
|
7
|
+
Use this playbook when the goal is to remove an existing module from the Cabloy monorepo.
|
|
8
|
+
|
|
9
|
+
Typical triggers include:
|
|
10
|
+
|
|
11
|
+
- delete a demo module
|
|
12
|
+
- retire a backend module
|
|
13
|
+
- remove a frontend module
|
|
14
|
+
- remove a fullstack module that exists in both Vona and Zova
|
|
15
|
+
- clean up stale generated runtime or type residues after a module was removed
|
|
16
|
+
|
|
17
|
+
## Step 1: Detect the repo and scope
|
|
18
|
+
|
|
19
|
+
Before deleting anything:
|
|
20
|
+
|
|
21
|
+
1. detect whether the active repo is Cabloy Basic or Cabloy Start
|
|
22
|
+
2. confirm whether the module is backend-only, frontend-only, or fullstack
|
|
23
|
+
3. inspect the root `package.json`
|
|
24
|
+
4. inspect `npm run vona` and `npm run zova`
|
|
25
|
+
|
|
26
|
+
This avoids deleting the wrong surfaces or using the wrong edition-specific assumptions.
|
|
27
|
+
|
|
28
|
+
## Step 2: Inventory the real module surfaces
|
|
29
|
+
|
|
30
|
+
Inspect the real source and direct dependency surfaces first.
|
|
31
|
+
|
|
32
|
+
Typical locations include:
|
|
33
|
+
|
|
34
|
+
- `vona/src/module/<module>` or suite-based backend module roots
|
|
35
|
+
- `zova/src/module/<module>` or suite-based frontend module roots
|
|
36
|
+
- `vona/package.json`
|
|
37
|
+
- `zova/package.json`
|
|
38
|
+
- generated registries and lockfiles
|
|
39
|
+
- tests that still target the module
|
|
40
|
+
|
|
41
|
+
If the user asked for a public scrub, also inspect `cabloy-docs/`. Otherwise, treat docs cleanup as a separate scope decision.
|
|
42
|
+
|
|
43
|
+
## Step 3: Remove source and direct references first
|
|
44
|
+
|
|
45
|
+
Start by removing the real source and direct workspace package references.
|
|
46
|
+
|
|
47
|
+
Typical order:
|
|
48
|
+
|
|
49
|
+
1. remove backend module source if in scope
|
|
50
|
+
2. remove frontend module source if in scope
|
|
51
|
+
3. remove direct workspace dependency entries from the relevant `package.json` files
|
|
52
|
+
4. refresh or clean generated registrations only after source removal
|
|
53
|
+
|
|
54
|
+
Do not start by hand-editing generated caches while the real module source or package references still exist.
|
|
55
|
+
|
|
56
|
+
## Step 4: Regenerate with the repo-owned workflow
|
|
57
|
+
|
|
58
|
+
After source cleanup, use the existing root scripts to refresh generated outputs.
|
|
59
|
+
|
|
60
|
+
Representative root commands in Cabloy Basic include:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm run build:zova:admin
|
|
64
|
+
npm run deps:vona
|
|
65
|
+
npm run deps:zova
|
|
66
|
+
npm run tsc
|
|
67
|
+
npm run test
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Fullstack default sequence
|
|
71
|
+
|
|
72
|
+
When the module exists on both the Vona and Zova sides, the usual sequence is:
|
|
73
|
+
|
|
74
|
+
1. `npm run build:zova:admin`
|
|
75
|
+
2. `npm run deps:vona`
|
|
76
|
+
3. `npm run deps:zova`
|
|
77
|
+
4. `npm run tsc`
|
|
78
|
+
|
|
79
|
+
This keeps the Zova Admin JS bundle and rest output aligned before Vona consumes downstream artifacts.
|
|
80
|
+
|
|
81
|
+
### Narrower branches
|
|
82
|
+
|
|
83
|
+
For backend-only removal, prefer the narrowest meaningful verification first:
|
|
84
|
+
|
|
85
|
+
- `npm run deps:vona`
|
|
86
|
+
- `npm run tsc`
|
|
87
|
+
- `npm run test` when runtime/test coupling is likely
|
|
88
|
+
|
|
89
|
+
For frontend-only removal, use the relevant Zova build/deps path first, then typecheck.
|
|
90
|
+
|
|
91
|
+
## Step 5: Clean generated runtime directories when residues remain stale
|
|
92
|
+
|
|
93
|
+
If stale module types or runtime entries still remain after the normal cleanup and regeneration flow, treat generated runtime directories as disposable working state.
|
|
94
|
+
|
|
95
|
+
In particular, the primary recovery targets for this workflow are:
|
|
96
|
+
|
|
97
|
+
- `vona/.vona`
|
|
98
|
+
- `zova/.zova`
|
|
99
|
+
|
|
100
|
+
These are not necessarily the only generated working directories in the repo, but they are the main stale-runtime targets for normal module-removal recovery.
|
|
101
|
+
|
|
102
|
+
Why this is safe:
|
|
103
|
+
|
|
104
|
+
- these directories are generated by the Vona and Zova CLI flows
|
|
105
|
+
- they are ignored by the repo because they are not source-of-truth files
|
|
106
|
+
- they may survive when a service or build process does not stop cleanly
|
|
107
|
+
|
|
108
|
+
After deleting them, rerun the normal regeneration flow and typecheck again.
|
|
109
|
+
|
|
110
|
+
## Step 6: Verify that the module is really gone
|
|
111
|
+
|
|
112
|
+
Search for remaining references to:
|
|
113
|
+
|
|
114
|
+
- the module relative name
|
|
115
|
+
- the backend workspace package name
|
|
116
|
+
- the frontend workspace package name
|
|
117
|
+
- route or resource names if applicable
|
|
118
|
+
|
|
119
|
+
Then verify with the narrowest meaningful commands first, followed by broader checks when needed.
|
|
120
|
+
|
|
121
|
+
Typical verification commands:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm run build:zova:admin
|
|
125
|
+
npm run deps:vona
|
|
126
|
+
npm run deps:zova
|
|
127
|
+
npm run tsc
|
|
128
|
+
npm run test
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The expected result is:
|
|
132
|
+
|
|
133
|
+
- no direct workspace dependency entries remain
|
|
134
|
+
- no generated registry still points at the removed module
|
|
135
|
+
- no stale typecheck failures still reference the module
|
|
136
|
+
- no important runtime or test surfaces still import it
|
|
137
|
+
|
|
138
|
+
## Step 7: Treat docs cleanup as an explicit second scope
|
|
139
|
+
|
|
140
|
+
Removing code/runtime surfaces does not automatically mean public docs should be rewritten.
|
|
141
|
+
|
|
142
|
+
Make this an explicit scope decision:
|
|
143
|
+
|
|
144
|
+
- code/runtime removal only
|
|
145
|
+
- code/runtime removal plus docs/examples scrub
|
|
146
|
+
|
|
147
|
+
If docs cleanup is in scope, update `cabloy-docs/` as a separate pass after runtime cleanup is stable.
|
|
148
|
+
|
|
149
|
+
## AI rule of thumb
|
|
150
|
+
|
|
151
|
+
A good Cabloy module-removal workflow is usually:
|
|
152
|
+
|
|
153
|
+
1. detect edition and scope
|
|
154
|
+
2. inventory real module surfaces
|
|
155
|
+
3. remove source and direct references
|
|
156
|
+
4. regenerate with repo entrypoints
|
|
157
|
+
5. clean generated runtime dirs only when stale residues remain
|
|
158
|
+
6. verify the module is really gone
|
|
159
|
+
|
|
160
|
+
Not:
|
|
161
|
+
|
|
162
|
+
1. delete a few generated files first
|
|
163
|
+
2. guess which paths matter
|
|
164
|
+
3. leave workspace dependencies or generated registrations stale
|
package/cabloy-docs/ai/skills.md
CHANGED
|
@@ -35,3 +35,14 @@ A strong Cabloy skill usually includes:
|
|
|
35
35
|
When a skill needs to apply an architectural rule such as backend class placement, prefer a branching decision tree that points back to durable docs instead of embedding the full architecture rationale inside the skill itself.
|
|
36
36
|
|
|
37
37
|
For edition-aware skills, use [Edition Detection for AI Workflows](/ai/edition-detection) and [Edition Consistency Checklist](/ai/edition-consistency-checklist) as the durable review surfaces before expanding edition-specific branches.
|
|
38
|
+
|
|
39
|
+
## Example workflow skills in this repo
|
|
40
|
+
|
|
41
|
+
Current examples include:
|
|
42
|
+
|
|
43
|
+
- `cabloy-workflow` for choosing the correct Cabloy work path before implementation
|
|
44
|
+
- `cabloy-contract-loop` for backend/frontend contract regeneration and drift diagnosis
|
|
45
|
+
- `cabloy-resource-field-update` for updating an existing backend resource field thread
|
|
46
|
+
- `cabloy-module-removal` for removing a backend, frontend, or fullstack module cleanly, including generated-runtime cleanup, stale-residue recovery, and verification
|
|
47
|
+
|
|
48
|
+
The module-removal workflow is a good example of why skills belong in `.claude/skills/` instead of `CLAUDE.md`: the task needs branching, cleanup order, recovery guidance for generated runtime directories such as `vona/.vona` and `zova/.zova`, and a verification checklist that would be too large for a short repo-wide rule.
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Backend Bean Scene Authoring
|
|
2
|
+
|
|
3
|
+
This guide explains the **advanced** Vona workflow for creating a **new backend bean scene**.
|
|
4
|
+
|
|
5
|
+
This is not the same as creating one more bean inside an existing scene such as `service`, `model`, or `dto`.
|
|
6
|
+
|
|
7
|
+
For ordinary bean creation inside an existing scene, use the existing CLI workflow documented in [Backend CLI](/backend/cli) and the scene-specific guides. This page is for framework extension work where you need to define a new scene contract.
|
|
8
|
+
|
|
9
|
+
## When you need this guide
|
|
10
|
+
|
|
11
|
+
Use this guide when you need to extend the backend bean system itself, for example:
|
|
12
|
+
|
|
13
|
+
- define a new decorator such as `@Something()`
|
|
14
|
+
- teach `:create:bean` how to scaffold that scene
|
|
15
|
+
- add new scene-level metadata behavior
|
|
16
|
+
- decide whether the scene should appear in module scope resources
|
|
17
|
+
- decide whether the scene should contribute to the general bean registry
|
|
18
|
+
|
|
19
|
+
If you only need a new service or model bean, you do **not** need this page.
|
|
20
|
+
|
|
21
|
+
## Mental model
|
|
22
|
+
|
|
23
|
+
For most scene-based backend beans, the scene is the middle layer inside the bean identity:
|
|
24
|
+
|
|
25
|
+
- bean identifier: `{module}.{scene}.{bean}`
|
|
26
|
+
- onion name: `{module}:{bean}`
|
|
27
|
+
- scene name: the operational family such as `service`, `model`, `entity`, `dto`, or `startup`
|
|
28
|
+
|
|
29
|
+
A practical exception is the built-in global `bean` scene, whose generated global shorthand entries use the plain bean name rather than the full `module.scene.bean` pattern.
|
|
30
|
+
|
|
31
|
+
The scene is not only a naming convention. It controls several framework behaviors:
|
|
32
|
+
|
|
33
|
+
- which decorator marks the class
|
|
34
|
+
- where the CLI places generated files
|
|
35
|
+
- whether the scene contributes to scope resources
|
|
36
|
+
- whether the scene contributes to general bean typing
|
|
37
|
+
- whether scene-specific metadata generation runs
|
|
38
|
+
|
|
39
|
+
## The smallest built-in pattern
|
|
40
|
+
|
|
41
|
+
The simplest built-in scene is a thin decorator wrapper over `createBeanDecorator(...)`.
|
|
42
|
+
|
|
43
|
+
Representative pattern:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { createBeanDecorator } from 'vona';
|
|
47
|
+
|
|
48
|
+
export function Service(): ClassDecorator {
|
|
49
|
+
return createBeanDecorator('service');
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That pattern is the first authoring surface of a new scene: give the scene a stable framework name.
|
|
54
|
+
|
|
55
|
+
Some scenes use richer decorator forms with options or scene-specific post-registration behavior. A good example is `Model()`, which is implemented outside the base bean module and passes scene options through the decorator contract.
|
|
56
|
+
|
|
57
|
+
## The backend authoring surfaces
|
|
58
|
+
|
|
59
|
+
A new backend bean scene usually touches five surfaces.
|
|
60
|
+
|
|
61
|
+
### 1. Decorator surface
|
|
62
|
+
|
|
63
|
+
Define the scene decorator and export it from the owning module.
|
|
64
|
+
|
|
65
|
+
Representative built-in patterns include:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
export function Bean(): ClassDecorator {
|
|
69
|
+
return createBeanDecorator('bean');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function Scope(): ClassDecorator {
|
|
73
|
+
return createBeanDecorator('scope');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
A scene-specific decorator can live in the base bean module or in a more specialized module. For example, `Model()` is implemented in the ORM module rather than the base bean module.
|
|
78
|
+
|
|
79
|
+
### 2. Scene typing surface
|
|
80
|
+
|
|
81
|
+
Add the scene to the declaration-merging type registry.
|
|
82
|
+
|
|
83
|
+
Representative pattern:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
declare module 'vona' {
|
|
87
|
+
export interface IBeanSceneRecord {
|
|
88
|
+
service: never;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This tells the framework and generated typings that the scene exists.
|
|
94
|
+
|
|
95
|
+
Some scenes also extend a scene-specific record in their owning module. For example, the built-in service scene contributes to `IServiceRecord` and then maps that into the broader onion surface.
|
|
96
|
+
|
|
97
|
+
### 3. Onion metadata surface
|
|
98
|
+
|
|
99
|
+
Register the scene in the owning module `package.json` under `vonaModule.onions`.
|
|
100
|
+
|
|
101
|
+
Representative built-in pattern:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"service": {
|
|
106
|
+
"sceneIsolate": true,
|
|
107
|
+
"scopeResource": true,
|
|
108
|
+
"beanGeneral": true,
|
|
109
|
+
"optionsGlobalInterfaceFrom": "vona-module-a-bean",
|
|
110
|
+
"boilerplate": "service/boilerplate"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
This metadata is one of the main contracts for `:create:bean` and metadata generation.
|
|
116
|
+
|
|
117
|
+
### 4. CLI boilerplate surface
|
|
118
|
+
|
|
119
|
+
Provide the scaffold template used by `npm run vona :create:bean sceneName beanName -- --module=...`.
|
|
120
|
+
|
|
121
|
+
Representative built-in boilerplate:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { BeanBase } from 'vona';
|
|
125
|
+
import { Bean } from 'vona-module-a-bean';
|
|
126
|
+
|
|
127
|
+
@Bean()
|
|
128
|
+
export class Bean<%=argv.beanNameCapitalize%> extends BeanBase {}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The important point is not the exact class body. The important point is that the scene owns a template and the CLI resolves it through the onion metadata.
|
|
132
|
+
|
|
133
|
+
### 5. Metadata generation surface
|
|
134
|
+
|
|
135
|
+
Add custom metadata generation only when the scene needs output beyond the default scene scan.
|
|
136
|
+
|
|
137
|
+
Representative built-in pattern:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
export default async function (options) {
|
|
141
|
+
const { sceneName, globFiles } = options;
|
|
142
|
+
// ...build declaration-merging content...
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
For example, the built-in `bean` scene adds `IBeanRecordGlobal` output through a custom metadata generator.
|
|
147
|
+
|
|
148
|
+
## How `vonaModule.onions` drives scene behavior
|
|
149
|
+
|
|
150
|
+
When adding a scene, the most important design step is deciding the scene flags.
|
|
151
|
+
|
|
152
|
+
### `sceneIsolate`
|
|
153
|
+
|
|
154
|
+
Use this when the scene should live in its own top-level folder rather than being mixed into `src/bean`.
|
|
155
|
+
|
|
156
|
+
Representative example:
|
|
157
|
+
|
|
158
|
+
- `service` uses `sceneIsolate: true`
|
|
159
|
+
- generated files live under `src/service/`
|
|
160
|
+
|
|
161
|
+
A non-isolated scene normally stays in `src/bean` using the `{scene}.{bean}` naming pattern.
|
|
162
|
+
|
|
163
|
+
### `scopeResource`
|
|
164
|
+
|
|
165
|
+
Use this when the scene should appear as a module scope resource such as `this.scope.service.student`.
|
|
166
|
+
|
|
167
|
+
If this flag is enabled, metadata generation will create module-scope typing such as:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
export interface IModuleService {
|
|
171
|
+
student: ServiceStudent;
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Scenes without scope-resource behavior should not set this flag just for convenience.
|
|
176
|
+
|
|
177
|
+
### `beanGeneral`
|
|
178
|
+
|
|
179
|
+
Use this when the scene should contribute to the general bean registry.
|
|
180
|
+
|
|
181
|
+
Representative generated output:
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
declare module 'vona' {
|
|
185
|
+
export interface IBeanRecordGeneral {
|
|
186
|
+
'demo-student.service.student': ServiceStudent;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This matters for container-oriented lookup and the broader typed bean surface.
|
|
192
|
+
|
|
193
|
+
### `boilerplate`
|
|
194
|
+
|
|
195
|
+
Use this to tell the CLI which template should be used when a bean of the scene is created.
|
|
196
|
+
|
|
197
|
+
### Multiple boilerplate variants
|
|
198
|
+
|
|
199
|
+
A backend scene can expose more than one named template.
|
|
200
|
+
|
|
201
|
+
A practical rule is:
|
|
202
|
+
|
|
203
|
+
- `boilerplate` provides the default template
|
|
204
|
+
- `--boilerplate=web` maps to `boilerplateWeb`
|
|
205
|
+
- more generally, `--boilerplate=name` maps to `boilerplateName`
|
|
206
|
+
|
|
207
|
+
This is useful when one scene needs multiple scaffold shapes for distinct runtime targets or authoring paths.
|
|
208
|
+
|
|
209
|
+
Representative built-in examples include `ssrMenu` and `ssrMenuGroup`, which expose both the default template and a `web` variant in module metadata.
|
|
210
|
+
|
|
211
|
+
### `metadataCustom`
|
|
212
|
+
|
|
213
|
+
Use this only when the scene needs additional generated output that is not covered by the standard metadata passes.
|
|
214
|
+
|
|
215
|
+
A good rule is:
|
|
216
|
+
|
|
217
|
+
- start without custom metadata if the default scene wiring is enough
|
|
218
|
+
- add `metadataCustom` only when the scene has a real extra output contract
|
|
219
|
+
|
|
220
|
+
## Authoring flow for a new backend scene
|
|
221
|
+
|
|
222
|
+
A practical Vona scene-authoring workflow is:
|
|
223
|
+
|
|
224
|
+
1. choose the owning module for the scene
|
|
225
|
+
2. add the scene decorator
|
|
226
|
+
3. export it from the module `src/lib/index.ts`
|
|
227
|
+
4. add the scene declaration-merging type and export it from `src/types/index.ts`
|
|
228
|
+
5. add the scene under `vonaModule.onions`
|
|
229
|
+
6. create the scene boilerplate for `:create:bean`
|
|
230
|
+
7. add custom metadata generation if the scene needs extra emitted typings
|
|
231
|
+
8. run bean creation in a representative module
|
|
232
|
+
9. inspect the generated `.metadata/index.ts` output
|
|
233
|
+
10. only then write any additional scene-specific docs or business examples
|
|
234
|
+
|
|
235
|
+
## What generated output should prove
|
|
236
|
+
|
|
237
|
+
A new scene is usually correct only if the generated metadata proves the intended contract.
|
|
238
|
+
|
|
239
|
+
Depending on scene flags, inspect for output such as:
|
|
240
|
+
|
|
241
|
+
- declaration merging for the scene itself
|
|
242
|
+
- `IBeanRecordGeneral`
|
|
243
|
+
- module scope-resource interfaces such as `IModuleService`
|
|
244
|
+
- bean instance helpers such as `$beanFullName` and `$onionName`
|
|
245
|
+
- scope-class integration for module resource access
|
|
246
|
+
|
|
247
|
+
Representative generated service output includes:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
export interface ServiceStudent {
|
|
251
|
+
get $beanFullName(): 'demo-student.service.student';
|
|
252
|
+
get $onionName(): 'demo-student:student';
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
and:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
export interface IModuleService {
|
|
260
|
+
student: ServiceStudent;
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
If the generated metadata does not match the scene design, fix the scene contract first rather than patching the generated output manually.
|
|
265
|
+
|
|
266
|
+
## A useful split: adding a scene vs adding a bean
|
|
267
|
+
|
|
268
|
+
Keep these two tasks separate.
|
|
269
|
+
|
|
270
|
+
### Add a bean inside an existing scene
|
|
271
|
+
|
|
272
|
+
Example:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
npm run vona :create:bean service student -- --module=demo-student
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
This uses an already-defined scene.
|
|
279
|
+
|
|
280
|
+
### Add a new scene
|
|
281
|
+
|
|
282
|
+
This requires framework extension work:
|
|
283
|
+
|
|
284
|
+
- new decorator
|
|
285
|
+
- new scene type registration
|
|
286
|
+
- new onion metadata entry
|
|
287
|
+
- new boilerplate
|
|
288
|
+
- optional metadata generation
|
|
289
|
+
|
|
290
|
+
That is why this topic belongs in an advanced guide.
|
|
291
|
+
|
|
292
|
+
## Design rules for new scenes
|
|
293
|
+
|
|
294
|
+
Before adding a scene, ask these questions.
|
|
295
|
+
|
|
296
|
+
### Should the scene be isolated?
|
|
297
|
+
|
|
298
|
+
Choose an isolated scene when the scene deserves its own first-class folder and operational identity, similar to `service`.
|
|
299
|
+
|
|
300
|
+
Choose a non-isolated scene when the scene is better modeled as a bean-family variant under `src/bean`.
|
|
301
|
+
|
|
302
|
+
### Should the scene appear in module scope?
|
|
303
|
+
|
|
304
|
+
Enable scope-resource generation only when the scene should behave like a normal module resource family.
|
|
305
|
+
|
|
306
|
+
If the scene is mainly metadata, infrastructure glue, or a special registry surface, scope exposure may be the wrong contract.
|
|
307
|
+
|
|
308
|
+
### Should the scene be part of the general bean registry?
|
|
309
|
+
|
|
310
|
+
Enable `beanGeneral` only when typed global/general bean lookup is part of the intended developer surface.
|
|
311
|
+
|
|
312
|
+
### Does the scene need custom metadata?
|
|
313
|
+
|
|
314
|
+
Do not add custom generation only because it is available. Add it when the scene needs a real emitted surface beyond the default metadata pipeline.
|
|
315
|
+
|
|
316
|
+
## Relationship to existing guides
|
|
317
|
+
|
|
318
|
+
Read this guide together with:
|
|
319
|
+
|
|
320
|
+
- [Backend Foundation](/backend/foundation)
|
|
321
|
+
- [Backend CLI](/backend/cli)
|
|
322
|
+
- [Service Guide](/backend/service-guide)
|
|
323
|
+
- [Model Guide](/backend/model-guide)
|
|
324
|
+
- [Entity Guide](/backend/entity-guide)
|
|
325
|
+
- [Backend Startup Guide](/backend/startup-guide)
|
|
326
|
+
|
|
327
|
+
Use the basic guides for normal bean creation. Use this page only when extending the scene system itself.
|
|
328
|
+
|
|
329
|
+
## Verification checklist
|
|
330
|
+
|
|
331
|
+
When authoring or documenting a new backend scene, verify in this order:
|
|
332
|
+
|
|
333
|
+
1. confirm the CLI command shape still exists:
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
npm run vona :create:bean --help
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
2. confirm the scene decorator, scene typing, and `vonaModule.onions` entry agree
|
|
340
|
+
3. create a test bean in a representative module
|
|
341
|
+
4. inspect the generated source placement
|
|
342
|
+
5. inspect `src/.metadata/index.ts` in that module
|
|
343
|
+
6. confirm scope resources and general bean output match the design
|
|
344
|
+
7. run the narrowest meaningful type or docs verification for the change
|
|
345
|
+
|
|
346
|
+
For repo-wide docs verification, also run:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
npm run docs:build
|
|
350
|
+
```
|
|
@@ -122,6 +122,24 @@ A practical bean-scene reading is:
|
|
|
122
122
|
- `:create:bean sceneName beanName -- --module=...` uses `sceneName` as the operational family slot inside the bean identifier
|
|
123
123
|
- this is why generated bean names later appear in forms such as `module.scene.bean`
|
|
124
124
|
|
|
125
|
+
## Bean boilerplate variants
|
|
126
|
+
|
|
127
|
+
Some backend bean scenes expose more than one scaffold template.
|
|
128
|
+
|
|
129
|
+
In those cases, use `--boilerplate=...` to select a named variant:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npm run vona :create:bean ssrMenu menuTest -- --module=demo-student --boilerplate=web
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
A practical rule is:
|
|
136
|
+
|
|
137
|
+
- the default scene template comes from the scene metadata `boilerplate`
|
|
138
|
+
- a named variant such as `--boilerplate=web` maps to a metadata key such as `boilerplateWeb`
|
|
139
|
+
- supported variants are scene-defined, so do not assume every scene exposes them
|
|
140
|
+
|
|
141
|
+
For the current cross-stack lookup table, see [Bean Scene Boilerplate Variants](/reference/bean-scene-boilerplates).
|
|
142
|
+
|
|
125
143
|
## Initializer-family examples
|
|
126
144
|
|
|
127
145
|
Not every backend resource is created through bean scenes.
|
|
@@ -131,13 +149,20 @@ Representative initializer commands include:
|
|
|
131
149
|
```bash
|
|
132
150
|
npm run vona :init:constant demo-student
|
|
133
151
|
npm run vona :init:types demo-student
|
|
152
|
+
npm run vona :init:lib demo-student
|
|
134
153
|
npm run vona :init:asset static -- --module=demo-student
|
|
135
154
|
```
|
|
136
155
|
|
|
137
156
|
A practical distinction is:
|
|
138
157
|
|
|
139
158
|
- `:create:bean` creates scene-based backend beans
|
|
140
|
-
- `:init:*` commands create module-scope resources such as constants, typings, or asset-resource structure
|
|
159
|
+
- `:init:*` commands create module-scope resources such as constants, typings, helper directories, or asset-resource structure
|
|
160
|
+
|
|
161
|
+
A practical helper-placement rule is:
|
|
162
|
+
|
|
163
|
+
- if a backend module needs reusable pure helper functions, initialize `src/lib` with `npm run vona :init:lib demo-student`
|
|
164
|
+
- place those shared helpers under `src/lib` and export shared entrypoints from `src/lib/index.ts`
|
|
165
|
+
- if the logic needs container-managed runtime behavior, do not force it into `src/lib`; re-evaluate `src/service` or another bean scene instead
|
|
141
166
|
|
|
142
167
|
## Relationship to modules, suites, and package metadata
|
|
143
168
|
|
|
@@ -73,6 +73,12 @@ class DtoStudentCreate {
|
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
When mixing helper metadata and an explicit zod schema in `@Api.field(...)`, apply the same ordering rule used by entities:
|
|
77
|
+
|
|
78
|
+
- place `z.xxx(...)` as the **last argument** because it returns the zod schema instance
|
|
79
|
+
- keep helper metadata such as `v.xxx(...)` and `ZovaRender.xxx(...)` before the zod schema
|
|
80
|
+
- otherwise helpers written after the zod schema may stop taking effect
|
|
81
|
+
|
|
76
82
|
For query-oriented DTOs, another important distinction is optional vs nullable:
|
|
77
83
|
|
|
78
84
|
- `v.optional()` means the field may be omitted
|