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.
Files changed (300) hide show
  1. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +207 -0
  2. package/.claude/skills/cabloy-backend-scaffold/evals/evals.json +29 -0
  3. package/.claude/skills/cabloy-backend-scaffold/references/backend-thread-map.md +52 -0
  4. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +39 -0
  5. package/.claude/skills/cabloy-contract-loop/SKILL.md +201 -0
  6. package/.claude/skills/cabloy-contract-loop/evals/evals.json +29 -0
  7. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +47 -0
  8. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +32 -0
  9. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +230 -0
  10. package/.claude/skills/cabloy-frontend-scaffold/evals/evals.json +35 -0
  11. package/.claude/skills/cabloy-frontend-scaffold/references/follow-up-checklist.md +41 -0
  12. package/.claude/skills/cabloy-frontend-scaffold/references/frontend-thread-map.md +54 -0
  13. package/.claude/skills/cabloy-workflow/SKILL.md +292 -0
  14. package/.claude/skills/cabloy-workflow/evals/evals.json +35 -0
  15. package/.claude/skills/cabloy-workflow/references/cli-strategy.md +39 -0
  16. package/.claude/skills/cabloy-workflow/references/edition-detection.md +30 -0
  17. package/.github/workflows/docs-pages.yml +56 -0
  18. package/.gitignore +1 -0
  19. package/CHANGELOG.md +54 -0
  20. package/CLAUDE.md +59 -0
  21. package/README.md +152 -0
  22. package/cabloy-docs/.vitepress/config.mjs +255 -0
  23. package/cabloy-docs/.vitepress/public/CNAME +1 -0
  24. package/cabloy-docs/.vitepress/theme/custom.css +64 -0
  25. package/cabloy-docs/.vitepress/theme/edition-badges.md +5 -0
  26. package/cabloy-docs/.vitepress/theme/index.js +5 -0
  27. package/cabloy-docs/ai/class-placement-rule.md +139 -0
  28. package/cabloy-docs/ai/cli-for-agents.md +56 -0
  29. package/cabloy-docs/ai/cli-to-skill-map.md +165 -0
  30. package/cabloy-docs/ai/docs-skills-rules-mapping.md +168 -0
  31. package/cabloy-docs/ai/edition-consistency-checklist.md +150 -0
  32. package/cabloy-docs/ai/edition-detection.md +30 -0
  33. package/cabloy-docs/ai/future-skill-roadmap.md +135 -0
  34. package/cabloy-docs/ai/global-bean-lookup.md +158 -0
  35. package/cabloy-docs/ai/introduction.md +62 -0
  36. package/cabloy-docs/ai/playbook-backend-module.md +111 -0
  37. package/cabloy-docs/ai/playbook-contract-regeneration.md +100 -0
  38. package/cabloy-docs/ai/playbook-frontend-page.md +99 -0
  39. package/cabloy-docs/ai/playbook-metadata-refresh.md +67 -0
  40. package/cabloy-docs/ai/repo-guidance.md +58 -0
  41. package/cabloy-docs/ai/rules-and-config.md +29 -0
  42. package/cabloy-docs/ai/skills.md +37 -0
  43. package/cabloy-docs/ai/verification.md +31 -0
  44. package/cabloy-docs/ai/virtual-decorator-guidance.md +206 -0
  45. package/cabloy-docs/backend/aop-overview.md +128 -0
  46. package/cabloy-docs/backend/auth-guide.md +151 -0
  47. package/cabloy-docs/backend/backend-essentials.md +128 -0
  48. package/cabloy-docs/backend/broadcast-guide.md +138 -0
  49. package/cabloy-docs/backend/cache-guide.md +70 -0
  50. package/cabloy-docs/backend/captcha-guide.md +162 -0
  51. package/cabloy-docs/backend/cli.md +173 -0
  52. package/cabloy-docs/backend/config-guide.md +249 -0
  53. package/cabloy-docs/backend/controller-aop-guide.md +270 -0
  54. package/cabloy-docs/backend/controller-guide.md +347 -0
  55. package/cabloy-docs/backend/crud-workflow.md +118 -0
  56. package/cabloy-docs/backend/dto-guide.md +161 -0
  57. package/cabloy-docs/backend/dto-infer-generation.md +153 -0
  58. package/cabloy-docs/backend/dynamic-datasource-guide.md +70 -0
  59. package/cabloy-docs/backend/election-guide.md +141 -0
  60. package/cabloy-docs/backend/entity-guide.md +150 -0
  61. package/cabloy-docs/backend/error-guide.md +108 -0
  62. package/cabloy-docs/backend/event-guide.md +183 -0
  63. package/cabloy-docs/backend/external-aop-guide.md +149 -0
  64. package/cabloy-docs/backend/field-indexes.md +79 -0
  65. package/cabloy-docs/backend/foundation.md +281 -0
  66. package/cabloy-docs/backend/i18n-guide.md +211 -0
  67. package/cabloy-docs/backend/internal-aop-guide.md +181 -0
  68. package/cabloy-docs/backend/introduction.md +95 -0
  69. package/cabloy-docs/backend/jwt-guide.md +276 -0
  70. package/cabloy-docs/backend/logger-guide.md +223 -0
  71. package/cabloy-docs/backend/mail-guide.md +189 -0
  72. package/cabloy-docs/backend/menu-guide.md +80 -0
  73. package/cabloy-docs/backend/migration-and-changes.md +192 -0
  74. package/cabloy-docs/backend/model-guide.md +274 -0
  75. package/cabloy-docs/backend/multi-database-datasource.md +171 -0
  76. package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +196 -0
  77. package/cabloy-docs/backend/openapi-guide.md +118 -0
  78. package/cabloy-docs/backend/orm-aggregate-group-guide.md +210 -0
  79. package/cabloy-docs/backend/orm-configuration-guide.md +165 -0
  80. package/cabloy-docs/backend/orm-guide.md +109 -0
  81. package/cabloy-docs/backend/orm-mutation-guide.md +195 -0
  82. package/cabloy-docs/backend/orm-select-guide.md +243 -0
  83. package/cabloy-docs/backend/queue-guide.md +271 -0
  84. package/cabloy-docs/backend/quickstart.md +141 -0
  85. package/cabloy-docs/backend/redis-guide.md +70 -0
  86. package/cabloy-docs/backend/redlock-guide.md +60 -0
  87. package/cabloy-docs/backend/relations-guide.md +250 -0
  88. package/cabloy-docs/backend/runtime-and-flavors.md +304 -0
  89. package/cabloy-docs/backend/schedule-guide.md +81 -0
  90. package/cabloy-docs/backend/scripts.md +116 -0
  91. package/cabloy-docs/backend/serialization-guide.md +192 -0
  92. package/cabloy-docs/backend/service-guide.md +166 -0
  93. package/cabloy-docs/backend/sharding-guide.md +49 -0
  94. package/cabloy-docs/backend/startup-guide.md +326 -0
  95. package/cabloy-docs/backend/transaction-guide.md +82 -0
  96. package/cabloy-docs/backend/unit-testing.md +209 -0
  97. package/cabloy-docs/backend/upload-guide.md +160 -0
  98. package/cabloy-docs/backend/user-access-guide.md +157 -0
  99. package/cabloy-docs/backend/validation-guide.md +80 -0
  100. package/cabloy-docs/backend/worker-guide.md +59 -0
  101. package/cabloy-docs/editions/cabloy-basic.md +26 -0
  102. package/cabloy-docs/editions/cabloy-start.md +55 -0
  103. package/cabloy-docs/editions/choosing-between-basic-and-start.md +84 -0
  104. package/cabloy-docs/editions/detection.md +31 -0
  105. package/cabloy-docs/editions/overview.md +107 -0
  106. package/cabloy-docs/frontend/api-guide.md +93 -0
  107. package/cabloy-docs/frontend/api-schema-guide.md +43 -0
  108. package/cabloy-docs/frontend/app-startup-guide.md +185 -0
  109. package/cabloy-docs/frontend/cli.md +78 -0
  110. package/cabloy-docs/frontend/component-guide.md +105 -0
  111. package/cabloy-docs/frontend/component-props-guide.md +97 -0
  112. package/cabloy-docs/frontend/component-v-model-guide.md +110 -0
  113. package/cabloy-docs/frontend/css-in-js-guide.md +151 -0
  114. package/cabloy-docs/frontend/design-principles.md +55 -0
  115. package/cabloy-docs/frontend/environment-config-guide.md +250 -0
  116. package/cabloy-docs/frontend/foundation.md +58 -0
  117. package/cabloy-docs/frontend/generic-component-guide.md +35 -0
  118. package/cabloy-docs/frontend/icon-engine-guide.md +88 -0
  119. package/cabloy-docs/frontend/introduction.md +33 -0
  120. package/cabloy-docs/frontend/ioc-and-beans.md +211 -0
  121. package/cabloy-docs/frontend/mock-guide.md +109 -0
  122. package/cabloy-docs/frontend/model-architecture.md +87 -0
  123. package/cabloy-docs/frontend/model-state-guide.md +70 -0
  124. package/cabloy-docs/frontend/module-scope.md +168 -0
  125. package/cabloy-docs/frontend/modules-and-suites.md +179 -0
  126. package/cabloy-docs/frontend/navigation-guards-guide.md +68 -0
  127. package/cabloy-docs/frontend/openapi-sdk-guide.md +102 -0
  128. package/cabloy-docs/frontend/page-guide.md +223 -0
  129. package/cabloy-docs/frontend/page-params-guide.md +87 -0
  130. package/cabloy-docs/frontend/page-query-guide.md +96 -0
  131. package/cabloy-docs/frontend/page-route-guide.md +147 -0
  132. package/cabloy-docs/frontend/quickstart.md +202 -0
  133. package/cabloy-docs/frontend/route-alias-guide.md +61 -0
  134. package/cabloy-docs/frontend/scripts.md +86 -0
  135. package/cabloy-docs/frontend/sdk-guide.md +45 -0
  136. package/cabloy-docs/frontend/server-data.md +74 -0
  137. package/cabloy-docs/frontend/ssr-client-only.md +40 -0
  138. package/cabloy-docs/frontend/ssr-env.md +51 -0
  139. package/cabloy-docs/frontend/ssr-init-data.md +46 -0
  140. package/cabloy-docs/frontend/ssr-overview.md +48 -0
  141. package/cabloy-docs/frontend/ssr-seo-meta.md +52 -0
  142. package/cabloy-docs/frontend/system-startup-guide.md +186 -0
  143. package/cabloy-docs/frontend/theme-guide.md +154 -0
  144. package/cabloy-docs/frontend/zod-guide.md +161 -0
  145. package/cabloy-docs/fullstack/cli.md +118 -0
  146. package/cabloy-docs/fullstack/comparison-with-other-frameworks.md +117 -0
  147. package/cabloy-docs/fullstack/edition-collaboration-differences.md +62 -0
  148. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +64 -0
  149. package/cabloy-docs/fullstack/introduction.md +81 -0
  150. package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -0
  151. package/cabloy-docs/fullstack/quickstart.md +89 -0
  152. package/cabloy-docs/fullstack/vona-zova-integration.md +86 -0
  153. package/cabloy-docs/fullstack/vscode-extensions.md +126 -0
  154. package/cabloy-docs/index.md +72 -0
  155. package/cabloy-docs/package.json +16 -0
  156. package/cabloy-docs/pnpm-lock.yaml +1607 -0
  157. package/cabloy-docs/reference/backend-directory-structure.md +88 -0
  158. package/cabloy-docs/reference/cli-reference.md +49 -0
  159. package/cabloy-docs/reference/glossary.md +38 -0
  160. package/cabloy-docs/reference/package-map.md +105 -0
  161. package/cabloy-docs/reference/repo-scripts.md +36 -0
  162. package/package.json +4 -1
  163. package/scripts/init.ts +12 -0
  164. package/scripts/upgrade.ts +31 -3
  165. package/vona/README.md +4 -4
  166. package/vona/README.zh-CN.md +4 -4
  167. package/vona/packages-vona/vona/package.json +1 -1
  168. package/vona/pnpm-lock.yaml +383 -38
  169. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/package.json +1 -1
  170. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/src/bean/summerCache.datasourceWrite.ts +2 -2
  171. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/package.json +1 -1
  172. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/.metadata/index.ts +49 -1
  173. package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/controller/memoryDiag.ts +97 -0
  174. package/vona/src/suite-vendor/a-cabloy/package.json +1 -1
  175. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
  176. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/src/bean/cacheRedis.captcha.ts +2 -2
  177. package/vona/src/suite-vendor/a-captcha/package.json +1 -1
  178. package/vona/src/suite-vendor/a-vona/modules/a-bean/cli/bean/metadata/generate.ts +5 -6
  179. package/vona/src/suite-vendor/a-vona/modules/a-bean/package.json +1 -1
  180. package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheMem/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  181. package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheRedis/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  182. package/vona/src/suite-vendor/a-vona/modules/a-cache/package.json +1 -1
  183. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/.metadata/index.ts +13 -2
  184. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/bean/bean.cache.ts +6 -7
  185. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheMemBase.ts → service/cacheMemBase_.ts} +3 -3
  186. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheRedisBase.ts → service/cacheRedisBase_.ts} +3 -3
  187. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/package.json +1 -1
  188. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.emailConfirm.ts +2 -2
  189. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.passwordReset.ts +2 -2
  190. package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
  191. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/bean/summerCache.json.ts +2 -2
  192. package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/databaseDialect/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  193. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  194. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +4 -3
  195. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.database.ts +3 -3
  196. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.model.ts +1 -1
  197. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/schedule.softDeletionPrune.ts +1 -1
  198. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/common/utils.ts +1 -1
  199. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/index.ts +1 -1
  200. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_cache.ts +1 -1
  201. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_meta.ts +1 -1
  202. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.modelBase.ts +0 -5
  203. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAggregate.ts +1 -1
  204. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoCreate.ts +1 -1
  205. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +1 -1
  206. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGroup.ts +1 -1
  207. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoMutate.ts +1 -1
  208. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoSelectAndCount.ts +1 -1
  209. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoUpdate.ts +1 -1
  210. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/index.ts +1 -0
  211. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/modelCacheBase.ts +3 -3
  212. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relations.ts +1 -1
  213. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsDynamic.ts +1 -1
  214. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsMutate.ts +1 -1
  215. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsStatic.ts +1 -1
  216. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheEntity_.ts +1 -1
  217. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheQuery_.ts +1 -1
  218. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/database.ts +2 -2
  219. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean/bean.databaseDialectBase.ts → service/databaseDialectBase_.ts} +38 -41
  220. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/db_.ts +2 -2
  221. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/relations_.ts +3 -3
  222. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/database.ts +0 -5
  223. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoGet.ts +1 -1
  224. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoMutate.ts +1 -1
  225. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoSelectAndCount.ts +1 -1
  226. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/model.ts +1 -1
  227. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelAggr.ts +1 -1
  228. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelCount.ts +1 -1
  229. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGeneral.ts +1 -1
  230. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGroup.ts +1 -1
  231. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelIncrement.ts +1 -1
  232. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relations.ts +1 -1
  233. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsColumns.ts +1 -1
  234. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDef.ts +1 -1
  235. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefDynamic.ts +1 -1
  236. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefMutate.ts +1 -1
  237. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsMutate.ts +1 -1
  238. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsTables.ts +1 -1
  239. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  240. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.betterSqlite3.ts +2 -2
  241. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +2 -2
  242. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.pg.ts +2 -2
  243. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  244. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +109 -40
  245. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permission.ts +2 -2
  246. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  247. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/bean/cacheRedis.startupDebounce.ts +2 -2
  248. package/vona/src/suite-vendor/a-vona/modules/a-summer/cli/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  249. package/vona/src/suite-vendor/a-vona/modules/a-summer/package.json +1 -1
  250. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/.metadata/index.ts +1 -1
  251. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/bean/bean.summer.ts +3 -3
  252. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localMem_.ts +3 -3
  253. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localRedis_.ts +3 -3
  254. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/{bean/bean.summerCacheBase.ts → service/summerCacheBase_.ts} +3 -3
  255. package/vona/src/suite-vendor/a-vona/modules/a-swagger/package.json +1 -1
  256. package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.rapidoc.ts +2 -2
  257. package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.swagger.ts +2 -2
  258. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  259. package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/cacheRedis.authToken.ts +2 -2
  260. package/vona/src/suite-vendor/a-vona/modules/a-worker/package.json +1 -1
  261. package/vona/src/suite-vendor/a-vona/modules/a-worker/src/bean/cacheRedis.workerAlive.ts +2 -2
  262. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  263. package/zova/README.md +5 -5
  264. package/zova/README.zh-CN.md +4 -4
  265. package/zova/package.original.json +4 -4
  266. package/zova/packages-cli/cli/package.json +2 -2
  267. package/zova/packages-cli/cli-set-front/package.json +2 -2
  268. package/zova/packages-utils/zova-jsx/package.json +2 -2
  269. package/zova/packages-utils/zova-vite/package.json +2 -2
  270. package/zova/packages-utils/zova-vite/templates/app/controller.tsx_ +3 -3
  271. package/zova/packages-zova/zova/package.json +3 -3
  272. package/zova/packages-zova/zova-core/package.json +2 -2
  273. package/zova/packages-zova/zova-core/src/bean/beanContainer.ts +3 -3
  274. package/zova/packages-zova/zova-core/src/bean/beanControllerPageBase.ts +1 -0
  275. package/zova/packages-zova/zova-core/src/core/component/module.ts +16 -16
  276. package/zova/packages-zova/zova-core/src/core/context/component.ts +35 -3
  277. package/zova/packages-zova/zova-core/src/core/context/util.ts +15 -11
  278. package/zova/pnpm-lock.yaml +1596 -1679
  279. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +11 -0
  280. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/page/toolMinimal.ts +9 -0
  281. package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolMinimal/controller.tsx +11 -0
  282. package/zova/src/suite/a-demo/modules/demo-basic/src/routes.ts +10 -0
  283. package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
  284. package/zova/src/suite-vendor/a-zova/modules/a-model/src/service/storage.ts +4 -5
  285. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  286. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/monkey.ts +1 -1
  287. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  288. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +36 -1
  289. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssrMetaStore.ts +7 -2
  290. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/monkey.ts +3 -0
  291. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/package.json +1 -1
  292. package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/src/service/ssrHandler.ts +70 -29
  293. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  294. package/zova/src/suite-vendor/a-zova/package.json +6 -6
  295. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud.ts +0 -0
  296. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_inner.ts +0 -0
  297. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_table.ts +0 -0
  298. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_knex.ts +0 -0
  299. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_utils.ts +0 -0
  300. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_view.ts +0 -0
@@ -0,0 +1,118 @@
1
+ # CRUD Workflow
2
+
3
+ This guide explains the Vona CRUD generator workflow in the Cabloy monorepo.
4
+
5
+ ## Why this page matters
6
+
7
+ CRUD is one of the clearest places where Cabloy’s CLI-first philosophy pays off.
8
+
9
+ Instead of creating controller, service, model, entity, DTO, metadata, locale, and test files by hand, Vona already provides generators that create the initial backend thread.
10
+
11
+ ## Generate a CRUD skeleton
12
+
13
+ Example: generate a CRUD workflow for `student` in module `demo-student`.
14
+
15
+ ```bash
16
+ npm run vona :tools:crud student -- --module=demo-student
17
+ ```
18
+
19
+ A lighter variant also exists:
20
+
21
+ ```bash
22
+ npm run vona :tools:crudBasic student -- --module=demo-student
23
+ ```
24
+
25
+ This is important because the repo already encodes both the full CRUD thread and a lighter CRUD-basic workflow in the CLI surface.
26
+
27
+ ## Generated structure
28
+
29
+ The generator creates a connected set of files, typically including:
30
+
31
+ - controller
32
+ - service
33
+ - model
34
+ - entity
35
+ - create/update DTOs
36
+ - meta version and index files
37
+ - locale files
38
+ - tests
39
+
40
+ This is exactly why this generator should be the default starting point. It gives a consistent starting shape across the backend thread.
41
+
42
+ A practical generated-output checklist usually includes:
43
+
44
+ - controller
45
+ - service
46
+ - model
47
+ - entity
48
+ - create/update DTOs
49
+ - `meta.version`
50
+ - locale assets
51
+ - test file
52
+ - package-version update for the next schema step
53
+
54
+ That checklist is useful because it makes the generated thread easier to inspect after the CLI run instead of treating CRUD generation as a black box.
55
+
56
+ ## The generated backend thread
57
+
58
+ The CRUD generator is not a shortcut around the architecture. It instantiates the same backend contract loop documented elsewhere.
59
+
60
+ A practical thread is:
61
+
62
+ 1. controller exposes the HTTP contract
63
+ 2. service owns orchestration
64
+ 3. model owns persistence behavior
65
+ 4. entity defines the field/data contract
66
+ 5. DTOs define operation-specific request/response contracts
67
+ 6. meta.version handles schema lifecycle
68
+ 7. tests verify the resulting contract through action execution
69
+
70
+ Read this guide together with:
71
+
72
+ - [Controller Guide](/backend/controller-guide)
73
+ - [Service Guide](/backend/service-guide)
74
+ - [Model Guide](/backend/model-guide)
75
+ - [Entity Guide](/backend/entity-guide)
76
+ - [DTO Guide](/backend/dto-guide)
77
+ - [Migration and Changes](/backend/migration-and-changes)
78
+ - [Unit Testing](/backend/unit-testing)
79
+
80
+ ## Recommended workflow
81
+
82
+ 1. run the CRUD generator
83
+ 2. inspect the generated files
84
+ 3. refine entity, DTO, model, service, and controller behavior for the real business case
85
+ 4. verify routes, model behavior, migration behavior, and tests
86
+
87
+ A practical expectation is that the generated test should already help verify the full contract thread rather than only file existence. In other words, generation should leave you with something that can immediately participate in CRUD-oriented action testing, migration verification, and later OpenAPI/frontend contract refinement.
88
+
89
+ This is the preferred path because it preserves framework conventions first, then applies domain-specific refinement second.
90
+
91
+ ## When to keep generated defaults vs refine them manually
92
+
93
+ A practical rule is:
94
+
95
+ - keep generated defaults when the backend thread already matches the business shape
96
+ - refine the generated code when response contracts, DTO behavior, controller metadata, model behavior, or test flow need stronger domain-specific semantics
97
+ - avoid replacing the generated thread wholesale unless the framework shape truly does not fit the use case
98
+
99
+ ## Relationship to DTO inference and OpenAPI
100
+
101
+ The generated thread is also part of the broader contract-emission path.
102
+
103
+ That means generated entity, DTO, controller, and validation structure can feed:
104
+
105
+ - backend OpenAPI output
106
+ - DTO inference and generation
107
+ - frontend SDK generation
108
+
109
+ For the cross-stack side of this loop, also see [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk).
110
+
111
+ ## Generated workflow checklist
112
+
113
+ When you see a request like “create a student CRUD” or “scaffold backend resources,” the correct default should be:
114
+
115
+ 1. inspect the Vona CLI
116
+ 2. use `:tools:crud` or `:tools:crudBasic` if one matches the need
117
+ 3. modify the generated output instead of hand-building the whole thread from scratch
118
+ 4. verify the resulting migration, controller, and test path instead of stopping at file creation
@@ -0,0 +1,161 @@
1
+ # DTO Guide
2
+
3
+ This guide explains how DTOs work in Vona within the Cabloy monorepo.
4
+
5
+ ## Why DTOs matter
6
+
7
+ DTOs are not only transport classes. In Vona, they are part of one contract system shared across:
8
+
9
+ - validation
10
+ - OpenAPI metadata
11
+ - serializer-facing response shape
12
+ - model-aware DTO inference
13
+ - frontend-facing generated contracts
14
+
15
+ That is why DTO design should be treated as a framework concern instead of only a controller-local convenience.
16
+
17
+ ## Create a DTO
18
+
19
+ Example: create a DTO named `studentCreate` in module `demo-student`.
20
+
21
+ ```bash
22
+ npm run vona :create:bean dto studentCreate -- --module=demo-student
23
+ ```
24
+
25
+ ## DTO definition
26
+
27
+ Representative pattern:
28
+
29
+ ```typescript
30
+ @Dto<IDtoOptionsStudentCreate>()
31
+ export class DtoStudentCreate {}
32
+ ```
33
+
34
+ ## DTOs in the backend contract loop
35
+
36
+ DTOs are the most explicit named contracts in the backend contract loop.
37
+
38
+ A useful split is:
39
+
40
+ - entities define reusable field/data structure close to persistence
41
+ - DTOs define explicit request/response contract artifacts
42
+ - inferred DTOs reduce duplication when the model/query shape is already strong enough
43
+
44
+ Read this guide together with:
45
+
46
+ - [Entity Guide](/backend/entity-guide)
47
+ - [DTO Infer and Generation](/backend/dto-infer-generation)
48
+ - [Validation Guide](/backend/validation-guide)
49
+ - [OpenAPI Guide](/backend/openapi-guide)
50
+
51
+ ## `@Api.field`
52
+
53
+ DTO field definitions use the same `@Api.field` mental model as entities.
54
+
55
+ That means DTOs can express:
56
+
57
+ - validation rules
58
+ - field metadata
59
+ - OpenAPI-facing schema information
60
+ - serializer-oriented response metadata when needed
61
+
62
+ For response-shaping behavior built on the same field metadata surface, see [Serialization Guide](/backend/serialization-guide).
63
+
64
+ Representative pattern:
65
+
66
+ ```typescript
67
+ class DtoStudentCreate {
68
+ @Api.field(v.title($locale('Name')), v.min(3))
69
+ name: string;
70
+
71
+ @Api.field(v.title($locale('Description')), v.optional())
72
+ description?: string;
73
+ }
74
+ ```
75
+
76
+ ## DTO options
77
+
78
+ Three especially important DTO option areas are:
79
+
80
+ - `independent`
81
+ - `openapi`
82
+ - `fields`
83
+
84
+ These options make DTOs configurable as reusable schema objects, not just local TypeScript classes.
85
+
86
+ A useful ownership rule is:
87
+
88
+ - DTO metadata defines the contract shape close to the class
89
+ - app config can still override broader DTO behavior
90
+ - inference tools can reduce how much hand-authored DTO code is needed
91
+
92
+ ## App-config override support
93
+
94
+ DTO options can also be configured through app config.
95
+
96
+ That matters because the DTO layer participates in the broader framework configuration system instead of being fully hardcoded in one file.
97
+
98
+ ## Mapped class tools
99
+
100
+ One of the most valuable DTO topics is reuse through mapped-class helpers.
101
+
102
+ Representative tools include:
103
+
104
+ - `$Class.pick`
105
+ - `$Class.partial`
106
+ - `$Class.omit`
107
+ - `$Class.mixin`
108
+
109
+ These let you derive DTOs from existing entities or DTOs instead of re-declaring the same field sets repeatedly.
110
+
111
+ ## Operation-specific DTO thinking
112
+
113
+ A practical way to think about DTO families is by operation shape.
114
+
115
+ Common operation families include:
116
+
117
+ - create DTOs
118
+ - update DTOs
119
+ - get DTOs
120
+ - list-and-count DTOs
121
+ - query DTOs
122
+ - query-page DTOs
123
+ - aggregate DTOs
124
+ - group DTOs
125
+
126
+ Some of these are hand-authored DTO classes. Others are better expressed through Vona’s inference helpers.
127
+
128
+ The important point is not to force every operation shape into one generic DTO when the framework already distinguishes them more precisely.
129
+
130
+ ## Explicit DTOs vs inferred DTOs
131
+
132
+ A practical split is:
133
+
134
+ - use explicit DTO classes when the contract needs a stable named artifact
135
+ - use inferred DTOs when the contract closely follows model structure or query shape
136
+ - wrap inferred DTOs in a named DTO class when reuse or discoverability becomes more important
137
+
138
+ For the inference side, see [DTO Infer and Generation](/backend/dto-infer-generation).
139
+
140
+ ## Relationship to ORM and controller contracts
141
+
142
+ DTOs sit between backend data structure and backend API contracts.
143
+
144
+ That means DTO design should often be read together with:
145
+
146
+ - [Model Guide](/backend/model-guide)
147
+ - [Relations Guide](/backend/relations-guide)
148
+ - [ORM Aggregate and Group Guide](/backend/orm-aggregate-group-guide)
149
+ - [OpenAPI Guide](/backend/openapi-guide)
150
+ - [Controller Guide](/backend/controller-guide)
151
+
152
+ ## Implementation checks for DTO changes
153
+
154
+ When creating DTOs:
155
+
156
+ 1. prefer reuse through mapped-class helpers when the shape is derived from existing classes
157
+ 2. keep DTO validation and OpenAPI concerns aligned through `@Api.field`
158
+ 3. decide whether the contract should be an explicit DTO class or an inferred DTO
159
+ 4. avoid re-declaring fields manually if Vona’s DTO-generation or class-derivation tools already solve the problem
160
+ 5. treat DTO design as part of the contract between backend handlers, models, and frontend integration
161
+ 6. choose explicit DTOs when named long-lived contracts matter, and inferred DTOs when the model/query shape already expresses the contract clearly
@@ -0,0 +1,153 @@
1
+ # DTO Infer and Generation
2
+
3
+ This guide explains how DTO inference and generation work in Vona within the Cabloy monorepo.
4
+
5
+ ## Why DTO inference matters
6
+
7
+ DTOs are essential for validation and OpenAPI metadata, but manually maintaining them becomes expensive and error-prone as models and relationships grow more complex.
8
+
9
+ Vona addresses that by dynamically inferring and generating DTOs from model structure and query shape.
10
+
11
+ ## DTO tools
12
+
13
+ Several DTO-oriented tools are available, including:
14
+
15
+ - `$Dto.get`
16
+ - `$Dto.listAndCount`
17
+ - `$Dto.query`
18
+ - `$Dto.queryPage`
19
+ - `$Dto.create`
20
+ - `$Dto.update`
21
+ - `$Dto.aggregate`
22
+ - `$Dto.group`
23
+
24
+ These tools let DTOs emerge from model-aware structure instead of always being hand-authored from scratch.
25
+
26
+ ## When each inferred DTO shape is useful
27
+
28
+ A practical mental model is:
29
+
30
+ - use `$Dto.get` for one-item read contracts
31
+ - use `$Dto.listAndCount` for paginated or list-plus-total contracts
32
+ - use `$Dto.query` and `$Dto.queryPage` for query-input or query-result patterns
33
+ - use `$Dto.create` and `$Dto.update` for write contracts derived from model structure
34
+ - use `$Dto.aggregate` and `$Dto.group` for summary-oriented result shapes
35
+
36
+ This matters because different ORM operations naturally produce different API contracts.
37
+
38
+ ## When inference should replace handwritten DTOs
39
+
40
+ A practical rule is:
41
+
42
+ - prefer inferred DTOs when the contract closely follows model structure or query shape
43
+ - prefer explicit DTO classes when the contract is long-lived, heavily customized, or needs a strong named public identity
44
+ - wrap inferred DTOs into named DTO classes when reuse becomes more important than one-off convenience
45
+
46
+ This is one of the most important distinctions in the backend contract loop.
47
+
48
+ ## Main-details example
49
+
50
+ A representative example uses an `Order -> Product` relation.
51
+
52
+ The key lesson is that when the return shape is richer than a simple entity array, an inferred DTO can capture the actual result shape more accurately than a hand-waved entity annotation.
53
+
54
+ Representative pattern:
55
+
56
+ ```typescript
57
+ @Api.body(v.array($Dto.get(() => ModelOrder, { include: { products: true } })))
58
+ ```
59
+
60
+ This shows the dynamic DTO layer participating directly in controller return contracts.
61
+
62
+ Another useful inferred pattern is action-derived contract reuse:
63
+
64
+ ```typescript
65
+ @Web.get('getUserDynamic')
66
+ @Api.body($Dto.get('test-vona:post'))
67
+ getPostDynamic() {}
68
+ ```
69
+
70
+ This is especially useful when a controller wants to expose the same contract shape that the model/action thread already defines elsewhere.
71
+
72
+ ## Relation-aware inference
73
+
74
+ DTO inference becomes especially powerful when the result shape depends on relations.
75
+
76
+ Examples include:
77
+
78
+ - static relations loaded through `include`
79
+ - dynamic relations loaded through `with`
80
+ - grouped or aggregated related substructures
81
+
82
+ That means DTO inference should often be considered together with relation design rather than only after the fact.
83
+
84
+ A representative relation-aware response pattern is:
85
+
86
+ ```typescript
87
+ @Api.body(v.array($Dto.get(() => ModelOrder, { include: { products: true } })))
88
+ ```
89
+
90
+ A practical rule is:
91
+
92
+ - keep inference inline when one action needs one contract shape only once
93
+ - wrap the inferred DTO into a named DTO class when the same relation-aware shape becomes part of a reusable public contract
94
+
95
+ ## Aggregate and group DTO inference
96
+
97
+ Summary-oriented ORM queries often benefit from inferred DTOs because the result shape is driven by `aggrs`, `groups`, and relation configuration.
98
+
99
+ A practical rule is:
100
+
101
+ - if the summary shape comes directly from ORM query structure, inference is often the cleanest option
102
+ - if the same summary contract is reused broadly, wrap the inferred DTO into a named DTO class
103
+
104
+ For the query side of this topic, also see [ORM Aggregate and Group Guide](/backend/orm-aggregate-group-guide).
105
+
106
+ ## Relationship to CRUD generation
107
+
108
+ Inferred DTOs are not separate from the CRUD workflow. They sit on the same contract loop.
109
+
110
+ A useful split is:
111
+
112
+ - CRUD generation gives you the initial backend thread
113
+ - explicit DTOs give you stable named operation contracts
114
+ - inferred DTOs let the contract stay close to model and query truth when a separate handwritten class would add little value
115
+
116
+ This helps keep the generated thread productive instead of forcing redundant DTO maintenance everywhere.
117
+
118
+ ## Encapsulating inferred DTOs
119
+
120
+ Inferred DTO logic can also be wrapped inside an explicit DTO class for reuse.
121
+
122
+ That is useful because it gives teams a spectrum of options:
123
+
124
+ - use inference directly for one endpoint
125
+ - wrap the inferred DTO into a named reusable class when the contract is important elsewhere too
126
+
127
+ ## Relationship to generation and metadata refresh
128
+
129
+ DTO inference and generation are not isolated authoring tricks. They are part of a broader backend contract workflow.
130
+
131
+ When model, relation, or controller contracts change, remember to consider the downstream metadata and generated-contract path as well.
132
+
133
+ Read this guide together with:
134
+
135
+ - [DTO Guide](/backend/dto-guide)
136
+ - [Relations Guide](/backend/relations-guide)
137
+ - [ORM Select Guide](/backend/orm-select-guide)
138
+ - [ORM Aggregate and Group Guide](/backend/orm-aggregate-group-guide)
139
+ - [OpenAPI Guide](/backend/openapi-guide)
140
+ - [Backend OpenAPI to Frontend SDK](/fullstack/openapi-to-sdk)
141
+
142
+ ## Implementation checks for DTO inference and generation changes
143
+
144
+ When evaluating a return shape or input contract that closely follows model structure, ask:
145
+
146
+ 1. should this DTO be inferred instead of handwritten?
147
+ 2. does model relationship structure already contain enough information?
148
+ 3. is the contract get/list/query/create/update/aggregate/group oriented?
149
+ 4. should the inferred DTO stay inline or be wrapped in a named DTO class?
150
+ 5. does the resulting DTO also affect OpenAPI and frontend generation paths?
151
+ 6. is CRUD generation already giving enough contract structure that another handwritten DTO would be redundant?
152
+
153
+ That helps reduce redundant type work and keeps contracts closer to the model truth.
@@ -0,0 +1,70 @@
1
+ # Dynamic Datasource Guide
2
+
3
+ This guide points from the backend docs to the deeper Cabloy dynamic-datasource architecture.
4
+
5
+ ## Current source of truth
6
+
7
+ This page is intentionally a backend-facing pointer page rather than a full standalone tutorial.
8
+
9
+ The older ORM page for dynamic datasource is intentionally brief because the deeper capability is provided by the `a-cabloy` suite.
10
+
11
+ In the new docs structure, treat dynamic datasource as a Cabloy-level capability with strong backend implications.
12
+
13
+ ## Why this matters
14
+
15
+ Dynamic datasource selection affects:
16
+
17
+ - how model operations are routed
18
+ - how related queries are resolved
19
+ - how transactions and cache behavior should be coordinated
20
+ - how queue and distributed flows should remain datasource-safe
21
+ - how multi-tenant or multi-project data architectures can be organized
22
+
23
+ So this is not only an implementation tweak. It is part of the system architecture.
24
+
25
+ ## Do not confuse three different routing layers
26
+
27
+ A useful distinction is:
28
+
29
+ - **ordinary datasource selection** can live in model metadata or app config
30
+ - **isolated-instance routing** can change the effective default datasource through instance config such as `isolateClient` and is primarily explained in [Multi-Database and Datasource Guide](/backend/multi-database-datasource) together with [Multi-Instance and Instance Resolution](/backend/multi-instance-and-instance-resolution)
31
+ - **dynamic datasource** begins when the routing decision depends on runtime context that cannot be declared once up front
32
+
33
+ This distinction matters because many backend tasks do not actually need dynamic datasource.
34
+
35
+ ## When a task becomes truly dynamic
36
+
37
+ A practical rule is:
38
+
39
+ - static datasource choice can live in model metadata or app config
40
+ - relation-level datasource choice can live in relation metadata
41
+ - instance-sensitive default routing can live in instance config
42
+ - dynamic datasource begins when routing depends on live context beyond those declarative mechanisms
43
+
44
+ That helps avoid overusing dynamic datasource when ordinary datasource configuration is sufficient.
45
+
46
+ ## Guidance for contributors and AI workflows
47
+
48
+ When a task mentions dynamic datasource behavior, do not stop at ordinary model configuration.
49
+
50
+ Instead:
51
+
52
+ 1. identify whether the routing decision is static, relation-level, instance-sensitive, model-level, or truly dynamic
53
+ 2. inspect the Cabloy-level datasource architecture and source code
54
+ 3. verify whether transactions, cache, relation loading, and queue behavior still align with the datasource routing strategy
55
+ 4. confirm that instance isolation or app-config defaults are not already enough for the task
56
+
57
+ ## Relationship to the broader ORM family
58
+
59
+ Read this guide together with:
60
+
61
+ - [Config Guide](/backend/config-guide)
62
+ - [Model Guide](/backend/model-guide)
63
+ - [Multi-Database and Datasource Guide](/backend/multi-database-datasource)
64
+ - [Relations Guide](/backend/relations-guide)
65
+ - [Queue Guide](/backend/queue-guide)
66
+ - [Sharding Guide](/backend/sharding-guide)
67
+
68
+ ## Documentation placement rule
69
+
70
+ Keep this page as the backend-facing pointer, but treat the Cabloy-level dynamic-datasource material as the deeper source of truth.
@@ -0,0 +1,141 @@
1
+ # Election Guide
2
+
3
+ ## Why election matters
4
+
5
+ In a distributed backend, multiple worker processes may all be capable of running the same logic, but some responsibilities should be owned only by one worker or by a small fixed number of workers.
6
+
7
+ Vona provides election for exactly that scenario.
8
+
9
+ This matters when backend code needs to:
10
+
11
+ - start a standalone service
12
+ - own a leader-like runtime responsibility
13
+ - recover ownership automatically when a worker exits
14
+ - allow limited parallel ownership instead of full fan-out execution
15
+
16
+ ## Core election model
17
+
18
+ The election model works like this:
19
+
20
+ 1. workers compete to obtain ownership of a named resource
21
+ 2. one worker, or a configured number of workers, acquires that ownership
22
+ 3. only the worker that obtains ownership starts the protected logic
23
+ 4. if an owning worker exits, other workers compete again and ownership can move automatically
24
+
25
+ That makes election a coordination primitive, not just a boolean lock.
26
+
27
+ ## Create `meta.election`
28
+
29
+ Example: create `meta.election` in module `demo-student`.
30
+
31
+ ```bash
32
+ npm run vona :create:bean meta election -- --module=demo-student
33
+ ```
34
+
35
+ Representative definition:
36
+
37
+ ```typescript
38
+ export type TypeElectionObtainResource = 'echo';
39
+
40
+ @Meta()
41
+ export class MetaElection extends BeanElectionBase<TypeElectionObtainResource> {}
42
+ ```
43
+
44
+ The resource type expresses which logical resources can be competed for inside the module.
45
+
46
+ ## Obtain ownership from a module monkey
47
+
48
+ Election usually participates in backend lifecycle hooks rather than ordinary request handlers.
49
+
50
+ Representative pattern:
51
+
52
+ ```typescript
53
+ export class Monkey extends BeanSimple implements IMonkeyAppStarted {
54
+ async appStarted() {
55
+ const scope = this.app.scope(__ThisModule__);
56
+ scope.election.obtain(
57
+ 'echo',
58
+ () => {
59
+ // custom logic
60
+ },
61
+ async () => {
62
+ // cleanup
63
+ },
64
+ );
65
+ }
66
+ }
67
+ ```
68
+
69
+ A useful mental model is:
70
+
71
+ - `appStarted()` is where the backend decides to compete for ownership
72
+ - `obtain(...)` starts the owned logic only on the worker that wins
73
+ - the cleanup callback releases or cleans up local resources when ownership ends
74
+
75
+ ## Tickets: allow more than one owner
76
+
77
+ Sometimes one owner is too restrictive, but full broadcast fan-out is too broad.
78
+
79
+ In that case, election supports `tickets`:
80
+
81
+ ```typescript
82
+ scope.election.obtain(
83
+ 'echo',
84
+ () => {
85
+ // custom logic
86
+ },
87
+ async () => {
88
+ // cleanup
89
+ },
90
+ { tickets: 2 },
91
+ );
92
+ ```
93
+
94
+ A practical interpretation is:
95
+
96
+ - `tickets: 1` means one owner
97
+ - `tickets: 2` means two workers may own the same resource simultaneously
98
+
99
+ This makes election useful for limited parallel ownership patterns.
100
+
101
+ ## When to use election vs queue vs broadcast
102
+
103
+ Read this guide together with:
104
+
105
+ - [Backend Startup Guide](/backend/startup-guide)
106
+ - [Queue Guide](/backend/queue-guide)
107
+ - [Broadcast Guide](/backend/broadcast-guide)
108
+ - [Worker Guide](/backend/worker-guide)
109
+ - [Redlock Guide](/backend/redlock-guide)
110
+
111
+ A practical boundary is:
112
+
113
+ - use **election** when only one worker, or a fixed small number of workers, should own the responsibility
114
+ - use **queue** when work should be pushed asynchronously to background execution
115
+ - use **broadcast** when many workers should all receive the message
116
+
117
+ This distinction is important because these abstractions solve different distributed coordination problems.
118
+
119
+ ## Relationship to startup lifecycle
120
+
121
+ Election often starts from backend startup hooks.
122
+
123
+ That means a common pattern is:
124
+
125
+ 1. backend startup reaches `appStarted`
126
+ 2. the module competes for an election resource
127
+ 3. the winning worker starts the protected service or loop
128
+ 4. ownership can fail over to another worker if the current owner exits
129
+
130
+ So startup answers _when lifecycle hooks fire_, while election answers _which worker should own a singleton-like responsibility_.
131
+
132
+ ## Implementation checks for distributed-election changes
133
+
134
+ When editing distributed backend coordination, ask:
135
+
136
+ 1. is this really a singleton-like ownership problem?
137
+ 2. should one worker own the responsibility, or should there be multiple tickets?
138
+ 3. does the ownership logic belong in backend startup hooks rather than a request path?
139
+ 4. would queue or broadcast be the wrong abstraction for this job?
140
+
141
+ That helps AI choose election only when the underlying coordination problem truly matches it.