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,35 @@
|
|
|
1
|
+
# Skills
|
|
2
|
+
|
|
3
|
+
Skills are the procedural layer of Cabloy’s AI development model.
|
|
4
|
+
|
|
5
|
+
## What a skill should do here
|
|
6
|
+
|
|
7
|
+
A Cabloy skill should reduce repeated reasoning cost by encoding workflows such as:
|
|
8
|
+
|
|
9
|
+
- choosing the correct backend or frontend entrypoint
|
|
10
|
+
- detecting the active edition
|
|
11
|
+
- selecting the right CLI command family
|
|
12
|
+
- deciding what to verify after generation or refactor work
|
|
13
|
+
|
|
14
|
+
## What a skill should not do by default
|
|
15
|
+
|
|
16
|
+
A skill should not re-implement framework scaffolding manually when the Vona or Zova CLI already provides that behavior.
|
|
17
|
+
|
|
18
|
+
If a generator or refactor command exists, the skill should orchestrate it instead of replacing it.
|
|
19
|
+
|
|
20
|
+
## Skill placement
|
|
21
|
+
|
|
22
|
+
- Use root `.claude/skills/` for cross-stack, monorepo-wide workflows.
|
|
23
|
+
- Use subtree-local `.claude/skills/` only when a workflow is truly specific to one framework area.
|
|
24
|
+
|
|
25
|
+
## Skill structure recommendation
|
|
26
|
+
|
|
27
|
+
A strong Cabloy skill usually includes:
|
|
28
|
+
|
|
29
|
+
1. repo and edition detection
|
|
30
|
+
2. CLI-first workflow selection
|
|
31
|
+
3. minimal manual fallback guidance
|
|
32
|
+
4. verification guidance
|
|
33
|
+
5. references to durable source-of-truth files
|
|
34
|
+
|
|
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.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Verification
|
|
2
|
+
|
|
3
|
+
AI-assisted work should finish with checks that match the scope of the change.
|
|
4
|
+
|
|
5
|
+
## Documentation verification
|
|
6
|
+
|
|
7
|
+
For public docs changes, verify at minimum:
|
|
8
|
+
|
|
9
|
+
- VitePress dev/build commands work
|
|
10
|
+
- navigation links resolve
|
|
11
|
+
- examples match current scripts and command names
|
|
12
|
+
- edition labels and notes are consistent
|
|
13
|
+
|
|
14
|
+
## Skill and rule verification
|
|
15
|
+
|
|
16
|
+
For skills and repo guidance:
|
|
17
|
+
|
|
18
|
+
- confirm the workflow still points to real command entrypoints
|
|
19
|
+
- confirm edition branches match the active repo markers and scripts
|
|
20
|
+
- confirm public docs, skills, and root `CLAUDE.md` tell the same story
|
|
21
|
+
|
|
22
|
+
## Code-generation verification
|
|
23
|
+
|
|
24
|
+
When a skill triggers code generation or refactor behavior:
|
|
25
|
+
|
|
26
|
+
- inspect generated output
|
|
27
|
+
- run targeted typecheck, tests, or build commands
|
|
28
|
+
- prefer existing root scripts when a full verification pass is needed
|
|
29
|
+
|
|
30
|
+
Verification is part of the workflow, not an optional afterthought.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# AOP Overview
|
|
2
|
+
|
|
3
|
+
## Why AOP matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona uses AOP to make cross-cutting backend behavior explicit, composable, and framework-native.
|
|
6
|
+
|
|
7
|
+
That matters because concerns such as middleware flow, authentication checks, validation, transactions, logging, caching, and error handling should not be re-implemented ad hoc in every controller or service method.
|
|
8
|
+
|
|
9
|
+
## The three AOP capability families
|
|
10
|
+
|
|
11
|
+
Vona AOP can be understood in three capability families:
|
|
12
|
+
|
|
13
|
+
1. **Controller AOP** for request-path behavior around controller actions
|
|
14
|
+
2. **Internal AOP** for adding behavior inside a class through decorators or magic methods
|
|
15
|
+
3. **External AOP** for attaching behavior to a class from the outside without editing the class source code
|
|
16
|
+
|
|
17
|
+
## Controller AOP families
|
|
18
|
+
|
|
19
|
+
The controller-facing AOP system includes five main aspect families:
|
|
20
|
+
|
|
21
|
+
- **middleware**
|
|
22
|
+
- **guard**
|
|
23
|
+
- **interceptor**
|
|
24
|
+
- **pipe**
|
|
25
|
+
- **filter**
|
|
26
|
+
|
|
27
|
+
These families work together to shape request execution, parameter handling, error behavior, and API policy.
|
|
28
|
+
|
|
29
|
+
## Execution model
|
|
30
|
+
|
|
31
|
+
Two controller AOP families use an onion-style execution model:
|
|
32
|
+
|
|
33
|
+
- **middleware**
|
|
34
|
+
- **interceptor**
|
|
35
|
+
|
|
36
|
+
That means they can run logic both before and after the controller action.
|
|
37
|
+
|
|
38
|
+
Other controller AOP families participate in more specialized stages:
|
|
39
|
+
|
|
40
|
+
- **guard** checks access or execution preconditions
|
|
41
|
+
- **pipe** transforms or validates request values
|
|
42
|
+
- **filter** handles exceptions and logging behavior
|
|
43
|
+
|
|
44
|
+
A practical controller-path mental model is:
|
|
45
|
+
|
|
46
|
+
1. system middleware runs before route matching
|
|
47
|
+
2. route matching happens
|
|
48
|
+
3. global and local middleware wrap the matched route
|
|
49
|
+
4. guards enforce access preconditions
|
|
50
|
+
5. pipes transform and validate incoming values
|
|
51
|
+
6. interceptors wrap controller execution
|
|
52
|
+
7. the controller action runs
|
|
53
|
+
8. filters handle thrown exceptions and logging customization when failures occur
|
|
54
|
+
|
|
55
|
+
That model is the fastest way to decide which aspect family should own a change.
|
|
56
|
+
|
|
57
|
+
## System, global, and local scope
|
|
58
|
+
|
|
59
|
+
Controller AOP also varies by scope:
|
|
60
|
+
|
|
61
|
+
- **system** middleware runs before route matching
|
|
62
|
+
- **global** aspects are auto-loaded and can be applied broadly with runtime filters such as `match`, `ignore`, `mode`, or `flavor`
|
|
63
|
+
- **local** aspects are attached directly to a controller class or action
|
|
64
|
+
|
|
65
|
+
Built-in aspects and shorthand decorators sit on top of the same general model.
|
|
66
|
+
|
|
67
|
+
Across controller, internal, and external AOP, the same operational ideas appear repeatedly:
|
|
68
|
+
|
|
69
|
+
- default options in the aspect definition
|
|
70
|
+
- per-usage option overrides
|
|
71
|
+
- app-config overrides through `config.onions`
|
|
72
|
+
- enable/disable switches
|
|
73
|
+
- runtime targeting through `mode` and `flavor`
|
|
74
|
+
- ordering through `dependencies` and `dependents`
|
|
75
|
+
- inspection of the effective chains at runtime
|
|
76
|
+
|
|
77
|
+
That consistency is one of the biggest reasons the Vona AOP surface stays learnable even though it covers many different extension points.
|
|
78
|
+
|
|
79
|
+
## Validation, OpenAPI, and AOP
|
|
80
|
+
|
|
81
|
+
Vona’s AOP model is closely connected to:
|
|
82
|
+
|
|
83
|
+
- controller argument handling through `@Arg.*`
|
|
84
|
+
- Zod-based validation
|
|
85
|
+
- Swagger/OpenAPI generation
|
|
86
|
+
|
|
87
|
+
That means AOP is not only about request middleware. It is also part of how Vona turns request contracts into typed, machine-readable framework behavior.
|
|
88
|
+
|
|
89
|
+
## Internal AOP
|
|
90
|
+
|
|
91
|
+
Internal AOP provides two main mechanisms:
|
|
92
|
+
|
|
93
|
+
- **AOP Method** for decorating class methods
|
|
94
|
+
- **Magic Method** for dynamic behavior such as `__get__`, `__set__`, or `__method__`
|
|
95
|
+
|
|
96
|
+
These mechanisms help keep code concise while still making transactions, logging, caching, scope lookup, and dynamic access patterns explicit.
|
|
97
|
+
|
|
98
|
+
## External AOP
|
|
99
|
+
|
|
100
|
+
External AOP uses `@Aop({ match: ... })` to attach behavior to another class by bean name.
|
|
101
|
+
|
|
102
|
+
This is useful when the desired extension logic should live outside the target class, for example when layering timing, logging, lifecycle hooks, or dynamic method interception onto an existing service or bean.
|
|
103
|
+
|
|
104
|
+
A simple ownership rule is:
|
|
105
|
+
|
|
106
|
+
- choose **controller AOP** when the concern belongs to the HTTP request path
|
|
107
|
+
- choose **internal AOP** when the behavior belongs naturally to the class that owns the method
|
|
108
|
+
- choose **external AOP** when the behavior should remain decoupled from the target class source
|
|
109
|
+
|
|
110
|
+
## Recommended reading path
|
|
111
|
+
|
|
112
|
+
For the unified docs, use this progression:
|
|
113
|
+
|
|
114
|
+
1. [Controller AOP Guide](/backend/controller-aop-guide)
|
|
115
|
+
2. [Validation Guide](/backend/validation-guide)
|
|
116
|
+
3. [Internal AOP Guide](/backend/internal-aop-guide)
|
|
117
|
+
4. [External AOP Guide](/backend/external-aop-guide)
|
|
118
|
+
|
|
119
|
+
## Questions for AOP-sensitive changes
|
|
120
|
+
|
|
121
|
+
When changing backend behavior in Vona, ask:
|
|
122
|
+
|
|
123
|
+
1. is this concern already represented by middleware, guard, interceptor, pipe, or filter?
|
|
124
|
+
2. should this logic be expressed through an internal AOP decorator instead of manual repetition?
|
|
125
|
+
3. is an external aspect a better fit than modifying the target class directly?
|
|
126
|
+
4. does the change interact with validation, OpenAPI, caching, transactions, or runtime environment controls?
|
|
127
|
+
|
|
128
|
+
That helps AI keep backend changes aligned with Vona’s real execution model rather than rewriting them into generic framework patterns.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Auth Guide
|
|
2
|
+
|
|
3
|
+
## Why auth matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona treats authentication as a framework-level capability rather than a one-off login endpoint.
|
|
6
|
+
|
|
7
|
+
That matters because real systems often need more than one authentication method, more than one credential source, and more than one post-auth workflow.
|
|
8
|
+
|
|
9
|
+
## Core auth model
|
|
10
|
+
|
|
11
|
+
The `a-auth` module provides a general authentication system built around **auth providers**.
|
|
12
|
+
|
|
13
|
+
This model supports:
|
|
14
|
+
|
|
15
|
+
- multiple authentication methods such as username/password and OAuth
|
|
16
|
+
- multiple clients per provider
|
|
17
|
+
- association of multiple authentication methods to one user
|
|
18
|
+
- migration of authentication methods from one user to another
|
|
19
|
+
|
|
20
|
+
## `bean.auth`
|
|
21
|
+
|
|
22
|
+
Vona exposes a global bean `bean.auth` so backend code can use all registered auth providers through one unified entrypoint.
|
|
23
|
+
|
|
24
|
+
Representative provider-generation workflow:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run vona :create:bean authProvider simple -- --module=auth-simple
|
|
28
|
+
npm run vona :create:bean authProvider oauth -- --module=auth-oauth
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Those providers still plug into the shared `:create:bean` command surface, which keeps auth extension aligned with the rest of Vona’s bean architecture.
|
|
32
|
+
|
|
33
|
+
### Username/password example
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const jwt = await this.bean.auth.authenticate('auth-simple:simple', {
|
|
37
|
+
clientOptions: { username: 'admin', password: '123456' },
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### OAuth example
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
await this.bean.auth.authenticate('auth-oauth:oauth', {
|
|
45
|
+
clientName: 'github',
|
|
46
|
+
state: { redirect: '/' },
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Auth provider types
|
|
51
|
+
|
|
52
|
+
### `auth-simple`
|
|
53
|
+
|
|
54
|
+
`auth-simple` provides an out-of-the-box username/password provider.
|
|
55
|
+
|
|
56
|
+
Representative flows include:
|
|
57
|
+
|
|
58
|
+
- register a new user by calling `bean.auth.authenticate(..., { state: { intention: 'register' } })`
|
|
59
|
+
- log in by calling `bean.auth.authenticate(..., { state: { intention: 'login' } })`
|
|
60
|
+
- sign out through `bean.passport.signout()`
|
|
61
|
+
|
|
62
|
+
It also exposes password-hash configuration through app config.
|
|
63
|
+
|
|
64
|
+
### `auth-oauth`
|
|
65
|
+
|
|
66
|
+
`auth-oauth` provides an OAuth-based provider model.
|
|
67
|
+
|
|
68
|
+
Representative capabilities include:
|
|
69
|
+
|
|
70
|
+
- built-in support for GitHub
|
|
71
|
+
- adding new OAuth strategies such as Google through client configuration and interface merging
|
|
72
|
+
- unified callback handling
|
|
73
|
+
- exchanging the returned OAuth code for a JWT token through the Passport API flow
|
|
74
|
+
- optional mock login behavior in development
|
|
75
|
+
|
|
76
|
+
## Provider and client model
|
|
77
|
+
|
|
78
|
+
A provider can expose multiple clients.
|
|
79
|
+
|
|
80
|
+
For example, one OAuth provider can expose `github`, `google`, or other client entries, each with its own strategy and credentials.
|
|
81
|
+
|
|
82
|
+
That means auth configuration is not hardwired to one provider/credential pair.
|
|
83
|
+
|
|
84
|
+
## State and auth intent
|
|
85
|
+
|
|
86
|
+
Authentication calls can carry state such as:
|
|
87
|
+
|
|
88
|
+
- `register`
|
|
89
|
+
- `login`
|
|
90
|
+
- `associate`
|
|
91
|
+
- `migrate`
|
|
92
|
+
- redirect target after successful OAuth flow
|
|
93
|
+
|
|
94
|
+
This is one of the reasons Vona auth can support richer account flows without scattering those rules across unrelated controller code.
|
|
95
|
+
|
|
96
|
+
## Profile-driven user creation
|
|
97
|
+
|
|
98
|
+
Auth providers usually return profile data rather than directly creating a final user shape by hand.
|
|
99
|
+
|
|
100
|
+
That profile is then consumed by the broader user and passport system.
|
|
101
|
+
|
|
102
|
+
This separation helps Vona keep provider logic, user logic, and business customization decoupled.
|
|
103
|
+
|
|
104
|
+
A practical rule is that the provider should prove identity and return a stable profile, while user creation and passport assembly remain downstream responsibilities handled by the user/passport layers.
|
|
105
|
+
|
|
106
|
+
## OAuth credentials and callback flow
|
|
107
|
+
|
|
108
|
+
OAuth credentials are configured through app config under the relevant auth provider client entry.
|
|
109
|
+
|
|
110
|
+
The typical flow is:
|
|
111
|
+
|
|
112
|
+
1. redirect to the provider
|
|
113
|
+
2. receive the OAuth callback code
|
|
114
|
+
3. exchange the code for a JWT token
|
|
115
|
+
4. continue through the passport and user flow
|
|
116
|
+
|
|
117
|
+
The out-of-the-box Passport controller in `home-user` exposes that exchange as `createPassportJwtFromOauthCode`, which is why frontend OAuth flows usually stay thin: the provider redirect happens first, and the frontend then asks the Passport API to finish JWT creation.
|
|
118
|
+
|
|
119
|
+
## Passport API relationship
|
|
120
|
+
|
|
121
|
+
The `home-user` module exposes out-of-the-box Passport APIs for common account flows such as:
|
|
122
|
+
|
|
123
|
+
- current passport retrieval
|
|
124
|
+
- login
|
|
125
|
+
- logout
|
|
126
|
+
- registration
|
|
127
|
+
- OAuth login
|
|
128
|
+
- associate / migrate auth methods
|
|
129
|
+
- token refresh
|
|
130
|
+
- temporary auth token creation
|
|
131
|
+
|
|
132
|
+
In the current repo implementation, these flows live in `home-user/src/controller/passport.ts`, where register/login call `bean.auth.authenticate(...)`, OAuth login uses provider/module path parameters, and token-oriented follow-up endpoints stay concentrated in one controller surface.
|
|
133
|
+
|
|
134
|
+
This guide focuses on the framework-level auth model. For the user/passport side, see [User Access Guide](/backend/user-access-guide).
|
|
135
|
+
|
|
136
|
+
## Relationship to controller AOP
|
|
137
|
+
|
|
138
|
+
Auth behavior is closely connected to controller AOP, especially guards.
|
|
139
|
+
|
|
140
|
+
Built-in passport-oriented guard shorthands such as `@Passport.public()` are documented from the request-path perspective in [Controller AOP Guide](/backend/controller-aop-guide).
|
|
141
|
+
|
|
142
|
+
## Implementation checks for authentication changes
|
|
143
|
+
|
|
144
|
+
When editing authentication behavior, ask:
|
|
145
|
+
|
|
146
|
+
1. is the right layer `bean.auth`, `bean.passport`, or controller guard configuration?
|
|
147
|
+
2. does this flow belong to username/password auth, OAuth auth, or both?
|
|
148
|
+
3. does a provider already exist instead of needing custom authentication code?
|
|
149
|
+
4. does the flow need register, login, associate, migrate, or redirect-aware state?
|
|
150
|
+
|
|
151
|
+
That helps AI keep auth logic aligned with Vona’s real backend architecture.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Backend Essentials
|
|
2
|
+
|
|
3
|
+
## Why this page exists
|
|
4
|
+
|
|
5
|
+
The backend docs already explain many Vona workflows in detail, but the core backend mental model spans several pages.
|
|
6
|
+
|
|
7
|
+
This page provides one compact entrypoint for that model.
|
|
8
|
+
|
|
9
|
+
Use it when you want to understand how backend code is organized before diving into feature-specific guides.
|
|
10
|
+
|
|
11
|
+
For the broader backend entry page that groups the main families, also see [Backend (Vona)](/backend/introduction).
|
|
12
|
+
|
|
13
|
+
## The three core clusters
|
|
14
|
+
|
|
15
|
+
The backend essentials family is easiest to understand as three connected clusters:
|
|
16
|
+
|
|
17
|
+
### 1. IoC and bean containers
|
|
18
|
+
|
|
19
|
+
Vona backend code is built around framework-managed beans rather than ad hoc class instantiation.
|
|
20
|
+
|
|
21
|
+
The key concepts are:
|
|
22
|
+
|
|
23
|
+
- app container
|
|
24
|
+
- ctx container
|
|
25
|
+
- new-bean creation
|
|
26
|
+
- dependency injection
|
|
27
|
+
- dependency lookup
|
|
28
|
+
- direct bean access
|
|
29
|
+
- bean identifiers and onion names
|
|
30
|
+
- bean scenes
|
|
31
|
+
- bean lifecycle hooks
|
|
32
|
+
- BeanBase built-in members
|
|
33
|
+
|
|
34
|
+
Read next:
|
|
35
|
+
|
|
36
|
+
- [Backend Foundation](/backend/foundation)
|
|
37
|
+
- [Service Guide](/backend/service-guide)
|
|
38
|
+
- [Class Placement Rule](/ai/class-placement-rule)
|
|
39
|
+
- [Backend Startup Guide](/backend/startup-guide)
|
|
40
|
+
|
|
41
|
+
### 2. Scope and module resource access
|
|
42
|
+
|
|
43
|
+
The most practical backend access model is module scope.
|
|
44
|
+
|
|
45
|
+
That includes:
|
|
46
|
+
|
|
47
|
+
- local module access through `this.scope`
|
|
48
|
+
- cross-module access through `this.$scope`
|
|
49
|
+
- resource categories such as service, model, entity, config, constant, locale, and error
|
|
50
|
+
- explicit leaves such as [Config Guide](/backend/config-guide) and [Error Guide](/backend/error-guide)
|
|
51
|
+
|
|
52
|
+
A useful refinement is that `constant` and `locale` should be treated as first-class scope resources too, not as secondary extras.
|
|
53
|
+
|
|
54
|
+
A practical split is:
|
|
55
|
+
|
|
56
|
+
- `config` and `error` help define backend policy and failure behavior
|
|
57
|
+
- `constant` and `locale` help define stable module vocabulary and translatable text surfaces
|
|
58
|
+
- all of them still fit the same scope-based access model rather than requiring ad hoc imports everywhere
|
|
59
|
+
|
|
60
|
+
This is one of the reasons backend code can stay concise without flattening everything into imports or manual container wiring.
|
|
61
|
+
|
|
62
|
+
Read next:
|
|
63
|
+
|
|
64
|
+
- [Service Guide](/backend/service-guide)
|
|
65
|
+
- [Model Guide](/backend/model-guide)
|
|
66
|
+
- [Entity Guide](/backend/entity-guide)
|
|
67
|
+
- [DTO Guide](/backend/dto-guide)
|
|
68
|
+
|
|
69
|
+
### 3. Modularization across suite / module / package
|
|
70
|
+
|
|
71
|
+
Vona backend architecture is also organized around structural units, not just source folders.
|
|
72
|
+
|
|
73
|
+
The main units are:
|
|
74
|
+
|
|
75
|
+
- suite
|
|
76
|
+
- module
|
|
77
|
+
- package
|
|
78
|
+
|
|
79
|
+
Those boundaries matter because they shape:
|
|
80
|
+
|
|
81
|
+
- naming
|
|
82
|
+
- dependency declarations
|
|
83
|
+
- generated file placement
|
|
84
|
+
- module-scope resource access
|
|
85
|
+
- backend CLI workflows
|
|
86
|
+
|
|
87
|
+
Read next:
|
|
88
|
+
|
|
89
|
+
- [Backend CLI](/backend/cli)
|
|
90
|
+
- [Backend Scripts](/backend/scripts)
|
|
91
|
+
- [Package Map](/reference/package-map)
|
|
92
|
+
|
|
93
|
+
## Suggested reading path
|
|
94
|
+
|
|
95
|
+
If you are new to backend architecture, read in this order:
|
|
96
|
+
|
|
97
|
+
1. [Backend Foundation](/backend/foundation)
|
|
98
|
+
2. [Backend CLI](/backend/cli)
|
|
99
|
+
3. [Backend Scripts](/backend/scripts)
|
|
100
|
+
4. [Service Guide](/backend/service-guide)
|
|
101
|
+
5. [Model Guide](/backend/model-guide)
|
|
102
|
+
6. [Entity Guide](/backend/entity-guide)
|
|
103
|
+
7. [DTO Guide](/backend/dto-guide)
|
|
104
|
+
8. [Runtime and Flavors](/backend/runtime-and-flavors)
|
|
105
|
+
9. [Backend Startup Guide](/backend/startup-guide)
|
|
106
|
+
|
|
107
|
+
## How this page relates to the rest of the backend docs
|
|
108
|
+
|
|
109
|
+
This page is a compact family hub, not the deep technical home for each backend topic.
|
|
110
|
+
|
|
111
|
+
A practical split is:
|
|
112
|
+
|
|
113
|
+
- [Backend (Vona)](/backend/introduction) is the broader backend entry page
|
|
114
|
+
- [Backend Foundation](/backend/foundation) explains the architecture-first model
|
|
115
|
+
- [Service Guide](/backend/service-guide) explains the most practical access patterns
|
|
116
|
+
- [Backend CLI](/backend/cli) and [Backend Scripts](/backend/scripts) explain workflow entrypoints
|
|
117
|
+
- [Package Map](/reference/package-map) grounds the structure in the real monorepo
|
|
118
|
+
|
|
119
|
+
## Implementation checks for backend-architecture changes
|
|
120
|
+
|
|
121
|
+
When changing backend code, ask:
|
|
122
|
+
|
|
123
|
+
1. is this capability best reached through local module scope, cross-module scope, injection, or direct bean access?
|
|
124
|
+
2. does the change belong to a module, a suite, or a shared package boundary?
|
|
125
|
+
3. is there already a CLI workflow or bean type that should be reused instead of manual scaffolding?
|
|
126
|
+
4. does the change belong to the architecture spine first, or only to one feature-specific guide?
|
|
127
|
+
|
|
128
|
+
That helps AI keep backend changes aligned with Vona’s real architecture instead of only copying local code patterns.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Broadcast Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how broadcast works in Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why broadcast matters
|
|
6
|
+
|
|
7
|
+
Broadcast lets one worker emit a message that multiple worker processes can receive and act on.
|
|
8
|
+
|
|
9
|
+
This is important because some business logic is not point-to-point background work. It is multi-worker coordination work.
|
|
10
|
+
|
|
11
|
+
## Create a broadcast
|
|
12
|
+
|
|
13
|
+
Example: create a broadcast named `echo` in module `demo-student`.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run vona :create:bean broadcast echo -- --module=demo-student
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Broadcast definition
|
|
20
|
+
|
|
21
|
+
Representative shape:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
@Broadcast()
|
|
25
|
+
export class BroadcastEcho
|
|
26
|
+
extends BeanBroadcastBase<TypeBroadcastEchoJobData>
|
|
27
|
+
implements IBroadcastExecute<TypeBroadcastEchoJobData>
|
|
28
|
+
{
|
|
29
|
+
async execute(data: TypeBroadcastEchoJobData, isEmitter?: boolean) {
|
|
30
|
+
if (!isEmitter) {
|
|
31
|
+
console.log(`pid: ${process.pid} message: ${data.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The `isEmitter` flag is especially important because it lets the current worker avoid duplicating work it already performed locally.
|
|
38
|
+
|
|
39
|
+
## Emit a broadcast
|
|
40
|
+
|
|
41
|
+
Representative usage:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
this.scope.broadcast.echo.emit({ message: 'Hello world' });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A practical interpretation is:
|
|
48
|
+
|
|
49
|
+
- the emitter starts the fan-out
|
|
50
|
+
- every receiving worker can execute the same logic
|
|
51
|
+
- the emitter can skip duplicate local work by checking `isEmitter`
|
|
52
|
+
|
|
53
|
+
## Broadcast options
|
|
54
|
+
|
|
55
|
+
Broadcast options include:
|
|
56
|
+
|
|
57
|
+
- `instance`
|
|
58
|
+
- `transaction`
|
|
59
|
+
|
|
60
|
+
Representative decorator pattern:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
@Broadcast({
|
|
64
|
+
instance: true,
|
|
65
|
+
transaction: true,
|
|
66
|
+
})
|
|
67
|
+
class BroadcastEcho {}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This matters because broadcast behavior may depend on tenant initialization or transactional execution guarantees.
|
|
71
|
+
|
|
72
|
+
## Configure broadcasts in app config
|
|
73
|
+
|
|
74
|
+
Broadcast options can also be overridden in app config.
|
|
75
|
+
|
|
76
|
+
Representative pattern:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
config.onions = {
|
|
80
|
+
broadcast: {
|
|
81
|
+
'demo-student:echo': {
|
|
82
|
+
instance: true,
|
|
83
|
+
transaction: true,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Broadcast vs queue vs election
|
|
90
|
+
|
|
91
|
+
Read this guide together with:
|
|
92
|
+
|
|
93
|
+
- [Backend Startup Guide](/backend/startup-guide)
|
|
94
|
+
- [Queue Guide](/backend/queue-guide)
|
|
95
|
+
- [Election Guide](/backend/election-guide)
|
|
96
|
+
- [Worker Guide](/backend/worker-guide)
|
|
97
|
+
|
|
98
|
+
A practical split is:
|
|
99
|
+
|
|
100
|
+
- use **broadcast** when many workers should all receive the same signal or perform the same category of work
|
|
101
|
+
- use **queue** when one background execution path should process a job asynchronously
|
|
102
|
+
- use **election** when only one worker, or a fixed small number of workers, should own the responsibility
|
|
103
|
+
|
|
104
|
+
This distinction matters because all three features are distributed primitives, but they solve different coordination problems.
|
|
105
|
+
|
|
106
|
+
## Relationship to backend runtime initialization
|
|
107
|
+
|
|
108
|
+
Broadcast is not the same as startup.
|
|
109
|
+
|
|
110
|
+
A useful mental model is:
|
|
111
|
+
|
|
112
|
+
- startup initializes backend capabilities and lifecycle hooks
|
|
113
|
+
- election chooses the owner for singleton-like responsibilities
|
|
114
|
+
- broadcast fans out a message to many workers after the runtime is active
|
|
115
|
+
|
|
116
|
+
That keeps runtime initialization separate from runtime signaling.
|
|
117
|
+
|
|
118
|
+
## Inspection
|
|
119
|
+
|
|
120
|
+
The effective broadcast list can be inspected for debugging and operational clarity.
|
|
121
|
+
|
|
122
|
+
Representative pattern:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
this.bean.onion.broadcast.inspect();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Implementation checks for multi-worker broadcast changes
|
|
129
|
+
|
|
130
|
+
When evaluating multi-worker coordination needs, ask:
|
|
131
|
+
|
|
132
|
+
1. is this really a queue job, or is it a broadcast?
|
|
133
|
+
2. should the emitter worker also execute the business logic?
|
|
134
|
+
3. does the logic require instance initialization?
|
|
135
|
+
4. should the execution run inside a transaction?
|
|
136
|
+
5. is this actually a singleton-ownership problem that belongs to election instead?
|
|
137
|
+
|
|
138
|
+
That helps distribute the right kind of work through the right abstraction.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Cache Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how ORM caching works in Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why caching is first-class in Vona
|
|
6
|
+
|
|
7
|
+
Large business systems often fail not because performance is impossible, but because performance strategy is bolted on too late and too inconsistently.
|
|
8
|
+
|
|
9
|
+
Vona responds by moving caching into the framework core.
|
|
10
|
+
|
|
11
|
+
That means cache behavior is not only an optimization technique. It is part of the default data model.
|
|
12
|
+
|
|
13
|
+
## Out-of-the-box behavior
|
|
14
|
+
|
|
15
|
+
One major point is that Vona ORM offers out-of-the-box caching.
|
|
16
|
+
|
|
17
|
+
In practice, that means ordinary ORM operations can benefit from framework-managed cache behavior without forcing the developer to hand-maintain every cache path.
|
|
18
|
+
|
|
19
|
+
## Entity cache
|
|
20
|
+
|
|
21
|
+
The entity cache centers on the mapping:
|
|
22
|
+
|
|
23
|
+
- entity id -> entity data
|
|
24
|
+
|
|
25
|
+
This is important because entity reads can become cheap and update/delete operations can invalidate the relevant entries systematically.
|
|
26
|
+
|
|
27
|
+
## Query cache
|
|
28
|
+
|
|
29
|
+
The query cache operates differently.
|
|
30
|
+
|
|
31
|
+
For normal queries, the cache is based on:
|
|
32
|
+
|
|
33
|
+
- hash of the query clause -> array of ids
|
|
34
|
+
|
|
35
|
+
Then the final data is resolved through entity-cache retrieval.
|
|
36
|
+
|
|
37
|
+
For aggregate and group operations, the cache can directly store the resulting computed data.
|
|
38
|
+
|
|
39
|
+
This is one of the key Vona ideas: query cache and entity cache cooperate instead of duplicating responsibility blindly.
|
|
40
|
+
|
|
41
|
+
## Cache configuration
|
|
42
|
+
|
|
43
|
+
Cache configuration exists at both:
|
|
44
|
+
|
|
45
|
+
- model options
|
|
46
|
+
- app config
|
|
47
|
+
|
|
48
|
+
Representative areas include:
|
|
49
|
+
|
|
50
|
+
- entity-cache mode and ttl
|
|
51
|
+
- query-cache mode and ttl
|
|
52
|
+
- related-model cache clearing
|
|
53
|
+
- custom cache-clearing logic
|
|
54
|
+
|
|
55
|
+
## Consistency strategy
|
|
56
|
+
|
|
57
|
+
Vona also clears or compensates cache automatically when model mutation occurs.
|
|
58
|
+
|
|
59
|
+
That matters because a useful cache is not only about hits. It is about correctness under change.
|
|
60
|
+
|
|
61
|
+
## Implementation checks for cache-sensitive data-access changes
|
|
62
|
+
|
|
63
|
+
When changing data-access behavior, ask:
|
|
64
|
+
|
|
65
|
+
1. is this path already covered by Vona’s built-in cache model?
|
|
66
|
+
2. does the model cache config need to be updated?
|
|
67
|
+
3. should related-model query caches also be cleared?
|
|
68
|
+
4. does transaction-aware cache compensation matter for this change?
|
|
69
|
+
|
|
70
|
+
That helps avoid both underusing and breaking the cache system.
|