cabloy 5.1.49 → 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 +46 -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/zova/packages-zova/zova/package.json +2 -2
- package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolTwo/controller.tsx +0 -2
- package/zova/src/suite/a-home/modules/home-base/src/config/locale/en-us.ts +1 -0
- package/zova/src/suite/a-home/modules/home-base/src/config/locale/zh-cn.ts +1 -0
- package/zova/src/suite/a-home/modules/home-base/src/page/errorNotFound/controller.tsx +8 -2
- package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/controller.tsx +1 -1
- package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.header.tsx +1 -1
- package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.locale.tsx +2 -5
- package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/render.tabs.tsx +1 -4
- package/zova/src/suite-vendor/a-zova/modules/a-router/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/bean/sys.router.ts +28 -6
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkeySys.ts +15 -3
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/router.ts +1 -0
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-routertabs/src/model/tabs.ts +4 -0
- package/zova/src/suite-vendor/a-zova/package.json +3 -3
- /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,189 @@
|
|
|
1
|
+
# Mail Guide
|
|
2
|
+
|
|
3
|
+
## Why mail matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona treats email delivery as a framework capability rather than a one-off SMTP utility call.
|
|
6
|
+
|
|
7
|
+
That matters because email sending often needs queue-backed execution, multiple clients, environment-specific configuration, and integration with user-access or other business workflows.
|
|
8
|
+
|
|
9
|
+
## Core mail model
|
|
10
|
+
|
|
11
|
+
The `a-mail` module provides email delivery on top of Nodemailer.
|
|
12
|
+
|
|
13
|
+
The most important framework-level pieces are:
|
|
14
|
+
|
|
15
|
+
- one or more **mail clients**
|
|
16
|
+
- a **default client**
|
|
17
|
+
- queue-backed sending
|
|
18
|
+
- configuration through app config or environment variables
|
|
19
|
+
|
|
20
|
+
## Mail clients
|
|
21
|
+
|
|
22
|
+
Mail clients are configured under the `a-mail` module config.
|
|
23
|
+
|
|
24
|
+
Representative configuration areas include:
|
|
25
|
+
|
|
26
|
+
- `defaultClient`
|
|
27
|
+
- `clients`
|
|
28
|
+
|
|
29
|
+
A client usually defines:
|
|
30
|
+
|
|
31
|
+
- `transport`
|
|
32
|
+
- `defaults`
|
|
33
|
+
|
|
34
|
+
### Transport
|
|
35
|
+
|
|
36
|
+
Transport settings describe how mail is actually delivered, for example:
|
|
37
|
+
|
|
38
|
+
- `service`
|
|
39
|
+
- `host`
|
|
40
|
+
- `port`
|
|
41
|
+
- `secure`
|
|
42
|
+
- `auth.user`
|
|
43
|
+
- `auth.pass`
|
|
44
|
+
|
|
45
|
+
### Defaults
|
|
46
|
+
|
|
47
|
+
Defaults provide common message values such as `from`.
|
|
48
|
+
|
|
49
|
+
## Built-in test service
|
|
50
|
+
|
|
51
|
+
Vona provides a built-in `test` mail service so email flows can be exercised during development without requiring a real mail server.
|
|
52
|
+
|
|
53
|
+
This is important because it makes email behavior easier to verify early instead of deferring all mail testing to production-like infrastructure.
|
|
54
|
+
|
|
55
|
+
## Configuration through app config and env
|
|
56
|
+
|
|
57
|
+
Mail configuration can be provided through:
|
|
58
|
+
|
|
59
|
+
- app config under `config.modules['a-mail']`
|
|
60
|
+
- environment variables such as `MAIL_DEFAULT_CLIENT` and related transport/default fields
|
|
61
|
+
|
|
62
|
+
That means operational mail behavior can remain configurable without rewriting application logic.
|
|
63
|
+
|
|
64
|
+
## Adding a new mail client
|
|
65
|
+
|
|
66
|
+
Projects can add additional clients for different email responsibilities, such as a dedicated `order` client.
|
|
67
|
+
|
|
68
|
+
This is useful when different workflows need different senders, transports, or message defaults.
|
|
69
|
+
|
|
70
|
+
Representative type extension:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
declare module 'vona-module-a-mail' {
|
|
74
|
+
export interface IMailClientRecord {
|
|
75
|
+
order: never;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
In the VSCode workflow, the `recordmailclient` snippet can generate the augmentation skeleton.
|
|
81
|
+
|
|
82
|
+
A representative config expansion is:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
config.modules = {
|
|
86
|
+
'a-mail': {
|
|
87
|
+
defaultClient: 'system',
|
|
88
|
+
clients: {
|
|
89
|
+
system: {
|
|
90
|
+
transport: { service: 'test' },
|
|
91
|
+
defaults: { from: 'no.reply@cabloy.com' },
|
|
92
|
+
},
|
|
93
|
+
order: {
|
|
94
|
+
transport: { service: 'test' },
|
|
95
|
+
defaults: { from: 'order@cabloy.com' },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## `bean.mail`
|
|
103
|
+
|
|
104
|
+
Vona exposes a global bean `bean.mail` for sending emails.
|
|
105
|
+
|
|
106
|
+
Representative pattern:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const mail: IMailOptions = {
|
|
110
|
+
to: 'someone@cabloy.com',
|
|
111
|
+
subject: 'this is a test mail',
|
|
112
|
+
text: 'message body!',
|
|
113
|
+
};
|
|
114
|
+
await this.bean.mail.send(mail);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
A specific client can also be selected explicitly:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
await this.bean.mail.send(mail, 'order');
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Queue-backed delivery
|
|
124
|
+
|
|
125
|
+
Vona sends mail through a built-in queue.
|
|
126
|
+
|
|
127
|
+
This is one of the most important architectural points of the mail system, because email delivery is naturally asynchronous and should not be tightly coupled to the immediate request path.
|
|
128
|
+
|
|
129
|
+
Queue behavior can be tuned through queue config, for example worker concurrency.
|
|
130
|
+
|
|
131
|
+
Representative config pattern:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
config.onions = {
|
|
135
|
+
queue: {
|
|
136
|
+
'a-mail:mail': {
|
|
137
|
+
options: {
|
|
138
|
+
worker: {
|
|
139
|
+
concurrency: 10,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
A useful ownership rule is:
|
|
148
|
+
|
|
149
|
+
- request or business logic decides _that_ a mail should be sent
|
|
150
|
+
- `bean.mail` decides which client to use
|
|
151
|
+
- the queue owns _when_ the actual delivery work runs
|
|
152
|
+
|
|
153
|
+
## Relationship to user-access and event workflows
|
|
154
|
+
|
|
155
|
+
Mail is commonly part of broader backend lifecycle behavior such as:
|
|
156
|
+
|
|
157
|
+
- account registration follow-up
|
|
158
|
+
- activation or confirmation mail
|
|
159
|
+
- notification workflows after business events
|
|
160
|
+
|
|
161
|
+
Read this guide together with:
|
|
162
|
+
|
|
163
|
+
- [User Access Guide](/backend/user-access-guide)
|
|
164
|
+
- [Event Guide](/backend/event-guide)
|
|
165
|
+
|
|
166
|
+
Those guides explain the flows where mail often becomes a downstream effect rather than the initiating business action.
|
|
167
|
+
|
|
168
|
+
In the current repo, the `a-mailconfirm` flow is a representative example: user-access events can trigger mail-confirm behavior, and that bean ultimately delegates delivery through `bean.mail.send(...)` instead of embedding transport details directly into the user workflow.
|
|
169
|
+
|
|
170
|
+
## When to use a dedicated mail client
|
|
171
|
+
|
|
172
|
+
Use a dedicated client when:
|
|
173
|
+
|
|
174
|
+
- a workflow needs a different sender identity
|
|
175
|
+
- a workflow needs a different transport
|
|
176
|
+
- a workflow needs separate operational handling from the default client
|
|
177
|
+
|
|
178
|
+
Use the default client when the mail path belongs to the general system mail flow.
|
|
179
|
+
|
|
180
|
+
## Implementation checks for backend mail changes
|
|
181
|
+
|
|
182
|
+
When editing backend mail behavior, ask:
|
|
183
|
+
|
|
184
|
+
1. should this email be sent through the default client or a dedicated client?
|
|
185
|
+
2. does the flow belong in the immediate request path or in a queue-backed asynchronous path?
|
|
186
|
+
3. is the existing `test` mail service enough for development verification?
|
|
187
|
+
4. does the mail behavior belong to a user-access lifecycle event or a broader business event workflow?
|
|
188
|
+
|
|
189
|
+
That helps AI keep email delivery aligned with Vona’s operational and event-driven backend model.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Menu Guide
|
|
2
|
+
|
|
3
|
+
## Why menus matter in Cabloy SSR flows
|
|
4
|
+
|
|
5
|
+
In Cabloy, SSR menu retrieval can be treated as a reusable backend capability instead of a one-off frontend-only concern.
|
|
6
|
+
|
|
7
|
+
That matters because shared menu retrieval makes it easier to reuse navigation logic across modules and editions.
|
|
8
|
+
|
|
9
|
+
## Core SSR menu model
|
|
10
|
+
|
|
11
|
+
The `a-ssr` module provides a general SSR menu system.
|
|
12
|
+
|
|
13
|
+
A project can ignore the system menu model and implement its own retrieval logic, but the built-in model is useful because it improves reuse, consistency, and scalability.
|
|
14
|
+
|
|
15
|
+
## `bean.ssr`
|
|
16
|
+
|
|
17
|
+
Vona exposes a global bean `bean.ssr` for SSR-facing menu retrieval.
|
|
18
|
+
|
|
19
|
+
A representative usage pattern is:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
const res = await this.bean.ssr.retrieveMenus(publicPath);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This allows a module-level menu service to:
|
|
26
|
+
|
|
27
|
+
1. ask the shared SSR menu system for the effective menu set
|
|
28
|
+
2. fall back to default local menus when needed
|
|
29
|
+
|
|
30
|
+
The current `home-base` implementation in this repo follows exactly that pattern in its menu service, which keeps this guide grounded in the real out-of-the-box SSR path.
|
|
31
|
+
|
|
32
|
+
## Fallback strategy
|
|
33
|
+
|
|
34
|
+
A practical menu service can:
|
|
35
|
+
|
|
36
|
+
- try shared SSR menu retrieval first
|
|
37
|
+
- return a module-defined default menu if no shared menu is available
|
|
38
|
+
|
|
39
|
+
That keeps menu integration flexible without giving up framework-level reuse.
|
|
40
|
+
|
|
41
|
+
## Menu API shape
|
|
42
|
+
|
|
43
|
+
A backend controller can expose the menu retrieval path directly:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
@Web.get(':publicPath?')
|
|
47
|
+
@Api.body(v.object(DtoMenus))
|
|
48
|
+
@Passport.public()
|
|
49
|
+
async retrieveMenus(@Arg.param('publicPath', v.optional()) publicPath?: string) {
|
|
50
|
+
return await this.scope.service.menu.retrieveMenus(publicPath);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This makes menu retrieval part of the broader backend contract surface.
|
|
55
|
+
|
|
56
|
+
In the current repo implementation, the out-of-the-box menu controller is public and delegates directly to `this.scope.service.menu.retrieveMenus(publicPath)`.
|
|
57
|
+
|
|
58
|
+
## Relationship to frontend integration
|
|
59
|
+
|
|
60
|
+
Menu retrieval is especially relevant in SSR-sensitive frontend flows.
|
|
61
|
+
|
|
62
|
+
The backend menu contract should be read together with frontend routing, SSR, and page-loading behavior, especially when different editions expose different module or menu structures.
|
|
63
|
+
|
|
64
|
+
A practical boundary is:
|
|
65
|
+
|
|
66
|
+
- backend decides how menus are retrieved, merged, and defaulted
|
|
67
|
+
- frontend decides how those menu DTOs are rendered into route or navigation state
|
|
68
|
+
|
|
69
|
+
That split helps avoid re-implementing menu policy independently on both sides.
|
|
70
|
+
|
|
71
|
+
## Implementation checks for SSR menu changes
|
|
72
|
+
|
|
73
|
+
When editing SSR menu behavior, ask:
|
|
74
|
+
|
|
75
|
+
1. should the logic use `bean.ssr.retrieveMenus(...)` instead of inventing a parallel retrieval path?
|
|
76
|
+
2. is there a default fallback menu that should remain available?
|
|
77
|
+
3. does the menu contract belong in backend API design, frontend route design, or both?
|
|
78
|
+
4. does the active edition affect the menu structure or public path assumptions?
|
|
79
|
+
|
|
80
|
+
That helps AI keep menu behavior aligned with Cabloy’s shared SSR architecture.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# Migration and Changes
|
|
2
|
+
|
|
3
|
+
This guide explains how migration and change management work in Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why this system exists
|
|
6
|
+
|
|
7
|
+
Vona provides a migration mechanism designed for long-lived modular projects.
|
|
8
|
+
|
|
9
|
+
Several important characteristics define this migration system:
|
|
10
|
+
|
|
11
|
+
- module-aware migration
|
|
12
|
+
- multi-tenant initialization support
|
|
13
|
+
- test-data support
|
|
14
|
+
- production-safe execution
|
|
15
|
+
- full access to the Vona ecosystem inside migration code
|
|
16
|
+
|
|
17
|
+
This makes migration in Vona more than a one-off schema script. It is part of the framework’s modular lifecycle.
|
|
18
|
+
|
|
19
|
+
## Migration in the backend contract loop
|
|
20
|
+
|
|
21
|
+
A useful backend-contract-loop lifecycle mental model is:
|
|
22
|
+
|
|
23
|
+
- entity and model define the current structural contract
|
|
24
|
+
- DTOs and controllers define the API contract on top of that structure
|
|
25
|
+
- `meta.version` manages schema evolution and initialization data
|
|
26
|
+
- tests verify that the migrated backend still satisfies the intended contract
|
|
27
|
+
|
|
28
|
+
That is why migration should be understood as part of the same backend thread, not as a separate maintenance topic.
|
|
29
|
+
|
|
30
|
+
## Define data version
|
|
31
|
+
|
|
32
|
+
Each module declares its current data version in its own `package.json`.
|
|
33
|
+
|
|
34
|
+
Representative pattern:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"name": "vona-module-demo-student",
|
|
39
|
+
"vonaModule": {
|
|
40
|
+
"fileVersion": 1
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The key rule is:
|
|
46
|
+
|
|
47
|
+
- increment `fileVersion` when a released module introduces a new schema change that must be applied in sequence
|
|
48
|
+
|
|
49
|
+
In the scaffolded CRUD workflow, this is not an isolated maintenance step. The generator-driven thread treats `fileVersion` as part of the same backend evolution path that also touches entity/model/controller/test resources.
|
|
50
|
+
|
|
51
|
+
## `meta.version`
|
|
52
|
+
|
|
53
|
+
Vona uses a bean named `meta.version` to organize migration code for a module.
|
|
54
|
+
|
|
55
|
+
Create it with:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run vona :create:bean meta version -- --module=demo-student
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Representative shell:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
@Meta()
|
|
65
|
+
export class MetaVersion extends BeanBase {}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Three change scenarios
|
|
69
|
+
|
|
70
|
+
Three migration scenarios are defined:
|
|
71
|
+
|
|
72
|
+
| Scenario | Purpose |
|
|
73
|
+
| -------- | ------------------------------------------------ |
|
|
74
|
+
| `update` | schema evolution such as tables and fields |
|
|
75
|
+
| `init` | instance- or tenant-specific initialization data |
|
|
76
|
+
| `test` | test-only data for the test environment |
|
|
77
|
+
|
|
78
|
+
This split is one of the most important Vona migration ideas because it separates:
|
|
79
|
+
|
|
80
|
+
- structural change
|
|
81
|
+
- initialization logic
|
|
82
|
+
- test data setup
|
|
83
|
+
|
|
84
|
+
A practical generated-thread interpretation is:
|
|
85
|
+
|
|
86
|
+
- `update` follows schema and entity/model evolution
|
|
87
|
+
- `init` follows instance-aware initialization needs introduced by the backend feature
|
|
88
|
+
- `test` keeps the generated or refined contract easy to verify under the test lifecycle
|
|
89
|
+
|
|
90
|
+
## Update: schema migration
|
|
91
|
+
|
|
92
|
+
Representative pattern:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
@Meta()
|
|
96
|
+
export class MetaVersion extends BeanBase implements IMetaVersionUpdate {
|
|
97
|
+
async update(options: IMetaVersionUpdateOptions) {
|
|
98
|
+
if (options.version === 1) {
|
|
99
|
+
await this.bean.model.createTable('demoStudent', table => {
|
|
100
|
+
table.basicFields();
|
|
101
|
+
table.string('name', 50);
|
|
102
|
+
table.string('description', 255);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
A typed style based on entity metadata is also supported, and it is usually the better long-term default when possible.
|
|
110
|
+
|
|
111
|
+
## Init: tenant-aware initialization
|
|
112
|
+
|
|
113
|
+
Representative pattern:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
@Meta()
|
|
117
|
+
export class MetaVersion extends BeanBase implements IMetaVersionInit {
|
|
118
|
+
async init(options: IMetaVersionInitOptions) {
|
|
119
|
+
if (options.version === 1) {
|
|
120
|
+
await this.scope.model.student.insert({
|
|
121
|
+
name: 'Tom',
|
|
122
|
+
description: 'This is a student',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The important point is that initialization can run per instance or tenant, which keeps tenant data isolated.
|
|
130
|
+
|
|
131
|
+
## Test: test-only data
|
|
132
|
+
|
|
133
|
+
Representative pattern:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
@Meta()
|
|
137
|
+
export class MetaVersion extends BeanBase implements IMetaVersionTest {
|
|
138
|
+
async test() {
|
|
139
|
+
await this.scope.model.student.insert({
|
|
140
|
+
name: 'Jimmy',
|
|
141
|
+
description: 'Only used in unit test',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This is valuable because test data becomes part of the structured migration lifecycle instead of being scattered across unrelated setup code.
|
|
148
|
+
|
|
149
|
+
## Version changes across the generated backend thread
|
|
150
|
+
|
|
151
|
+
When the generated CRUD thread evolves, migration should evolve with it.
|
|
152
|
+
|
|
153
|
+
A practical sequence is:
|
|
154
|
+
|
|
155
|
+
1. increment `fileVersion`
|
|
156
|
+
2. add or adjust entity/model structure
|
|
157
|
+
3. update `meta.version` logic
|
|
158
|
+
4. rerun migration locally
|
|
159
|
+
5. verify the contract through tests and controller actions
|
|
160
|
+
|
|
161
|
+
This keeps schema change, backend contract change, and verification tightly connected.
|
|
162
|
+
|
|
163
|
+
## Local development workflow
|
|
164
|
+
|
|
165
|
+
One important distinction for local development is:
|
|
166
|
+
|
|
167
|
+
- when iterating locally, you often want to recreate the database and re-run migration logic without bumping `fileVersion`
|
|
168
|
+
|
|
169
|
+
Representative commands:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
npm run test
|
|
173
|
+
cd vona && npm run db:reset
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
A practical decision rule is:
|
|
177
|
+
|
|
178
|
+
- use `db:reset` when you mainly need to replay migration/database setup locally
|
|
179
|
+
- use `test` when you need to verify that migration, controller behavior, and the broader generated contract thread still work together
|
|
180
|
+
|
|
181
|
+
## Implementation checks for migration-sensitive changes
|
|
182
|
+
|
|
183
|
+
When changing backend schema or module initialization behavior, do not only edit entities and models.
|
|
184
|
+
|
|
185
|
+
Also ask:
|
|
186
|
+
|
|
187
|
+
1. does this change require a `fileVersion` increment?
|
|
188
|
+
2. does `meta.version` need an `update`, `init`, or `test` branch?
|
|
189
|
+
3. should the local verification path include `test` or `db:reset`?
|
|
190
|
+
4. does the change affect the CRUD-generated thread or frontend-facing API contract as well?
|
|
191
|
+
|
|
192
|
+
That prevents schema changes from being documented in code but never integrated into the module lifecycle.
|