cabloy 5.1.50 → 5.1.51
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 +207 -0
- package/.claude/skills/cabloy-backend-scaffold/evals/evals.json +29 -0
- package/.claude/skills/cabloy-backend-scaffold/references/backend-thread-map.md +52 -0
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +39 -0
- package/.claude/skills/cabloy-contract-loop/SKILL.md +201 -0
- package/.claude/skills/cabloy-contract-loop/evals/evals.json +29 -0
- package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +47 -0
- package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +32 -0
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +230 -0
- package/.claude/skills/cabloy-frontend-scaffold/evals/evals.json +35 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +41 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/frontend-thread-map.md +54 -0
- package/.claude/skills/cabloy-workflow/SKILL.md +288 -0
- package/.claude/skills/cabloy-workflow/evals/evals.json +35 -0
- package/.claude/skills/cabloy-workflow/references/cli-strategy.md +39 -0
- package/.claude/skills/cabloy-workflow/references/edition-detection.md +29 -0
- package/.github/workflows/docs-pages.yml +54 -0
- package/.gitignore +1 -0
- package/CHANGELOG.md +29 -0
- package/CLAUDE.md +59 -0
- package/README.md +137 -0
- package/cabloy-docs/.vitepress/config.mjs +222 -0
- package/cabloy-docs/.vitepress/public/CNAME +1 -0
- package/cabloy-docs/.vitepress/theme/custom.css +64 -0
- package/cabloy-docs/.vitepress/theme/edition-badges.md +5 -0
- package/cabloy-docs/.vitepress/theme/index.js +5 -0
- package/cabloy-docs/ai/class-placement-rule.md +138 -0
- package/cabloy-docs/ai/cli-for-agents.md +56 -0
- package/cabloy-docs/ai/cli-to-skill-map.md +165 -0
- package/cabloy-docs/ai/docs-skills-rules-mapping.md +167 -0
- package/cabloy-docs/ai/edition-detection.md +30 -0
- package/cabloy-docs/ai/future-skill-roadmap.md +135 -0
- package/cabloy-docs/ai/global-bean-lookup.md +157 -0
- package/cabloy-docs/ai/introduction.md +62 -0
- package/cabloy-docs/ai/playbook-backend-module.md +111 -0
- package/cabloy-docs/ai/playbook-contract-regeneration.md +100 -0
- package/cabloy-docs/ai/playbook-frontend-page.md +99 -0
- package/cabloy-docs/ai/playbook-metadata-refresh.md +67 -0
- package/cabloy-docs/ai/repo-guidance.md +58 -0
- package/cabloy-docs/ai/rules-and-config.md +29 -0
- package/cabloy-docs/ai/skills.md +35 -0
- package/cabloy-docs/ai/verification.md +30 -0
- package/cabloy-docs/backend/aop-overview.md +128 -0
- package/cabloy-docs/backend/auth-guide.md +151 -0
- package/cabloy-docs/backend/backend-essentials.md +128 -0
- package/cabloy-docs/backend/broadcast-guide.md +138 -0
- package/cabloy-docs/backend/cache-guide.md +70 -0
- package/cabloy-docs/backend/captcha-guide.md +162 -0
- package/cabloy-docs/backend/cli.md +173 -0
- package/cabloy-docs/backend/config-guide.md +249 -0
- package/cabloy-docs/backend/controller-aop-guide.md +270 -0
- package/cabloy-docs/backend/controller-guide.md +347 -0
- package/cabloy-docs/backend/crud-workflow.md +118 -0
- package/cabloy-docs/backend/dto-guide.md +161 -0
- package/cabloy-docs/backend/dto-infer-generation.md +153 -0
- package/cabloy-docs/backend/dynamic-datasource-guide.md +70 -0
- package/cabloy-docs/backend/election-guide.md +141 -0
- package/cabloy-docs/backend/entity-guide.md +150 -0
- package/cabloy-docs/backend/error-guide.md +108 -0
- package/cabloy-docs/backend/event-guide.md +183 -0
- package/cabloy-docs/backend/external-aop-guide.md +149 -0
- package/cabloy-docs/backend/field-indexes.md +79 -0
- package/cabloy-docs/backend/foundation.md +281 -0
- package/cabloy-docs/backend/i18n-guide.md +211 -0
- package/cabloy-docs/backend/internal-aop-guide.md +181 -0
- package/cabloy-docs/backend/introduction.md +95 -0
- package/cabloy-docs/backend/jwt-guide.md +276 -0
- package/cabloy-docs/backend/logger-guide.md +223 -0
- package/cabloy-docs/backend/mail-guide.md +189 -0
- package/cabloy-docs/backend/menu-guide.md +80 -0
- package/cabloy-docs/backend/migration-and-changes.md +192 -0
- package/cabloy-docs/backend/model-guide.md +274 -0
- package/cabloy-docs/backend/multi-database-datasource.md +171 -0
- package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +196 -0
- package/cabloy-docs/backend/openapi-guide.md +118 -0
- package/cabloy-docs/backend/orm-aggregate-group-guide.md +210 -0
- package/cabloy-docs/backend/orm-configuration-guide.md +165 -0
- package/cabloy-docs/backend/orm-guide.md +109 -0
- package/cabloy-docs/backend/orm-mutation-guide.md +195 -0
- package/cabloy-docs/backend/orm-select-guide.md +243 -0
- package/cabloy-docs/backend/queue-guide.md +271 -0
- package/cabloy-docs/backend/quickstart.md +141 -0
- package/cabloy-docs/backend/redis-guide.md +70 -0
- package/cabloy-docs/backend/redlock-guide.md +60 -0
- package/cabloy-docs/backend/relations-guide.md +250 -0
- package/cabloy-docs/backend/runtime-and-flavors.md +304 -0
- package/cabloy-docs/backend/schedule-guide.md +81 -0
- package/cabloy-docs/backend/scripts.md +116 -0
- package/cabloy-docs/backend/serialization-guide.md +192 -0
- package/cabloy-docs/backend/service-guide.md +166 -0
- package/cabloy-docs/backend/sharding-guide.md +49 -0
- package/cabloy-docs/backend/startup-guide.md +326 -0
- package/cabloy-docs/backend/transaction-guide.md +82 -0
- package/cabloy-docs/backend/unit-testing.md +209 -0
- package/cabloy-docs/backend/upload-guide.md +160 -0
- package/cabloy-docs/backend/user-access-guide.md +157 -0
- package/cabloy-docs/backend/validation-guide.md +80 -0
- package/cabloy-docs/backend/worker-guide.md +59 -0
- package/cabloy-docs/editions/cabloy-basic.md +25 -0
- package/cabloy-docs/editions/cabloy-start.md +24 -0
- package/cabloy-docs/editions/detection.md +31 -0
- package/cabloy-docs/editions/overview.md +44 -0
- package/cabloy-docs/frontend/api-guide.md +93 -0
- package/cabloy-docs/frontend/api-schema-guide.md +43 -0
- package/cabloy-docs/frontend/app-startup-guide.md +185 -0
- package/cabloy-docs/frontend/cli.md +78 -0
- package/cabloy-docs/frontend/component-guide.md +105 -0
- package/cabloy-docs/frontend/component-props-guide.md +97 -0
- package/cabloy-docs/frontend/component-v-model-guide.md +110 -0
- package/cabloy-docs/frontend/css-in-js-guide.md +151 -0
- package/cabloy-docs/frontend/design-principles.md +55 -0
- package/cabloy-docs/frontend/environment-config-guide.md +250 -0
- package/cabloy-docs/frontend/foundation.md +57 -0
- package/cabloy-docs/frontend/generic-component-guide.md +35 -0
- package/cabloy-docs/frontend/icon-engine-guide.md +88 -0
- package/cabloy-docs/frontend/introduction.md +32 -0
- package/cabloy-docs/frontend/ioc-and-beans.md +211 -0
- package/cabloy-docs/frontend/mock-guide.md +109 -0
- package/cabloy-docs/frontend/model-architecture.md +87 -0
- package/cabloy-docs/frontend/model-state-guide.md +70 -0
- package/cabloy-docs/frontend/module-scope.md +168 -0
- package/cabloy-docs/frontend/modules-and-suites.md +179 -0
- package/cabloy-docs/frontend/navigation-guards-guide.md +68 -0
- package/cabloy-docs/frontend/openapi-sdk-guide.md +102 -0
- package/cabloy-docs/frontend/page-guide.md +223 -0
- package/cabloy-docs/frontend/page-params-guide.md +87 -0
- package/cabloy-docs/frontend/page-query-guide.md +96 -0
- package/cabloy-docs/frontend/page-route-guide.md +147 -0
- package/cabloy-docs/frontend/quickstart.md +201 -0
- package/cabloy-docs/frontend/route-alias-guide.md +61 -0
- package/cabloy-docs/frontend/scripts.md +86 -0
- package/cabloy-docs/frontend/sdk-guide.md +45 -0
- package/cabloy-docs/frontend/server-data.md +74 -0
- package/cabloy-docs/frontend/ssr-client-only.md +40 -0
- package/cabloy-docs/frontend/ssr-env.md +51 -0
- package/cabloy-docs/frontend/ssr-init-data.md +46 -0
- package/cabloy-docs/frontend/ssr-overview.md +48 -0
- package/cabloy-docs/frontend/ssr-seo-meta.md +52 -0
- package/cabloy-docs/frontend/system-startup-guide.md +186 -0
- package/cabloy-docs/frontend/theme-guide.md +154 -0
- package/cabloy-docs/frontend/zod-guide.md +161 -0
- package/cabloy-docs/fullstack/edition-collaboration-differences.md +61 -0
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +64 -0
- package/cabloy-docs/fullstack/introduction.md +69 -0
- package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -0
- package/cabloy-docs/fullstack/quickstart.md +86 -0
- package/cabloy-docs/fullstack/vona-zova-integration.md +86 -0
- package/cabloy-docs/index.md +73 -0
- package/cabloy-docs/package.json +16 -0
- package/cabloy-docs/pnpm-lock.yaml +1607 -0
- package/cabloy-docs/reference/backend-directory-structure.md +88 -0
- package/cabloy-docs/reference/cli-reference.md +49 -0
- package/cabloy-docs/reference/glossary.md +38 -0
- package/cabloy-docs/reference/package-map.md +105 -0
- package/cabloy-docs/reference/repo-scripts.md +36 -0
- package/package.json +4 -1
- package/scripts/init.ts +12 -0
- package/scripts/upgrade.ts +31 -3
- package/vona/README.md +3 -3
- package/vona/README.zh-CN.md +4 -4
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/src/bean/summerCache.datasourceWrite.ts +2 -2
- package/vona/src/suite-vendor/a-cabloy/package.json +1 -1
- package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
- package/vona/src/suite-vendor/a-captcha/modules/a-captcha/src/bean/cacheRedis.captcha.ts +2 -2
- package/vona/src/suite-vendor/a-captcha/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-bean/cli/bean/metadata/generate.ts +5 -6
- package/vona/src/suite-vendor/a-vona/modules/a-bean/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheMem/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheRedis/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-cache/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-cache/src/.metadata/index.ts +13 -2
- package/vona/src/suite-vendor/a-vona/modules/a-cache/src/bean/bean.cache.ts +6 -7
- package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheMemBase.ts → service/cacheMemBase_.ts} +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheRedisBase.ts → service/cacheRedisBase_.ts} +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.emailConfirm.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.passwordReset.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/bean/summerCache.json.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/databaseDialect/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +4 -3
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.database.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.model.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/schedule.softDeletionPrune.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/common/utils.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_cache.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_meta.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.modelBase.ts +0 -5
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAggregate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoCreate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGroup.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoMutate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoSelectAndCount.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoUpdate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/modelCacheBase.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relations.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsDynamic.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsMutate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsStatic.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheEntity_.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheQuery_.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/database.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean/bean.databaseDialectBase.ts → service/databaseDialectBase_.ts} +38 -41
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/db_.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/relations_.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/database.ts +0 -5
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoGet.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoMutate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoSelectAndCount.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/model.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelAggr.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelCount.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGeneral.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGroup.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelIncrement.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relations.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsColumns.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDef.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefDynamic.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefMutate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsMutate.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsTables.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.betterSqlite3.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.pg.ts +2 -2
- 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 +109 -40
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permission.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-startup/src/bean/cacheRedis.startupDebounce.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-summer/cli/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-summer/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-summer/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-summer/src/bean/bean.summer.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localMem_.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localRedis_.ts +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-summer/src/{bean/bean.summerCacheBase.ts → service/summerCacheBase_.ts} +3 -3
- package/vona/src/suite-vendor/a-vona/modules/a-swagger/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.rapidoc.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.swagger.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/cacheRedis.authToken.ts +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-worker/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-worker/src/bean/cacheRedis.workerAlive.ts +2 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/README.md +4 -4
- package/zova/README.zh-CN.md +4 -4
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud.ts +0 -0
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_inner.ts +0 -0
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_table.ts +0 -0
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_knex.ts +0 -0
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_utils.ts +0 -0
- /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_view.ts +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Icon Engine Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how the icon engine works in Zova within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why the icon engine exists
|
|
6
|
+
|
|
7
|
+
In large systems, no fixed built-in icon set is ever enough.
|
|
8
|
+
|
|
9
|
+
Zova’s icon engine solves that problem by treating icons as a modular, asynchronous, UI-library-independent resource system.
|
|
10
|
+
|
|
11
|
+
## Core advantages
|
|
12
|
+
|
|
13
|
+
Several important advantages stand out:
|
|
14
|
+
|
|
15
|
+
- easy icon maintenance
|
|
16
|
+
- performance-conscious loading behavior
|
|
17
|
+
- asynchronous loading on demand
|
|
18
|
+
- UI-library independence
|
|
19
|
+
|
|
20
|
+
This is especially important for Cabloy because the same icon strategy should work across Basic and Start even when their UI libraries differ.
|
|
21
|
+
|
|
22
|
+
## Basic concepts
|
|
23
|
+
|
|
24
|
+
The icon engine is organized around two ideas:
|
|
25
|
+
|
|
26
|
+
### Icon group
|
|
27
|
+
|
|
28
|
+
A group combines multiple SVG icons into one asynchronously loaded unit.
|
|
29
|
+
|
|
30
|
+
### Icon module
|
|
31
|
+
|
|
32
|
+
An icon module can contain multiple groups, and a system can contain multiple icon modules.
|
|
33
|
+
|
|
34
|
+
## Naming convention
|
|
35
|
+
|
|
36
|
+
The naming convention is:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
{moduleName}:{groupName}:{iconName}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Representative example:
|
|
43
|
+
|
|
44
|
+
- full name: `home-icon:default:add`
|
|
45
|
+
|
|
46
|
+
There are also shorthand rules, such as:
|
|
47
|
+
|
|
48
|
+
- `::add`
|
|
49
|
+
- `:auth:github`
|
|
50
|
+
- `test-othericon::icon`
|
|
51
|
+
|
|
52
|
+
This matters because icon use is part of the framework’s typed, discoverable resource model.
|
|
53
|
+
|
|
54
|
+
## Access helpers
|
|
55
|
+
|
|
56
|
+
Two important helpers are:
|
|
57
|
+
|
|
58
|
+
- `icon` for typed icon-name access and completion
|
|
59
|
+
- `iconh` for directly generating the icon vnode
|
|
60
|
+
|
|
61
|
+
## UI-library independence
|
|
62
|
+
|
|
63
|
+
The icon engine exposes a unified interface that can be used from multiple UI libraries.
|
|
64
|
+
|
|
65
|
+
This is one of the clearest places where Zova’s architecture deliberately protects higher-level app code from UI-library churn.
|
|
66
|
+
|
|
67
|
+
## Create and build icons
|
|
68
|
+
|
|
69
|
+
A simple process looks like this:
|
|
70
|
+
|
|
71
|
+
1. initialize the icon skeleton
|
|
72
|
+
2. place SVG icons into the module/group directory
|
|
73
|
+
3. regenerate metadata
|
|
74
|
+
|
|
75
|
+
The metadata generation step matters because icons are part of the framework’s typed resource graph.
|
|
76
|
+
|
|
77
|
+
## Implementation checks for icon-related changes
|
|
78
|
+
|
|
79
|
+
When adding icons, do not hardcode one-off icon usage patterns too quickly.
|
|
80
|
+
|
|
81
|
+
A better default is to ask:
|
|
82
|
+
|
|
83
|
+
1. should the icon belong in an existing icon module or a new one?
|
|
84
|
+
2. what group should own it?
|
|
85
|
+
3. should metadata be regenerated after adding the icon?
|
|
86
|
+
4. is the chosen icon usage path still UI-library-independent?
|
|
87
|
+
|
|
88
|
+
That keeps icon work maintainable and consistent across editions.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Frontend (Zova)
|
|
2
|
+
|
|
3
|
+
This page is the frontend hub for contributors who are documenting, designing, or extending frontend work in the Cabloy repository.
|
|
4
|
+
|
|
5
|
+
Zova is the frontend half of the Cabloy fullstack architecture.
|
|
6
|
+
|
|
7
|
+
## What Zova is responsible for
|
|
8
|
+
|
|
9
|
+
- page and component architecture
|
|
10
|
+
- SSR, SPA, Web, and Admin rendering flows
|
|
11
|
+
- data access patterns such as `$fetch`, `$api`, and generated SDKs
|
|
12
|
+
- UI library integration
|
|
13
|
+
- route, icon, and component type generation
|
|
14
|
+
- frontend-side refactors and code generation through the Zova CLI
|
|
15
|
+
|
|
16
|
+
## How to approach frontend work
|
|
17
|
+
|
|
18
|
+
For contributor and automation workflows in this repository, prefer this order:
|
|
19
|
+
|
|
20
|
+
1. inspect the root `package.json` and `npm run zova` entrypoint
|
|
21
|
+
2. inspect Zova CLI command families such as `create:*`, `init:*`, `refactor:*`, `tools:*`, and `openapi:*`
|
|
22
|
+
3. inspect the active edition before assuming a UI stack
|
|
23
|
+
4. document shared concepts once, then isolate edition-specific notes where the module set or UI library differs
|
|
24
|
+
|
|
25
|
+
## Edition impact
|
|
26
|
+
|
|
27
|
+
Frontend work is where Cabloy Basic and Cabloy Start differ most clearly.
|
|
28
|
+
|
|
29
|
+
- **Cabloy Basic** uses a frontend stack centered on DaisyUI and TailwindCSS in the current docs and examples.
|
|
30
|
+
- **Cabloy Start** uses Vuetify and ships different frontend modules as a private value-add project.
|
|
31
|
+
|
|
32
|
+
Because of this, automation and docs should always detect the active edition before recommending page-level, component-level, or UI-library-specific work.
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# IoC and Beans
|
|
2
|
+
|
|
3
|
+
## Why IoC matters in Zova
|
|
4
|
+
|
|
5
|
+
Zova uses IoC as a unifying frontend architecture rather than treating it as a small dependency-injection helper.
|
|
6
|
+
|
|
7
|
+
That matters because state sharing, resource access, lifecycle behavior, and cross-module composition all need to stay structured as the system grows.
|
|
8
|
+
|
|
9
|
+
## The four state-sharing scopes
|
|
10
|
+
|
|
11
|
+
A key Zova idea is that several common sharing scopes can be handled through one IoC-centered model:
|
|
12
|
+
|
|
13
|
+
- component-internal
|
|
14
|
+
- between-components
|
|
15
|
+
- app-global
|
|
16
|
+
- system-level
|
|
17
|
+
|
|
18
|
+
This replaces the need to switch constantly between unrelated mechanisms for each sharing scope.
|
|
19
|
+
|
|
20
|
+
## The three container types
|
|
21
|
+
|
|
22
|
+
Zova uses three main IoC containers:
|
|
23
|
+
|
|
24
|
+
- **sys container** for system-wide singleton-style beans
|
|
25
|
+
- **app container** for request-scoped or app-scoped beans
|
|
26
|
+
- **ctx container** for component-instance-local beans
|
|
27
|
+
|
|
28
|
+
This is one of the main reasons Zova can support both SSR-aware behavior and strongly structured frontend logic.
|
|
29
|
+
|
|
30
|
+
## Bean classes
|
|
31
|
+
|
|
32
|
+
Zova’s IoC model is built around bean classes provided by modules.
|
|
33
|
+
|
|
34
|
+
All beans inherit from `BeanBase`, which exposes common framework capabilities and gives each bean a structured place inside the broader frontend architecture.
|
|
35
|
+
|
|
36
|
+
## `BeanBase`
|
|
37
|
+
|
|
38
|
+
`BeanBase` provides built-in members and is also a host for extended members injected by modules and adapters.
|
|
39
|
+
|
|
40
|
+
Representative members include:
|
|
41
|
+
|
|
42
|
+
- `sys`
|
|
43
|
+
- `app`
|
|
44
|
+
- `ctx`
|
|
45
|
+
- `bean`
|
|
46
|
+
- `scope`
|
|
47
|
+
- `$el`
|
|
48
|
+
- `$event`
|
|
49
|
+
- `$ssr`
|
|
50
|
+
- `$useMeta`
|
|
51
|
+
|
|
52
|
+
Page and component beans also get frontend-specific members such as:
|
|
53
|
+
|
|
54
|
+
- `$params`
|
|
55
|
+
- `$query`
|
|
56
|
+
- `$props`
|
|
57
|
+
|
|
58
|
+
Module and UI adapters can further extend the base surface.
|
|
59
|
+
|
|
60
|
+
## Injection methods
|
|
61
|
+
|
|
62
|
+
Zova supports two main styles:
|
|
63
|
+
|
|
64
|
+
- **dependency injection** through `@Use`
|
|
65
|
+
- **dependency lookup** through the container and scope model
|
|
66
|
+
|
|
67
|
+
A key Zova preference is to keep the code concise by favoring dependency lookup where it leads to clearer business code.
|
|
68
|
+
|
|
69
|
+
## Resolution rules
|
|
70
|
+
|
|
71
|
+
A bean can be resolved by:
|
|
72
|
+
|
|
73
|
+
- bean class
|
|
74
|
+
- bean identifier
|
|
75
|
+
- registration name
|
|
76
|
+
- variable name
|
|
77
|
+
|
|
78
|
+
The most important design point is that cross-module access should prefer bean identifiers over hardwired file-path coupling.
|
|
79
|
+
|
|
80
|
+
### Representative `@Use` patterns
|
|
81
|
+
|
|
82
|
+
Same-module injection can stay class-oriented and concise:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { ModelTodo } from '../../bean/model.todo.js';
|
|
86
|
+
|
|
87
|
+
class ControllerTodo {
|
|
88
|
+
@Use()
|
|
89
|
+
$$modelTodo: ModelTodo;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Cross-module injection should usually prefer a bean identifier so the consuming module does not depend on the provider’s internal file path layout:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import type { ModelTabs } from 'zova-module-a-routertabs';
|
|
97
|
+
|
|
98
|
+
class ControllerLayout {
|
|
99
|
+
@Use('a-routertabs.model.tabs')
|
|
100
|
+
$$modelTabs: ModelTabs;
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
In practice, Zova can still preserve the ergonomic class-based development experience while compiling cross-module usage back toward bean-identifier-based resolution.
|
|
105
|
+
|
|
106
|
+
### Hierarchical injection patterns
|
|
107
|
+
|
|
108
|
+
Hierarchical injection replaces many cases where a generic Vue app would fall back to `provide/inject`.
|
|
109
|
+
|
|
110
|
+
Representative child lookup pattern:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import type { ModelTabs } from 'zova-module-a-routertabs';
|
|
114
|
+
|
|
115
|
+
class Child {
|
|
116
|
+
@Use({ injectionScope: 'host' })
|
|
117
|
+
$$modelTabs: ModelTabs;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
That keeps parent/child sharing aligned with the same IoC model instead of introducing a separate state-sharing mechanism.
|
|
122
|
+
|
|
123
|
+
## Injection scopes
|
|
124
|
+
|
|
125
|
+
Zova supports several injection scopes:
|
|
126
|
+
|
|
127
|
+
- `sys`
|
|
128
|
+
- `app`
|
|
129
|
+
- `ctx`
|
|
130
|
+
- `new`
|
|
131
|
+
- `host`
|
|
132
|
+
- `skipSelf`
|
|
133
|
+
|
|
134
|
+
This allows code to be explicit about whether a bean should be shared globally, per request, per component instance, or created fresh.
|
|
135
|
+
|
|
136
|
+
## Hierarchical injection
|
|
137
|
+
|
|
138
|
+
The `host` and `skipSelf` scopes provide hierarchical lookup behavior.
|
|
139
|
+
|
|
140
|
+
This replaces much of the conventional Vue `provide/inject` style with an IoC-native rule set.
|
|
141
|
+
|
|
142
|
+
That means parent/child sharing can stay aligned with the same overall bean model instead of becoming a separate architectural subsystem.
|
|
143
|
+
|
|
144
|
+
## Lifecycle
|
|
145
|
+
|
|
146
|
+
All beans can define two lifecycle methods:
|
|
147
|
+
|
|
148
|
+
- `__init__`
|
|
149
|
+
- `__dispose__`
|
|
150
|
+
|
|
151
|
+
These lifecycle hooks are important because they give beans a structured place for initialization and cleanup logic.
|
|
152
|
+
|
|
153
|
+
Representative uses include:
|
|
154
|
+
|
|
155
|
+
- computed setup
|
|
156
|
+
- watchers
|
|
157
|
+
- derived state wiring
|
|
158
|
+
- resource cleanup
|
|
159
|
+
|
|
160
|
+
Representative initialization pattern:
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
export class Counter {
|
|
164
|
+
count: number = 0;
|
|
165
|
+
count2: string;
|
|
166
|
+
|
|
167
|
+
protected async __init__() {
|
|
168
|
+
this.count2 = this.$computed(() => {
|
|
169
|
+
return `=== ${this.count} ===`;
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
this.$watch(
|
|
173
|
+
() => this.count,
|
|
174
|
+
() => {
|
|
175
|
+
console.log('changed: ', this.count);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
That gives a bean one consistent place to wire reactive behavior instead of scattering setup logic through unrelated hooks.
|
|
183
|
+
|
|
184
|
+
## Bean identifiers and loose coupling
|
|
185
|
+
|
|
186
|
+
Bean identifiers are a key part of Zova’s modular architecture.
|
|
187
|
+
|
|
188
|
+
They make cross-module access more stable and decoupled than always relying on direct file-path imports.
|
|
189
|
+
|
|
190
|
+
This matters especially in large systems, where business modules should remain reusable and composable.
|
|
191
|
+
|
|
192
|
+
## Relationship to other frontend guides
|
|
193
|
+
|
|
194
|
+
Read this together with:
|
|
195
|
+
|
|
196
|
+
- [Modules and Suites](/frontend/modules-and-suites)
|
|
197
|
+
- [Module Scope](/frontend/module-scope)
|
|
198
|
+
- [Frontend Design Principles](/frontend/design-principles)
|
|
199
|
+
|
|
200
|
+
Those pages explain how beans fit into module boundaries, scope-based resources, and the broader Zova architectural model.
|
|
201
|
+
|
|
202
|
+
## Implementation checks for frontend bean-architecture changes
|
|
203
|
+
|
|
204
|
+
When editing Zova frontend code, ask:
|
|
205
|
+
|
|
206
|
+
1. should this behavior live in a bean instead of a framework-neutral helper?
|
|
207
|
+
2. is the right sharing scope `ctx`, `app`, or `sys`?
|
|
208
|
+
3. should dependency injection or dependency lookup be preferred here?
|
|
209
|
+
4. does this component or page already rely on lifecycle hooks, hierarchical injection, or bean identifiers that should be preserved?
|
|
210
|
+
|
|
211
|
+
That helps AI keep frontend changes aligned with Zova’s real architectural model instead of drifting toward generic Vue patterns.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Mock Guide
|
|
2
|
+
|
|
3
|
+
## Why mock matters in Zova
|
|
4
|
+
|
|
5
|
+
Zova provides an out-of-the-box mock mechanism so frontend development can continue even when a real backend integration path is incomplete or intentionally decoupled.
|
|
6
|
+
|
|
7
|
+
That matters because page, API, and server-data workflows often need stable response shapes before the final backend contract is available.
|
|
8
|
+
|
|
9
|
+
## Core mock model
|
|
10
|
+
|
|
11
|
+
The Zova mock mechanism is based on `vite-plugin-fake-server` and is integrated into the frontend development workflow.
|
|
12
|
+
|
|
13
|
+
A mock route is typically defined in a `.fake.ts` file inside the relevant module.
|
|
14
|
+
|
|
15
|
+
## Mock file structure
|
|
16
|
+
|
|
17
|
+
Representative example:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { defineFakeRoute } from 'vite-plugin-fake-server-turbo/client';
|
|
21
|
+
|
|
22
|
+
export default defineFakeRoute([
|
|
23
|
+
{
|
|
24
|
+
url: '/home/layout/menu/select',
|
|
25
|
+
method: 'get',
|
|
26
|
+
response: () => {
|
|
27
|
+
return {
|
|
28
|
+
code: 0,
|
|
29
|
+
message: 'Success',
|
|
30
|
+
data: [],
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
]);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Key points:
|
|
38
|
+
|
|
39
|
+
- mock files use the `.fake.ts` extension
|
|
40
|
+
- `defineFakeRoute(...)` provides the route definition shape
|
|
41
|
+
- each mock route describes the request path, method, and response
|
|
42
|
+
|
|
43
|
+
## Where mock files belong
|
|
44
|
+
|
|
45
|
+
Mocks belong near the frontend module that consumes or defines the route shape.
|
|
46
|
+
|
|
47
|
+
Representative example:
|
|
48
|
+
|
|
49
|
+
- `src/suite/a-home/modules/home-layout/mock/menu.fake.ts`
|
|
50
|
+
|
|
51
|
+
This keeps mock behavior close to the page, API, or business module that depends on it.
|
|
52
|
+
|
|
53
|
+
## Relationship to frontend APIs and server data
|
|
54
|
+
|
|
55
|
+
Mocking fits naturally with:
|
|
56
|
+
|
|
57
|
+
- [API Guide](/frontend/api-guide)
|
|
58
|
+
- [Server Data](/frontend/server-data)
|
|
59
|
+
- [Page Guide](/frontend/page-guide)
|
|
60
|
+
|
|
61
|
+
A common workflow is:
|
|
62
|
+
|
|
63
|
+
1. define or update the frontend page or API contract
|
|
64
|
+
2. provide a mock route with the expected response shape
|
|
65
|
+
3. build page, component, or model behavior against that mock response
|
|
66
|
+
4. later replace the mock-backed path with the real backend contract when ready
|
|
67
|
+
|
|
68
|
+
## Configuration
|
|
69
|
+
|
|
70
|
+
Mock behavior is configured through environment variables such as:
|
|
71
|
+
|
|
72
|
+
- `MOCK_ENABLED`
|
|
73
|
+
- `MOCK_LOGGER`
|
|
74
|
+
- `MOCK_BASE_NAME`
|
|
75
|
+
- `MOCK_BUILD`
|
|
76
|
+
- `MOCK_BUILD_PORT`
|
|
77
|
+
- `MOCK_BUILD_OUTPUT`
|
|
78
|
+
- `MOCK_BUILD_CORS`
|
|
79
|
+
|
|
80
|
+
These settings control whether mocks are enabled, whether a standalone fake server should be built, and how the mock server behaves.
|
|
81
|
+
|
|
82
|
+
## Development and production behavior
|
|
83
|
+
|
|
84
|
+
By default, production builds do not generate the fake server.
|
|
85
|
+
|
|
86
|
+
If a standalone fake server should be generated during build, `MOCK_BUILD` must be enabled.
|
|
87
|
+
|
|
88
|
+
That means mock support can be used in development only, or intentionally packaged for separate deployment when needed.
|
|
89
|
+
|
|
90
|
+
## When to use mock
|
|
91
|
+
|
|
92
|
+
Use mock when:
|
|
93
|
+
|
|
94
|
+
- frontend page or API work needs stable response data before the backend is ready
|
|
95
|
+
- you want to prototype UI behavior against an expected contract
|
|
96
|
+
- you want repeatable local demo or development behavior without a live backend dependency
|
|
97
|
+
|
|
98
|
+
Do not treat mock as the final source of truth for the contract when a real backend/OpenAPI path already exists.
|
|
99
|
+
|
|
100
|
+
## Implementation checks for mock-versus-contract decisions
|
|
101
|
+
|
|
102
|
+
When editing frontend integration paths, ask:
|
|
103
|
+
|
|
104
|
+
1. is the real backend contract available yet?
|
|
105
|
+
2. should this flow use a temporary mock route or a real `$api`/OpenAPI path?
|
|
106
|
+
3. does the mock response shape match the intended page, API, or model contract?
|
|
107
|
+
4. should mock be enabled only for development, or is a standalone fake server also needed?
|
|
108
|
+
|
|
109
|
+
That helps AI keep frontend development moving without confusing temporary mock behavior with final backend truth.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Model Architecture
|
|
2
|
+
|
|
3
|
+
This guide explains the overall model architecture in Zova within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why Zova models matter
|
|
6
|
+
|
|
7
|
+
Zova uses a unified `Model` mechanism to manage several kinds of data that other frontend stacks often split across unrelated tools.
|
|
8
|
+
|
|
9
|
+
This is one of the most important architectural ideas in Zova.
|
|
10
|
+
|
|
11
|
+
## Four kinds of global state
|
|
12
|
+
|
|
13
|
+
The model architecture can be understood through four common data categories:
|
|
14
|
+
|
|
15
|
+
- asynchronous data, usually from the server
|
|
16
|
+
- local storage data
|
|
17
|
+
- cookie data
|
|
18
|
+
- in-memory data
|
|
19
|
+
|
|
20
|
+
In Zova, these can all participate in one broader model-centered system instead of forcing developers to switch between unrelated mental models.
|
|
21
|
+
|
|
22
|
+
## Relationship to TanStack Query
|
|
23
|
+
|
|
24
|
+
One key point is explicit: the base of Zova Model is TanStack Query.
|
|
25
|
+
|
|
26
|
+
That matters because Zova is not discarding the strengths of TanStack Query. It is building a more unified and framework-friendly usage model on top of it.
|
|
27
|
+
|
|
28
|
+
## Key model capabilities
|
|
29
|
+
|
|
30
|
+
Several important capabilities remain central in the unified docs:
|
|
31
|
+
|
|
32
|
+
### 1. Support for async and sync data
|
|
33
|
+
|
|
34
|
+
The model system is not limited to server data. It also extends the same broader mechanism to synchronous data categories.
|
|
35
|
+
|
|
36
|
+
### 2. Automatic caching
|
|
37
|
+
|
|
38
|
+
Remote data can be cached locally, while local-storage or cookie-backed data can be accessed through unified model patterns.
|
|
39
|
+
|
|
40
|
+
### 3. Automatic update behavior
|
|
41
|
+
|
|
42
|
+
The model system supports data freshness and update behavior instead of treating state as static snapshots.
|
|
43
|
+
|
|
44
|
+
### 4. Reduced duplicate requests
|
|
45
|
+
|
|
46
|
+
When multiple parts of the app need the same data, the framework avoids unnecessary repeated requests.
|
|
47
|
+
|
|
48
|
+
### 5. Memory optimization
|
|
49
|
+
|
|
50
|
+
Model-managed data does not need to occupy memory forever. Cache lifecycle and release behavior matter, especially for large long-running applications.
|
|
51
|
+
|
|
52
|
+
### 6. Persistence
|
|
53
|
+
|
|
54
|
+
Model-managed data can participate in persistence strategies so refreshes do not always mean starting from nothing.
|
|
55
|
+
|
|
56
|
+
### 7. SSR support
|
|
57
|
+
|
|
58
|
+
The model system helps smooth out SSR differences across data categories and makes hydration more natural.
|
|
59
|
+
|
|
60
|
+
### 8. Namespace isolation
|
|
61
|
+
|
|
62
|
+
Because data is managed through model beans, the bean identity itself helps provide namespace isolation and reduces collision risk.
|
|
63
|
+
|
|
64
|
+
## Create a model bean
|
|
65
|
+
|
|
66
|
+
Representative pattern:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { Model } from 'zova';
|
|
70
|
+
import { BeanModelBase } from 'zova-module-a-model';
|
|
71
|
+
|
|
72
|
+
@Model()
|
|
73
|
+
export class ModelTodo extends BeanModelBase {}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Practical implications for frontend state design
|
|
77
|
+
|
|
78
|
+
When asked to add frontend state, do not immediately assume a generic Vue/Pinia-style answer.
|
|
79
|
+
|
|
80
|
+
A better default is to ask:
|
|
81
|
+
|
|
82
|
+
1. is this state already a good fit for a Zova model?
|
|
83
|
+
2. is the data async or sync, and does that distinction matter to the model choice?
|
|
84
|
+
3. does SSR or persistence make the model layer especially valuable here?
|
|
85
|
+
4. is there already a model bean that should own this state instead of adding a new ad hoc state container?
|
|
86
|
+
|
|
87
|
+
That keeps the code aligned with Zova’s actual architecture.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Model State Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how model-based server-data state works in Zova within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why the model layer exists
|
|
6
|
+
|
|
7
|
+
Zova uses model-based state management on top of API access so remote data can participate in a more unified caching and usage model.
|
|
8
|
+
|
|
9
|
+
This improves runtime performance and developer experience by building on top of TanStack Query rather than exposing only raw request flows.
|
|
10
|
+
|
|
11
|
+
## Create a model
|
|
12
|
+
|
|
13
|
+
Example: create a model named `menu` in module `demo-student`.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run zova :create:bean model menu -- --module=demo-student
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Model definition
|
|
20
|
+
|
|
21
|
+
Representative pattern:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
@Model()
|
|
25
|
+
export class ModelMenu {
|
|
26
|
+
retrieveMenus() {
|
|
27
|
+
return this.$useStateData({
|
|
28
|
+
queryKey: ['retrieveMenus'],
|
|
29
|
+
queryFn: async () => {
|
|
30
|
+
return await this.$api.homeBaseMenu.retrieveMenus({
|
|
31
|
+
params: { publicPath: '' },
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This pattern is important because it shows that model logic is not just local state. It is also the place where cached remote data becomes a reusable abstraction.
|
|
40
|
+
|
|
41
|
+
## Using a model
|
|
42
|
+
|
|
43
|
+
Representative pattern:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
@Use()
|
|
47
|
+
$$modelMenu: ModelMenu;
|
|
48
|
+
|
|
49
|
+
protected render() {
|
|
50
|
+
const { data, error } = this.$$modelMenu.retrieveMenus();
|
|
51
|
+
if (error) return <div>{error.message}</div>;
|
|
52
|
+
return <div>{data}</div>;
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Relationship to the server-data ladder
|
|
57
|
+
|
|
58
|
+
In the new docs, think about the layers like this:
|
|
59
|
+
|
|
60
|
+
- `$fetch` → direct request access
|
|
61
|
+
- `$api` → business-oriented service methods
|
|
62
|
+
- `Model` → cached, reusable, UI-friendly remote state
|
|
63
|
+
|
|
64
|
+
That makes the model layer one of the most important bridges between backend contracts and frontend rendering.
|
|
65
|
+
|
|
66
|
+
## Implementation checks for model-based state changes
|
|
67
|
+
|
|
68
|
+
When you see repeated frontend data usage, caching concerns, or UI state that depends on remote data, ask whether the right abstraction is a model instead of a direct API call in the page.
|
|
69
|
+
|
|
70
|
+
That usually leads to cleaner SSR behavior, cleaner reuse, and a more Cabloy-native structure.
|