cabloy 5.1.50 → 5.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) 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 +288 -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 +29 -0
  17. package/.github/workflows/docs-pages.yml +54 -0
  18. package/.gitignore +1 -0
  19. package/CHANGELOG.md +29 -0
  20. package/CLAUDE.md +59 -0
  21. package/README.md +137 -0
  22. package/cabloy-docs/.vitepress/config.mjs +222 -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 +138 -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 +167 -0
  31. package/cabloy-docs/ai/edition-detection.md +30 -0
  32. package/cabloy-docs/ai/future-skill-roadmap.md +135 -0
  33. package/cabloy-docs/ai/global-bean-lookup.md +157 -0
  34. package/cabloy-docs/ai/introduction.md +62 -0
  35. package/cabloy-docs/ai/playbook-backend-module.md +111 -0
  36. package/cabloy-docs/ai/playbook-contract-regeneration.md +100 -0
  37. package/cabloy-docs/ai/playbook-frontend-page.md +99 -0
  38. package/cabloy-docs/ai/playbook-metadata-refresh.md +67 -0
  39. package/cabloy-docs/ai/repo-guidance.md +58 -0
  40. package/cabloy-docs/ai/rules-and-config.md +29 -0
  41. package/cabloy-docs/ai/skills.md +35 -0
  42. package/cabloy-docs/ai/verification.md +30 -0
  43. package/cabloy-docs/backend/aop-overview.md +128 -0
  44. package/cabloy-docs/backend/auth-guide.md +151 -0
  45. package/cabloy-docs/backend/backend-essentials.md +128 -0
  46. package/cabloy-docs/backend/broadcast-guide.md +138 -0
  47. package/cabloy-docs/backend/cache-guide.md +70 -0
  48. package/cabloy-docs/backend/captcha-guide.md +162 -0
  49. package/cabloy-docs/backend/cli.md +173 -0
  50. package/cabloy-docs/backend/config-guide.md +249 -0
  51. package/cabloy-docs/backend/controller-aop-guide.md +270 -0
  52. package/cabloy-docs/backend/controller-guide.md +347 -0
  53. package/cabloy-docs/backend/crud-workflow.md +118 -0
  54. package/cabloy-docs/backend/dto-guide.md +161 -0
  55. package/cabloy-docs/backend/dto-infer-generation.md +153 -0
  56. package/cabloy-docs/backend/dynamic-datasource-guide.md +70 -0
  57. package/cabloy-docs/backend/election-guide.md +141 -0
  58. package/cabloy-docs/backend/entity-guide.md +150 -0
  59. package/cabloy-docs/backend/error-guide.md +108 -0
  60. package/cabloy-docs/backend/event-guide.md +183 -0
  61. package/cabloy-docs/backend/external-aop-guide.md +149 -0
  62. package/cabloy-docs/backend/field-indexes.md +79 -0
  63. package/cabloy-docs/backend/foundation.md +281 -0
  64. package/cabloy-docs/backend/i18n-guide.md +211 -0
  65. package/cabloy-docs/backend/internal-aop-guide.md +181 -0
  66. package/cabloy-docs/backend/introduction.md +95 -0
  67. package/cabloy-docs/backend/jwt-guide.md +276 -0
  68. package/cabloy-docs/backend/logger-guide.md +223 -0
  69. package/cabloy-docs/backend/mail-guide.md +189 -0
  70. package/cabloy-docs/backend/menu-guide.md +80 -0
  71. package/cabloy-docs/backend/migration-and-changes.md +192 -0
  72. package/cabloy-docs/backend/model-guide.md +274 -0
  73. package/cabloy-docs/backend/multi-database-datasource.md +171 -0
  74. package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +196 -0
  75. package/cabloy-docs/backend/openapi-guide.md +118 -0
  76. package/cabloy-docs/backend/orm-aggregate-group-guide.md +210 -0
  77. package/cabloy-docs/backend/orm-configuration-guide.md +165 -0
  78. package/cabloy-docs/backend/orm-guide.md +109 -0
  79. package/cabloy-docs/backend/orm-mutation-guide.md +195 -0
  80. package/cabloy-docs/backend/orm-select-guide.md +243 -0
  81. package/cabloy-docs/backend/queue-guide.md +271 -0
  82. package/cabloy-docs/backend/quickstart.md +141 -0
  83. package/cabloy-docs/backend/redis-guide.md +70 -0
  84. package/cabloy-docs/backend/redlock-guide.md +60 -0
  85. package/cabloy-docs/backend/relations-guide.md +250 -0
  86. package/cabloy-docs/backend/runtime-and-flavors.md +304 -0
  87. package/cabloy-docs/backend/schedule-guide.md +81 -0
  88. package/cabloy-docs/backend/scripts.md +116 -0
  89. package/cabloy-docs/backend/serialization-guide.md +192 -0
  90. package/cabloy-docs/backend/service-guide.md +166 -0
  91. package/cabloy-docs/backend/sharding-guide.md +49 -0
  92. package/cabloy-docs/backend/startup-guide.md +326 -0
  93. package/cabloy-docs/backend/transaction-guide.md +82 -0
  94. package/cabloy-docs/backend/unit-testing.md +209 -0
  95. package/cabloy-docs/backend/upload-guide.md +160 -0
  96. package/cabloy-docs/backend/user-access-guide.md +157 -0
  97. package/cabloy-docs/backend/validation-guide.md +80 -0
  98. package/cabloy-docs/backend/worker-guide.md +59 -0
  99. package/cabloy-docs/editions/cabloy-basic.md +25 -0
  100. package/cabloy-docs/editions/cabloy-start.md +24 -0
  101. package/cabloy-docs/editions/detection.md +31 -0
  102. package/cabloy-docs/editions/overview.md +44 -0
  103. package/cabloy-docs/frontend/api-guide.md +93 -0
  104. package/cabloy-docs/frontend/api-schema-guide.md +43 -0
  105. package/cabloy-docs/frontend/app-startup-guide.md +185 -0
  106. package/cabloy-docs/frontend/cli.md +78 -0
  107. package/cabloy-docs/frontend/component-guide.md +105 -0
  108. package/cabloy-docs/frontend/component-props-guide.md +97 -0
  109. package/cabloy-docs/frontend/component-v-model-guide.md +110 -0
  110. package/cabloy-docs/frontend/css-in-js-guide.md +151 -0
  111. package/cabloy-docs/frontend/design-principles.md +55 -0
  112. package/cabloy-docs/frontend/environment-config-guide.md +250 -0
  113. package/cabloy-docs/frontend/foundation.md +57 -0
  114. package/cabloy-docs/frontend/generic-component-guide.md +35 -0
  115. package/cabloy-docs/frontend/icon-engine-guide.md +88 -0
  116. package/cabloy-docs/frontend/introduction.md +32 -0
  117. package/cabloy-docs/frontend/ioc-and-beans.md +211 -0
  118. package/cabloy-docs/frontend/mock-guide.md +109 -0
  119. package/cabloy-docs/frontend/model-architecture.md +87 -0
  120. package/cabloy-docs/frontend/model-state-guide.md +70 -0
  121. package/cabloy-docs/frontend/module-scope.md +168 -0
  122. package/cabloy-docs/frontend/modules-and-suites.md +179 -0
  123. package/cabloy-docs/frontend/navigation-guards-guide.md +68 -0
  124. package/cabloy-docs/frontend/openapi-sdk-guide.md +102 -0
  125. package/cabloy-docs/frontend/page-guide.md +223 -0
  126. package/cabloy-docs/frontend/page-params-guide.md +87 -0
  127. package/cabloy-docs/frontend/page-query-guide.md +96 -0
  128. package/cabloy-docs/frontend/page-route-guide.md +147 -0
  129. package/cabloy-docs/frontend/quickstart.md +201 -0
  130. package/cabloy-docs/frontend/route-alias-guide.md +61 -0
  131. package/cabloy-docs/frontend/scripts.md +86 -0
  132. package/cabloy-docs/frontend/sdk-guide.md +45 -0
  133. package/cabloy-docs/frontend/server-data.md +74 -0
  134. package/cabloy-docs/frontend/ssr-client-only.md +40 -0
  135. package/cabloy-docs/frontend/ssr-env.md +51 -0
  136. package/cabloy-docs/frontend/ssr-init-data.md +46 -0
  137. package/cabloy-docs/frontend/ssr-overview.md +48 -0
  138. package/cabloy-docs/frontend/ssr-seo-meta.md +52 -0
  139. package/cabloy-docs/frontend/system-startup-guide.md +186 -0
  140. package/cabloy-docs/frontend/theme-guide.md +154 -0
  141. package/cabloy-docs/frontend/zod-guide.md +161 -0
  142. package/cabloy-docs/fullstack/edition-collaboration-differences.md +61 -0
  143. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +64 -0
  144. package/cabloy-docs/fullstack/introduction.md +69 -0
  145. package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -0
  146. package/cabloy-docs/fullstack/quickstart.md +86 -0
  147. package/cabloy-docs/fullstack/vona-zova-integration.md +86 -0
  148. package/cabloy-docs/index.md +73 -0
  149. package/cabloy-docs/package.json +16 -0
  150. package/cabloy-docs/pnpm-lock.yaml +1607 -0
  151. package/cabloy-docs/reference/backend-directory-structure.md +88 -0
  152. package/cabloy-docs/reference/cli-reference.md +49 -0
  153. package/cabloy-docs/reference/glossary.md +38 -0
  154. package/cabloy-docs/reference/package-map.md +105 -0
  155. package/cabloy-docs/reference/repo-scripts.md +36 -0
  156. package/package.json +4 -1
  157. package/scripts/init.ts +12 -0
  158. package/scripts/upgrade.ts +31 -3
  159. package/vona/README.md +3 -3
  160. package/vona/README.zh-CN.md +4 -4
  161. package/vona/packages-vona/vona/package.json +1 -1
  162. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/package.json +1 -1
  163. package/vona/src/suite-vendor/a-cabloy/modules/a-datasharding/src/bean/summerCache.datasourceWrite.ts +2 -2
  164. package/vona/src/suite-vendor/a-cabloy/package.json +1 -1
  165. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
  166. package/vona/src/suite-vendor/a-captcha/modules/a-captcha/src/bean/cacheRedis.captcha.ts +2 -2
  167. package/vona/src/suite-vendor/a-captcha/package.json +1 -1
  168. package/vona/src/suite-vendor/a-vona/modules/a-bean/cli/bean/metadata/generate.ts +5 -6
  169. package/vona/src/suite-vendor/a-vona/modules/a-bean/package.json +1 -1
  170. package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheMem/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  171. package/vona/src/suite-vendor/a-vona/modules/a-cache/cli/cacheRedis/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  172. package/vona/src/suite-vendor/a-vona/modules/a-cache/package.json +1 -1
  173. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/.metadata/index.ts +13 -2
  174. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/bean/bean.cache.ts +6 -7
  175. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheMemBase.ts → service/cacheMemBase_.ts} +3 -3
  176. package/vona/src/suite-vendor/a-vona/modules/a-cache/src/{bean/bean.cacheRedisBase.ts → service/cacheRedisBase_.ts} +3 -3
  177. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/package.json +1 -1
  178. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.emailConfirm.ts +2 -2
  179. package/vona/src/suite-vendor/a-vona/modules/a-mailconfirm/src/bean/cacheRedis.passwordReset.ts +2 -2
  180. package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
  181. package/vona/src/suite-vendor/a-vona/modules/a-openapi/src/bean/summerCache.json.ts +2 -2
  182. package/vona/src/suite-vendor/a-vona/modules/a-orm/cli/databaseDialect/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  183. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  184. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +4 -3
  185. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.database.ts +3 -3
  186. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/bean.model.ts +1 -1
  187. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/bean/schedule.softDeletionPrune.ts +1 -1
  188. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/common/utils.ts +1 -1
  189. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/index.ts +1 -1
  190. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_cache.ts +1 -1
  191. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_meta.ts +1 -1
  192. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.modelBase.ts +0 -5
  193. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAggregate.ts +1 -1
  194. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoCreate.ts +1 -1
  195. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +1 -1
  196. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGroup.ts +1 -1
  197. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoMutate.ts +1 -1
  198. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoSelectAndCount.ts +1 -1
  199. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoUpdate.ts +1 -1
  200. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/index.ts +1 -0
  201. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/modelCacheBase.ts +3 -3
  202. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relations.ts +1 -1
  203. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsDynamic.ts +1 -1
  204. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsMutate.ts +1 -1
  205. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/relationsStatic.ts +1 -1
  206. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheEntity_.ts +1 -1
  207. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/cacheQuery_.ts +1 -1
  208. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/database.ts +2 -2
  209. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean/bean.databaseDialectBase.ts → service/databaseDialectBase_.ts} +38 -41
  210. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/db_.ts +2 -2
  211. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/relations_.ts +3 -3
  212. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/database.ts +0 -5
  213. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoGet.ts +1 -1
  214. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoMutate.ts +1 -1
  215. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/dto/dtoSelectAndCount.ts +1 -1
  216. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/model.ts +1 -1
  217. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelAggr.ts +1 -1
  218. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelCount.ts +1 -1
  219. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGeneral.ts +1 -1
  220. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelGroup.ts +1 -1
  221. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/modelIncrement.ts +1 -1
  222. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relations.ts +1 -1
  223. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsColumns.ts +1 -1
  224. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDef.ts +1 -1
  225. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefDynamic.ts +1 -1
  226. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsDefMutate.ts +1 -1
  227. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsMutate.ts +1 -1
  228. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsTables.ts +1 -1
  229. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
  230. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.betterSqlite3.ts +2 -2
  231. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +2 -2
  232. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.pg.ts +2 -2
  233. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  234. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +109 -40
  235. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permission.ts +2 -2
  236. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  237. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/bean/cacheRedis.startupDebounce.ts +2 -2
  238. package/vona/src/suite-vendor/a-vona/modules/a-summer/cli/boilerplate/{{sceneName}}.{{beanName}}.ts_ +2 -2
  239. package/vona/src/suite-vendor/a-vona/modules/a-summer/package.json +1 -1
  240. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/.metadata/index.ts +1 -1
  241. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/bean/bean.summer.ts +3 -3
  242. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localMem_.ts +3 -3
  243. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/service/localRedis_.ts +3 -3
  244. package/vona/src/suite-vendor/a-vona/modules/a-summer/src/{bean/bean.summerCacheBase.ts → service/summerCacheBase_.ts} +3 -3
  245. package/vona/src/suite-vendor/a-vona/modules/a-swagger/package.json +1 -1
  246. package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.rapidoc.ts +2 -2
  247. package/vona/src/suite-vendor/a-vona/modules/a-swagger/src/bean/summerCache.swagger.ts +2 -2
  248. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  249. package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/cacheRedis.authToken.ts +2 -2
  250. package/vona/src/suite-vendor/a-vona/modules/a-worker/package.json +1 -1
  251. package/vona/src/suite-vendor/a-vona/modules/a-worker/src/bean/cacheRedis.workerAlive.ts +2 -2
  252. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  253. package/zova/README.md +4 -4
  254. package/zova/README.zh-CN.md +4 -4
  255. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud.ts +0 -0
  256. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_inner.ts +0 -0
  257. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_crud_table.ts +0 -0
  258. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_knex.ts +0 -0
  259. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_utils.ts +0 -0
  260. /package/vona/src/suite-vendor/a-vona/modules/a-orm/src/{bean → lib}/bean.model/bean.model_view.ts +0 -0
@@ -0,0 +1,274 @@
1
+ # Model Guide
2
+
3
+ This guide explains how models work in Vona within the Cabloy monorepo.
4
+
5
+ ## Why models matter in the backend contract loop
6
+
7
+ Models are the persistence-facing layer of the backend contract loop.
8
+
9
+ A useful split is:
10
+
11
+ - controllers define HTTP-facing contracts
12
+ - services orchestrate business flow
13
+ - models own ORM-facing persistence behavior
14
+ - entities and DTOs shape the data contract around that behavior
15
+
16
+ That means model design affects not only SQL behavior, but also CRUD defaults, DTO assumptions, OpenAPI-facing contracts, and test setup.
17
+
18
+ ## Create a model
19
+
20
+ Example: create a model named `student` in module `demo-student`.
21
+
22
+ ```bash
23
+ npm run vona :create:bean model student -- --module=demo-student
24
+ ```
25
+
26
+ ## Model definition
27
+
28
+ Representative pattern:
29
+
30
+ ```typescript
31
+ import { BeanModelBase, Model } from 'vona-module-a-orm';
32
+ import { EntityStudent } from '../entity/student.ts';
33
+
34
+ @Model({ entity: EntityStudent })
35
+ export class ModelStudent extends BeanModelBase<EntityStudent> {}
36
+ ```
37
+
38
+ The key relationship is that a model is bound to an entity and exposes ORM-oriented operations for that entity.
39
+
40
+ ## Using a model
41
+
42
+ Using models in Vona supports both dependency injection and dependency lookup, but dependency lookup is usually the clearer default.
43
+
44
+ ### Lookup in the current module
45
+
46
+ ```typescript
47
+ class ServiceStudent {
48
+ async findAll(): Promise<EntityStudent[]> {
49
+ return await this.scope.model.student.select();
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Lookup across modules
55
+
56
+ ```typescript
57
+ class ServiceStudent {
58
+ async findAll(): Promise<EntityStudent[]> {
59
+ return await this.$scope.demoStudent.model.student.select();
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Direct container access
65
+
66
+ ```typescript
67
+ class ServiceStudent {
68
+ async findAll(): Promise<EntityStudent[]> {
69
+ return await this.bean._getBean('demo-student.model.student').select();
70
+ }
71
+ }
72
+ ```
73
+
74
+ This is one of the important backend layer boundaries:
75
+
76
+ - services should usually orchestrate through models
77
+ - models should remain the main persistence-facing abstraction instead of bypassing directly to ad hoc SQL everywhere
78
+
79
+ ## Basic CRUD patterns
80
+
81
+ ### Create
82
+
83
+ ```typescript
84
+ return await this.scope.model.student.insert(student);
85
+ ```
86
+
87
+ ### Read
88
+
89
+ ```typescript
90
+ return await this.scope.model.student.select();
91
+ return await this.scope.model.student.getById(id);
92
+ ```
93
+
94
+ ### Update
95
+
96
+ ```typescript
97
+ return await this.scope.model.student.updateById(id, student);
98
+ ```
99
+
100
+ ### Delete
101
+
102
+ ```typescript
103
+ return await this.scope.model.student.deleteById(id);
104
+ ```
105
+
106
+ These methods are also part of the generated CRUD thread; see [CRUD Workflow](/backend/crud-workflow).
107
+
108
+ ## Query-builder support
109
+
110
+ Vona models are built on Knex, so the model layer also supports lower-level query builder access when needed.
111
+
112
+ Representative patterns:
113
+
114
+ ```typescript
115
+ this.scope.model.student.builder().where('name', 'tom').orderBy('name');
116
+ this.scope.model.student.builderSelect().where('name', 'tom').orderBy('name');
117
+ this.scope.model.student.query('select * from demoStudent');
118
+ ```
119
+
120
+ A practical rule is:
121
+
122
+ - prefer model methods and model-aware query paths first
123
+ - use builder or raw SQL only when the higher-level model surface is not enough
124
+
125
+ ## Important model options
126
+
127
+ Several important model options include:
128
+
129
+ - `entity`
130
+ - `table`
131
+ - `disableDeleted`
132
+ - `disableInstance`
133
+ - `disableCreateTime`
134
+ - `disableUpdateTime`
135
+ - `softDeletionPrune`
136
+ - `client`
137
+ - `cache`
138
+ - `relations`
139
+
140
+ These options matter because Vona models are not only raw database adapters. They also carry framework-level behavior such as soft deletion, multi-instance support, datasource selection, caching, and relations.
141
+
142
+ ## App-config overrides
143
+
144
+ Model options can also be configured in app config.
145
+
146
+ Representative pattern:
147
+
148
+ ```typescript
149
+ config.onions = {
150
+ model: {
151
+ 'demo-student:student': {
152
+ disableDeleted: true,
153
+ disableInstance: true,
154
+ client: 'mysql',
155
+ cache: false,
156
+ },
157
+ },
158
+ };
159
+ ```
160
+
161
+ This is one of the key contract-loop ideas: model behavior is not defined only inside the model file. It can also be refined through project configuration.
162
+
163
+ ## Dynamic table partitioning
164
+
165
+ Model supports dynamic table partitioning.
166
+
167
+ Representative pattern:
168
+
169
+ ```typescript
170
+ @Model({
171
+ table: (ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) => {
172
+ return `${defaultTable}_${moment().format('YYYYMMDD')}`;
173
+ },
174
+ })
175
+ class ModelOrder {}
176
+ ```
177
+
178
+ This matters because some persistence decisions belong at the model abstraction level even when they materially change how the table is resolved.
179
+
180
+ ## Soft deletion and multi-instance defaults
181
+
182
+ By default, Vona models support:
183
+
184
+ - soft deletion
185
+ - multi-instance or multi-tenancy filtering
186
+
187
+ That means model behavior can be richer than a naïve SQL wrapper. For example, a normal `select()` already participates in instance filtering and deleted-record filtering unless configured otherwise.
188
+
189
+ A practical implication is:
190
+
191
+ - contract and test behavior should not assume raw-table semantics when the model layer is active
192
+
193
+ ## Instance-aware model semantics
194
+
195
+ One important current-runtime distinction is that ordinary model usage is instance-aware by default.
196
+
197
+ A practical interpretation is:
198
+
199
+ - normal model operations participate in the current instance context
200
+ - instance-aware filtering is part of normal model behavior unless disabled
201
+ - request-scoped code should usually preserve that behavior instead of bypassing it casually
202
+
203
+ This is why `disableInstance` is a meaningful semantic choice rather than a minor ORM toggle.
204
+
205
+ Use it only when the model truly should ignore the active instance boundary.
206
+
207
+ Another practical implication is:
208
+
209
+ - lower-level builder or raw-SQL flows may need extra care when you are reproducing behavior that the ordinary model path would have applied automatically
210
+
211
+ For the broader instance/config story, also see [Config Guide](/backend/config-guide).
212
+
213
+ ## Datasource selection
214
+
215
+ Vona supports `multi-database` and `multi-datasource` behavior at the model layer.
216
+
217
+ Representative modes include:
218
+
219
+ - default datasource
220
+ - static datasource in model options
221
+ - app-config datasource override
222
+ - adaptive datasource through a function
223
+ - dynamic datasource chosen in code with `newInstance(...)`
224
+
225
+ Representative dynamic pattern:
226
+
227
+ ```typescript
228
+ const modelMysql = this.scope.model.student.newInstance('mysql');
229
+ return await modelMysql.select();
230
+ ```
231
+
232
+ This matters because backend contract behavior can depend on datasource choice, not just on query shape.
233
+
234
+ In the current runtime, datasource choice can also change indirectly through instance isolation. If the active instance is configured as isolated, the effective default datasource may switch through that instance’s `isolateClient` setting even when the calling code did not name a datasource explicitly.
235
+
236
+ That is why model behavior should be read together with:
237
+
238
+ - [Config Guide](/backend/config-guide)
239
+ - [Multi-Database and Datasource Guide](/backend/multi-database-datasource)
240
+
241
+ ## Cache behavior
242
+
243
+ Vona models enable cache behavior by default.
244
+
245
+ A practical distinction is:
246
+
247
+ - entity cache stores entity records
248
+ - query cache stores query-derived entity id sets
249
+
250
+ That means model behavior affects performance and consistency semantics, not only data retrieval.
251
+
252
+ For the broader cache story, also see [Cache Guide](/backend/cache-guide).
253
+
254
+ ## Relationship to the backend contract loop
255
+
256
+ Read this guide together with:
257
+
258
+ - [Service Guide](/backend/service-guide)
259
+ - [Entity Guide](/backend/entity-guide)
260
+ - [DTO Guide](/backend/dto-guide)
261
+ - [OpenAPI Guide](/backend/openapi-guide)
262
+ - [CRUD Workflow](/backend/crud-workflow)
263
+ - [Migration and Changes](/backend/migration-and-changes)
264
+
265
+ ## Implementation checks for model-layer changes
266
+
267
+ When creating backend persistence logic:
268
+
269
+ 1. start from the model and entity pairing
270
+ 2. prefer model methods and model-aware query paths
271
+ 3. preserve Vona soft-delete and instance-aware behavior unless there is a real reason not to
272
+ 4. choose deliberately among local scope, cross-module scope, and direct bean access
273
+ 5. remember that datasource, cache, and model options can change the behavior of the backend contract loop
274
+ 6. drop to raw SQL or lower-level query builder logic only when the higher-level model surface is insufficient
@@ -0,0 +1,171 @@
1
+ # Multi-Database and Datasource Guide
2
+
3
+ This guide explains how multi-database and multi-datasource support works in Vona within the Cabloy monorepo.
4
+
5
+ ## Why this matters
6
+
7
+ Vona ORM is designed for business systems that may need:
8
+
9
+ - multiple database engines
10
+ - multiple datasources
11
+ - cross-datasource relation queries
12
+ - datasource-aware topology decisions
13
+ - isolated-instance database routing
14
+
15
+ This is an important part of the framework’s large-system positioning.
16
+
17
+ ## Core model
18
+
19
+ A representative example uses related models such as `User` and `Order`.
20
+
21
+ The key idea is that model relations can remain meaningful even when the participating data lives on different datasources.
22
+
23
+ ## Datasource setup
24
+
25
+ Three important pieces define the datasource setup:
26
+
27
+ 1. datasource type definitions
28
+ 2. datasource configuration in app config
29
+ 3. model or relation-level selection of which datasource to use
30
+
31
+ That means datasource choice is part of the typed application model, not just a hidden runtime string.
32
+
33
+ ## Default datasource selection
34
+
35
+ In the current runtime, ordinary datasource selection starts from `config.database.defaultClient`.
36
+
37
+ A practical order is:
38
+
39
+ 1. use the explicitly requested datasource when one is provided
40
+ 2. otherwise fall back to the configured default datasource
41
+ 3. if the current instance is isolated, allow the instance’s `isolateClient` to override the ordinary default
42
+
43
+ This is why datasource selection belongs partly to config and partly to request/runtime context.
44
+
45
+ ## Explicit client selection
46
+
47
+ One pattern is to create a model instance bound to a chosen datasource dynamically.
48
+
49
+ Representative pattern:
50
+
51
+ ```typescript
52
+ const modelMysql = this.scope.model.student.newInstance('mysql');
53
+ return await modelMysql.select();
54
+ ```
55
+
56
+ This is useful when the decision is explicit in business logic rather than implied by config defaults.
57
+
58
+ ## Model-level, relation-level, and app-config-level defaults
59
+
60
+ You can simplify ordinary usage by declaring datasource choices in:
61
+
62
+ - model options
63
+ - relation options
64
+ - app config
65
+
66
+ That reduces repeated dynamic selection in ordinary business code.
67
+
68
+ A practical distinction is:
69
+
70
+ - use model or app-config defaults when one datasource should usually win
71
+ - use relation metadata when different parts of a graph need different datasources
72
+ - use explicit runtime selection when the current task truly needs to choose in code
73
+
74
+ ## Ordinary multi-datasource behavior vs isolated-instance routing
75
+
76
+ One of the most important backend distinctions is:
77
+
78
+ - **ordinary multi-datasource behavior** chooses among datasources for business or topology reasons
79
+ - **isolated-instance routing** changes the effective default datasource because the active instance is configured as isolated
80
+
81
+ In the current repo, an isolated instance can declare:
82
+
83
+ - `isolate: true`
84
+ - `isolateClient: 'isolateTest'`
85
+
86
+ That means a request can remain model-native while still landing on a different default datasource because of instance configuration.
87
+
88
+ ## Instance-aware database strategy
89
+
90
+ This matters because backend database strategy is not only about choosing MySQL vs PostgreSQL vs Sqlite3.
91
+
92
+ It is also about deciding whether:
93
+
94
+ - all instances share one datasource layout
95
+ - some instances share data while others isolate storage
96
+ - a test or tenant-specific instance should use a dedicated client
97
+
98
+ A practical example in the current repo is the `isolateTest` client used together with an isolated test instance.
99
+
100
+ ## Concrete isolated datasource pattern in this repo
101
+
102
+ In the current app config, `isolateTest` is created by cloning the currently selected default client into a dedicated isolated client slot.
103
+
104
+ That pattern matters because it shows that isolated-instance routing does not require a completely separate datasource architecture from day one. It can start from the ordinary default client and then create an isolated variant for instance-aware routing.
105
+
106
+ A practical runtime split in the current repo is:
107
+
108
+ - base config defines `isolateTest` from the current default client
109
+ - dev/test config enables an isolated instance that points at `isolateClient: 'isolateTest'`
110
+ - prod config can explicitly unset `isolateTest` when that isolated test-oriented client should not remain active
111
+
112
+ ## Relation-level datasource selection
113
+
114
+ Relation options can also specify datasource metadata.
115
+
116
+ That matters because different parts of a related object graph may need different datasource bindings.
117
+
118
+ ## Datasource levels and execution isolation
119
+
120
+ Datasource architecture is not only about routing to the right database. It is also about isolation across execution contexts.
121
+
122
+ In distributed flows such as `pushAsync`, Vona can move work to a higher datasource level so background execution does not contend with the current request context for the same constrained connection pool.
123
+
124
+ That is why datasource design should be read together with:
125
+
126
+ - queue behavior
127
+ - transaction behavior
128
+ - relation loading
129
+ - runtime and distributed execution patterns
130
+
131
+ ## Topology guidance
132
+
133
+ A practical way to think about topology is:
134
+
135
+ - use ordinary datasource selection for routine multi-datasource routing
136
+ - use isolated-instance config when the default database route should vary by instance
137
+ - use relation metadata when cross-datasource object graphs must still feel model-native
138
+ - use explicit runtime selection when business flow must choose a datasource directly
139
+ - escalate to sharding or deeper Cabloy architecture when the problem is no longer just datasource choice but data-distribution design
140
+
141
+ ## Relationship to config, model, and dynamic datasource
142
+
143
+ Read this guide together with:
144
+
145
+ - [Config Guide](/backend/config-guide)
146
+ - [Runtime and Flavors](/backend/runtime-and-flavors)
147
+ - [Model Guide](/backend/model-guide)
148
+ - [Dynamic Datasource Guide](/backend/dynamic-datasource-guide)
149
+ - [Sharding Guide](/backend/sharding-guide)
150
+ - [Queue Guide](/backend/queue-guide)
151
+ - [Relations Guide](/backend/relations-guide)
152
+
153
+ A practical split is:
154
+
155
+ - this guide explains ordinary multi-database and multi-datasource behavior
156
+ - config and instance docs explain why the effective default may differ by runtime or instance
157
+ - the dynamic datasource guide points to deeper routing architecture
158
+ - the sharding guide points to deeper data-distribution architecture
159
+
160
+ ## Implementation checks for multi-datasource changes
161
+
162
+ When changing backend data flow in a multi-datasource system, ask:
163
+
164
+ 1. is the model using an explicit datasource, a model default, or the current effective default datasource?
165
+ 2. does the active instance change that default through `isolateClient`?
166
+ 3. do related models need different datasource bindings?
167
+ 4. should the datasource choice live in runtime logic, relation metadata, model metadata, or app config?
168
+ 5. does the transaction, queue, or cache path need to match the same datasource choice?
169
+ 6. is the problem still ordinary datasource routing, or has it become a dynamic-datasource or sharding concern?
170
+
171
+ That keeps multi-datasource logic coherent instead of fragile.
@@ -0,0 +1,196 @@
1
+ # Multi-Instance and Instance Resolution
2
+
3
+ This guide explains how multi-instance behavior works in Vona within the Cabloy monorepo.
4
+
5
+ ## Why this matters
6
+
7
+ In Vona, backend runtime behavior is not always global-only.
8
+
9
+ A backend application may need:
10
+
11
+ - a shared default instance
12
+ - named instances for tenant-like separation
13
+ - isolated instances with their own datasource routing
14
+ - instance-aware config, startup, and model behavior
15
+
16
+ That is why multi-instance behavior should be understood as part of the backend runtime/config family, not only as an ORM detail.
17
+
18
+ ## Three practical layers
19
+
20
+ A useful mental model is:
21
+
22
+ - runtime and config decide how instances are declared
23
+ - request context decides which instance is active
24
+ - model and datasource behavior decide how that instance affects persistence
25
+
26
+ ## Instance config shape
27
+
28
+ In the current runtime, instance behavior is configured under `config.instance`.
29
+
30
+ Representative shape:
31
+
32
+ ```typescript
33
+ config.instance = {
34
+ getInstanceName: undefined,
35
+ queryField: $protocolKey('x-vona-instance-name'),
36
+ headerField: $protocolKey('x-vona-instance-name'),
37
+ instances: {
38
+ '': { password: '', title: '' },
39
+ 'shareTest': { password: '', title: '' },
40
+ 'isolateTest': {
41
+ password: '',
42
+ title: '',
43
+ id: 1000,
44
+ isolate: true,
45
+ isolateClient: 'isolateTest',
46
+ },
47
+ },
48
+ };
49
+ ```
50
+
51
+ The important fields are:
52
+
53
+ - `getInstanceName`
54
+ - `queryField`
55
+ - `headerField`
56
+ - `instances`
57
+ - per-instance options such as `id`, `isolate`, `isolateClient`, and `config`
58
+
59
+ ## Shared instance vs isolated instance
60
+
61
+ A practical distinction is:
62
+
63
+ - a **shared** instance participates in the normal shared datasource strategy
64
+ - an **isolated** instance can route to its own datasource through `isolateClient`
65
+
66
+ This means multi-instance behavior is not only a naming concern. It can materially change which database path the backend uses.
67
+
68
+ ## How the active instance name is resolved
69
+
70
+ In the current runtime, the instance name is resolved in this order:
71
+
72
+ 1. `getInstanceName(ctx)` if provided
73
+ 2. the configured query field
74
+ 3. the configured header field
75
+ 4. subdomain-derived instance name
76
+
77
+ This matters because request routing, config, and datasource behavior may all depend on the resolved instance name.
78
+
79
+ A special case is also supported:
80
+
81
+ - `'null'` is normalized to `null`
82
+
83
+ A practical fallback rule is:
84
+
85
+ - subdomain-based instance resolution only becomes relevant if custom getter, query-field, and header-field resolution did not already determine the instance name
86
+
87
+ ## Instance edge cases to remember
88
+
89
+ A few current-runtime edge cases are worth remembering:
90
+
91
+ - disabled instances can be declared with `false`
92
+ - isolated instances require an explicit `id`
93
+ - instance-name resolution is cached on the current context once determined
94
+ - the instance record can be created or refreshed through the instance service before the effective config is cached
95
+
96
+ ## What context exposes
97
+
98
+ Once instance resolution is active, the request context can expose:
99
+
100
+ - `ctx.instanceName`
101
+ - `ctx.instance`
102
+ - `ctx.config`
103
+
104
+ A practical distinction is:
105
+
106
+ - `ctx.instanceName` identifies the active instance
107
+ - `ctx.instance` is the loaded instance record
108
+ - `ctx.config` is the effective config merged for that instance-aware context
109
+
110
+ That means request-scoped backend code can stay instance-aware without manually reassembling config or routing rules.
111
+
112
+ ## How instance config affects effective backend config
113
+
114
+ This page owns the request-context and instance-aware merge view. For env-file precedence and mode/flavor selection, see [Runtime and Flavors](/backend/runtime-and-flavors). For the broader config-layering surface, see [Config Guide](/backend/config-guide).
115
+
116
+ In the current runtime, instance-aware config is built by merging:
117
+
118
+ 1. `app.config`
119
+ 2. static config under `config.instance.instances[instanceName].config`
120
+ 3. any persisted config stored on the instance record
121
+
122
+ This is why instance behavior belongs partly to config docs and partly to runtime docs.
123
+
124
+ A practical merge-order mental model is:
125
+
126
+ 1. start from `app.config`
127
+ 2. merge static instance config from `config.instance.instances[instanceName].config`
128
+ 3. merge persisted config stored on the instance record
129
+ 4. expose the result through `ctx.config`
130
+
131
+ For the broader config-layering story, also see [Config Guide](/backend/config-guide).
132
+
133
+ ## How instance affects startup behavior
134
+
135
+ Startup is also instance-aware.
136
+
137
+ A practical split is:
138
+
139
+ - app startup handles backend-wide initialization
140
+ - instance startup handles per-instance initialization after the app is ready for instances
141
+
142
+ In the current runtime:
143
+
144
+ - `test` and `dev` eagerly start the default instance
145
+ - production-style flows iterate configured static instances
146
+ - instance startup work is queued and coordinated so one instance can initialize cleanly
147
+
148
+ For the lifecycle view, also see [Backend Startup Guide](/backend/startup-guide).
149
+
150
+ ## How instance affects datasource selection
151
+
152
+ One of the most important multi-instance consequences is datasource routing.
153
+
154
+ In the current runtime, datasource selection can work like this:
155
+
156
+ 1. use an explicit datasource when code names one
157
+ 2. otherwise use the configured default datasource
158
+ 3. if the active instance is isolated, let `isolateClient` override that default
159
+
160
+ This is why instance isolation should be understood together with datasource strategy rather than documented as an unrelated feature.
161
+
162
+ For the datasource view, also see [Multi-Database and Datasource Guide](/backend/multi-database-datasource).
163
+
164
+ ## How instance affects model behavior
165
+
166
+ Ordinary model operations are instance-aware by default.
167
+
168
+ That means:
169
+
170
+ - normal model flows participate in instance filtering
171
+ - instance-aware config and startup can influence model behavior indirectly
172
+ - `disableInstance` changes semantics and should be used deliberately
173
+
174
+ For the model-layer perspective, also see [Model Guide](/backend/model-guide).
175
+
176
+ ## Relationship to runtime and config docs
177
+
178
+ Read this guide together with:
179
+
180
+ - [Runtime and Flavors](/backend/runtime-and-flavors)
181
+ - [Config Guide](/backend/config-guide)
182
+ - [Backend Startup Guide](/backend/startup-guide)
183
+ - [Model Guide](/backend/model-guide)
184
+ - [Multi-Database and Datasource Guide](/backend/multi-database-datasource)
185
+
186
+ ## Implementation checks for instance-resolution changes
187
+
188
+ When editing backend runtime, datasource, or tenant-like behavior, ask:
189
+
190
+ 1. how is the current instance name resolved?
191
+ 2. is the task about shared-instance behavior or isolated-instance behavior?
192
+ 3. should the logic read `app.config` or `ctx.config`?
193
+ 4. does instance startup or instance config need to change as well?
194
+ 5. does datasource routing change indirectly through `isolateClient` even if no model call names a client explicitly?
195
+
196
+ That keeps multi-instance behavior aligned with the current Vona runtime rather than treating it as a loose convention.