cabloy 5.1.50 → 5.1.52
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 +292 -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 +30 -0
- package/.github/workflows/docs-pages.yml +56 -0
- package/.gitignore +1 -0
- package/CHANGELOG.md +54 -0
- package/CLAUDE.md +59 -0
- package/README.md +152 -0
- package/cabloy-docs/.vitepress/config.mjs +255 -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 +139 -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 +168 -0
- package/cabloy-docs/ai/edition-consistency-checklist.md +150 -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 +158 -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 +37 -0
- package/cabloy-docs/ai/verification.md +31 -0
- package/cabloy-docs/ai/virtual-decorator-guidance.md +206 -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 +26 -0
- package/cabloy-docs/editions/cabloy-start.md +55 -0
- package/cabloy-docs/editions/choosing-between-basic-and-start.md +84 -0
- package/cabloy-docs/editions/detection.md +31 -0
- package/cabloy-docs/editions/overview.md +107 -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 +58 -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 +33 -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 +202 -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/cli.md +118 -0
- package/cabloy-docs/fullstack/comparison-with-other-frameworks.md +117 -0
- package/cabloy-docs/fullstack/edition-collaboration-differences.md +62 -0
- package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +64 -0
- package/cabloy-docs/fullstack/introduction.md +81 -0
- package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -0
- package/cabloy-docs/fullstack/quickstart.md +89 -0
- package/cabloy-docs/fullstack/vona-zova-integration.md +86 -0
- package/cabloy-docs/fullstack/vscode-extensions.md +126 -0
- package/cabloy-docs/index.md +72 -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 +4 -4
- package/vona/README.zh-CN.md +4 -4
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/pnpm-lock.yaml +383 -38
- 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/modules/a-ssr/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/.metadata/index.ts +49 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/controller/memoryDiag.ts +97 -0
- 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 +5 -5
- package/zova/README.zh-CN.md +4 -4
- package/zova/package.original.json +4 -4
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/package.json +2 -2
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-utils/zova-vite/templates/app/controller.tsx_ +3 -3
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +2 -2
- package/zova/packages-zova/zova-core/src/bean/beanContainer.ts +3 -3
- package/zova/packages-zova/zova-core/src/bean/beanControllerPageBase.ts +1 -0
- package/zova/packages-zova/zova-core/src/core/component/module.ts +16 -16
- package/zova/packages-zova/zova-core/src/core/context/component.ts +35 -3
- package/zova/packages-zova/zova-core/src/core/context/util.ts +15 -11
- package/zova/pnpm-lock.yaml +1596 -1679
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +11 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/page/toolMinimal.ts +9 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolMinimal/controller.tsx +11 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/routes.ts +10 -0
- package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/service/storage.ts +4 -5
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/monkey.ts +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +36 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssrMetaStore.ts +7 -2
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/monkey.ts +3 -0
- package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/src/service/ssrHandler.ts +70 -29
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +6 -6
- /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,209 @@
|
|
|
1
|
+
# Unit Testing
|
|
2
|
+
|
|
3
|
+
This guide explains the most important Vona testing workflows in the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why testing is emphasized
|
|
6
|
+
|
|
7
|
+
Test-driven development remains a strong default in the Cabloy monorepo.
|
|
8
|
+
|
|
9
|
+
Vona’s testing story is valuable because it is closely integrated with:
|
|
10
|
+
|
|
11
|
+
- app initialization
|
|
12
|
+
- Redis cleanup
|
|
13
|
+
- database recreation
|
|
14
|
+
- migration execution
|
|
15
|
+
- request-context simulation
|
|
16
|
+
- action-level API verification
|
|
17
|
+
|
|
18
|
+
That means tests can exercise framework behavior in a realistic way.
|
|
19
|
+
|
|
20
|
+
## Unit testing in the backend contract loop
|
|
21
|
+
|
|
22
|
+
A useful backend-contract-loop testing mental model is:
|
|
23
|
+
|
|
24
|
+
- migration prepares the structural state
|
|
25
|
+
- controllers expose the route/action surface
|
|
26
|
+
- services and models execute the business and persistence logic
|
|
27
|
+
- tests verify the resulting contract through scoped access and action execution
|
|
28
|
+
|
|
29
|
+
This is why Vona testing should not be reduced to isolated helper-unit testing only.
|
|
30
|
+
|
|
31
|
+
## Create a test file
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm run vona :create:test student -- --module=demo-student
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Execute tests
|
|
40
|
+
|
|
41
|
+
From the root repository:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm run test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A typical Vona test flow includes:
|
|
48
|
+
|
|
49
|
+
1. create a global `app` object
|
|
50
|
+
2. clean Redis data
|
|
51
|
+
3. recreate the database
|
|
52
|
+
4. execute migration code
|
|
53
|
+
5. run the test files
|
|
54
|
+
|
|
55
|
+
This is one of the most important distinctions from ordinary app flow: test execution rebuilds and verifies the framework lifecycle, not only the target function.
|
|
56
|
+
|
|
57
|
+
## Reset database without running tests
|
|
58
|
+
|
|
59
|
+
Representative command:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cd vona && npm run db:reset
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This is useful when you want to reapply migration logic without running the entire test suite.
|
|
66
|
+
|
|
67
|
+
## Coverage
|
|
68
|
+
|
|
69
|
+
Representative command:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd vona && npm run cov
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Mock request context
|
|
76
|
+
|
|
77
|
+
One of the most important Vona testing patterns is simulating a request context.
|
|
78
|
+
|
|
79
|
+
Representative shape:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
await app.bean.executor.mockCtx(async () => {
|
|
83
|
+
// test logic here
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Locale-sensitive variants and additional request-context helpers are also available.
|
|
88
|
+
|
|
89
|
+
## Working with module scope in tests
|
|
90
|
+
|
|
91
|
+
Representative pattern:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const scopeStudent = app.scope('demo-student');
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This lets tests exercise:
|
|
98
|
+
|
|
99
|
+
- services
|
|
100
|
+
- models
|
|
101
|
+
- entities
|
|
102
|
+
- controller actions
|
|
103
|
+
|
|
104
|
+
through the same scoped abstractions used in application code.
|
|
105
|
+
|
|
106
|
+
## Testing controllers through actions
|
|
107
|
+
|
|
108
|
+
Representative pattern:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
await app.bean.executor.performAction('get', '/demo/student');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This is especially useful because it exercises the controller path more realistically than only unit-testing isolated helper functions.
|
|
115
|
+
|
|
116
|
+
A practical rule is:
|
|
117
|
+
|
|
118
|
+
- use direct service/model assertions when the test target is truly internal behavior
|
|
119
|
+
- use `performAction(...)` when the goal is to verify the backend API contract as a controller-facing workflow
|
|
120
|
+
|
|
121
|
+
A representative contract-verification pattern is:
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
await app.bean.executor.performAction('patch', '/test/rest/product/:id', {
|
|
125
|
+
params: { id: productId },
|
|
126
|
+
body: dataUpdate,
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This is a good default because the same test can exercise params, body, route wiring, validation, and response behavior together.
|
|
131
|
+
|
|
132
|
+
## Authentication simulation
|
|
133
|
+
|
|
134
|
+
Tests can also simulate signin and signout behavior.
|
|
135
|
+
|
|
136
|
+
Representative patterns include:
|
|
137
|
+
|
|
138
|
+
- `signinMock()`
|
|
139
|
+
- `signinMock('admin')`
|
|
140
|
+
- `signout()`
|
|
141
|
+
|
|
142
|
+
This is important for testing permission-sensitive flows.
|
|
143
|
+
|
|
144
|
+
A practical CRUD-style pattern is:
|
|
145
|
+
|
|
146
|
+
- sign in
|
|
147
|
+
- call create via `performAction(..., { body })`
|
|
148
|
+
- call list/query and verify inclusion
|
|
149
|
+
- call update via params + body
|
|
150
|
+
- call find-one and verify new state
|
|
151
|
+
- call delete and verify final state
|
|
152
|
+
- sign out
|
|
153
|
+
|
|
154
|
+
This keeps auth-sensitive CRUD verification close to the real controller contract path.
|
|
155
|
+
|
|
156
|
+
## Assertion and error-handling helpers
|
|
157
|
+
|
|
158
|
+
Two practical testing helpers are:
|
|
159
|
+
|
|
160
|
+
- Node’s built-in `assert`
|
|
161
|
+
- `catchError` from `@cabloy/utils`
|
|
162
|
+
|
|
163
|
+
These help keep tests explicit while still fitting the framework’s async execution style.
|
|
164
|
+
|
|
165
|
+
## End-to-end CRUD test story
|
|
166
|
+
|
|
167
|
+
A realistic CRUD test usually verifies a whole backend thread, not only one method call.
|
|
168
|
+
|
|
169
|
+
A practical sequence is:
|
|
170
|
+
|
|
171
|
+
1. create request data
|
|
172
|
+
2. sign in if auth is required
|
|
173
|
+
3. call create action
|
|
174
|
+
4. call list/query action and verify inclusion
|
|
175
|
+
5. call update action
|
|
176
|
+
6. call find-one action and verify the new state
|
|
177
|
+
7. call delete action
|
|
178
|
+
8. verify the final deleted/not-found state
|
|
179
|
+
9. sign out
|
|
180
|
+
|
|
181
|
+
This is the most framework-native verification path because it tests route, validation, DTO, service, model, and migration assumptions together.
|
|
182
|
+
|
|
183
|
+
## Relationship to migration and CRUD generation
|
|
184
|
+
|
|
185
|
+
Read this guide together with:
|
|
186
|
+
|
|
187
|
+
- [CRUD Workflow](/backend/crud-workflow)
|
|
188
|
+
- [Migration and Changes](/backend/migration-and-changes)
|
|
189
|
+
- [Controller Guide](/backend/controller-guide)
|
|
190
|
+
|
|
191
|
+
A practical split is:
|
|
192
|
+
|
|
193
|
+
- CRUD generation creates the initial backend thread
|
|
194
|
+
- migration keeps that thread structurally valid over time
|
|
195
|
+
- tests verify the resulting contract through realistic execution
|
|
196
|
+
|
|
197
|
+
## Implementation checks for backend testing changes
|
|
198
|
+
|
|
199
|
+
When adding or changing backend behavior, do not stop at code generation.
|
|
200
|
+
|
|
201
|
+
It should also ask:
|
|
202
|
+
|
|
203
|
+
1. should a module test be created or updated?
|
|
204
|
+
2. does the change need request-context simulation?
|
|
205
|
+
3. does it affect migration/setup behavior that should be covered through the test flow?
|
|
206
|
+
4. should controller behavior be verified through `performAction` rather than only direct method calls?
|
|
207
|
+
5. does the change affect the end-to-end CRUD thread rather than only one isolated function?
|
|
208
|
+
|
|
209
|
+
That leads to much stronger and more framework-native verification.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Upload Guide
|
|
2
|
+
|
|
3
|
+
## Why upload matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona treats file upload as a request-path capability that should integrate cleanly with controller decorators, validation-style metadata, and automatic temporary-file handling.
|
|
6
|
+
|
|
7
|
+
That matters because upload flows often combine files, structured form fields, OpenAPI-facing request contracts, and cleanup responsibilities.
|
|
8
|
+
|
|
9
|
+
## Core upload model
|
|
10
|
+
|
|
11
|
+
Vona implements upload capabilities on top of Busboy.
|
|
12
|
+
|
|
13
|
+
The most important framework-facing pieces are:
|
|
14
|
+
|
|
15
|
+
- the upload interceptor enabled by `@Core.fileUpload()`
|
|
16
|
+
- file and field parameter decorators under `@Arg.*`
|
|
17
|
+
- automatic temporary-file lifecycle handling
|
|
18
|
+
|
|
19
|
+
## Upload interceptor
|
|
20
|
+
|
|
21
|
+
File upload is enabled through the upload interceptor.
|
|
22
|
+
|
|
23
|
+
Representative pattern:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
@Web.post('file')
|
|
27
|
+
@Core.fileUpload()
|
|
28
|
+
@Api.contentType('application/json')
|
|
29
|
+
async uploadFile(@Arg.file('file1', v.title('Upload Single File')) file1: IUploadFile) {
|
|
30
|
+
return file1.file;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The upload interceptor:
|
|
35
|
+
|
|
36
|
+
- parses incoming upload data
|
|
37
|
+
- stores uploaded files in temporary files
|
|
38
|
+
- exposes those files to controller parameters
|
|
39
|
+
- automatically cleans up the temporary files after the business logic completes
|
|
40
|
+
|
|
41
|
+
## Single-file upload
|
|
42
|
+
|
|
43
|
+
Single-file upload usually uses `@Arg.file(...)`.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
@Arg.file('file1', v.title('Upload Single File')) file1: IUploadFile
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`IUploadFile` includes fields such as:
|
|
50
|
+
|
|
51
|
+
- `name`
|
|
52
|
+
- `file`
|
|
53
|
+
- `info.filename`
|
|
54
|
+
- `info.encoding`
|
|
55
|
+
- `info.mimeType`
|
|
56
|
+
|
|
57
|
+
This gives controller code both the temporary file path and the original upload metadata.
|
|
58
|
+
|
|
59
|
+
## Multiple-file upload
|
|
60
|
+
|
|
61
|
+
Multiple-file upload uses `@Arg.files(...)`.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
@Arg.files('files', v.title('Upload Multiple Files')) files: IUploadFile[]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This is the preferred pattern when one field name represents an array of uploaded files.
|
|
68
|
+
|
|
69
|
+
## Form fields alongside files
|
|
70
|
+
|
|
71
|
+
Upload flows often include normal form fields in addition to file data.
|
|
72
|
+
|
|
73
|
+
Vona supports both:
|
|
74
|
+
|
|
75
|
+
- `@Arg.field(...)`
|
|
76
|
+
- `@Arg.fields(...)`
|
|
77
|
+
|
|
78
|
+
### `@Arg.field(...)`
|
|
79
|
+
|
|
80
|
+
Use this when the frontend sends one field value directly, or a serialized array-like value under a single form entry.
|
|
81
|
+
|
|
82
|
+
Representative frontend shape:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const formData = new FormData();
|
|
86
|
+
formData.append('name', 'vona');
|
|
87
|
+
formData.append('tags', ['node', 'typescript']);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### `@Arg.fields(...)`
|
|
91
|
+
|
|
92
|
+
Use this when the frontend appends the same field key multiple times, for example multiple `tags` entries in `FormData`.
|
|
93
|
+
|
|
94
|
+
Representative frontend shape:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
const formData = new FormData();
|
|
98
|
+
formData.append('name', 'vona');
|
|
99
|
+
formData.append('tags', 'node');
|
|
100
|
+
formData.append('tags', 'typescript');
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This distinction matters because frontend upload construction style affects how the backend should read field values.
|
|
104
|
+
|
|
105
|
+
## JSON content type note
|
|
106
|
+
|
|
107
|
+
When an upload endpoint returns JSON data, it is useful to set:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
@Api.contentType('application/json')
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
That helps keep the API contract explicit even when the client upload request is multipart-based.
|
|
114
|
+
|
|
115
|
+
## Relationship to controller design
|
|
116
|
+
|
|
117
|
+
Upload is best understood as a controller-facing request-path capability.
|
|
118
|
+
|
|
119
|
+
Read this guide together with:
|
|
120
|
+
|
|
121
|
+
- [Controller Guide](/backend/controller-guide)
|
|
122
|
+
- [Validation Guide](/backend/validation-guide)
|
|
123
|
+
- [OpenAPI Guide](/backend/openapi-guide)
|
|
124
|
+
|
|
125
|
+
These guides explain the broader request-decorator, validation, and contract-generation model that upload participates in.
|
|
126
|
+
|
|
127
|
+
A useful boundary is:
|
|
128
|
+
|
|
129
|
+
- the upload interceptor owns multipart parsing and temporary-file lifecycle
|
|
130
|
+
- controller decorators own request-shape declaration
|
|
131
|
+
- business logic should focus on what to do with the uploaded content once those two layers have normalized the input
|
|
132
|
+
|
|
133
|
+
## Typical backend workflow
|
|
134
|
+
|
|
135
|
+
A practical upload flow often looks like this:
|
|
136
|
+
|
|
137
|
+
1. enable the upload interceptor with `@Core.fileUpload()`
|
|
138
|
+
2. declare file and form-field parameters with `@Arg.file`, `@Arg.files`, `@Arg.field`, or `@Arg.fields`
|
|
139
|
+
3. apply titles or validation-oriented helpers where useful
|
|
140
|
+
4. process the temporary files inside the controller or delegated service logic
|
|
141
|
+
5. return the desired result while letting the interceptor handle cleanup
|
|
142
|
+
|
|
143
|
+
In the current repo, test upload controllers also demonstrate a broader shape with mixed usage such as:
|
|
144
|
+
|
|
145
|
+
- raw `@Arg.fields()` access to all parsed fields
|
|
146
|
+
- named `@Arg.field(...)` extraction
|
|
147
|
+
- named `@Arg.file(...)` and `@Arg.files(...)` extraction in the same endpoint
|
|
148
|
+
|
|
149
|
+
That is a good reminder that upload endpoints can stay declarative even when multipart payloads become fairly rich.
|
|
150
|
+
|
|
151
|
+
## Implementation checks for backend upload changes
|
|
152
|
+
|
|
153
|
+
When editing backend upload behavior, ask:
|
|
154
|
+
|
|
155
|
+
1. is the request-path correctly using `@Core.fileUpload()`?
|
|
156
|
+
2. should this parameter use `@Arg.file`, `@Arg.files`, `@Arg.field`, or `@Arg.fields`?
|
|
157
|
+
3. does the frontend upload construction style match the backend field decorators?
|
|
158
|
+
4. should the response contract explicitly declare JSON content type or related metadata?
|
|
159
|
+
|
|
160
|
+
That helps AI keep upload flows aligned with Vona’s real request and cleanup model.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# User Access Guide
|
|
2
|
+
|
|
3
|
+
## Why user access matters in Vona
|
|
4
|
+
|
|
5
|
+
Vona separates general user, role, and passport capabilities from business-specific customization.
|
|
6
|
+
|
|
7
|
+
That matters because the framework needs to stay reusable while still supporting project-specific identity, role, and activation workflows.
|
|
8
|
+
|
|
9
|
+
## Core access model
|
|
10
|
+
|
|
11
|
+
The user-access model is centered on three framework-level concepts:
|
|
12
|
+
|
|
13
|
+
- **user**
|
|
14
|
+
- **role**
|
|
15
|
+
- **passport**
|
|
16
|
+
|
|
17
|
+
## `IUser`
|
|
18
|
+
|
|
19
|
+
The `a-user` module provides `IUser` as the core interface for the current user model.
|
|
20
|
+
|
|
21
|
+
Representative fields include:
|
|
22
|
+
|
|
23
|
+
- `id`
|
|
24
|
+
- `name`
|
|
25
|
+
- `avatar`
|
|
26
|
+
- `email`
|
|
27
|
+
- `mobile`
|
|
28
|
+
- `activated`
|
|
29
|
+
- `locale`
|
|
30
|
+
- `anonymous`
|
|
31
|
+
|
|
32
|
+
The `locale` field matters because current-locale resolution can fall back to the user locale in request context handling; see [I18n Guide](/backend/i18n-guide).
|
|
33
|
+
|
|
34
|
+
## `bean.user`
|
|
35
|
+
|
|
36
|
+
Vona exposes `bean.user` as the general business-facing API for user operations.
|
|
37
|
+
|
|
38
|
+
Behind that unified API, the `home-user` module customizes behavior through `ServiceUserAdapter`, which is why business code can keep calling `bean.user` while the project still retains control over how users are created, looked up, updated, or removed.
|
|
39
|
+
|
|
40
|
+
Representative capabilities include:
|
|
41
|
+
|
|
42
|
+
- register a user
|
|
43
|
+
- activate a user
|
|
44
|
+
- create an anonymous user
|
|
45
|
+
- find a user by name or id
|
|
46
|
+
- update or remove a user
|
|
47
|
+
- register a user from OAuth profile data
|
|
48
|
+
|
|
49
|
+
This gives business logic a stable entrypoint even when deeper adapter behavior is customized elsewhere.
|
|
50
|
+
|
|
51
|
+
## `IRole` and `bean.role`
|
|
52
|
+
|
|
53
|
+
The `a-user` module also provides `IRole` and a global bean `bean.role`.
|
|
54
|
+
|
|
55
|
+
As with users, the stable business-facing surface is backed by a project-customizable adapter layer, here via `ServiceRoleAdapter` in `home-user`.
|
|
56
|
+
|
|
57
|
+
Representative capabilities include:
|
|
58
|
+
|
|
59
|
+
- find a role by name or id
|
|
60
|
+
- find all roles for a user
|
|
61
|
+
|
|
62
|
+
This makes role lookup part of the same framework-level access model as user lookup.
|
|
63
|
+
|
|
64
|
+
## `IPassport` and `bean.passport`
|
|
65
|
+
|
|
66
|
+
When a request successfully authenticates, Vona creates a passport containing access-related context such as:
|
|
67
|
+
|
|
68
|
+
- current user
|
|
69
|
+
- current auth record
|
|
70
|
+
- current roles
|
|
71
|
+
|
|
72
|
+
`bean.passport` provides a unified calling surface for passport behavior.
|
|
73
|
+
|
|
74
|
+
In the default `home-user` implementation, `ServicePassportAdapter` is what decides how passport state is serialized into JWT payloads and deserialized back into user/auth/role context on later requests.
|
|
75
|
+
|
|
76
|
+
Representative capabilities include:
|
|
77
|
+
|
|
78
|
+
- get the current passport
|
|
79
|
+
- get current user/auth/roles
|
|
80
|
+
- check authentication or activation state
|
|
81
|
+
- sign in or sign out
|
|
82
|
+
- mock sign in for tests
|
|
83
|
+
- sign in as anonymous
|
|
84
|
+
- refresh JWT tokens
|
|
85
|
+
- create temporary auth tokens
|
|
86
|
+
|
|
87
|
+
## Current user and current roles
|
|
88
|
+
|
|
89
|
+
Backend code can retrieve the current user through several framework-native paths.
|
|
90
|
+
|
|
91
|
+
### Controller parameter decorator
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
@Arg.user() user: IUser
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Passport bean
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const user = this.bean.passport.currentUser;
|
|
101
|
+
const roles = this.bean.passport.currentRoles;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Request context
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
const user = this.ctx.user;
|
|
108
|
+
const passport = this.ctx.passport;
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Anonymous user behavior
|
|
112
|
+
|
|
113
|
+
When anonymous access is allowed, Vona can create an anonymous user object automatically.
|
|
114
|
+
|
|
115
|
+
That means request-path access rules and user identity handling stay consistent even before full authentication.
|
|
116
|
+
|
|
117
|
+
## Registration and activation
|
|
118
|
+
|
|
119
|
+
Vona’s user system is connected to event-driven customization points.
|
|
120
|
+
|
|
121
|
+
Representative flows include:
|
|
122
|
+
|
|
123
|
+
- registration
|
|
124
|
+
- activation
|
|
125
|
+
- assigning default roles
|
|
126
|
+
- sending email confirmation or similar follow-up logic
|
|
127
|
+
|
|
128
|
+
Those follow-up email behaviors often connect directly to queue-backed mail delivery; see [Mail Guide](/backend/mail-guide).
|
|
129
|
+
|
|
130
|
+
The framework-level user APIs stay stable while project-specific modules can customize what happens before or after those core steps through event-driven hooks and related extension logic.
|
|
131
|
+
|
|
132
|
+
The legacy user docs showed this especially clearly:
|
|
133
|
+
|
|
134
|
+
- registration can trigger follow-up mail-confirm flows
|
|
135
|
+
- activation can assign default roles such as `admin`
|
|
136
|
+
- `autoActivate` can suppress the extra activation step when the business flow allows it
|
|
137
|
+
|
|
138
|
+
## Relationship to auth and controller AOP
|
|
139
|
+
|
|
140
|
+
This guide focuses on the user/role/passport model itself.
|
|
141
|
+
|
|
142
|
+
Read it together with:
|
|
143
|
+
|
|
144
|
+
- [Auth Guide](/backend/auth-guide) for provider-driven authentication
|
|
145
|
+
- [Controller AOP Guide](/backend/controller-aop-guide) for `@Passport.*` and guard-based request-path behavior
|
|
146
|
+
- [Event Guide](/backend/event-guide) for event-driven customization around registration, activation, and related lifecycle hooks
|
|
147
|
+
|
|
148
|
+
## Implementation checks for user-access changes
|
|
149
|
+
|
|
150
|
+
When editing user or access logic, ask:
|
|
151
|
+
|
|
152
|
+
1. is the right layer `bean.user`, `bean.role`, `bean.passport`, or an auth provider?
|
|
153
|
+
2. does the flow depend on current user, current roles, or current passport state?
|
|
154
|
+
3. should anonymous, activated, or admin behavior be handled through existing framework conventions?
|
|
155
|
+
4. does the change belong in business logic, event-driven customization, or request-path guard configuration?
|
|
156
|
+
|
|
157
|
+
That helps AI keep access logic aligned with Vona’s real identity architecture.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Validation Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how validation works in Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why validation matters in Vona
|
|
6
|
+
|
|
7
|
+
Vona builds validation around Zod and integrates it directly into controller argument handling, DTOs, entities, and OpenAPI generation.
|
|
8
|
+
|
|
9
|
+
That means validation is not an isolated input-checking step. It is part of the contract layer shared across runtime behavior, types, and API documentation.
|
|
10
|
+
|
|
11
|
+
## Automatic schema inference
|
|
12
|
+
|
|
13
|
+
One very important convenience is that if a parameter type is a basic type, DTO, or entity, Vona can automatically infer the corresponding Zod schema.
|
|
14
|
+
|
|
15
|
+
Representative cases:
|
|
16
|
+
|
|
17
|
+
- `number` → `z.number()`
|
|
18
|
+
- DTO → `z.object({...})`
|
|
19
|
+
- Entity → `z.object({...})`
|
|
20
|
+
|
|
21
|
+
This matters because Vona tries to keep the contract surface concise while still producing strong runtime validation.
|
|
22
|
+
|
|
23
|
+
In controller AOP terms, this usually means built-in argument handling is enough for many request parameters without creating a custom pipe or argument pipe first.
|
|
24
|
+
|
|
25
|
+
## Explicit schema rules
|
|
26
|
+
|
|
27
|
+
You can also pass explicit schema rules when automatic inference is not enough.
|
|
28
|
+
|
|
29
|
+
Representative pattern:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
findOne(@Arg.query('id', z.number().min(6)) id: number) {}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Extending the inferred schema
|
|
36
|
+
|
|
37
|
+
Inferred schemas can also be extended through helper tools like:
|
|
38
|
+
|
|
39
|
+
- `v.optional`
|
|
40
|
+
- `v.default`
|
|
41
|
+
- `v.array`
|
|
42
|
+
- `v.lazy`
|
|
43
|
+
|
|
44
|
+
That is important because many real validation cases need augmentation rather than total replacement.
|
|
45
|
+
|
|
46
|
+
## `@Arg.filter`
|
|
47
|
+
|
|
48
|
+
The validation layer also supports more advanced query-style inputs through `@Arg.filter`, which ties into DTO/query helper structures.
|
|
49
|
+
|
|
50
|
+
This is a good example of validation being connected to higher-level query semantics, not only primitive field checks.
|
|
51
|
+
|
|
52
|
+
## Tool groups
|
|
53
|
+
|
|
54
|
+
These helper tools fall into groups such as:
|
|
55
|
+
|
|
56
|
+
- basic tools
|
|
57
|
+
- string tools
|
|
58
|
+
- OpenAPI tools
|
|
59
|
+
- serializer tools
|
|
60
|
+
- Zod tools
|
|
61
|
+
|
|
62
|
+
For response-side shaping with those serializer helpers, see [Serialization Guide](/backend/serialization-guide).
|
|
63
|
+
|
|
64
|
+
- query filter tools
|
|
65
|
+
- special tools like `v.tableIdentity`
|
|
66
|
+
|
|
67
|
+
This matters because the right answer is often “use the existing helper vocabulary” instead of hand-writing a one-off schema pattern.
|
|
68
|
+
|
|
69
|
+
## Implementation checks for request-validation changes
|
|
70
|
+
|
|
71
|
+
When changing request contracts, ask:
|
|
72
|
+
|
|
73
|
+
1. can Vona infer the schema automatically?
|
|
74
|
+
2. does the contract need explicit extension through the `v` helpers?
|
|
75
|
+
3. does the same validation surface also feed OpenAPI and DTO behavior?
|
|
76
|
+
4. is the validation logic better expressed at the controller, DTO, or entity layer?
|
|
77
|
+
|
|
78
|
+
That produces more consistent backend contracts.
|
|
79
|
+
|
|
80
|
+
For the broader request-path model around pipes, guards, middleware, interceptors, and filters, see [Controller AOP Guide](/backend/controller-aop-guide). Captcha verification flows commonly intersect with this request-path layer through a local interceptor; see [Captcha Guide](/backend/captcha-guide).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Worker Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how workers fit into Vona within the Cabloy monorepo.
|
|
4
|
+
|
|
5
|
+
## Why workers matter
|
|
6
|
+
|
|
7
|
+
Vona uses a distributed worker-process architecture, which means the backend runtime is naturally multi-process rather than assuming one long-lived server instance only.
|
|
8
|
+
|
|
9
|
+
This matters because operational behavior, reload behavior, queue execution, broadcast, and auth-sensitive runtime logic can all depend on worker semantics.
|
|
10
|
+
|
|
11
|
+
## `bean.worker`
|
|
12
|
+
|
|
13
|
+
A global worker-management bean provides capabilities such as:
|
|
14
|
+
|
|
15
|
+
- get current worker id
|
|
16
|
+
- exit current worker
|
|
17
|
+
- exit all workers
|
|
18
|
+
- reload current worker
|
|
19
|
+
- reload all workers
|
|
20
|
+
- manage alive state
|
|
21
|
+
|
|
22
|
+
This makes worker control part of the application’s operational surface.
|
|
23
|
+
|
|
24
|
+
## `SERVER_WORKERS`
|
|
25
|
+
|
|
26
|
+
Worker count can be controlled through env or command-line setup.
|
|
27
|
+
|
|
28
|
+
Representative idea:
|
|
29
|
+
|
|
30
|
+
- development often uses multiple workers to expose distributed-environment issues earlier
|
|
31
|
+
- single-worker modes still matter for Docker or simpler execution scenarios
|
|
32
|
+
|
|
33
|
+
A practical runtime reading in the current repo is:
|
|
34
|
+
|
|
35
|
+
- `SERVER_WORKERS` becomes part of backend server config
|
|
36
|
+
- `npm run dev` and `cd vona && npm run dev` normally exercise multi-worker behavior
|
|
37
|
+
- `dev:one`, `start:one`, and Docker-oriented single-worker flows remain important when you want simpler runtime shape or one-worker debugging
|
|
38
|
+
|
|
39
|
+
## Worker control behavior
|
|
40
|
+
|
|
41
|
+
At a high level:
|
|
42
|
+
|
|
43
|
+
- `reload()` targets the current worker
|
|
44
|
+
- `reloadAll()` broadcasts reload intent across workers
|
|
45
|
+
- `exit()` closes the current app process and exits
|
|
46
|
+
- `exitAll()` broadcasts a process-exit intent across workers
|
|
47
|
+
|
|
48
|
+
This matters because worker control belongs to runtime behavior, not only to deployment tooling.
|
|
49
|
+
|
|
50
|
+
## Implementation checks for worker-sensitive runtime changes
|
|
51
|
+
|
|
52
|
+
When touching runtime or operational backend behavior, ask:
|
|
53
|
+
|
|
54
|
+
1. does this assume a single-process runtime incorrectly?
|
|
55
|
+
2. does the behavior change across worker count or worker lifecycle?
|
|
56
|
+
3. is this a place where reload or worker-control operations matter?
|
|
57
|
+
4. should the verification path consider multi-worker behavior explicitly?
|
|
58
|
+
|
|
59
|
+
That keeps backend reasoning aligned with Vona’s actual runtime architecture.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Cabloy Basic
|
|
2
|
+
|
|
3
|
+
Cabloy Basic is the public framework/reference edition you are reading right now.
|
|
4
|
+
|
|
5
|
+
## Repository marker
|
|
6
|
+
|
|
7
|
+
The repository root contains:
|
|
8
|
+
|
|
9
|
+
- `__CABLOY_BASIC__`
|
|
10
|
+
|
|
11
|
+
This marker is the quickest safe signal for docs, skills, and rules that need to distinguish Cabloy Basic from Cabloy Start.
|
|
12
|
+
|
|
13
|
+
## Typical role
|
|
14
|
+
|
|
15
|
+
Use Cabloy Basic as the public reference edition for:
|
|
16
|
+
|
|
17
|
+
- shared architecture explanations
|
|
18
|
+
- root scripts and monorepo entrypoints
|
|
19
|
+
- Vona and Zova source browsing
|
|
20
|
+
- public CLI-backed workflows
|
|
21
|
+
- public user-facing documentation
|
|
22
|
+
- projects created with `npm create cabloy`
|
|
23
|
+
|
|
24
|
+
## Frontend bias
|
|
25
|
+
|
|
26
|
+
In the current source and docs, Cabloy Basic examples commonly align with a shared frontend engineering layer built on Zova, Vue, Vite, and Quasar tooling, plus a Basic-specific UI layer built with DaisyUI + Tailwind CSS. That does not mean Zova is limited to that UI stack, but it does mean docs and AI outputs should not accidentally project Vuetify-specific assumptions into Cabloy Basic unless the current source explicitly requires it.
|