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,281 @@
|
|
|
1
|
+
# Backend Foundation
|
|
2
|
+
|
|
3
|
+
This guide explains the core architectural role of Vona in the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## What Vona is in Cabloy
|
|
6
|
+
|
|
7
|
+
Vona is the backend half of the Cabloy fullstack architecture.
|
|
8
|
+
|
|
9
|
+
It is designed for building `SSR`, `SPA`, `Web`, and `Admin` experiences in one broader system while keeping frontend and backend concerns separated enough to evolve independently.
|
|
10
|
+
|
|
11
|
+
## Fullstack mechanism
|
|
12
|
+
|
|
13
|
+
The core fullstack pattern remains the same:
|
|
14
|
+
|
|
15
|
+
- Zova provides the frontend framework
|
|
16
|
+
- Vona provides the backend framework
|
|
17
|
+
- the backend and frontend cooperate through generated artifacts, runtime integration, and shared conventions
|
|
18
|
+
|
|
19
|
+
Important integration channels include:
|
|
20
|
+
|
|
21
|
+
- backend-generated Swagger/OpenAPI metadata for frontend SDK generation
|
|
22
|
+
- frontend-generated route, icon, and component types that can feed backend-side usage and tooling
|
|
23
|
+
- shared monorepo scripts that make both sides visible to humans and AI systems
|
|
24
|
+
|
|
25
|
+
## Why Vona matters for backend and fullstack development
|
|
26
|
+
|
|
27
|
+
Vona combines backend productivity, DTO generation, CRUD-oriented workflows, multi-tenancy, and broad infrastructure support. In the monorepo docs, the key point is this:
|
|
28
|
+
|
|
29
|
+
Vona is not only a backend framework. Its conventions already encode a large amount of fullstack knowledge that contributors and automation should reuse instead of re-deriving manually.
|
|
30
|
+
|
|
31
|
+
That is why the docs, skills, and rules in this repo prefer:
|
|
32
|
+
|
|
33
|
+
- `npm run vona`
|
|
34
|
+
- CLI-driven generation
|
|
35
|
+
- source-truth route and module inspection
|
|
36
|
+
- verification against current scripts and code
|
|
37
|
+
|
|
38
|
+
## High-value backend capabilities
|
|
39
|
+
|
|
40
|
+
The most important enduring Vona capabilities include:
|
|
41
|
+
|
|
42
|
+
- modular architecture for suites and modules
|
|
43
|
+
- IOC container and dependency lookup
|
|
44
|
+
- AOP support across controller, internal, and external aspects
|
|
45
|
+
- a structured request-path model for middleware, guards, interceptors, pipes, and filters
|
|
46
|
+
- DTO inference and generation
|
|
47
|
+
- CRUD-oriented workflows
|
|
48
|
+
- multi-tenancy
|
|
49
|
+
- authentication, captcha, and user-access infrastructure
|
|
50
|
+
- multi-database and multi-datasource support
|
|
51
|
+
- transaction support
|
|
52
|
+
- caching, including two-layer cache
|
|
53
|
+
- playground support for quick verification
|
|
54
|
+
|
|
55
|
+
## The backend essentials model
|
|
56
|
+
|
|
57
|
+
The backend essentials model is built around three connected ideas:
|
|
58
|
+
|
|
59
|
+
- IoC containers and bean identity
|
|
60
|
+
- scope as the module resource facade
|
|
61
|
+
- suite / module / package boundaries as architectural units
|
|
62
|
+
|
|
63
|
+
For the broader backend hub, also see [Backend (Vona)](/backend/introduction). For the compact essentials-family hub, also see [Backend Essentials](/backend/backend-essentials).
|
|
64
|
+
|
|
65
|
+
## IoC containers and bean access
|
|
66
|
+
|
|
67
|
+
Vona uses framework-managed beans instead of expecting ordinary code to construct everything manually.
|
|
68
|
+
|
|
69
|
+
A useful distinction is:
|
|
70
|
+
|
|
71
|
+
- the **app container** owns global backend beans
|
|
72
|
+
- the **ctx container** owns request-scoped access
|
|
73
|
+
- **new-bean creation** allows fresh bean instances when a workflow really needs them
|
|
74
|
+
|
|
75
|
+
That means backend code can choose among:
|
|
76
|
+
|
|
77
|
+
- dependency injection
|
|
78
|
+
- dependency lookup
|
|
79
|
+
- direct bean access
|
|
80
|
+
- explicit new-bean creation
|
|
81
|
+
|
|
82
|
+
A practical rule is:
|
|
83
|
+
|
|
84
|
+
- prefer dependency lookup for concise business code
|
|
85
|
+
- use injection when the surrounding code already follows that pattern
|
|
86
|
+
- use direct bean access when you truly need container-level control
|
|
87
|
+
|
|
88
|
+
## Access-style comparison
|
|
89
|
+
|
|
90
|
+
| Access style | Best for | Representative shape |
|
|
91
|
+
| -------------------- | ------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
92
|
+
| Dependency injection | explicit wiring in the current class | `@Use('demo-student.service.student')` |
|
|
93
|
+
| Dependency lookup | ordinary module-oriented business code | `this.scope.service.student` |
|
|
94
|
+
| Direct bean access | container-aware control or request-scoped lookup | `this.bean._getBean(...)`, `this.ctx.bean._getBean(...)` |
|
|
95
|
+
| Fresh bean creation | workflows that should not reuse the ordinary resolved bean instance | `this.bean._newBean(...)` |
|
|
96
|
+
|
|
97
|
+
## Dependency injection vs dependency lookup vs direct bean access
|
|
98
|
+
|
|
99
|
+
These three access styles solve related but different problems.
|
|
100
|
+
|
|
101
|
+
### Dependency injection
|
|
102
|
+
|
|
103
|
+
Dependency injection is explicit and type-friendly.
|
|
104
|
+
|
|
105
|
+
Representative pattern:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
class ControllerStudent {
|
|
109
|
+
@Use('demo-student.service.student')
|
|
110
|
+
serviceStudent: ServiceStudent;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Dependency lookup
|
|
115
|
+
|
|
116
|
+
Dependency lookup is often the most concise default.
|
|
117
|
+
|
|
118
|
+
Representative patterns:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
this.scope.service.student.findOne();
|
|
122
|
+
this.$scope.demoStudent.service.student.findOne();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Direct bean access
|
|
126
|
+
|
|
127
|
+
Direct bean access exposes the container layer more explicitly.
|
|
128
|
+
|
|
129
|
+
Representative patterns:
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
this.bean._getBean('demo-student.service.student');
|
|
133
|
+
this.ctx.bean._getBean('demo-student.service.student');
|
|
134
|
+
this.bean._newBean('demo-student.service.student');
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The important conceptual split is:
|
|
138
|
+
|
|
139
|
+
- injection wires a dependency into the current class
|
|
140
|
+
- lookup navigates the module resource facade
|
|
141
|
+
- direct bean access reaches the container more explicitly
|
|
142
|
+
|
|
143
|
+
## Bean identifier, onion name, and bean scenes
|
|
144
|
+
|
|
145
|
+
Legacy Vona essentials docs made bean identity more explicit, and that identity layer is still useful.
|
|
146
|
+
|
|
147
|
+
The most important terms are:
|
|
148
|
+
|
|
149
|
+
- **bean identifier**: a dotted identity such as `{moduleName}.{sceneName}.{beanName}`
|
|
150
|
+
- **onion name**: a colon-based framework name such as `{moduleName}:{beanName}`
|
|
151
|
+
- **bean scene**: the operational family a bean belongs to, such as service, model, startup, queue, or broadcast
|
|
152
|
+
|
|
153
|
+
This matters because naming is not cosmetic. It affects:
|
|
154
|
+
|
|
155
|
+
- injection by identifier
|
|
156
|
+
- config override paths
|
|
157
|
+
- inspect tooling
|
|
158
|
+
- CLI-created bean organization
|
|
159
|
+
|
|
160
|
+
A practical naming rule is:
|
|
161
|
+
|
|
162
|
+
- bean identifier uses the fully qualified `module.scene.bean` form such as `demo-student.service.student`
|
|
163
|
+
- onion name uses the shorter `module:bean` form such as `demo-student:student`
|
|
164
|
+
- bean scene is the middle grouping layer that turns one module into operational families like `service`, `model`, `entity`, `dto`, or `startup`
|
|
165
|
+
|
|
166
|
+
For deciding whether backend base classes belong in `src/lib`, `src/service`, or the global bean shorthand surface, also see [Class Placement Rule](/ai/class-placement-rule).
|
|
167
|
+
|
|
168
|
+
## BeanBase built-ins
|
|
169
|
+
|
|
170
|
+
A large part of the backend essentials model is that ordinary backend beans already inherit a useful working surface from `BeanBase`.
|
|
171
|
+
|
|
172
|
+
Representative built-ins include:
|
|
173
|
+
|
|
174
|
+
- `app`
|
|
175
|
+
- `ctx`
|
|
176
|
+
- `bean`
|
|
177
|
+
- `scope`
|
|
178
|
+
- `$scope`
|
|
179
|
+
- `$logger`
|
|
180
|
+
- `$loggerChild(...)`
|
|
181
|
+
- locale-oriented helpers such as `$text`
|
|
182
|
+
|
|
183
|
+
This matters because backend code usually should not reassemble those access points manually. The framework already places them on the base bean surface.
|
|
184
|
+
|
|
185
|
+
## Bean lifecycle vocabulary
|
|
186
|
+
|
|
187
|
+
Backend bean behavior also includes lifecycle concepts.
|
|
188
|
+
|
|
189
|
+
Representative lifecycle hooks include:
|
|
190
|
+
|
|
191
|
+
- `__init__`
|
|
192
|
+
- `__dispose__`
|
|
193
|
+
|
|
194
|
+
That lifecycle vocabulary matters because some backend capabilities are more than static helpers. They may need initialization, teardown, or startup-scoped behavior.
|
|
195
|
+
|
|
196
|
+
## Scope as the module resource facade
|
|
197
|
+
|
|
198
|
+
The most practical backend access model is scope.
|
|
199
|
+
|
|
200
|
+
Scope groups a module’s resources behind one structured facade, including areas such as:
|
|
201
|
+
|
|
202
|
+
- service
|
|
203
|
+
- model
|
|
204
|
+
- entity
|
|
205
|
+
- config
|
|
206
|
+
- constant
|
|
207
|
+
- locale
|
|
208
|
+
- error
|
|
209
|
+
|
|
210
|
+
The key distinction is:
|
|
211
|
+
|
|
212
|
+
- `this.scope` means local module resources
|
|
213
|
+
- `this.$scope.<module>` means cross-module resources
|
|
214
|
+
- `app.scope(...)` means explicit app-level scope lookup outside the local class shorthand
|
|
215
|
+
|
|
216
|
+
This is one of the reasons Vona backend code can stay concise without flattening everything into arbitrary imports.
|
|
217
|
+
|
|
218
|
+
## Suite / module / package boundaries
|
|
219
|
+
|
|
220
|
+
Vona architecture is not only about classes and beans. It is also about structural boundaries.
|
|
221
|
+
|
|
222
|
+
The core units are:
|
|
223
|
+
|
|
224
|
+
- **suite**
|
|
225
|
+
- **module**
|
|
226
|
+
- **package**
|
|
227
|
+
|
|
228
|
+
These units matter because they shape:
|
|
229
|
+
|
|
230
|
+
- generation targets from the CLI
|
|
231
|
+
- naming and identifiers
|
|
232
|
+
- dependency declarations
|
|
233
|
+
- resource access patterns
|
|
234
|
+
- documentation and ownership boundaries
|
|
235
|
+
|
|
236
|
+
That is why backend modularization should be treated as architecture, not just folder layout.
|
|
237
|
+
|
|
238
|
+
For the current monorepo shape, also see [Package Map](/reference/package-map).
|
|
239
|
+
|
|
240
|
+
## Relationship to Cabloy Basic and Cabloy Start
|
|
241
|
+
|
|
242
|
+
Most of these backend concepts are shared across both editions.
|
|
243
|
+
|
|
244
|
+
The differences usually appear at the integration boundary, for example:
|
|
245
|
+
|
|
246
|
+
- which frontend modules consume the backend output
|
|
247
|
+
- which Zova flavors are paired with the backend
|
|
248
|
+
- which edition-specific assets or routes are present
|
|
249
|
+
|
|
250
|
+
So the rule is:
|
|
251
|
+
|
|
252
|
+
- explain the backend capability once
|
|
253
|
+
- annotate edition-specific integration points only where they actually diverge
|
|
254
|
+
|
|
255
|
+
## Suggested next pages
|
|
256
|
+
|
|
257
|
+
Use these groups to move from the architecture-first model into the deeper backend families.
|
|
258
|
+
|
|
259
|
+
### Essentials and workflow entry pages
|
|
260
|
+
|
|
261
|
+
- [Backend (Vona)](/backend/introduction)
|
|
262
|
+
- [Backend Essentials](/backend/backend-essentials)
|
|
263
|
+
- [Backend CLI](/backend/cli)
|
|
264
|
+
- [Backend Scripts](/backend/scripts)
|
|
265
|
+
- [Service Guide](/backend/service-guide)
|
|
266
|
+
|
|
267
|
+
### Contract and data leaves
|
|
268
|
+
|
|
269
|
+
- [Controller Guide](/backend/controller-guide)
|
|
270
|
+
- [Model Guide](/backend/model-guide)
|
|
271
|
+
- [Entity Guide](/backend/entity-guide)
|
|
272
|
+
- [DTO Guide](/backend/dto-guide)
|
|
273
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
274
|
+
|
|
275
|
+
### Runtime and distributed leaves
|
|
276
|
+
|
|
277
|
+
- [Runtime and Flavors](/backend/runtime-and-flavors)
|
|
278
|
+
- [Config Guide](/backend/config-guide)
|
|
279
|
+
- [Backend Startup Guide](/backend/startup-guide)
|
|
280
|
+
- [Worker Guide](/backend/worker-guide)
|
|
281
|
+
- [Queue Guide](/backend/queue-guide)
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# I18n Guide
|
|
2
|
+
|
|
3
|
+
## Why i18n matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona treats locale and timezone handling as framework-level backend capabilities rather than ad hoc request helpers.
|
|
6
|
+
|
|
7
|
+
That matters because backend contracts, entity metadata, user-facing messages, and request-context behavior all need consistent localization rules.
|
|
8
|
+
|
|
9
|
+
## The two main i18n dimensions
|
|
10
|
+
|
|
11
|
+
In the backend docs, i18n is best understood through two related dimensions:
|
|
12
|
+
|
|
13
|
+
- **locale** for language resources and localized metadata
|
|
14
|
+
- **timezone** for request-context time interpretation
|
|
15
|
+
|
|
16
|
+
## Module locale resources
|
|
17
|
+
|
|
18
|
+
Each module can provide its own locale resources.
|
|
19
|
+
|
|
20
|
+
Representative initialization workflow:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm run vona :init:locale demo-student
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Representative files include:
|
|
27
|
+
|
|
28
|
+
- `src/module/demo-student/src/config/locale/en-us.ts`
|
|
29
|
+
- `src/module/demo-student/src/config/locale/zh-cn.ts`
|
|
30
|
+
|
|
31
|
+
This makes localization part of the module model rather than a single global string table.
|
|
32
|
+
|
|
33
|
+
## Accessing locale resources
|
|
34
|
+
|
|
35
|
+
Backend code can access locale resources through the module scope.
|
|
36
|
+
|
|
37
|
+
### Current-module access
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
const message1 = this.scope.locale.StudentName();
|
|
41
|
+
const message2 = this.scope.locale.StudentName.locale('en-us');
|
|
42
|
+
const message3 = this.scope.locale.StudentName.locale('zh-cn');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Cross-module access
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
const message1 = this.$scope.demoStudent.locale.StudentName();
|
|
49
|
+
const message2 = this.$scope.demoStudent.locale.StudentName.locale('en-us');
|
|
50
|
+
const message3 = this.$scope.demoStudent.locale.StudentName.locale('zh-cn');
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Project-level override
|
|
54
|
+
|
|
55
|
+
Project-level locale resources can override module-level resources.
|
|
56
|
+
|
|
57
|
+
Representative override files include:
|
|
58
|
+
|
|
59
|
+
- `src/backend/config/locale/en-us.ts`
|
|
60
|
+
- `src/backend/config/locale/zh-cn.ts`
|
|
61
|
+
|
|
62
|
+
That means modules can provide defaults while the project still controls final wording when needed.
|
|
63
|
+
|
|
64
|
+
A useful ownership rule is:
|
|
65
|
+
|
|
66
|
+
- module locale files define reusable defaults close to the module
|
|
67
|
+
- project locale files adjust wording for the current application
|
|
68
|
+
- request context decides which locale is active for the current call
|
|
69
|
+
|
|
70
|
+
## Current locale in request context
|
|
71
|
+
|
|
72
|
+
The current locale is available on the request context.
|
|
73
|
+
|
|
74
|
+
### Get current locale
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const locale = this.ctx.locale;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Set current locale
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
this.ctx.locale = 'en-us';
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Get default locale
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const localeDefault = this.$scope.locale.config.locale.defaultLocale;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Locale configuration and resolution order
|
|
93
|
+
|
|
94
|
+
The `a-locale` module exposes locale settings such as:
|
|
95
|
+
|
|
96
|
+
- `defaultLocale`
|
|
97
|
+
- `queryField`
|
|
98
|
+
- `headerField`
|
|
99
|
+
- `cookieField`
|
|
100
|
+
|
|
101
|
+
The current locale is resolved in this order:
|
|
102
|
+
|
|
103
|
+
- query field
|
|
104
|
+
- header field
|
|
105
|
+
- cookie field
|
|
106
|
+
- user locale
|
|
107
|
+
- `Accept-Language`
|
|
108
|
+
- default locale
|
|
109
|
+
|
|
110
|
+
This is important because locale is not guessed from only one source.
|
|
111
|
+
|
|
112
|
+
## Adding a new language
|
|
113
|
+
|
|
114
|
+
Vona ships with default locales such as `en-us` and `zh-cn`, and additional languages can be added through interface merging and new locale files.
|
|
115
|
+
|
|
116
|
+
That means locale support is extensible at the type level as well as the resource-file level.
|
|
117
|
+
|
|
118
|
+
Representative type extension:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
declare module 'vona' {
|
|
122
|
+
export interface ILocaleRecord {
|
|
123
|
+
'zh-tw': never;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
In the VSCode workflow, the `recordlocale` snippet can generate the augmentation skeleton.
|
|
129
|
+
|
|
130
|
+
## Plural support
|
|
131
|
+
|
|
132
|
+
Locale resources can express plural-aware strings through naming conventions such as:
|
|
133
|
+
|
|
134
|
+
- `TestApples_`
|
|
135
|
+
- `TestApples_0`
|
|
136
|
+
- `TestApples_1`
|
|
137
|
+
|
|
138
|
+
Multiple-parameter variants are also supported through ordinal-aware suffix conventions.
|
|
139
|
+
|
|
140
|
+
This makes plural handling part of the localization model instead of forcing each project to invent its own formatting layer.
|
|
141
|
+
|
|
142
|
+
## Timezone support
|
|
143
|
+
|
|
144
|
+
Vona also tracks timezone in the request context.
|
|
145
|
+
|
|
146
|
+
### Get current timezone
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const tz = this.ctx.tz;
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Set current timezone
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
this.ctx.tz = 'America/New_York';
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
A representative use case is parsing request-driven date filters with the current timezone instead of assuming server-local time:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
const dateStart = DateTime.fromISO(dateStartStr, { zone: this.ctx.tz });
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The `a-locale` module exposes timezone settings such as:
|
|
165
|
+
|
|
166
|
+
- `defaultTz`
|
|
167
|
+
- `queryField`
|
|
168
|
+
- `headerField`
|
|
169
|
+
- `cookieField`
|
|
170
|
+
|
|
171
|
+
The current timezone is resolved in this order:
|
|
172
|
+
|
|
173
|
+
- query field
|
|
174
|
+
- header field
|
|
175
|
+
- cookie field
|
|
176
|
+
- user timezone
|
|
177
|
+
- default timezone
|
|
178
|
+
- system timezone fallback
|
|
179
|
+
|
|
180
|
+
## OpenAPI and entity metadata localization
|
|
181
|
+
|
|
182
|
+
One of the most important backend i18n capabilities is that entity and OpenAPI-facing metadata can be localized.
|
|
183
|
+
|
|
184
|
+
Representative helpers include:
|
|
185
|
+
|
|
186
|
+
- `$localeScope(...)`
|
|
187
|
+
- module-local `$locale(...)`
|
|
188
|
+
|
|
189
|
+
That allows fields such as `title`, `description`, or other metadata to stay machine-readable while still producing localized developer-facing output.
|
|
190
|
+
|
|
191
|
+
## Relationship to other backend guides
|
|
192
|
+
|
|
193
|
+
Read this guide together with:
|
|
194
|
+
|
|
195
|
+
- [Entity Guide](/backend/entity-guide)
|
|
196
|
+
- [Error Guide](/backend/error-guide)
|
|
197
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
198
|
+
- [User Access Guide](/backend/user-access-guide)
|
|
199
|
+
|
|
200
|
+
These guides show how i18n affects entity metadata, API contracts, and user-scoped request behavior.
|
|
201
|
+
|
|
202
|
+
## Implementation checks for backend localization changes
|
|
203
|
+
|
|
204
|
+
When editing backend localization-sensitive behavior, ask:
|
|
205
|
+
|
|
206
|
+
1. does this text belong in module locale resources instead of inline strings?
|
|
207
|
+
2. should the value respect current locale, current timezone, or both?
|
|
208
|
+
3. does the change affect OpenAPI or entity metadata localization?
|
|
209
|
+
4. should the project override module defaults instead of editing shared resources directly?
|
|
210
|
+
|
|
211
|
+
That helps AI keep backend localization aligned with Vona’s real request-context and metadata model.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Internal AOP Guide
|
|
2
|
+
|
|
3
|
+
## Why internal AOP matters
|
|
4
|
+
|
|
5
|
+
Internal AOP is how Vona adds behavior inside a class without forcing the developer to duplicate the same logic across many methods.
|
|
6
|
+
|
|
7
|
+
This is especially useful for:
|
|
8
|
+
|
|
9
|
+
- transactions
|
|
10
|
+
- logging
|
|
11
|
+
- caching
|
|
12
|
+
- scope-based lookup
|
|
13
|
+
- dynamic property and method behavior
|
|
14
|
+
|
|
15
|
+
## Two internal AOP mechanisms
|
|
16
|
+
|
|
17
|
+
Vona provides two main internal mechanisms:
|
|
18
|
+
|
|
19
|
+
- **AOP Method**
|
|
20
|
+
- **Magic Method**
|
|
21
|
+
|
|
22
|
+
## AOP Method
|
|
23
|
+
|
|
24
|
+
AOP Method extends class methods through decorators.
|
|
25
|
+
|
|
26
|
+
It can be used on controller methods, service methods, and other class methods that should participate in reusable around-execution behavior.
|
|
27
|
+
|
|
28
|
+
Representative CLI generation pattern:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run vona :create:bean aopMethod log -- --module=demo-student
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
That generator-backed workflow matters because AOP Method beans participate in the same onion metadata system as other Vona extension points.
|
|
35
|
+
|
|
36
|
+
### Representative custom AOP Method
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
@AopMethod<IAopMethodOptionsLog>()
|
|
40
|
+
class AopMethodLog {
|
|
41
|
+
async execute(_options, _args, next) {
|
|
42
|
+
const timeBegin = Date.now();
|
|
43
|
+
const res = await next();
|
|
44
|
+
const timeEnd = Date.now();
|
|
45
|
+
console.log('time:', timeEnd - timeBegin);
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Representative usage
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
@Aspect.aopMethod('demo-student:log')
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Parameter model
|
|
58
|
+
|
|
59
|
+
AOP Method supports:
|
|
60
|
+
|
|
61
|
+
- typed options
|
|
62
|
+
- default values
|
|
63
|
+
- per-usage overrides
|
|
64
|
+
- app-config overrides
|
|
65
|
+
- enable/disable
|
|
66
|
+
- `mode` and `flavor`
|
|
67
|
+
- ordering through `dependencies` and `dependents`
|
|
68
|
+
|
|
69
|
+
A representative precedence model is:
|
|
70
|
+
|
|
71
|
+
- usage-site override
|
|
72
|
+
- then `config.onions.aopMethod`
|
|
73
|
+
- then decorator default values
|
|
74
|
+
|
|
75
|
+
That makes AOP Method practical for both framework-wide defaults and one-off method specialization.
|
|
76
|
+
|
|
77
|
+
## Built-in internal AOP helpers
|
|
78
|
+
|
|
79
|
+
Several built-in AOP Method helpers already exist.
|
|
80
|
+
|
|
81
|
+
Representative examples include:
|
|
82
|
+
|
|
83
|
+
- `a-logger:log`
|
|
84
|
+
- `a-orm:transaction`
|
|
85
|
+
- `a-caching:cachingGet`
|
|
86
|
+
- `a-caching:cachingSet`
|
|
87
|
+
- `a-caching:cachingDel`
|
|
88
|
+
- `a-caching:cachingClear`
|
|
89
|
+
|
|
90
|
+
These built-ins also expose shorthand decorators such as:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
@Core.log({ level: 'info' })
|
|
94
|
+
@Core.transaction({ isolationLevel: 'READ_COMMITTED', propagation: 'REQUIRED' })
|
|
95
|
+
@Caching.get({ cacheName: 'module-name:xxx' })
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For the broader logger-client, rotation, and level model behind `@Core.log(...)`, see [Logger Guide](/backend/logger-guide).
|
|
99
|
+
|
|
100
|
+
## Magic Method
|
|
101
|
+
|
|
102
|
+
Magic Method provides dynamic behavior through conventional method names such as:
|
|
103
|
+
|
|
104
|
+
- `__get__`
|
|
105
|
+
- `__set__`
|
|
106
|
+
- `__method__`
|
|
107
|
+
- `__init__`
|
|
108
|
+
- `__dispose__`
|
|
109
|
+
|
|
110
|
+
A useful ownership rule is that Magic Method is about changing how the class itself exposes properties, lookup, or lifecycle behavior, while AOP Method is about wrapping a named method call with reusable around-execution logic.
|
|
111
|
+
|
|
112
|
+
### Why this matters
|
|
113
|
+
|
|
114
|
+
Magic Method is one of the reasons Vona can keep dependency lookup and scope-driven APIs concise.
|
|
115
|
+
|
|
116
|
+
A representative example is module scope lookup:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
this.scope.model.student.selectAndCount(params);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Instead of requiring verbose injection or manual bean lookup, Vona can resolve the target dynamically through magic-method conventions.
|
|
123
|
+
|
|
124
|
+
### CRUD-oriented example
|
|
125
|
+
|
|
126
|
+
Magic Method can also simplify ORM usage:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
this.scope.model.student.getById(id);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
This reads more naturally than always spelling out lower-level query objects manually.
|
|
133
|
+
|
|
134
|
+
### Custom `__get__` and `__set__`
|
|
135
|
+
|
|
136
|
+
Any class can define custom dynamic property behavior:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
protected __get__(prop: string) {
|
|
140
|
+
return this._colors[prop];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
protected __set__(prop: string, value: any): boolean {
|
|
144
|
+
if (this._colors[prop] === undefined) return false;
|
|
145
|
+
this._colors[prop] = value;
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Type merging can then expose those dynamic properties more safely.
|
|
151
|
+
|
|
152
|
+
That is the key discipline when using Magic Method: keep the runtime shortcut and the type surface aligned, so dynamic behavior still reads like a deliberate framework abstraction rather than an untyped trick.
|
|
153
|
+
|
|
154
|
+
## Choosing between AOP Method and Magic Method
|
|
155
|
+
|
|
156
|
+
Use this rule of thumb:
|
|
157
|
+
|
|
158
|
+
- use **AOP Method** when the goal is to decorate or wrap a class method
|
|
159
|
+
- use **Magic Method** when the goal is dynamic property, lookup, lifecycle, or generic method behavior
|
|
160
|
+
|
|
161
|
+
## Relationship to other backend guides
|
|
162
|
+
|
|
163
|
+
Internal AOP connects directly to:
|
|
164
|
+
|
|
165
|
+
- [Service Guide](/backend/service-guide)
|
|
166
|
+
- [Model Guide](/backend/model-guide)
|
|
167
|
+
- [Transaction Guide](/backend/transaction-guide)
|
|
168
|
+
- [Cache Guide](/backend/cache-guide)
|
|
169
|
+
|
|
170
|
+
These guides often show the business-facing results of internal AOP, while this page explains the underlying extension model.
|
|
171
|
+
|
|
172
|
+
## Questions for internal AOP changes
|
|
173
|
+
|
|
174
|
+
When editing backend classes, ask:
|
|
175
|
+
|
|
176
|
+
1. is there already an AOP Method or shorthand for this behavior?
|
|
177
|
+
2. is a magic-method pattern already part of the framework abstraction here?
|
|
178
|
+
3. should scope lookup or dynamic method behavior be preserved instead of rewritten into a heavier pattern?
|
|
179
|
+
4. does the change interact with caching, transactions, logging, or lifecycle hooks?
|
|
180
|
+
|
|
181
|
+
That helps AI preserve Vona’s internal extension model instead of replacing it with generic patterns.
|