cabloy 5.1.110 → 5.1.112
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/.cabloy-version +1 -1
- package/.claude/skills/cabloy-backend-scaffold/SKILL.md +29 -1
- package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +12 -0
- package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +3 -0
- package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +4 -0
- package/.claude/skills/cabloy-master-detail/SKILL.md +13 -2
- package/.github/workflows/playwright-e2e.yml +45 -0
- package/.gitignore +1 -0
- package/CHANGELOG.md +23 -0
- package/CLAUDE.md +4 -1
- package/README.md +8 -8
- package/cabloy-docs/backend/crud-workflow.md +10 -0
- package/cabloy-docs/backend/foundation.md +29 -4
- package/cabloy-docs/backend/introduction.md +1 -1
- package/cabloy-docs/backend/model-guide.md +9 -11
- package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +18 -0
- package/cabloy-docs/backend/service-guide.md +1 -1
- package/cabloy-docs/frontend/a-router-guide.md +1 -1
- package/cabloy-docs/frontend/introduction.md +1 -1
- package/cabloy-docs/frontend/navigation-guards-guide.md +20 -11
- package/cabloy-docs/frontend/route-alias-guide.md +24 -0
- package/cabloy-docs/frontend/scripts.md +71 -24
- package/cabloy-docs/frontend/ssr-init-data.md +25 -0
- package/cabloy-docs/frontend/ssr-review-checklist.md +17 -7
- package/cabloy-docs/frontend/use-state-data-best-practices.md +4 -0
- package/cabloy-docs/frontend/zova-router-under-the-hood.md +4 -1
- package/cabloy-docs/fullstack/comparison-with-other-frameworks.md +19 -13
- package/cabloy-docs/fullstack/introduction.md +10 -10
- package/cabloy-docs/fullstack/quickstart.md +23 -1
- package/cabloy-docs/index.md +14 -14
- package/cabloy-docs/reference/package-map.md +11 -7
- package/cabloy-docs/reference/repo-scripts.md +108 -23
- package/e2e/scripts/e2e.ts +1 -1
- package/e2e/specs/a-commerce/commerce.spec.ts +124 -1
- package/package.json +2 -1
- package/scripts/init.ts +6 -12
- package/scripts/upgrade.ts +3 -1
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/pnpm-lock.yaml +70 -55
- package/vona/src/backend/config/config/config.ts +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/package.json +4 -2
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +732 -2
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/locales.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/meta.index.ts +14 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/meta.version.ts +52 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.category.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.product.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/bean/ssrMenu.sku.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +19 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +19 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/category.ts +65 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/product.ts +86 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/controller/sku.ts +65 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryCreate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectReq.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categorySelectResItem.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryUpdate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/categoryView.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productCreate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublic.tsx +38 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSelectReq.tsx +23 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productPublicSku.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectReq.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectResItem.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productUpdate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productView.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuCreate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectReq.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuSelectResItem.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuUpdate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/skuView.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/category.tsx +53 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/product.tsx +48 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/sku.tsx +66 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/category.ts +15 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/product.ts +46 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/sku.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/category.ts +47 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/product.ts +162 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/sku.ts +76 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/catalog.test.ts +358 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/category.test.ts +91 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/product.test.ts +154 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/sku.test.ts +190 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/package.json +2 -1
- package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +342 -5
- package/vona/src/suite/a-commerce/modules/commerce-member/src/.metadata/locales.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/meta.index.ts +12 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/bean/meta.version.ts +31 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/config/locale/en-us.ts +12 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/config/locale/zh-cn.ts +12 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/controller/address.ts +59 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressCreate.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectReq.tsx +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressSelectResItem.tsx +53 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressUpdate.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/dto/addressView.tsx +39 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/entity/address.tsx +76 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/model/address.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/src/service/address.ts +84 -0
- package/vona/src/suite/a-commerce/modules/commerce-member/test/addressOwnership.test.ts +203 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/package.json +52 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/src/.metadata/index.ts +55 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/src/.metadata/this.ts +2 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/src/bean/meta.version.ts +80 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/src/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/tsconfig.build.json +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-seed/tsconfig.json +7 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/package.json +4 -2
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +192 -2
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/locales.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/meta.version.ts +32 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenu.home.ts +3 -1
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenuGroup.catalog.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/bean/ssrMenuGroup.inventory.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/en-us.ts +5 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/zh-cn.ts +5 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/controller/operator.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/dto/operatorContext.ts +21 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/src/service/operator.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/meta.version.test.ts +44 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/operatorAccess.test.ts +55 -0
- package/vona/src/suite/a-commerce/modules/commerce-siteadmin/test/ssrMenu.test.ts +77 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/package.json +2 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +773 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/locales.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.index.ts +23 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/meta.version.ts +79 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.stockAudit.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/bean/ssrMenu.stockBalance.ts +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/cart.ts +48 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/stockAudit.ts +38 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/stockBalance.ts +49 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartAddItem.tsx +19 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartItem.tsx +34 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartUpdateItem.tsx +15 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/cartView.tsx +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAdjust.tsx +32 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditCreate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectReq.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditSelectResItem.tsx +33 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditUpdate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockAuditView.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceCreate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectReq.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectRes.tsx +11 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceSelectResItem.tsx +33 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceUpdate.tsx +28 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/stockBalanceView.tsx +25 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/cart.tsx +24 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/cartItem.tsx +30 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockAudit.tsx +86 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockBalance.tsx +53 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/entity/stockReservation.tsx +63 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/index.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +17 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/cartItem.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockAudit.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockBalance.ts +15 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/model/stockReservation.ts +10 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/cart.ts +152 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockAudit.ts +20 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/stockBalance.ts +305 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/cartOwnership.test.ts +174 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockAudit.test.ts +37 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockBalance.test.ts +186 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/stockReservation.test.ts +262 -0
- package/vona/src/suite/a-commerce/package.json +1 -0
- package/vona/src/suite/a-commerce/tsconfig.json +3 -0
- package/vona/src/suite/a-home/modules/home-user/src/.metadata/index.ts +7 -1
- package/vona/src/suite/a-home/modules/home-user/test/role.test.ts +14 -23
- package/vona/src/suite/a-training/modules/training-record/src/.metadata/index.ts +10 -8
- package/vona/src/suite/a-training/modules/training-recordsubject/src/.metadata/index.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +3 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +1 -1
- package/vona/src/suite-vendor/a-auth/modules/a-auth/package.json +1 -1
- package/vona/src/suite-vendor/a-auth/modules/a-auth/src/.metadata/index.ts +7 -3
- package/vona/src/suite-vendor/a-auth/modules/auth-simple/package.json +1 -1
- package/vona/src/suite-vendor/a-auth/modules/auth-simple/src/.metadata/index.ts +2 -0
- package/vona/src/suite-vendor/a-auth/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/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-datasource/src/.metadata/index.ts +3 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-socket/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-socket/src/.metadata/index.ts +1 -1
- 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 +47 -47
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssrhmr/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-status/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-status/src/.metadata/index.ts +2 -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/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-captcha/package.json +1 -1
- package/vona/src/suite-vendor/a-file/modules/a-file/package.json +1 -1
- package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/index.ts +42 -38
- package/vona/src/suite-vendor/a-file/package.json +2 -2
- package/vona/src/suite-vendor/a-image/modules/a-image/package.json +1 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/index.ts +42 -38
- package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +1 -1
- package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/.metadata/index.ts +42 -27
- package/vona/src/suite-vendor/a-image/package.json +1 -1
- package/vona/src/suite-vendor/a-paypal/modules/a-paypal/package.json +1 -1
- package/vona/src/suite-vendor/a-paypal/modules/a-paypal/src/.metadata/index.ts +3 -1
- package/vona/src/suite-vendor/a-paypal/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-beanmutate/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-body/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-body/src/.metadata/index.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 +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-error/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-error/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-event/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-event/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-executor/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-executor/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-hmr/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-hmr/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-instance/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-instance/src/.metadata/index.ts +3 -1
- package/vona/src/suite-vendor/a-vona/modules/a-jwt/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-jwt/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-mail/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-mail/src/.metadata/index.ts +3 -1
- 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/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-onion/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-onion/src/.metadata/index.ts +1 -1
- 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/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/model/metadata/generate.ts +5 -11
- 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/lib/bean.model/bean.model_cache.ts +52 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +4 -10
- package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-security/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-security/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-serialization/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-serialization/src/.metadata/index.ts +1 -1
- 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-user/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-user/src/.metadata/index.ts +4 -5
- package/vona/src/suite-vendor/a-vona/modules/a-validation/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-validation/src/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-version/src/.metadata/index.ts +6 -0
- package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/.metadata/index.ts +1 -1
- 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/.metadata/index.ts +1 -1
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/package.json +1 -1
- package/zova/packages-cli/cli-set-front/src/lib/bean/toolsMetadata/generateScope.ts +1 -1
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +14 -14
- package/zova/src/front/config/config/config.cabloyCommerce.ts +5 -1
- package/zova/src/front/config/config/config.cabloyCommerceAdmin.ts +2 -1
- package/zova/src/suite/a-commerce/modules/commerce-catalog/cli/openapi.config.ts +9 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/package.json +2 -1
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +202 -3
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/page/catalogue.ts +23 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/page/product.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/commerceCatalogProduct.ts +52 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/schemas.ts +412 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/api/openapi/types.ts +7159 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/apiSchema/commerceCatalogProduct.ts +20 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/index.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/model/catalogue.ts +38 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/page/catalogue/controller.tsx +71 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/page/product/controller.tsx +108 -0
- package/zova/src/suite/a-commerce/modules/commerce-catalog/src/routes.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/cli/openapi.config.ts +9 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/package.json +2 -1
- package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/index.ts +182 -3
- package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/.metadata/page/address.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/commerceMemberAddress.ts +111 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +432 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +7445 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/apiSchema/commerceMemberAddress.ts +35 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/config/locale/en-us.ts +17 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/config/locale/zh-cn.ts +17 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/index.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/model/address.ts +38 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +194 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/routes.ts +12 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/cli/openapi.config.ts +9 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/package.json +2 -1
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/index.ts +175 -3
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/.metadata/page/dashboard.ts +9 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/commerceSiteadminOperator.ts +25 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/schemas.ts +304 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/api/openapi/types.ts +5710 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/apiSchema/commerceSiteadminOperator.ts +13 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/en-us.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/config/locale/zh-cn.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/index.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/model/operator.ts +17 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/page/dashboard/controller.tsx +34 -0
- package/zova/src/suite/a-commerce/modules/commerce-siteadmin/src/routes.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +15 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/package.json +2 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +182 -3
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/.metadata/page/cart.ts +19 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeCart.ts +99 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +446 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +7651 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeCart.ts +35 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/index.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +77 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +108 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/routes.ts +12 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +5 -5
- package/zova/src/suite/a-demo/modules/demo-todo/src/.metadata/index.ts +2 -2
- package/zova/src/suite/a-home/modules/home-base/src/service/routerGuards.ts +18 -10
- package/zova/src/suite/a-home/modules/home-indexweb/src/.metadata/index.ts +2 -2
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/.metadata/index.ts +4 -4
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +1 -0
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-bean/cli/controller/metadata/generateMetaPage.ts +3 -1
- package/zova/src/suite-vendor/a-zova/modules/a-bean/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-fetch/package.json +2 -2
- 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/model/sdk.ts +3 -1
- 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 +35 -8
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkeySys.ts +28 -12
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/service/routerGuards.ts +6 -8
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/router.ts +14 -2
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/types/utils.ts +4 -1
- package/zova/src/suite-vendor/a-zova/package.json +5 -5
- package/CLAUDE.local.md +0 -4
- /package/e2e/specs/{a-basic → cabloy-basic}/basic.spec.ts +0 -0
package/.cabloy-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.1.
|
|
1
|
+
5.1.112
|
|
@@ -140,7 +140,35 @@ Check whether the feature needs:
|
|
|
140
140
|
- `meta.version`
|
|
141
141
|
- field indexes
|
|
142
142
|
- relation definitions
|
|
143
|
-
- datasource or cache considerations
|
|
143
|
+
- datasource or cache considerations, including cross-Model query-cache dependencies
|
|
144
|
+
|
|
145
|
+
For normal resource persistence, preserve Vona's default active-instance scope:
|
|
146
|
+
|
|
147
|
+
- in the current tenancy model, a tenant corresponds to an instance and ordinary model CRUD handles the current `iid`
|
|
148
|
+
- do not expose caller-controlled `iid` or tenant selection in ordinary resource DTOs or controller logic
|
|
149
|
+
- treat a record absent from an ordinary scoped model lookup as absent; do not use raw cross-instance probes merely to choose between `403` and not-found behavior
|
|
150
|
+
- use `disableInstance`, plain builders, or raw SQL only for an explicit global/system or otherwise authorized contract
|
|
151
|
+
- model a future multi-merchant requirement as a separate boundary within an instance, with its own ownership and authorization rules
|
|
152
|
+
|
|
153
|
+
For the canonical explanation, read [Multi-Instance and Instance Resolution](../../../cabloy-docs/backend/multi-instance-and-instance-resolution.md) and [Model Guide](../../../cabloy-docs/backend/model-guide.md).
|
|
154
|
+
|
|
155
|
+
### Cross-module resource lookup
|
|
156
|
+
|
|
157
|
+
Choose the narrowest lookup form before evaluating module dependency intent:
|
|
158
|
+
|
|
159
|
+
- use `this.scope` for resources owned by the current `BeanBase` module
|
|
160
|
+
- use `this.$scope.<fixedModule>` when the target module is statically known and the typed shorthand is available
|
|
161
|
+
- use `app.scope('<module-name>')` in tests or standalone code with an application reference instead of BeanBase shorthands
|
|
162
|
+
- use `this.app.scope(moduleName)` or `app.scope(moduleName)` when the module name is genuinely selected at runtime; do not replace a fixed module target with a dynamic string lookup merely for style
|
|
163
|
+
|
|
164
|
+
Then distinguish runtime lookup from a true module dependency:
|
|
165
|
+
|
|
166
|
+
- lookup resolves a resource from a module already composed into the application; it does not by itself require a `vonaModule.dependencies` entry or create a circular dependency edge
|
|
167
|
+
- add `vonaModule.dependencies` only when the feature genuinely requires the target module's availability, dependency-first ordering, or minimum compatible version
|
|
168
|
+
- do not add a dependency declaration merely because code looks up another module's service, model, config, locale, or other resource
|
|
169
|
+
- scope lookup cannot make an absent module available; validate application/suite composition separately when the target must exist
|
|
170
|
+
|
|
171
|
+
For the canonical distinction, read [Backend Foundation](../../../cabloy-docs/backend/foundation.md#scope-lookup-vs-module-dependencies) and [Package Map](../../../cabloy-docs/reference/package-map.md).
|
|
144
172
|
|
|
145
173
|
### Verification
|
|
146
174
|
|
|
@@ -28,8 +28,20 @@ After generating or extending a backend thread, check which follow-up layers app
|
|
|
28
28
|
- relations
|
|
29
29
|
- datasource choice
|
|
30
30
|
- cache behavior
|
|
31
|
+
- cross-Model query-cache dependencies: when a source mutation can change another Model's cached query members, totals, projections, includes, or visibility, declare exactly one directed `modelsClear` / `modelsClearedBy` edge
|
|
32
|
+
- keep the dependency graph acyclic and free of duplicate edges; do not declare both forms for the same edge because propagation is transitive and current runtime collection does not deduplicate targets
|
|
33
|
+
- when `modelsClearedByFn` is required, treat it as replacement behavior and explicitly own the target clear and any necessary downstream propagation
|
|
34
|
+
- prefer normal Model/service mutation paths so source invalidation, commit-time re-clear, and configured double-delete remain active
|
|
35
|
+
- add a warm-query → mutate-source → repeat-query regression test for each new dependency path; read [Vona Cross-Model Query-Cache Dependencies](../../../../.docs-internal/architecture/vona-cross-model-query-cache-dependencies.md) for the source-backed decision rules
|
|
31
36
|
- transaction behavior
|
|
32
37
|
|
|
38
|
+
## Module composition and dependency intent
|
|
39
|
+
|
|
40
|
+
- target module is already composed into the application when code uses cross-module scope lookup
|
|
41
|
+
- cross-module `this.$scope.<module>` or `app.scope(...)` lookup alone does not require `vonaModule.dependencies`
|
|
42
|
+
- `vonaModule.dependencies` is added only for a genuine target-module availability, dependency-first ordering, or minimum-version requirement
|
|
43
|
+
- do not create speculative dependency edges or circular declarations merely to document a lookup
|
|
44
|
+
|
|
33
45
|
## Verification follow-up
|
|
34
46
|
|
|
35
47
|
- unit tests
|
|
@@ -136,6 +136,8 @@ Check whether the feature needs:
|
|
|
136
136
|
- SSR init-data updates
|
|
137
137
|
- OpenAPI SDK regeneration
|
|
138
138
|
- schema-driven UI or `$apiSchema` review
|
|
139
|
+
- SSR hydration-equivalence review: classify state as SSR-required or intentionally deferred; keep server HTML and the hydration-time client render equivalent; defer private, cookie-unavailable, or browser-only query/load/render branches to an explicit post-hydration, admission, mounted, or interaction boundary
|
|
140
|
+
- distinguish `$useStateData(...)` query ownership from readiness waits: `disableSuspenseOnInit` only skips its init-time suspense kick and does not prevent query creation or fetches; choose `$QueryEnsureLoaded(...)` or freshness helpers only at the later boundary that needs them
|
|
139
141
|
- reverse fullstack handoff when newly added frontend resources will later be consumed by backend metadata or backend tooling
|
|
140
142
|
|
|
141
143
|
If the frontend change introduces resources such as a custom form-field renderer, table-cell renderer, or other generated metadata that backend `ZovaRender.field(...)` / `ZovaRender.cell(...)` will consume, do not treat the task as frontend-only cleanup.
|
|
@@ -166,6 +168,7 @@ Check whether the feature needs:
|
|
|
166
168
|
- build
|
|
167
169
|
- metadata regeneration verification
|
|
168
170
|
- SSR or route-path verification
|
|
171
|
+
- hydration-time initial-render equivalence when SSR, private state, browser-only state, or async model state changes
|
|
169
172
|
- edition-specific flavor, SSR site baseline, and project-asset verification
|
|
170
173
|
|
|
171
174
|
### SSR theme review reminder
|
|
@@ -13,6 +13,10 @@ After generating or extending a frontend thread, check which follow-up layers ap
|
|
|
13
13
|
|
|
14
14
|
- API service or model alignment
|
|
15
15
|
- SSR init-data needs
|
|
16
|
+
- classify render-driving state as SSR-required or intentionally deferred; server HTML and the hydration-time client render must remain equivalent
|
|
17
|
+
- for intentionally deferred private, cookie-unavailable, or browser-only state, keep the same neutral shell/placeholder through hydration and begin query/load/render work only at an explicit post-hydration, admission, mounted, or interaction boundary
|
|
18
|
+
- `disableSuspenseOnInit` skips only the init-time suspense kick; do not treat it as a no-fetch or hydration-deferral mechanism
|
|
19
|
+
- use `$QueryEnsureLoaded(...)` only where loaded data is explicitly required; choose freshness helpers when the boundary requires domain-valid data
|
|
16
20
|
- OpenAPI SDK or schema-driven layer impact
|
|
17
21
|
- backend contract reminder if frontend depends on generated backend contract output
|
|
18
22
|
- if backend metadata will consume newly added frontend render resources, run the relevant Zova build first and then `npm run deps:vona`
|
|
@@ -152,7 +152,18 @@ Important rule:
|
|
|
152
152
|
|
|
153
153
|
- do not start from hand-patching DTO placement or relation semantics until the generator path and specimen shape have been checked first
|
|
154
154
|
|
|
155
|
-
## Step 6:
|
|
155
|
+
## Step 6: Preserve the instance boundary across the aggregate
|
|
156
|
+
|
|
157
|
+
Master-detail ownership is separate from Vona's tenant/instance boundary:
|
|
158
|
+
|
|
159
|
+
- in the current tenancy model, a tenant corresponds to an instance and normal parent/detail model operations retain the active instance scope
|
|
160
|
+
- relation and foreign-key checks must preserve that scope; aggregate ownership does not authorize bypassing it
|
|
161
|
+
- treat a missing parent or detail from the normal scoped aggregate flow as absent; do not add unscoped existence probes merely to distinguish a foreign-instance row
|
|
162
|
+
- if a future multi-merchant design is needed, model merchant ownership explicitly within the instance in addition to the aggregate relation
|
|
163
|
+
|
|
164
|
+
For the canonical tenancy explanation, read [Multi-Instance and Instance Resolution](../../../cabloy-docs/backend/multi-instance-and-instance-resolution.md) and [Model Guide](../../../cabloy-docs/backend/model-guide.md).
|
|
165
|
+
|
|
166
|
+
## Step 7: Keep fullstack boundaries explicit
|
|
156
167
|
|
|
157
168
|
This skill is primarily for backend detail aggregation.
|
|
158
169
|
|
|
@@ -166,7 +177,7 @@ Use this skill first when the core problem is still:
|
|
|
166
177
|
- aggregate vs standalone detail mode
|
|
167
178
|
- nested detail DTO naming or placement in a scaffolding context
|
|
168
179
|
|
|
169
|
-
## Step
|
|
180
|
+
## Step 8: Verification guidance
|
|
170
181
|
|
|
171
182
|
Always finish with verification that matches the detail shape.
|
|
172
183
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: playwright-e2e
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
jobs:
|
|
7
|
+
test:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
env:
|
|
10
|
+
DATABASE_DEFAULT_CLIENT: sqlite3
|
|
11
|
+
PNPM_CONFIG_MINIMUM_RELEASE_AGE: 0
|
|
12
|
+
services:
|
|
13
|
+
redis:
|
|
14
|
+
image: redis:latest
|
|
15
|
+
ports:
|
|
16
|
+
- 6379:6379
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v6
|
|
19
|
+
- uses: actions/setup-node@v6
|
|
20
|
+
with:
|
|
21
|
+
node-version: 24
|
|
22
|
+
- uses: pnpm/action-setup@v5
|
|
23
|
+
with:
|
|
24
|
+
version: 11.5.2
|
|
25
|
+
- name: init
|
|
26
|
+
run: npm run init
|
|
27
|
+
- name: install Chromium
|
|
28
|
+
run: npx playwright install --with-deps chromium
|
|
29
|
+
- name: run Basic E2E baseline
|
|
30
|
+
run: npm run test:e2e:basic:clean
|
|
31
|
+
- name: build Commerce Zova artifacts
|
|
32
|
+
run: npm run build:zova:commerce
|
|
33
|
+
- name: synchronize Vona dependencies
|
|
34
|
+
run: npm run deps:vona
|
|
35
|
+
- name: run Commerce E2E baseline
|
|
36
|
+
run: npm run test:e2e:commerce:clean
|
|
37
|
+
- name: upload Playwright artifacts
|
|
38
|
+
if: failure()
|
|
39
|
+
uses: actions/upload-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: playwright-artifacts
|
|
42
|
+
path: |
|
|
43
|
+
playwright-report/
|
|
44
|
+
test-results/
|
|
45
|
+
if-no-files-found: ignore
|
package/.gitignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.1.112
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- Add commerce member address ownership support.
|
|
8
|
+
- Add commerce cart capabilities.
|
|
9
|
+
- Add a commerce test seed module.
|
|
10
|
+
- Add rules and catalog capabilities.
|
|
11
|
+
- Add server-side rendered menu support.
|
|
12
|
+
- Add commerce site administration capabilities.
|
|
13
|
+
|
|
14
|
+
### Improvements
|
|
15
|
+
|
|
16
|
+
- Update commerce DTOs, controllers, routing, product handling, stock balances, and upgrade flows.
|
|
17
|
+
- Add Playwright end-to-end test workflow coverage.
|
|
18
|
+
- Refine full-stack positioning documentation.
|
|
19
|
+
|
|
20
|
+
## 5.1.111
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
- Update the application functionality.
|
|
25
|
+
|
|
3
26
|
## 5.1.110
|
|
4
27
|
|
|
5
28
|
### Features
|
package/CLAUDE.md
CHANGED
|
@@ -54,7 +54,8 @@ Before inventing a custom implementation path:
|
|
|
54
54
|
- For Zova frontend analysis, do not default to generic Vue reinterpretation first. Read the code through Zova’s controller / bean / IoC architecture before mapping it to Vue concepts.
|
|
55
55
|
- For Zova source-reading or Vue-vs-Zova explanation tasks, start from the frontend reading guides and source-reading map in `cabloy-docs/frontend/` before doing framework-neutral reinterpretation.
|
|
56
56
|
- For frontend async state that affects rendering or interaction across consumers, prefer model-owned `$useStateData(...)` over controller-managed fetch/cache state.
|
|
57
|
-
- Default to establishing such query state during render. Use `disableSuspenseOnInit: true` only for relatively stable query-backed state when you want to skip the init-time `query.suspense()` kick;
|
|
57
|
+
- Default to establishing such query state during render. Use `disableSuspenseOnInit: true` only for relatively stable query-backed state when you want to skip the init-time `query.suspense()` kick; it does not prevent query creation, fetches, or hydration-time rendering. If strict readiness is needed later, wait explicitly at the interaction boundary.
|
|
58
|
+
- In SSR, keep server HTML and the client's hydration-time initial render equivalent. When server rendering intentionally omits private, cookie-unavailable, or browser-only state, keep the same neutral shell or placeholder through hydration and defer its query/load/render branch to an explicit post-hydration, admission, mounted, or interaction boundary.
|
|
58
59
|
- Keep repo-wide AI rules in `CLAUDE.md` short and durable; put branching Zova analysis workflows in `.claude/skills/`.
|
|
59
60
|
- For SSR theme-sensitive frontend work, detect the active edition marker and UI library before making assumptions. Cabloy Basic currently means DaisyUI + Tailwind CSS assumptions; Cabloy Start currently means Vuetify assumptions.
|
|
60
61
|
- In Web SSR without cookie-backed theme resolution, do not treat server reads of `$theme.dark`, `$theme.darkMode`, or `$token` as final browser truth. Keep theme-sensitive SSR branching hydration-tolerant or defer final theme-sensitive decisions to the client.
|
|
@@ -68,6 +69,8 @@ Before inventing a custom implementation path:
|
|
|
68
69
|
- When backend code references `this.bean.xxx`, `ctx.bean.xxx`, or `app.bean.xxx`, use `IBeanRecordGlobal` and module `src/.metadata/index.ts` as the first static lookup surface; use `IBeanRecordGeneral` or `src/service` only when the target is not a global shorthand.
|
|
69
70
|
- When adding a persisted field to an existing backend resource, ask the user whether `vonaModule.fileVersion` should be incremented before changing `meta.version.ts` or the module schema path. If yes, add a new migration version and bump `fileVersion`. If no, keep the current `fileVersion` and fold the schema change into the current version path. Do not assume the versioning strategy without confirmation.
|
|
70
71
|
- In shared-database multitenancy, do not use `table.unique(...)` for business uniqueness. Keep ordinary indexes for lookup performance and enforce tenant-scoped uniqueness in the business layer.
|
|
72
|
+
- In Vona, a tenant corresponds to an instance. Ordinary resource-model CRUD is automatically scoped to the active instance; treat records absent from that scope as absent, and do not use raw cross-instance probes merely to choose between `403` and not-found behavior. Model future multi-merchant boundaries explicitly inside an instance.
|
|
73
|
+
- Model cross-Model query-cache dependencies as one directed, acyclic `modelsClear` / `modelsClearedBy` graph, and verify source mutations refresh warmed dependent queries; read `.docs-internal/architecture/vona-cross-model-query-cache-dependencies.md` before designing a nontrivial graph.
|
|
71
74
|
- For `@Api.field(...)` and related schemaLike composition, framework guards now preserve previously attached OpenAPI metadata across schema rebuilds, but structure-shaping schemaLike is still order-sensitive. Treat `v.object(...)`, `v.array(...)`, `v.optional()`, `v.nullable()`, `v.default(...)`, and preprocess/transform wrappers as structure-shaping; keep the final structure-defining schemaLike last and verify emitted schema/OpenAPI output after such edits.
|
|
72
75
|
|
|
73
76
|
## Verification expectations
|
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
Cabloy is a Node.js fullstack framework for AI vibe coding.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**One fullstack system for AI vibe coding—bidirectional type sync, CLI-first workflows, docs, and skills.**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Instead of stitching separate backend and frontend stacks together, Cabloy keeps their contracts, tooling, and guidance connected in one repository. Vona, Zova, and suite-based modules provide the aligned architecture behind that workflow.
|
|
14
14
|
|
|
15
15
|
[Documentation](https://docs.cabloy.com) · [npm](https://www.npmjs.com/package/cabloy) · [Web Demo](https://cabloy.com) · [Admin Demo](https://cabloy.com/admin) · [GitHub](https://github.com/cabloy/cabloy)
|
|
16
16
|
|
|
@@ -102,12 +102,12 @@ npm run upgrade
|
|
|
102
102
|
|
|
103
103
|
## Highlights
|
|
104
104
|
|
|
105
|
-
- **One
|
|
106
|
-
- **
|
|
107
|
-
- **
|
|
108
|
-
- **
|
|
109
|
-
- **
|
|
110
|
-
- **
|
|
105
|
+
- **One fullstack system** — build backend and frontend together instead of assembling separate stacks
|
|
106
|
+
- **Bidirectional type sync** — use the contract loop to keep backend contracts and frontend metadata aligned in both directions
|
|
107
|
+
- **CLI-first workflows** — use explicit commands for scaffolding, generation, refactors, and verification
|
|
108
|
+
- **Docs and skills** — give people and AI agents reusable, source-grounded guidance for the current repository
|
|
109
|
+
- **Vona + Zova** — use aligned backend and frontend layers for code sharing and cross-stack consistency
|
|
110
|
+
- **Modular delivery** — organize capabilities as suites and modules, then deliver SSR, SPA, Web, and Admin applications with shared conventions
|
|
111
111
|
|
|
112
112
|
## Technology Stack
|
|
113
113
|
|
|
@@ -95,6 +95,16 @@ Read this guide together with:
|
|
|
95
95
|
- [Migration and Changes](/backend/migration-and-changes)
|
|
96
96
|
- [Unit Testing](/backend/unit-testing)
|
|
97
97
|
|
|
98
|
+
## Instance-scoped CRUD
|
|
99
|
+
|
|
100
|
+
Generated controller, service, and model flows retain Vona's default active-instance scope. In the current tenancy model, a tenant corresponds to an instance, so ordinary resource CRUD should not accept caller-controlled `iid` or tenant selection.
|
|
101
|
+
|
|
102
|
+
When a normal scoped view, update, or delete target is not found, preserve its absent/not-found semantics. Do not run an unscoped raw-table probe merely to discover whether another instance owns the same identifier and convert that result into `403`.
|
|
103
|
+
|
|
104
|
+
If a future requirement introduces multiple merchants inside one instance, model that as an explicit additional business boundary with its own ownership, authorization, relations, indexes, and tests. It does not replace the existing instance scope.
|
|
105
|
+
|
|
106
|
+
For the runtime tenancy boundary, see [Multi-Instance and Instance Resolution](/backend/multi-instance-and-instance-resolution). For model-level behavior and exceptional raw/builder usage, see [Model Guide](/backend/model-guide).
|
|
107
|
+
|
|
98
108
|
## Recommended workflow
|
|
99
109
|
|
|
100
110
|
1. run the CRUD generator
|
|
@@ -232,14 +232,39 @@ Scope groups a module’s resources behind one structured facade, including area
|
|
|
232
232
|
- locale
|
|
233
233
|
- error
|
|
234
234
|
|
|
235
|
-
|
|
235
|
+
Choose the narrowest lookup form that matches what is known at the call site:
|
|
236
236
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
| Situation | Preferred form | Example |
|
|
238
|
+
| -------------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------------------------------- |
|
|
239
|
+
| Resource belongs to the current `BeanBase` module | `this.scope` | `this.scope.model.stockBalance` |
|
|
240
|
+
| Another module is fixed in source and `$scope` is available | `this.$scope.<fixedModule>` | `this.$scope.commerceCatalog.model.sku` |
|
|
241
|
+
| Code has an application reference rather than `BeanBase` shorthands, such as a test or standalone helper | `app.scope('<module-name>')` | `app.scope('commerce-catalog').model.sku` |
|
|
242
|
+
| A class uses the explicit application API or selects the module name at runtime | `this.app.scope(moduleName)` | `this.app.scope(moduleName)` |
|
|
243
|
+
|
|
244
|
+
Prefer `this.scope` for module-local business code and `this.$scope.<fixedModule>` for a statically known cross-module target. Use `app.scope(...)` or `this.app.scope(...)` when the shorthand is unavailable or the module name is genuinely dynamic. Do not replace a fixed typed shorthand with a string lookup merely for style, or mix equivalent fixed lookup forms in one access path.
|
|
240
245
|
|
|
241
246
|
This is one of the reasons Vona backend code can stay concise without flattening everything into arbitrary imports.
|
|
242
247
|
|
|
248
|
+
## Scope lookup vs module dependencies
|
|
249
|
+
|
|
250
|
+
All of the lookup forms above resolve a resource from a module that is already part of the active application composition. Fixed cross-module Bean code normally uses:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const modelSku = this.$scope.commerceCatalog.model.sku;
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
A test or standalone helper with an application reference can use:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
const modelSku = app.scope('commerce-catalog').model.sku;
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Using `this.$scope.<fixedModule>`, `app.scope(...)`, or `this.app.scope(...)` does not by itself require adding the target module to the caller's `vonaModule.dependencies`. Lookup does not create a module dependency edge, so lookup alone cannot create a circular dependency.
|
|
263
|
+
|
|
264
|
+
Scope lookup also does not compose, install, load, or order an absent module. The target must already be available through suite/application composition. Declare `vonaModule.dependencies` only when the caller has a genuine requirement for a target module's availability, dependency-first ordering, or minimum compatible version—not merely because it looks up that module's service, model, config, locale, or another resource.
|
|
265
|
+
|
|
266
|
+
For the package, suite, and module dependency distinction, see [Package Map](/reference/package-map).
|
|
267
|
+
|
|
243
268
|
## Suite / module / package boundaries
|
|
244
269
|
|
|
245
270
|
Vona architecture is not only about classes and beans. It is also about structural boundaries.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This page is the backend hub for Cabloy users, contributors, and AI vibe coding workflows that need the backend side of the framework.
|
|
4
4
|
|
|
5
|
-
Vona is the backend
|
|
5
|
+
Vona is the backend layer of Cabloy’s one fullstack system, supporting bidirectional type sync, CLI-first workflows, and source-grounded docs and skills.
|
|
6
6
|
|
|
7
7
|
## What Vona is responsible for
|
|
8
8
|
|
|
@@ -199,23 +199,21 @@ A practical implication is:
|
|
|
199
199
|
|
|
200
200
|
## Instance-aware model semantics
|
|
201
201
|
|
|
202
|
-
One important current-runtime distinction is that ordinary model usage is instance-aware by default.
|
|
202
|
+
One important current-runtime distinction is that ordinary model usage is instance-aware by default. In Vona's current tenancy model, the active instance is the tenant boundary.
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
For normal resource models, the model layer handles the active instance `iid` as part of ordinary persistence behavior:
|
|
205
205
|
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
- request-scoped code should
|
|
206
|
+
- inserts receive the active instance identity
|
|
207
|
+
- selects, `getById`, counts, updates, and deletes receive the active instance predicate
|
|
208
|
+
- request-scoped code should preserve this behavior instead of accepting caller-controlled tenant or `iid` scope
|
|
209
209
|
|
|
210
|
-
This is why `disableInstance` is a meaningful semantic choice rather than a minor ORM toggle.
|
|
210
|
+
This is why `disableInstance` is a meaningful semantic choice rather than a minor ORM toggle. Use it only for a genuinely global/system model or another explicitly authorized contract that must ignore the active instance boundary.
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
A scoped miss is absent in the current tenant/instance. Do not use `disableInstance`, a plain builder, or raw SQL merely to probe another instance and choose between `403` and not-found behavior. A real authorization failure can still be `403`; the distinction is that an ordinary resource lookup should not disclose cross-instance existence.
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
Lower-level builders and raw SQL need extra care when replacing ordinary model behavior. Preserve the active instance predicate when the operation is meant to remain instance-scoped, and document the authorization and audit contract when it deliberately is not.
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
For the broader instance/config story, also see [Config Guide](/backend/config-guide).
|
|
216
|
+
For the tenancy terminology and runtime boundary, see [Multi-Instance and Instance Resolution](/backend/multi-instance-and-instance-resolution). For generated resource flows, see [CRUD Workflow](/backend/crud-workflow). For the broader instance/config story, also see [Config Guide](/backend/config-guide).
|
|
219
217
|
|
|
220
218
|
## Datasource selection
|
|
221
219
|
|
|
@@ -191,6 +191,24 @@ That means:
|
|
|
191
191
|
|
|
192
192
|
For the model-layer perspective, also see [Model Guide](/backend/model-guide).
|
|
193
193
|
|
|
194
|
+
## Tenancy boundary: one Vona tenant per instance
|
|
195
|
+
|
|
196
|
+
In Vona's current tenancy model, a tenant corresponds to an instance. The resolved active instance is the data-isolation boundary for ordinary resource code.
|
|
197
|
+
|
|
198
|
+
For resources that inherit the normal entity base behavior:
|
|
199
|
+
|
|
200
|
+
- `iid` persists the instance discriminator when instances share a datasource
|
|
201
|
+
- normal model CRUD uses the active `ctx.instance.id` rather than a caller-supplied tenant or `iid`
|
|
202
|
+
- isolated instances can add a separate datasource boundary through `isolateClient`, but they still remain separate instances
|
|
203
|
+
|
|
204
|
+
This means a normal scoped lookup has one business result when it finds no row: that resource is absent in the current tenant/instance. Do not bypass model scope or issue an unscoped secondary lookup merely to reveal that another instance has the same identifier and change the result to `403`.
|
|
205
|
+
|
|
206
|
+
This rule does not eliminate genuine authorization failures. Return `403` when the current request is not authorized to perform an operation on a resource that is available in its authorized scope. The rule only prevents ordinary scoped misses from becoming cross-instance existence disclosures.
|
|
207
|
+
|
|
208
|
+
Do not use instance selection to represent a future merchant, store, organization, or similar business boundary. A multi-merchant design belongs inside one instance and needs explicit merchant ownership, authorization, relations, indexes, and tests in addition to the existing instance boundary.
|
|
209
|
+
|
|
210
|
+
For the operational model rules, see [Model Guide](/backend/model-guide). For generated resource behavior, see [CRUD Workflow](/backend/crud-workflow).
|
|
211
|
+
|
|
194
212
|
## Relationship to runtime and config docs
|
|
195
213
|
|
|
196
214
|
Read this guide together with:
|
|
@@ -94,7 +94,7 @@ A useful distinction is:
|
|
|
94
94
|
- `this.scope` means local module resources
|
|
95
95
|
- `this.$scope.<module>` means cross-module resources
|
|
96
96
|
|
|
97
|
-
That same access model also appears for model, entity, config, locale, and other scope resources.
|
|
97
|
+
That same access model also appears for model, entity, config, locale, and other scope resources. Cross-module scope lookup alone does not require a `vonaModule.dependencies` entry; see [Backend Foundation](/backend/foundation#scope-lookup-vs-module-dependencies) for the distinction between lookup and a true module dependency.
|
|
98
98
|
|
|
99
99
|
## Direct bean access
|
|
100
100
|
|
|
@@ -122,7 +122,7 @@ Its main jobs are:
|
|
|
122
122
|
- merge config-route overrides
|
|
123
123
|
- synthesize alias routes when needed
|
|
124
124
|
- wrap routed pages with layout routes when `meta.layout` requires it
|
|
125
|
-
- expose helpers such as `getPagePath(...)`, `resolveName(...)`, and `ensureRoute(...)`
|
|
125
|
+
- expose helpers such as `getPagePath(...)`, `getAliasPath(...)`, `resolveName(...)`, and `ensureRoute(...)`
|
|
126
126
|
|
|
127
127
|
This is the file that most clearly shows how a module-local route record becomes operational router structure.
|
|
128
128
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This page is the frontend hub for Cabloy users, contributors, and AI vibe coding workflows that need the frontend side of the framework.
|
|
4
4
|
|
|
5
|
-
Zova is the frontend
|
|
5
|
+
Zova is the frontend layer of Cabloy’s one fullstack system, supporting bidirectional type sync, CLI-first workflows, and source-grounded docs and skills.
|
|
6
6
|
|
|
7
7
|
## What Zova is responsible for
|
|
8
8
|
|
|
@@ -16,34 +16,39 @@ Typical uses include:
|
|
|
16
16
|
|
|
17
17
|
The `home-base` module provides a router-guard service hook where custom logic can be added.
|
|
18
18
|
|
|
19
|
+
Use the pure `app.$getPagePath(...)` family to construct a guard destination. Use the imperative `app.$gotoPage(...)` family from event handlers or workflows that intentionally start navigation. Do not call `$gotoLogin()` or `$gotoAccessDenied()` from a `beforeEach` guard and then return `false`: Client-side `$goto...()` starts a nested navigation while `false` aborts the navigation currently being guarded.
|
|
20
|
+
|
|
19
21
|
Representative shape:
|
|
20
22
|
|
|
21
23
|
```typescript
|
|
22
24
|
class ServiceRouterGuards {
|
|
23
25
|
protected onRouterGuards(router: BeanRouter) {
|
|
24
26
|
router.beforeEach(async to => {
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const [_res, err] = await catchError(() => {
|
|
31
|
-
return this.$passport.ensurePassport();
|
|
32
|
-
});
|
|
27
|
+
if (to.meta.requiresAuth === false) return;
|
|
28
|
+
if (this.sys.config.ssr.cookieDisabledOnServer) return;
|
|
29
|
+
|
|
30
|
+
if (!this.$passport.isAuthenticated) {
|
|
31
|
+
const [_res, err] = await catchError(() => this.$passport.ensurePassport());
|
|
33
32
|
if (err) {
|
|
34
33
|
this.$errorHandler(err, 'onRouterGuards');
|
|
35
34
|
return false;
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!this.$passport.isAuthenticated) {
|
|
39
|
+
const pagePath = this.app.$getPagePathLogin(to.fullPath);
|
|
40
|
+
if (process.env.SERVER) {
|
|
41
|
+
this.app.$redirect(pagePath);
|
|
40
42
|
}
|
|
43
|
+
return pagePath;
|
|
41
44
|
}
|
|
42
45
|
});
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
```
|
|
46
49
|
|
|
50
|
+
`$getPagePathLogin(to.fullPath)` preserves the protected destination as `returnTo` without starting navigation. On the Client, returning that path lets Vue Router redirect the current navigation atomically. On the Server, `$redirect(...)` preserves the SSR HTTP redirect flow.
|
|
51
|
+
|
|
47
52
|
## Why route meta matters here
|
|
48
53
|
|
|
49
54
|
The example makes a key architectural point: navigation guards are tightly coupled to route metadata such as `requiresAuth`.
|
|
@@ -54,6 +59,10 @@ That means route configuration and guard behavior should be read together, not a
|
|
|
54
59
|
|
|
55
60
|
The example also references SSR-related configuration such as cookie handling on the server side.
|
|
56
61
|
|
|
62
|
+
When `SSR_COOKIE=false`, `cookieDisabledOnServer` is true only during server rendering. The guard deliberately allows the protected route's neutral SSR entry, then the browser restores Passport state and applies the same admission policy after hydration. This preserves equivalent server and hydration-time initial rendering without weakening Client-side protection.
|
|
63
|
+
|
|
64
|
+
For cookie-enabled SSR, a rejected request must still use `$redirect(...)` so the SSR layer returns its HTTP redirect response. On the Client, return a route path or route-location object from the guard instead of using an imperative `$goto...()` helper.
|
|
65
|
+
|
|
57
66
|
So guards are not purely a client-side router concern. In Cabloy/Zova, they can also intersect with SSR behavior.
|
|
58
67
|
|
|
59
68
|
## Implementation checks for navigation-guard changes
|
|
@@ -50,6 +50,30 @@ The distinction matters:
|
|
|
50
50
|
- use `routes.path` for normal path-based aliases
|
|
51
51
|
- use `routes.name` when the route depends on params-aware naming
|
|
52
52
|
|
|
53
|
+
## Generate a configured alias path
|
|
54
|
+
|
|
55
|
+
When application code needs a user-facing URL for a named route, use the canonical route name with `$router.getAliasPath(...)`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const path = this.$router.getAliasPath('demo-todo:item', {
|
|
59
|
+
params: {
|
|
60
|
+
id: '42',
|
|
61
|
+
locale: true,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const absoluteUrl = this.$router.getAliasPath(
|
|
65
|
+
'demo-todo:item',
|
|
66
|
+
{ params: { id: '42', locale: true } },
|
|
67
|
+
true,
|
|
68
|
+
);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The helper returns the configured alias path, such as `/zh-cn/todo/42`, or `undefined` when that route name has no configured alias. Pass `true` as the third argument when an absolute URL is required; it uses the same host and public-path conversion as `$router.getPagePath(..., true)`. `locale: true` uses the active locale and omits the configured default locale from an optional locale segment.
|
|
72
|
+
|
|
73
|
+
Use the canonical generated route name. Do not construct `$alias:<name>` or strip `/__alias__` in application code: those are private router implementation details.
|
|
74
|
+
|
|
75
|
+
Use `$router.getPagePath(...)` for a known canonical path template, `$router.getAliasPath(...)` for a configured public alias by canonical route name, and `$router.resolveName(...)` for canonical named-route resolution. Do not add alias behavior to `getPagePath(...)`, because aliases are configured against route names rather than page-path templates.
|
|
76
|
+
|
|
53
77
|
## Implementation checks for route-alias changes
|
|
54
78
|
|
|
55
79
|
When changing user-facing routes, ask:
|