cabloy 5.1.61 → 5.1.63

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 (230) hide show
  1. package/.claude/skills/cabloy-backend-scaffold/SKILL.md +2 -0
  2. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +1 -1
  3. package/.claude/skills/cabloy-domain-planning/SKILL.md +212 -0
  4. package/.claude/skills/cabloy-frontend-scaffold/SKILL.md +2 -0
  5. package/CHANGELOG.md +55 -0
  6. package/CLAUDE.md +1 -0
  7. package/cabloy-docs/.vitepress/config.mjs +158 -12
  8. package/cabloy-docs/ai/docs-skills-rules-mapping.md +8 -0
  9. package/cabloy-docs/ai/future-skill-roadmap.md +2 -0
  10. package/cabloy-docs/ai/skills.md +1 -0
  11. package/cabloy-docs/backend/backend-contract-emission-output-inspection.md +189 -0
  12. package/cabloy-docs/backend/backend-contract-emission-source-reading-map.md +160 -0
  13. package/cabloy-docs/backend/backend-contract-emission-specimen.md +170 -0
  14. package/cabloy-docs/backend/backend-resource-module-contract-chain.md +323 -0
  15. package/cabloy-docs/backend/backend-source-reading-debug-checklist.md +173 -0
  16. package/cabloy-docs/backend/backend-source-reading-roadmap.md +129 -0
  17. package/cabloy-docs/backend/backend-source-reading-verify-playbook.md +166 -0
  18. package/cabloy-docs/backend/bean-scene-authoring.md +4 -4
  19. package/cabloy-docs/backend/broadcast-guide.md +3 -3
  20. package/cabloy-docs/backend/cli.md +20 -11
  21. package/cabloy-docs/backend/config-guide.md +4 -4
  22. package/cabloy-docs/backend/controller-aop-guide.md +10 -10
  23. package/cabloy-docs/backend/controller-guide.md +12 -2
  24. package/cabloy-docs/backend/crud-workflow.md +7 -3
  25. package/cabloy-docs/backend/dto-guide.md +12 -2
  26. package/cabloy-docs/backend/dto-infer-generation.md +201 -25
  27. package/cabloy-docs/backend/election-guide.md +2 -2
  28. package/cabloy-docs/backend/entity-guide.md +12 -3
  29. package/cabloy-docs/backend/error-guide.md +3 -3
  30. package/cabloy-docs/backend/event-guide.md +4 -4
  31. package/cabloy-docs/backend/external-aop-guide.md +2 -2
  32. package/cabloy-docs/backend/field-indexes.md +9 -3
  33. package/cabloy-docs/backend/foundation.md +8 -8
  34. package/cabloy-docs/backend/i18n-guide.md +6 -6
  35. package/cabloy-docs/backend/internal-aop-guide.md +2 -2
  36. package/cabloy-docs/backend/introduction.md +13 -0
  37. package/cabloy-docs/backend/migration-and-changes.md +3 -3
  38. package/cabloy-docs/backend/model-guide.md +16 -6
  39. package/cabloy-docs/backend/openapi-guide.md +3 -0
  40. package/cabloy-docs/backend/queue-guide.md +3 -3
  41. package/cabloy-docs/backend/redlock-guide.md +2 -2
  42. package/cabloy-docs/backend/schedule-guide.md +2 -2
  43. package/cabloy-docs/backend/scripts.md +8 -0
  44. package/cabloy-docs/backend/serialization-guide.md +2 -2
  45. package/cabloy-docs/backend/service-guide.md +18 -9
  46. package/cabloy-docs/backend/startup-guide.md +5 -5
  47. package/cabloy-docs/backend/status-guide.md +7 -7
  48. package/cabloy-docs/backend/unit-testing.md +3 -3
  49. package/cabloy-docs/backend/vona-source-reading-map.md +157 -0
  50. package/cabloy-docs/backend/websocket-protocol-guide.md +5 -5
  51. package/cabloy-docs/backend/websocket-usage-guide.md +15 -8
  52. package/cabloy-docs/frontend/a-model-under-the-hood.md +281 -0
  53. package/cabloy-docs/frontend/a-openapi-under-the-hood.md +248 -0
  54. package/cabloy-docs/frontend/a-router-guide.md +307 -0
  55. package/cabloy-docs/frontend/api-guide.md +4 -4
  56. package/cabloy-docs/frontend/api-schema-guide.md +1 -0
  57. package/cabloy-docs/frontend/app-startup-guide.md +7 -4
  58. package/cabloy-docs/frontend/bean-scene-authoring.md +1 -1
  59. package/cabloy-docs/frontend/behavior-guide.md +16 -16
  60. package/cabloy-docs/frontend/cli.md +5 -5
  61. package/cabloy-docs/frontend/command-scene-authoring.md +17 -8
  62. package/cabloy-docs/frontend/component-guide.md +5 -5
  63. package/cabloy-docs/frontend/component-props-guide.md +1 -1
  64. package/cabloy-docs/frontend/component-v-model-guide.md +2 -2
  65. package/cabloy-docs/frontend/filter-query-select-data-flow-guide.md +260 -0
  66. package/cabloy-docs/frontend/form-guide.md +27 -30
  67. package/cabloy-docs/frontend/form-scene-to-page-meta-guide.md +303 -0
  68. package/cabloy-docs/frontend/foundation.md +10 -6
  69. package/cabloy-docs/frontend/frontend-source-reading-roadmap.md +249 -0
  70. package/cabloy-docs/frontend/generated-contract-consumption-debug-checklist.md +190 -0
  71. package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +205 -0
  72. package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +157 -0
  73. package/cabloy-docs/frontend/generated-contract-consumption-specimen.md +203 -0
  74. package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +189 -0
  75. package/cabloy-docs/frontend/generic-component-guide.md +1 -1
  76. package/cabloy-docs/frontend/introduction.md +29 -7
  77. package/cabloy-docs/frontend/model-architecture.md +38 -2
  78. package/cabloy-docs/frontend/model-resource-cookbook.md +11 -8
  79. package/cabloy-docs/frontend/model-resource-internals-deep-dive.md +238 -0
  80. package/cabloy-docs/frontend/model-resource-owner-pattern.md +22 -2
  81. package/cabloy-docs/frontend/model-resource-usage-guide.md +22 -6
  82. package/cabloy-docs/frontend/model-state-guide.md +12 -9
  83. package/cabloy-docs/frontend/module-scope.md +8 -8
  84. package/cabloy-docs/frontend/modules-and-suites.md +2 -1
  85. package/cabloy-docs/frontend/navigation-guards-guide.md +7 -0
  86. package/cabloy-docs/frontend/openapi-sdk-guide.md +12 -4
  87. package/cabloy-docs/frontend/page-guide.md +9 -9
  88. package/cabloy-docs/frontend/page-meta-guide.md +466 -0
  89. package/cabloy-docs/frontend/page-params-guide.md +3 -3
  90. package/cabloy-docs/frontend/page-query-guide.md +2 -2
  91. package/cabloy-docs/frontend/page-route-guide.md +6 -0
  92. package/cabloy-docs/frontend/permission-formscene-action-visibility-guide.md +263 -0
  93. package/cabloy-docs/frontend/quickstart.md +14 -2
  94. package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +271 -0
  95. package/cabloy-docs/frontend/resource-list-page-deep-dive.md +279 -0
  96. package/cabloy-docs/frontend/rest-resource-source-reading-map.md +522 -0
  97. package/cabloy-docs/frontend/rest-resource-under-the-hood.md +622 -0
  98. package/cabloy-docs/frontend/root-behaviors-guide.md +282 -0
  99. package/cabloy-docs/frontend/route-alias-guide.md +6 -0
  100. package/cabloy-docs/frontend/router-stack-guide.md +229 -0
  101. package/cabloy-docs/frontend/router-tabs-introduction.md +26 -3
  102. package/cabloy-docs/frontend/router-tabs-layout-integration.md +367 -0
  103. package/cabloy-docs/frontend/router-tabs-mechanism.md +6 -0
  104. package/cabloy-docs/frontend/router-tabs-route-meta-cookbook.md +7 -0
  105. package/cabloy-docs/frontend/router-tabs-vs-stack.md +167 -0
  106. package/cabloy-docs/frontend/router-view-hosts-guide.md +450 -0
  107. package/cabloy-docs/frontend/server-data.md +2 -1
  108. package/cabloy-docs/frontend/system-startup-guide.md +2 -2
  109. package/cabloy-docs/frontend/table-action-visibility-permission-flow-guide.md +263 -0
  110. package/cabloy-docs/frontend/table-cell-cookbook.md +571 -0
  111. package/cabloy-docs/frontend/table-guide.md +373 -0
  112. package/cabloy-docs/frontend/table-resource-crud-cookbook.md +496 -0
  113. package/cabloy-docs/frontend/zova-app-guide.md +251 -0
  114. package/cabloy-docs/frontend/zova-form-source-reading-map.md +7 -9
  115. package/cabloy-docs/frontend/zova-form-under-the-hood.md +5 -0
  116. package/cabloy-docs/frontend/zova-router-under-the-hood.md +561 -0
  117. package/cabloy-docs/frontend/zova-source-reading-map.md +101 -7
  118. package/cabloy-docs/frontend/zova-table-controller-render-supplement.md +225 -0
  119. package/cabloy-docs/frontend/zova-table-source-reading-map.md +317 -0
  120. package/cabloy-docs/frontend/zova-table-under-the-hood.md +532 -0
  121. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-debug-checklist.md +245 -0
  122. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-source-reading-map.md +139 -0
  123. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions-verify-playbook.md +248 -0
  124. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions.md +511 -0
  125. package/cabloy-docs/fullstack/contract-loop-playbook.md +8 -2
  126. package/cabloy-docs/fullstack/edition-collaboration-differences.md +6 -0
  127. package/cabloy-docs/fullstack/frontend-metadata-to-backend.md +181 -48
  128. package/cabloy-docs/fullstack/introduction.md +3 -0
  129. package/cabloy-docs/fullstack/openapi-to-sdk.md +116 -2
  130. package/cabloy-docs/fullstack/suites-and-modules.md +333 -0
  131. package/cabloy-docs/fullstack/tutorial-1-first-module.md +3 -0
  132. package/cabloy-docs/fullstack/tutorial-2-first-crud.md +4 -0
  133. package/cabloy-docs/fullstack/tutorial-3-frontend-metadata-sharing.md +4 -0
  134. package/cabloy-docs/fullstack/tutorial-4-custom-level-renderers.md +31 -19
  135. package/cabloy-docs/fullstack/tutorial-5-backend-contract-sharing.md +5 -0
  136. package/cabloy-docs/fullstack/tutorial-6-one-contract-four-uses.md +4 -0
  137. package/cabloy-docs/fullstack/tutorials-overview.md +1 -1
  138. package/cabloy-docs/reference/bean-scene-boilerplates.md +13 -13
  139. package/cabloy-docs/reference/package-map.md +4 -3
  140. package/package.json +1 -1
  141. package/vona/pnpm-lock.yaml +22 -258
  142. package/vona/src/suite/a-training/modules/training-student/package.json +53 -0
  143. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +400 -0
  144. package/vona/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +18 -0
  145. package/vona/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  146. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.index.ts +12 -0
  147. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +21 -0
  148. package/vona/src/suite/a-training/modules/training-student/src/bean/ssrMenu.student.ts +29 -0
  149. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +15 -0
  150. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +15 -0
  151. package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +74 -0
  152. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +28 -0
  153. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +44 -0
  154. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectRes.tsx +11 -0
  155. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +45 -0
  156. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +42 -0
  157. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +28 -0
  158. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +25 -0
  159. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +84 -0
  160. package/vona/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  161. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +10 -0
  162. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +57 -0
  163. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +173 -0
  164. package/vona/src/suite/a-training/modules/training-student/tsconfig.build.json +11 -0
  165. package/vona/src/suite/a-training/modules/training-student/tsconfig.json +7 -0
  166. package/vona/src/suite/a-training/package.json +12 -0
  167. package/vona/src/suite/a-training/tsconfig.base.json +4 -0
  168. package/vona/src/suite/a-training/tsconfig.json +10 -0
  169. package/zova/packages-zova/zova/package.json +2 -2
  170. package/zova/pnpm-lock.yaml +423 -682
  171. package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolOne/render.tsx +5 -3
  172. package/zova/src/suite/a-home/modules/home-login/src/page/login/render.tsx +5 -3
  173. package/zova/src/suite/a-training/modules/training-student/cli/openapi.config.ts +9 -0
  174. package/zova/src/suite/a-training/modules/training-student/package.json +57 -0
  175. package/zova/src/suite/a-training/modules/training-student/src/.metadata/component/formFieldLevel.ts +31 -0
  176. package/zova/src/suite/a-training/modules/training-student/src/.metadata/index.ts +258 -0
  177. package/zova/src/suite/a-training/modules/training-student/src/.metadata/locales.ts +7 -0
  178. package/zova/src/suite/a-training/modules/training-student/src/.metadata/this.ts +2 -0
  179. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/baseURL.ts +5 -0
  180. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/index.ts +3 -0
  181. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +196 -0
  182. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +4146 -0
  183. package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +151 -0
  184. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +43 -0
  185. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionDeleteForce.tsx +53 -0
  186. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.actionSummary.tsx +56 -0
  187. package/zova/src/suite/a-training/modules/training-student/src/bean/tableCell.level.tsx +63 -0
  188. package/zova/src/suite/a-training/modules/training-student/src/component/formFieldLevel/controller.tsx +117 -0
  189. package/zova/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +9 -0
  190. package/zova/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +9 -0
  191. package/zova/src/suite/a-training/modules/training-student/src/index.ts +2 -0
  192. package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +42 -0
  193. package/zova/src/suite/a-training/modules/training-student/tsconfig.build.json +13 -0
  194. package/zova/src/suite/a-training/modules/training-student/tsconfig.json +5 -0
  195. package/zova/src/suite/a-training/package.json +12 -0
  196. package/zova/src/suite/a-training/tsconfig.base.json +4 -0
  197. package/zova/src/suite/a-training/tsconfig.json +4 -0
  198. package/zova/src/suite/cabloy-basic/modules/basic-app/package.json +60 -0
  199. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/index.ts +137 -0
  200. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/locales.ts +7 -0
  201. package/zova/src/suite/cabloy-basic/modules/basic-app/src/.metadata/this.ts +2 -0
  202. package/zova/src/suite/cabloy-basic/modules/basic-app/src/bean/behavior.appModal.tsx +260 -0
  203. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/config.ts +39 -0
  204. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/locale/en-us.ts +7 -0
  205. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/locale/zh-cn.ts +7 -0
  206. package/zova/src/suite/cabloy-basic/modules/basic-app/src/index.ts +4 -0
  207. package/zova/src/suite/cabloy-basic/modules/basic-app/src/lib/appModalItem.ts +16 -0
  208. package/zova/src/suite/cabloy-basic/modules/basic-app/src/lib/index.ts +1 -0
  209. package/zova/src/suite/cabloy-basic/modules/basic-app/src/monkey.ts +38 -0
  210. package/zova/src/suite/cabloy-basic/modules/basic-app/src/monkeySys.ts +14 -0
  211. package/zova/src/suite/cabloy-basic/modules/basic-app/src/service/appModal.ts +89 -0
  212. package/zova/src/suite/cabloy-basic/modules/basic-app/src/types/appModal.ts +52 -0
  213. package/zova/src/suite/cabloy-basic/modules/basic-app/src/types/index.ts +1 -0
  214. package/zova/src/suite/cabloy-basic/modules/basic-app/tsconfig.build.json +13 -0
  215. package/zova/src/suite/cabloy-basic/modules/basic-app/tsconfig.json +5 -0
  216. package/zova/src/suite/cabloy-basic/modules/basic-commands/package.json +6 -1
  217. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/.metadata/index.ts +16 -0
  218. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.alert.tsx +8 -14
  219. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.confirm.tsx +10 -7
  220. package/zova/src/suite/cabloy-basic/modules/basic-commands/src/bean/command.prompt.tsx +30 -0
  221. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockForm/controller.tsx +5 -3
  222. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/formFieldSelect/controller.tsx +29 -7
  223. package/zova/src/suite/cabloy-basic/modules/basic-select/src/component/select/controller.tsx +34 -11
  224. package/zova/src/suite/cabloy-basic/modules/basic-table/package.json +6 -1
  225. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionDelete.tsx +4 -2
  226. package/zova/src/suite/cabloy-basic/package.json +1 -0
  227. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  228. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +3 -3
  229. package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/tableCell.ts +1 -1
  230. package/zova/src/suite-vendor/a-zova/package.json +2 -2
@@ -0,0 +1,11 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { $Dto } from 'vona-module-a-orm';
4
+ import { Dto } from 'vona-module-a-web';
5
+
6
+ import { DtoStudentSelectResItem } from './studentSelectResItem.tsx';
7
+
8
+ export interface IDtoOptionsStudentSelectRes extends IDecoratorDtoOptions {}
9
+
10
+ @Dto<IDtoOptionsStudentSelectRes>()
11
+ export class DtoStudentSelectRes extends $Dto.listAndCount(DtoStudentSelectResItem) {}
@@ -0,0 +1,45 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { Api, v } from 'vona-module-a-openapiutils';
4
+ import { $Dto } from 'vona-module-a-orm';
5
+ import { Dto } from 'vona-module-a-web';
6
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
7
+
8
+ import { $locale } from '../.metadata/locales.ts';
9
+ import { ModelStudent } from '../model/student.ts';
10
+
11
+ export interface IDtoOptionsStudentSelectResItem extends IDecoratorDtoOptions {}
12
+
13
+ @Dto<IDtoOptionsStudentSelectResItem>({
14
+ blocks: [
15
+ ZovaRender.block('basic-page:blockPage', {
16
+ blocks: [
17
+ ZovaRender.block('basic-page:blockFilter'),
18
+ ZovaRender.block('basic-page:blockToolbarBulk', {
19
+ actions: [ZovaRender.tableActionBulk('basic-table:actionCreate')],
20
+ }),
21
+ ZovaRender.block('basic-page:blockTable'),
22
+ ZovaRender.block('basic-page:blockPager'),
23
+ ],
24
+ }),
25
+ ],
26
+ })
27
+ export class DtoStudentSelectResItem extends $Dto.get(() => ModelStudent) {
28
+ @Api.field(
29
+ v.title($locale('Operations')),
30
+ ZovaRender.order(1, 'max'),
31
+ ZovaRender.cell('basic-table:actionOperationsRow', {
32
+ actions: [
33
+ ZovaRender.tableActionRow('training-student:actionSummary', {
34
+ permission: { actionInherit: 'view' },
35
+ }),
36
+ ZovaRender.tableActionRow('basic-table:actionUpdate'),
37
+ ZovaRender.tableActionRow('basic-table:actionDelete'),
38
+ ZovaRender.tableActionRow('training-student:actionDeleteForce', {
39
+ permission: { actionInherit: 'delete' },
40
+ }),
41
+ ],
42
+ }),
43
+ )
44
+ _operationsRow?: unknown;
45
+ }
@@ -0,0 +1,42 @@
1
+ import type { TableIdentity } from 'table-identity';
2
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
3
+
4
+ import { Api, v } from 'vona-module-a-openapiutils';
5
+ import { Dto } from 'vona-module-a-web';
6
+
7
+ import { $locale } from '../.metadata/locales.ts';
8
+
9
+ export interface IDtoOptionsStudentSummary extends IDecoratorDtoOptions {}
10
+
11
+ @Dto<IDtoOptionsStudentSummary>()
12
+ export class DtoStudentSummary {
13
+ @Api.field(v.tableIdentity())
14
+ id: TableIdentity;
15
+
16
+ @Api.field(v.title($locale('Name')))
17
+ name: string;
18
+
19
+ @Api.field(
20
+ v.title($locale('Mobile')),
21
+ v.serializerReplace({
22
+ patternFrom: /^(\d{3})\d{4}(\d+)$/,
23
+ patternTo: '$1****$2',
24
+ }),
25
+ )
26
+ mobile: string;
27
+
28
+ @Api.field(v.title($locale('Level')))
29
+ level: 1 | 2 | 3;
30
+
31
+ @Api.field(v.title($locale('LevelTitle')))
32
+ levelTitle: string;
33
+
34
+ @Api.field(v.title($locale('Description')), v.optional())
35
+ description?: string;
36
+
37
+ @Api.field(v.title($locale('DescriptionLength')))
38
+ descriptionLength: number;
39
+
40
+ @Api.field(v.title($locale('Summary')))
41
+ summaryText: string;
42
+ }
@@ -0,0 +1,28 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { $Dto } from 'vona-module-a-orm';
4
+ import { Dto } from 'vona-module-a-web';
5
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
6
+
7
+ import { ModelStudent } from '../model/student.ts';
8
+
9
+ export interface IDtoOptionsStudentUpdate extends IDecoratorDtoOptions {}
10
+
11
+ @Dto<IDtoOptionsStudentUpdate>({
12
+ blocks: [
13
+ ZovaRender.block('basic-pageentry:blockPageEntry', {
14
+ blocks: [
15
+ ZovaRender.block('basic-pageentry:blockForm'),
16
+ ZovaRender.block('basic-pageentry:blockToolbarRow', {
17
+ actions: [
18
+ ZovaRender.formActionRow('basic-form:actionSubmit', {
19
+ permission: { actionInherit: 'update', formScene: ['create', 'edit'] },
20
+ }),
21
+ ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
22
+ ],
23
+ }),
24
+ ],
25
+ }),
26
+ ],
27
+ })
28
+ export class DtoStudentUpdate extends $Dto.update(() => ModelStudent) {}
@@ -0,0 +1,25 @@
1
+ import type { IDecoratorDtoOptions } from 'vona-module-a-web';
2
+
3
+ import { $Dto } from 'vona-module-a-orm';
4
+ import { Dto } from 'vona-module-a-web';
5
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
6
+
7
+ import { ModelStudent } from '../model/student.ts';
8
+
9
+ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions {}
10
+
11
+ @Dto<IDtoOptionsStudentView>({
12
+ blocks: [
13
+ ZovaRender.block('basic-pageentry:blockPageEntry', {
14
+ blocks: [
15
+ ZovaRender.block('basic-pageentry:blockForm'),
16
+ ZovaRender.block('basic-pageentry:blockToolbarRow', {
17
+ actions: [
18
+ ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
19
+ ],
20
+ }),
21
+ ],
22
+ }),
23
+ ],
24
+ })
25
+ export class DtoStudentView extends $Dto.get(() => ModelStudent) {}
@@ -0,0 +1,84 @@
1
+ import type { IDecoratorEntityOptions } from 'vona-module-a-orm';
2
+
3
+ import { $makeMetadata, Api, v } from 'vona-module-a-openapiutils';
4
+ import { Entity, EntityBase } from 'vona-module-a-orm';
5
+ import z from 'zod';
6
+ import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
7
+
8
+ import { $locale } from '../.metadata/locales.ts';
9
+
10
+ export const studentLevelSchema = z.union([z.literal(1), z.literal(2), z.literal(3)]);
11
+
12
+ export const studentLevelItems = [
13
+ { value: 1, title: $locale('LevelBeginner') },
14
+ { value: 2, title: $locale('LevelIntermediate') },
15
+ { value: 3, title: $locale('LevelAdvanced') },
16
+ ];
17
+
18
+ export interface IEntityOptionsStudent extends IDecoratorEntityOptions {}
19
+
20
+ @Entity<IEntityOptionsStudent>('trainingStudent', {
21
+ openapi: { title: $locale('Student') },
22
+ fields: {
23
+ id: $makeMetadata(ZovaRender.order(1, 'core')),
24
+ iid: $makeMetadata(ZovaRender.visible(false)),
25
+ deleted: $makeMetadata(ZovaRender.visible(false)),
26
+ createdAt: $makeMetadata(
27
+ ZovaRender.order(-2, 'max'),
28
+ ZovaRender.field('basic-date:formFieldDate'),
29
+ ZovaRender.cell('basic-date:date'),
30
+ ),
31
+ updatedAt: $makeMetadata(
32
+ ZovaRender.order(-1, 'max'),
33
+ ZovaRender.field('basic-date:formFieldDate'),
34
+ ZovaRender.cell('basic-date:date'),
35
+ ),
36
+ },
37
+ })
38
+ export class EntityStudent extends EntityBase {
39
+ @Api.field(
40
+ v.title($locale('Name')),
41
+ v.required(),
42
+ v.min(2),
43
+ ZovaRender.order(1),
44
+ ZovaRender.cell('basic-table:actionView'),
45
+ )
46
+ name: string;
47
+
48
+ @Api.field(v.title($locale('Description')), v.optional(), ZovaRender.order(2))
49
+ description?: string;
50
+
51
+ @Api.field(
52
+ v.title($locale('Mobile')),
53
+ v.required(),
54
+ v.min(11),
55
+ v.serializerReplace({
56
+ patternFrom: /^(\d{3})\d{4}(\d+)$/,
57
+ patternTo: '$1****$2',
58
+ }),
59
+ ZovaRender.order(3),
60
+ )
61
+ mobile: string;
62
+
63
+ @Api.field(
64
+ v.title($locale('Level')),
65
+ v.required(),
66
+ ZovaRender.order(4),
67
+ // Tutorial 3 built-in form renderer example. Keep it commented here for side-by-side comparison.
68
+ // ZovaRender.field('basic-select:formFieldSelect', {
69
+ // items: studentLevelItems,
70
+ // placeholder: $locale('Level'),
71
+ // }),
72
+ // Tutorial 3 built-in table cell renderer example.
73
+ // ZovaRender.cell('basic-select:select', { items: studentLevelItems }),
74
+ // Tutorial 4 custom form renderer example used by the current implementation.
75
+ ZovaRender.field('training-student:formFieldLevel', {
76
+ items: studentLevelItems,
77
+ placeholder: $locale('Level'),
78
+ }),
79
+ // Tutorial 4 custom table cell renderer example used by the current implementation.
80
+ ZovaRender.cell('training-student:level', { items: studentLevelItems }),
81
+ studentLevelSchema,
82
+ )
83
+ level: 1 | 2 | 3;
84
+ }
@@ -0,0 +1,2 @@
1
+ export * from './.metadata/locales.ts';
2
+ export * from './.metadata/index.ts';
@@ -0,0 +1,10 @@
1
+ import type { IDecoratorModelOptions } from 'vona-module-a-orm';
2
+
3
+ import { BeanModelBase, Model } from 'vona-module-a-orm';
4
+
5
+ import { EntityStudent } from '../entity/student.tsx';
6
+
7
+ export interface IModelOptionsStudent extends IDecoratorModelOptions<EntityStudent> {}
8
+
9
+ @Model<IModelOptionsStudent>({ entity: EntityStudent })
10
+ export class ModelStudent extends BeanModelBase<EntityStudent> {}
@@ -0,0 +1,57 @@
1
+ import type { TableIdentity } from 'table-identity';
2
+ import type { IQueryParams } from 'vona-module-a-orm';
3
+
4
+ import { BeanBase } from 'vona';
5
+ import { Service } from 'vona-module-a-bean';
6
+
7
+ import type { DtoStudentCreate } from '../dto/studentCreate.tsx';
8
+ import type { DtoStudentSelectRes } from '../dto/studentSelectRes.tsx';
9
+ import type { DtoStudentSummary } from '../dto/studentSummary.tsx';
10
+ import type { DtoStudentUpdate } from '../dto/studentUpdate.tsx';
11
+ import type { DtoStudentView } from '../dto/studentView.tsx';
12
+ import type { EntityStudent } from '../entity/student.tsx';
13
+ import type { ModelStudent } from '../model/student.ts';
14
+
15
+ @Service()
16
+ export class ServiceStudent extends BeanBase {
17
+ async create(student: DtoStudentCreate): Promise<EntityStudent> {
18
+ return await this.scope.model.student.insert(student);
19
+ }
20
+
21
+ async select(params?: IQueryParams<ModelStudent>): Promise<DtoStudentSelectRes> {
22
+ return await this.scope.model.student.selectAndCount(params);
23
+ }
24
+
25
+ async view(id: TableIdentity): Promise<DtoStudentView | undefined> {
26
+ return await this.scope.model.student.getById(id);
27
+ }
28
+
29
+ async update(id: TableIdentity, student: DtoStudentUpdate) {
30
+ return await this.scope.model.student.updateById(id, student);
31
+ }
32
+
33
+ async summary(id: TableIdentity): Promise<DtoStudentSummary | undefined> {
34
+ const student = await this.scope.model.student.getById(id);
35
+ if (!student) return undefined;
36
+ const descriptionLength = student.description?.length ?? 0;
37
+ const levelTitle = String(student.level);
38
+ return {
39
+ id: student.id,
40
+ name: student.name,
41
+ mobile: student.mobile,
42
+ level: student.level,
43
+ levelTitle,
44
+ description: student.description,
45
+ descriptionLength,
46
+ summaryText: `${student.name} is in level ${student.level}. Description length: ${descriptionLength}.`,
47
+ };
48
+ }
49
+
50
+ async delete(id: TableIdentity) {
51
+ return await this.scope.model.student.deleteById(id);
52
+ }
53
+
54
+ async deleteForce(id: TableIdentity) {
55
+ return await this.scope.model.student.deleteById(id, { disableDeleted: true });
56
+ }
57
+ }
@@ -0,0 +1,173 @@
1
+ import type {
2
+ DtoStudentCreate,
3
+ DtoStudentSelectRes,
4
+ DtoStudentSummary,
5
+ DtoStudentUpdate,
6
+ EntityStudent,
7
+ } from 'vona-module-training-student';
8
+
9
+ import assert from 'node:assert';
10
+ import { describe, it } from 'node:test';
11
+ import { app } from 'vona-mock';
12
+
13
+ describe('student.test.ts', () => {
14
+ it('action:student', async () => {
15
+ await app.bean.executor.mockCtx(async () => {
16
+ // data
17
+ const mobile = '13812345678';
18
+ const maskedMobile = '138****5678';
19
+ const mobileUpdate = '13987654321';
20
+ const maskedMobileUpdate = '139****4321';
21
+ const data: DtoStudentCreate = {
22
+ name: '__Tom__',
23
+ description: 'This is a test',
24
+ mobile,
25
+ level: 1,
26
+ };
27
+ const dataUpdate: DtoStudentUpdate = {
28
+ name: '__TomNew__',
29
+ description: 'This is a test',
30
+ mobile: mobileUpdate,
31
+ level: 2,
32
+ };
33
+ // login
34
+ await app.bean.passport.signinMock();
35
+ // create
36
+ const studentId = await app.bean.executor.performAction('post', '/training/student', {
37
+ body: data,
38
+ });
39
+ assert.equal(!!studentId, true);
40
+ // findMany
41
+ const selectRes: DtoStudentSelectRes = await app.bean.executor.performAction(
42
+ 'get',
43
+ '/training/student',
44
+ );
45
+ const studentItem = selectRes.list.find(item => item.name === data.name);
46
+ assert.equal(!!studentItem, true);
47
+ assert.equal(studentItem!.level, data.level);
48
+ assert.equal(studentItem!.mobile, maskedMobile);
49
+ // findMany: level filter
50
+ const selectResByLevel: DtoStudentSelectRes = await app.bean.executor.performAction(
51
+ 'get',
52
+ '/training/student',
53
+ {
54
+ query: {
55
+ level: data.level,
56
+ },
57
+ },
58
+ );
59
+ assert.equal(
60
+ selectResByLevel.list.some(item => item.name === data.name),
61
+ true,
62
+ );
63
+ assert.equal(
64
+ selectResByLevel.list.every(item => item.level === data.level),
65
+ true,
66
+ );
67
+ // update
68
+ await app.bean.executor.performAction('patch', '/training/student/:id', {
69
+ params: { id: studentId },
70
+ body: dataUpdate,
71
+ });
72
+ // findOne
73
+ let student: EntityStudent = await app.bean.executor.performAction(
74
+ 'get',
75
+ '/training/student/:id',
76
+ { params: { id: studentId } },
77
+ );
78
+ assert.equal(student.name, dataUpdate.name);
79
+ assert.equal(student.level, dataUpdate.level);
80
+ assert.equal(student.mobile, maskedMobileUpdate);
81
+ const studentRaw = await app.bean.scope('training-student').model.student.getById(studentId, {
82
+ disableDeleted: true,
83
+ });
84
+ assert.equal(studentRaw!.mobile, mobileUpdate);
85
+ // summary
86
+ const summary: DtoStudentSummary = await app.bean.executor.performAction(
87
+ 'get',
88
+ '/training/student/summary/:id',
89
+ { params: { id: studentId } },
90
+ );
91
+ assert.equal(summary.name, dataUpdate.name);
92
+ assert.equal(summary.mobile, maskedMobileUpdate);
93
+ assert.equal(summary.level, dataUpdate.level);
94
+ assert.equal(summary.descriptionLength, dataUpdate.description?.length);
95
+ assert.equal(typeof summary.levelTitle, 'string');
96
+ assert.equal(typeof summary.summaryText, 'string');
97
+ // delete
98
+ await app.bean.executor.performAction('delete', '/training/student/:id', {
99
+ params: { id: student.id },
100
+ });
101
+ // findOne
102
+ student = await app.bean.executor.performAction('get', '/training/student/:id', {
103
+ params: { id: student.id },
104
+ });
105
+ assert.equal(student, undefined);
106
+ // create again for force delete
107
+ const studentIdForce = await app.bean.executor.performAction('post', '/training/student', {
108
+ body: data,
109
+ });
110
+ await app.bean.executor.performAction('delete', '/training/student/deleteForce/:id', {
111
+ params: { id: studentIdForce },
112
+ });
113
+ const studentForce = await app.bean
114
+ .scope('training-student')
115
+ .model.student.getById(studentIdForce, {
116
+ disableDeleted: true,
117
+ });
118
+ assert.equal(studentForce, undefined);
119
+ // logout
120
+ await app.bean.passport.signout();
121
+ });
122
+ });
123
+
124
+ it('action:student:level invalid', async () => {
125
+ await app.bean.executor.mockCtx(async () => {
126
+ await app.bean.passport.signinMock();
127
+ await assert.rejects(async () => {
128
+ await app.bean.executor.performAction('post', '/training/student', {
129
+ body: {
130
+ name: '__Tom__',
131
+ description: 'This is a test',
132
+ mobile: '13812345678',
133
+ level: 4,
134
+ },
135
+ });
136
+ });
137
+ await app.bean.passport.signout();
138
+ });
139
+ });
140
+
141
+ it('action:student:mobile required', async () => {
142
+ await app.bean.executor.mockCtx(async () => {
143
+ await app.bean.passport.signinMock();
144
+ await assert.rejects(async () => {
145
+ await app.bean.executor.performAction('post', '/training/student', {
146
+ body: {
147
+ name: '__Tom__',
148
+ description: 'This is a test',
149
+ level: 1,
150
+ },
151
+ });
152
+ });
153
+ await app.bean.passport.signout();
154
+ });
155
+ });
156
+
157
+ it('action:student:mobile too short', async () => {
158
+ await app.bean.executor.mockCtx(async () => {
159
+ await app.bean.passport.signinMock();
160
+ await assert.rejects(async () => {
161
+ await app.bean.executor.performAction('post', '/training/student', {
162
+ body: {
163
+ name: '__Tom__',
164
+ description: 'This is a test',
165
+ mobile: '1381234567',
166
+ level: 1,
167
+ },
168
+ });
169
+ });
170
+ await app.bean.passport.signout();
171
+ });
172
+ });
173
+ });
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "emitDeclarationOnly": true,
8
+ "outDir": "dist"
9
+ },
10
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json"]
11
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "noEmit": true
5
+ },
6
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json", "test"]
7
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "vona-suite-a-training",
3
+ "version": "5.0.0",
4
+ "description": "",
5
+ "author": "",
6
+ "files": [],
7
+ "type": "module",
8
+ "dependencies": {
9
+ "vona-module-training-student": "^5.0.0"
10
+ },
11
+ "title": "a-training"
12
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../../tsconfig.base",
3
+ "compilerOptions": {}
4
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "./tsconfig.base",
3
+ "compilerOptions": {},
4
+ "references": [
5
+ {
6
+ "path": "modules/training-student/tsconfig.build.json"
7
+ }
8
+ ],
9
+ "exclude": ["modules"]
10
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova",
3
- "version": "5.1.103",
3
+ "version": "5.1.104",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A vue3 framework with ioc",
6
6
  "keywords": [
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "zova-core": "^5.1.57",
49
- "zova-suite-a-zova": "^5.1.102"
49
+ "zova-suite-a-zova": "^5.1.103"
50
50
  },
51
51
  "devDependencies": {
52
52
  "clean-package": "^2.2.0",