cabloy 5.1.158 → 5.1.160

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 (120) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/skills/cabloy-contract-loop/SKILL.md +24 -7
  3. package/.claude/skills/cabloy-contract-loop/evals/evals.json +12 -0
  4. package/.claude/skills/cabloy-contract-loop/references/contract-loop-map.md +28 -0
  5. package/.claude/skills/cabloy-contract-loop/references/verification-checklist.md +19 -2
  6. package/.claude/skills/cabloy-resource-field-update/SKILL.md +18 -0
  7. package/.claude/skills/cabloy-zova-source-reading/SKILL.md +14 -0
  8. package/.claude/skills/cabloy-zova-source-reading/references/core-reading-paths.md +10 -0
  9. package/.github/workflows/docs-pages.yml +18 -2
  10. package/CHANGELOG.md +31 -0
  11. package/package.json +2 -1
  12. package/repo-docs/.vitepress/config.mjs +45 -4
  13. package/repo-docs/.vitepress/theme/components/GitHubRepositoriesNav.vue +255 -0
  14. package/repo-docs/.vitepress/theme/custom.css +21 -0
  15. package/repo-docs/.vitepress/theme/index.js +7 -1
  16. package/repo-docs/backend/department-management.md +98 -0
  17. package/repo-docs/backend/menu-authorization.md +124 -0
  18. package/repo-docs/backend/rbac-authorization.md +117 -0
  19. package/repo-docs/backend/resource-field-update.md +49 -2
  20. package/repo-docs/backend/role-management.md +92 -0
  21. package/repo-docs/backend/shared-rbac-architecture.md +339 -0
  22. package/repo-docs/backend/user-management.md +92 -0
  23. package/repo-docs/blogs/index.md +2 -0
  24. package/repo-docs/frontend/form-layout-guide.md +6 -6
  25. package/repo-docs/frontend/model-resource-owner-pattern.md +2 -0
  26. package/repo-docs/frontend/page-guide.md +12 -0
  27. package/repo-docs/frontend/page-meta-guide.md +27 -0
  28. package/repo-docs/frontend/permission-formscene-action-visibility-guide.md +5 -3
  29. package/repo-docs/frontend/ssr-architecture-overview.md +4 -0
  30. package/repo-docs/frontend/ssr-build-deploy-guide.md +1 -1
  31. package/repo-docs/frontend/table-action-visibility-permission-flow-guide.md +2 -0
  32. package/repo-docs/frontend/table-guide.md +75 -22
  33. package/repo-docs/frontend/table-resource-crud-cookbook.md +25 -4
  34. package/repo-docs/frontend/zova-form-source-reading-map.md +2 -2
  35. package/repo-docs/frontend/zova-form-under-the-hood.md +1 -1
  36. package/repo-docs/frontend/zova-reactivity-under-the-hood.md +65 -9
  37. package/repo-docs/frontend/zova-table-source-reading-map.md +54 -19
  38. package/repo-docs/frontend/zova-table-under-the-hood.md +70 -39
  39. package/repo-docs/fullstack/contract-loop-playbook.md +2 -0
  40. package/repo-docs/fullstack/ssr-site-and-flavor-setup.md +198 -0
  41. package/repo-docs/fullstack/vona-zova-integration.md +2 -0
  42. package/repo-e2e/docs/playwright.config.ts +37 -0
  43. package/repo-e2e/docs/specs/blogs-index.spec.ts +180 -0
  44. package/repo-e2e/docs/specs/github-repositories-nav.spec.ts +69 -0
  45. package/repo-e2e/docs/test-results/.last-run.json +4 -0
  46. package/repo-e2e/specs/cabloy-basic.spec.ts +136 -2
  47. package/test-results/.last-run.json +20 -2
  48. package/test-results/a-commerce-ATP-ADDR-01-aut-11dea-ss-through-Web-self-service/error-context.md +238 -0
  49. package/test-results/a-commerce-ATP-SPC-01-Coup-ef380-mantic-Admin-field-controls/error-context.md +240 -0
  50. package/test-results/a-commerce-ATP-SPC-02-Cate-9f120-on-and-publication-controls/error-context.md +238 -0
  51. package/test-results/a-commerce-ATP-SPC-02-Prod-5f92a-on-and-publication-controls/error-context.md +238 -0
  52. package/test-results/a-commerce-ATP-SPC-02-SKU--2e61e-ency-and-lifecycle-controls/error-context.md +238 -0
  53. package/test-results/a-commerce-ATP-SPC-04-Stoc-fa895--readonly-and-mutation-free/error-context.md +235 -0
  54. package/test-results/a-commerce-ATP-SPC-05-syst-fb406-e-without-mutation-controls/error-context.md +238 -0
  55. package/test-results/a-commerce-Commerce-sessio-4e963-ie-selects-raw-server-theme/error-context.md +226 -0
  56. package/test-results/a-commerce-Commerce-theme--062fe--without-hydration-mismatch/error-context.md +229 -0
  57. package/test-results/a-commerce-PayPal-browser--8672c-t-or-open-an-awaiting-order/error-context.md +238 -0
  58. package/test-results/a-commerce-Payment-callbac-f56c2--reconciles-after-hydration/error-context.md +238 -0
  59. package/test-results/a-commerce-Payment-cancell-3fc74-ified-provider-confirmation/error-context.md +238 -0
  60. package/test-results/a-commerce-Phase-50-60-aut-71d61--observes-operator-shipment/error-context.md +238 -0
  61. package/test-results/a-commerce-Phase-60-custom-407cd-ecutes-a-whole-order-refund/error-context.md +238 -0
  62. package/test-results/cabloy-basic-ATP-BASIC-TAB-e7253-and-pins-configured-columns/error-context.md +240 -0
  63. package/test-results/markdown-ATP-SPC-02-Produc-9d5c2-link-toolbar-edits-Markdown/error-context.md +211 -0
  64. package/test-results/markdown-ATP-SPC-02-Produc-9d6ea-t-editor-and-saves-Markdown/error-context.md +238 -0
  65. package/vona/packages-cli/cli/package.json +1 -1
  66. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/entity/{{resourceName}}.tsx_ +1 -1
  67. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/entity/{{resourceName}}.tsx_ +1 -1
  68. package/vona/packages-cli/cli-set-api/package.json +1 -1
  69. package/vona/packages-vona/vona/package.json +1 -1
  70. package/vona/pnpm-lock.yaml +79 -52
  71. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/en-us.ts +3 -0
  72. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/config/locale/zh-cn.ts +3 -0
  73. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productCreate.tsx +2 -0
  74. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productUpdate.tsx +2 -0
  75. package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productView.tsx +2 -0
  76. package/vona/src/suite/a-training/modules/training-record/src/dto/recordCreate.tsx +1 -0
  77. package/vona/src/suite/a-training/modules/training-record/src/dto/recordSelectReq.tsx +3 -7
  78. package/vona/src/suite/a-training/modules/training-record/src/dto/recordUpdate.tsx +1 -0
  79. package/vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx +1 -0
  80. package/vona/src/suite/a-training/modules/training-record/src/entity/record.tsx +8 -0
  81. package/vona/src/suite/a-training/modules/training-record/test/record.test.ts +51 -0
  82. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +3 -0
  83. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +3 -0
  84. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +1 -0
  85. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +1 -0
  86. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +1 -0
  87. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +1 -0
  88. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +10 -1
  89. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +99 -1
  90. package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +1 -1
  91. package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
  92. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  93. package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
  94. package/vona/src/suite-vendor/a-vona/modules/a-web/src/bean/pipe.filter.ts +85 -57
  95. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  96. package/zova/packages-cli/cli/package.json +2 -2
  97. package/zova/packages-cli/cli-set-front/cli/templates/rest/render.ts +2 -0
  98. package/zova/packages-cli/cli-set-front/cli/templates/rest/rest.ts +13 -3
  99. package/zova/packages-cli/cli-set-front/package.json +1 -1
  100. package/zova/packages-zova/zova/package.json +2 -2
  101. package/zova/pnpm-lock.yaml +16 -16
  102. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +31 -11
  103. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx +3 -0
  104. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx +1 -1
  105. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/render.tsx +68 -8
  106. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  107. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +4 -0
  108. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  109. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  110. package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/formLayout.ts +0 -6
  111. package/zova/src/suite-vendor/a-zova/modules/a-form/test/lib/formLayout.test.ts +16 -9
  112. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  113. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/model/sdk.ts +4 -0
  114. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/rest.ts +13 -2
  115. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/schema.ts +1 -0
  116. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  117. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +50 -0
  118. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/render.tsx +60 -7
  119. package/zova/src/suite-vendor/a-zova/modules/a-table/src/types/table.ts +6 -4
  120. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -22,6 +22,7 @@ const studentContentField = $makeSchema(
22
22
  export interface IDtoOptionsStudentView extends IDecoratorDtoOptions<'_descriptionMarkdown'> {}
23
23
 
24
24
  @Dto<IDtoOptionsStudentView>({
25
+ openapi: { title: $locale('ViewStudent') },
25
26
  blocks: [
26
27
  ZovaRender.block('basic-pageentry:blockPageEntry', {
27
28
  blocks: [
@@ -19,11 +19,12 @@ export interface IEntityOptionsStudent extends IDecoratorEntityOptions {}
19
19
  @Entity<IEntityOptionsStudent>('trainingStudent', {
20
20
  openapi: { title: $locale('Student') },
21
21
  fields: {
22
- id: $makeMetadata(ZovaRender.order(1, 'core')),
22
+ id: $makeMetadata(ZovaRender.order(1, 'core'), ZovaRender.column({ width: 50, fixed: 'left' })),
23
23
  iid: $makeMetadata(ZovaRender.visible(false)),
24
24
  deleted: $makeMetadata(ZovaRender.visible(false)),
25
25
  createdAt: $makeMetadata(
26
26
  ZovaRender.order(-2, 'max'),
27
+ ZovaRender.column({ align: 'center', width: 180, enableSorting: true }),
27
28
  ZovaRender.field('basic-date:formFieldDate'),
28
29
  ZovaRender.cell('basic-date:date'),
29
30
  ),
@@ -40,6 +41,13 @@ export class EntityStudent extends EntityBase {
40
41
  v.required(),
41
42
  v.min(2),
42
43
  ZovaRender.order(1),
44
+ ZovaRender.column({
45
+ align: 'left',
46
+ width: 240,
47
+ fixed: 'left',
48
+ enableSorting: true,
49
+ sortDescFirst: true,
50
+ }),
43
51
  ZovaRender.cell('basic-table:actionView'),
44
52
  )
45
53
  name: string;
@@ -82,6 +90,7 @@ export class EntityStudent extends EntityBase {
82
90
  v.title($locale('Level')),
83
91
  v.required(),
84
92
  ZovaRender.order(5),
93
+ ZovaRender.column({ align: 'center', width: 140, enableSorting: true }),
85
94
  // Tutorial 3 built-in form renderer example. Keep it commented here for side-by-side comparison.
86
95
  // ZovaRender.field('basic-select:formFieldSelect', {
87
96
  // items: studentLevelItems,
@@ -13,7 +13,7 @@ import {
13
13
  import { DtoDetailRecordResItem } from '../src/dto/detailRecordResItem.tsx';
14
14
  import { DtoStudentSummary } from '../src/dto/studentSummary.tsx';
15
15
 
16
- describe('student.test.ts', () => {
16
+ describe('student.test.ts', { concurrency: false }, () => {
17
17
  it('action:student:formLayoutMetadata', async () => {
18
18
  await app.bean.executor.mockCtx(async () => {
19
19
  for (const DtoClass of [DtoStudentCreate, DtoStudentUpdate, DtoStudentView]) {
@@ -95,6 +95,104 @@ describe('student.test.ts', () => {
95
95
  });
96
96
  });
97
97
 
98
+ it('action:student:tableColumnMetadata', async () => {
99
+ await app.bean.executor.mockCtx(async () => {
100
+ const apiJson = await app.bean.openapi.generateJsonOfClass(DtoStudentSelectResItem);
101
+ const component = Object.values(apiJson.components!.schemas as any).find(item => {
102
+ return (item as any).properties?._operationsRow;
103
+ }) as any;
104
+ assert.deepEqual(
105
+ {
106
+ align: component.properties.name.rest.table.align,
107
+ width: component.properties.name.rest.table.width,
108
+ fixed: component.properties.name.rest.table.fixed,
109
+ enableSorting: component.properties.name.rest.table.enableSorting,
110
+ },
111
+ { align: 'left', width: 240, fixed: 'left', enableSorting: true },
112
+ );
113
+ assert.deepEqual(
114
+ {
115
+ align: component.properties.level.rest.table.align,
116
+ width: component.properties.level.rest.table.width,
117
+ enableSorting: component.properties.level.rest.table.enableSorting,
118
+ },
119
+ { align: 'center', width: 140, enableSorting: true },
120
+ );
121
+ assert.deepEqual(
122
+ {
123
+ align: component.properties.createdAt.rest.table.align,
124
+ width: component.properties.createdAt.rest.table.width,
125
+ enableSorting: component.properties.createdAt.rest.table.enableSorting,
126
+ },
127
+ { align: 'center', width: 180, enableSorting: true },
128
+ );
129
+ assert.deepEqual(
130
+ {
131
+ align: component.properties._operationsRow.rest.table.align,
132
+ width: component.properties._operationsRow.rest.table.width,
133
+ fixed: component.properties._operationsRow.rest.table.fixed,
134
+ },
135
+ { align: 'center', width: 360, fixed: 'right' },
136
+ );
137
+ });
138
+ });
139
+
140
+ it('action:student:serverSorting', async () => {
141
+ await app.bean.executor.mockCtx(async () => {
142
+ await app.bean.passport.signinMock();
143
+ const studentIds: string[] = [];
144
+ const names = ['__StudentSortA__', '__StudentSortZ__'];
145
+ try {
146
+ for (const [index, name] of names.entries()) {
147
+ const studentId = await app.bean.executor.performAction('post', '/training/student', {
148
+ body: {
149
+ name,
150
+ mobile: `13812345${678 + index}`,
151
+ level: 1,
152
+ },
153
+ });
154
+ studentIds.push(studentId);
155
+ }
156
+ const ascending: DtoStudentSelectRes = await app.bean.executor.performAction(
157
+ 'get',
158
+ '/training/student',
159
+ { query: { orders: [['name', 'asc']] } },
160
+ );
161
+ const descending: DtoStudentSelectRes = await app.bean.executor.performAction(
162
+ 'get',
163
+ '/training/student',
164
+ { query: { orders: [['name', 'desc']] } },
165
+ );
166
+ const ascendingIndexes = names.map(name =>
167
+ ascending.list.findIndex(item => item.name === name),
168
+ );
169
+ const descendingIndexes = names.map(name =>
170
+ descending.list.findIndex(item => item.name === name),
171
+ );
172
+ assert.equal(
173
+ ascendingIndexes.every(index => index >= 0),
174
+ true,
175
+ );
176
+ assert.equal(
177
+ descendingIndexes.every(index => index >= 0),
178
+ true,
179
+ );
180
+ assert.equal(ascendingIndexes[0] < ascendingIndexes[1], true);
181
+ assert.equal(descendingIndexes[0] > descendingIndexes[1], true);
182
+ } finally {
183
+ for (const studentId of studentIds.reverse()) {
184
+ await app
185
+ .scope('training-student')
186
+ .model.studentContent.delete({ studentId }, { disableDeleted: true });
187
+ await app
188
+ .scope('training-student')
189
+ .model.student.deleteById(studentId, { disableDeleted: true });
190
+ }
191
+ await app.bean.passport.signout();
192
+ }
193
+ });
194
+ });
195
+
98
196
  it('action:student:emittedDtoSchemas', async () => {
99
197
  await app.bean.executor.mockCtx(async () => {
100
198
  const summaryApiJson = await app.bean.openapi.generateJsonOfClass(DtoStudentSummary);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-rbac",
3
- "version": "5.0.4",
3
+ "version": "5.0.5",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "Vona Module"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-cabloy",
3
- "version": "5.1.50",
3
+ "version": "5.1.51",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "vona-module-a-cabloy": "workspace:^",
11
11
  "vona-module-a-markdown": "^5.0.3",
12
- "vona-module-a-rbac": "^5.0.4",
12
+ "vona-module-a-rbac": "^5.0.5",
13
13
  "vona-module-a-socket": "workspace:^",
14
14
  "vona-module-a-ssr": "workspace:^",
15
15
  "vona-module-a-ssrhmr": "workspace:^"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-permission",
3
- "version": "5.1.20",
3
+ "version": "5.1.21",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-module-a-web",
3
- "version": "5.1.22",
3
+ "version": "5.1.23",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "keywords": [
@@ -25,6 +25,7 @@ import type {
25
25
  export type TypePipeFilterData = ITableQuery;
26
26
 
27
27
  export type TypePipeFilterResult = TypeQueryParamsPatch;
28
+ type TypeQueryJoin = NonNullable<TypeQueryParamsPatch['joins']>[number];
28
29
 
29
30
  export interface IPipeOptionsFilter
30
31
  extends IDecoratorPipeOptions, IDecoratorPipeOptionsArgument, ValidatorOptions {}
@@ -68,10 +69,13 @@ export class PipeFilter
68
69
  private async _transform(value: TypePipeFilterData, options: IPipeOptionsFilter) {
69
70
  // 1. system: columns/where/orders/pageNo/pageSize
70
71
  const params = this._transformSystem(value);
72
+ const rootOpenapi = ZodMetadata.getOpenapiMetadata(options.schema!) as
73
+ | ISchemaObjectExtensionField
74
+ | undefined;
71
75
  // 2. fields
72
- await this._transformFields(params, value, options);
76
+ await this._transformFields(params, value, options, rootOpenapi);
73
77
  // 3. system: orders
74
- this._transformOrders(params, options);
78
+ this._transformOrders(params, options, rootOpenapi);
75
79
  // ok
76
80
  return params;
77
81
  }
@@ -104,32 +108,75 @@ export class PipeFilter
104
108
  return params;
105
109
  }
106
110
 
107
- private _transformOrders(params: TypeQueryParamsPatch, options: IPipeOptionsFilter) {
111
+ private _transformOrders(
112
+ params: TypeQueryParamsPatch,
113
+ options: IPipeOptionsFilter,
114
+ rootOpenapi: ISchemaObjectExtensionField | undefined,
115
+ ) {
108
116
  if (!params.orders) return;
109
- // openapi
110
- const openapi: ISchemaObjectExtensionField | undefined = ZodMetadata.getOpenapiMetadata(
111
- options.schema!,
112
- ) as ISchemaObjectExtensionField | undefined;
113
- const table = openapi?.filter?.table;
114
- // loop
115
117
  for (const order of params.orders) {
116
- const field = order[0] as string;
117
- if (field.includes('.')) continue;
118
- let tableCurrent = table;
119
- let fieldCurrent = field;
120
- const fieldSchema = ZodMetadata.getFieldSchema(options.schema, field);
121
- if (fieldSchema) {
122
- const openapi: ISchemaObjectExtensionField | undefined = ZodMetadata.getOpenapiMetadata(
123
- fieldSchema,
124
- ) as ISchemaObjectExtensionField | undefined;
125
- if (openapi?.filter?.table) {
126
- tableCurrent = openapi?.filter?.table;
127
- }
128
- if (openapi?.filter?.originalName) {
129
- fieldCurrent = openapi?.filter?.originalName;
130
- }
118
+ if (!Array.isArray(order) || order.length !== 2) {
119
+ throw new Error('invalid order');
120
+ }
121
+ const [key, direction] = order;
122
+ if (typeof key !== 'string' || (direction !== 'asc' && direction !== 'desc')) {
123
+ throw new Error('invalid order');
124
+ }
125
+ const info = this._resolveField(key, options, rootOpenapi);
126
+ if (!info || info.openapi?.filter?.capabilities?.order === false) {
127
+ throw new Error(`invalid order field: ${key}`);
131
128
  }
132
- cast(order)[0] = tableCurrent ? `${tableCurrent}.${fieldCurrent}` : fieldCurrent;
129
+ cast(order)[0] = info.orderFullName;
130
+ this._addJoin(params, info.joinInfo);
131
+ }
132
+ }
133
+
134
+ private _resolveField(
135
+ key: string,
136
+ options: IPipeOptionsFilter,
137
+ rootOpenapi: ISchemaObjectExtensionField | undefined,
138
+ ) {
139
+ const fieldSchema = ZodMetadata.getFieldSchema(options.schema!, key);
140
+ if (!fieldSchema) {
141
+ if (!rootOpenapi?.filter?.table) {
142
+ return { orderFullName: key };
143
+ }
144
+ const keyParts = key.split('.');
145
+ const [table, field] = keyParts;
146
+ if (!table || !field || keyParts.length !== 2) return;
147
+ const resolved = this._resolveField(field, options, rootOpenapi);
148
+ if (!resolved || resolved.orderFullName !== key) return;
149
+ return resolved;
150
+ }
151
+ const fieldSchemaInner = ZodMetadata.unwrapChained(fieldSchema);
152
+ const openapi: ISchemaObjectExtensionField | undefined = ZodMetadata.getOpenapiMetadata(
153
+ fieldSchema,
154
+ ) as ISchemaObjectExtensionField | undefined;
155
+ const originalName = openapi?.filter?.originalName ?? key;
156
+ const table = openapi?.filter?.table ?? rootOpenapi?.filter?.table;
157
+ const joinInfo = openapi?.filter?.joinOn
158
+ ? ([
159
+ openapi.filter.joinType ?? 'innerJoin',
160
+ openapi.filter.table,
161
+ openapi.filter.joinOn,
162
+ ] as TypeQueryJoin)
163
+ : undefined;
164
+ return {
165
+ fieldSchema,
166
+ fieldSchemaInner,
167
+ openapi,
168
+ originalName,
169
+ fullName: joinInfo ? `${openapi?.filter?.table}.${originalName}` : originalName,
170
+ orderFullName: table ? `${table}.${originalName}` : originalName,
171
+ joinInfo,
172
+ };
173
+ }
174
+
175
+ private _addJoin(params: TypeQueryParamsPatch, joinInfo: TypeQueryJoin | undefined) {
176
+ if (!joinInfo) return;
177
+ if (!params.joins) params.joins = [];
178
+ if (params.joins.findIndex(item => item[1] === joinInfo[1]) === -1) {
179
+ params.joins.push(joinInfo);
133
180
  }
134
181
  }
135
182
 
@@ -139,36 +186,21 @@ export class PipeFilter
139
186
  params: TypeQueryParamsPatch,
140
187
  value: any,
141
188
  options: IPipeOptionsFilter,
189
+ rootOpenapi: ISchemaObjectExtensionField | undefined,
142
190
  ) {
143
191
  if (__FieldsSystem.includes(key)) return;
144
- const fieldSchema = ZodMetadata.getFieldSchema(options.schema, key);
145
- if (!fieldSchema) return;
146
- const fieldSchemaInner = ZodMetadata.unwrapChained(fieldSchema);
147
- // openapi
148
- const openapi: ISchemaObjectExtensionField | undefined = ZodMetadata.getOpenapiMetadata(
149
- fieldSchema,
150
- ) as ISchemaObjectExtensionField | undefined;
151
- const [transformName] = openapi?.filter?.transform ?? ['a-web:base', undefined];
192
+ const info = this._resolveField(key, options, rootOpenapi);
193
+ if (!info) return;
194
+ const { fieldSchema, fieldSchemaInner, openapi, originalName, fullName, joinInfo } = info;
195
+ const [transformName, transformOptions] = openapi?.filter?.transform ?? [
196
+ 'a-web:base',
197
+ undefined,
198
+ ];
152
199
  const fieldNullable = fieldValue === null && isNullableSchema(fieldSchema);
153
200
  if (isNilOrEmptyString(fieldValue) && !fieldNullable) return;
154
- // name
155
- const originalName = openapi?.filter?.originalName ?? key;
156
- let fullName: string;
157
- // joins
158
- let joinInfo;
159
- if (openapi?.filter?.joinOn) {
160
- const joinType = openapi.filter.joinType ?? 'innerJoin';
161
- const joinTable = openapi.filter.table;
162
- const joinOn = openapi.filter.joinOn;
163
- joinInfo = [joinType, joinTable, joinOn];
164
- fullName = `${joinTable}.${originalName}`;
165
- } else {
166
- fullName = originalName;
167
- }
168
201
  // check where
169
202
  if (Object.prototype.hasOwnProperty.call(params.where, fullName)) return;
170
203
  // filter transform
171
- const [, transformOptions] = openapi?.filter?.transform ?? ['a-web:base', undefined];
172
204
  const transformOptions2 = this.bean.onion.filterTransform.getOnionOptionsDynamic(
173
205
  transformName as keyof IFilterTransformRecord,
174
206
  transformOptions,
@@ -182,7 +214,7 @@ export class PipeFilter
182
214
  if (!beanInstance.where) {
183
215
  throw new Error(`filterTransform.where not found: ${beanFullName}`);
184
216
  }
185
- const info = {
217
+ const transformInfo = {
186
218
  params,
187
219
  query: value,
188
220
  options,
@@ -194,17 +226,12 @@ export class PipeFilter
194
226
  schema: fieldSchema,
195
227
  openapi,
196
228
  };
197
- const resTransform = await beanInstance.where(info, transformOptions2);
229
+ const resTransform = await beanInstance.where(transformInfo, transformOptions2);
198
230
  if (resTransform !== undefined) {
199
231
  // where
200
232
  params.where[fullName] = resTransform;
201
233
  // join
202
- if (joinInfo) {
203
- if (!params.joins) params.joins = [];
204
- if (params.joins.findIndex(item => item[1] === joinInfo.joinTable) === -1) {
205
- params.joins.push(joinInfo);
206
- }
207
- }
234
+ this._addJoin(params, joinInfo);
208
235
  }
209
236
  }
210
237
 
@@ -212,10 +239,11 @@ export class PipeFilter
212
239
  params: TypeQueryParamsPatch,
213
240
  value: any,
214
241
  options: IPipeOptionsFilter,
242
+ rootOpenapi: ISchemaObjectExtensionField | undefined,
215
243
  ) {
216
244
  // loop
217
245
  for (const key in value) {
218
- await this._transformField(key, value[key], params, value, options);
246
+ await this._transformField(key, value[key], params, value, options, rootOpenapi);
219
247
  }
220
248
  }
221
249
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-vona",
3
- "version": "5.1.84",
3
+ "version": "5.1.85",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-cli",
3
- "version": "1.2.105",
3
+ "version": "1.2.106",
4
4
  "gitHead": "6f675a8cc46d596142c591c28a40cc4d82fcc6cc",
5
5
  "description": "zova cli",
6
6
  "keywords": [
@@ -44,7 +44,7 @@
44
44
  "@cabloy/process-helper": "^3.1.8",
45
45
  "fs-extra": "^11.3.5",
46
46
  "semver": "^7.6.2",
47
- "zova-cli-set-front": "^1.2.103"
47
+ "zova-cli-set-front": "^1.2.104"
48
48
  },
49
49
  "devDependencies": {
50
50
  "clean-package": "^2.2.0",
@@ -17,6 +17,7 @@ import {
17
17
  schemaRenderTableActionRowJsx,
18
18
  } from './component.ts';
19
19
  import {
20
+ schemaRenderColumn,
20
21
  schemaRenderDisableNotifyChanged,
21
22
  schemaRenderFieldSource,
22
23
  schemaRenderLayout,
@@ -35,6 +36,7 @@ export const ZovaRender = {
35
36
  disableNotifyChanged: schemaRenderDisableNotifyChanged,
36
37
  onEffect: schemaRenderOnEffect,
37
38
  fieldSource: schemaRenderFieldSource,
39
+ column: schemaRenderColumn,
38
40
  // component
39
41
  field: schemaRenderField,
40
42
  fieldJsx: schemaRenderFieldJsx,
@@ -1,8 +1,12 @@
1
1
  import type z from 'zod';
2
2
 
3
- import type { TypeFormSchemaScene, TypeFormFieldOnEffect } from 'zova-module-a-openapi';
4
- import type { IResourceFormFieldLayoutOptions } from 'zova-module-a-openapi';
5
- import type { TypeSchemaScene } from 'zova-module-a-openapi';
3
+ import type {
4
+ IResourceFormFieldLayoutOptions,
5
+ ITableColumnOptions,
6
+ TypeFormFieldOnEffect,
7
+ TypeFormSchemaScene,
8
+ TypeSchemaScene,
9
+ } from 'zova-module-a-openapi';
6
10
  import type { TypeSchemaOrderLevel } from 'zova-module-a-openapi';
7
11
 
8
12
  import { _generalSchemaRest, _order } from './inner.ts';
@@ -78,3 +82,9 @@ export function schemaRenderOrder<T extends z.ZodType>(
78
82
  return _generalSchemaRest(schema, options, scene);
79
83
  };
80
84
  }
85
+
86
+ export function schemaRenderColumn<T extends z.ZodType>(options: ITableColumnOptions) {
87
+ return function (schema: T): T {
88
+ return schema.openapi({ rest: { table: options } });
89
+ };
90
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-cli-set-front",
3
- "version": "1.2.103",
3
+ "version": "1.2.104",
4
4
  "gitHead": "6f675a8cc46d596142c591c28a40cc4d82fcc6cc",
5
5
  "description": "zova cli-set-front",
6
6
  "keywords": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova",
3
- "version": "5.1.155",
3
+ "version": "5.1.156",
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.88",
49
- "zova-suite-a-zova": "^5.1.154"
49
+ "zova-suite-a-zova": "^5.1.155"
50
50
  },
51
51
  "devDependencies": {
52
52
  "clean-package": "^2.2.0",
@@ -449,7 +449,7 @@ importers:
449
449
  specifier: ^7.6.2
450
450
  version: 7.8.5
451
451
  zova-cli-set-front:
452
- specifier: ^1.2.102
452
+ specifier: ^1.2.104
453
453
  version: link:../cli-set-front
454
454
  devDependencies:
455
455
  clean-package:
@@ -558,7 +558,7 @@ importers:
558
558
  specifier: ^1.1.17
559
559
  version: link:../../packages-utils/zova-openapi
560
560
  zova-vite:
561
- specifier: ^1.1.44
561
+ specifier: ^1.1.45
562
562
  version: link:../../packages-utils/zova-vite
563
563
  devDependencies:
564
564
  clean-package:
@@ -761,8 +761,8 @@ importers:
761
761
  specifier: ^7.28.6
762
762
  version: 7.29.7(@babel/core@7.29.7)
763
763
  '@cabloy/dotenv':
764
- specifier: ^1.2.8
765
- version: 1.2.8
764
+ specifier: ^1.2.9
765
+ version: 1.2.9
766
766
  '@cabloy/extend':
767
767
  specifier: ^3.2.8
768
768
  version: 3.2.8
@@ -870,7 +870,7 @@ importers:
870
870
  specifier: ^5.1.88
871
871
  version: link:../zova-core
872
872
  zova-suite-a-zova:
873
- specifier: ^5.1.154
873
+ specifier: ^5.1.155
874
874
  version: link:../../src/suite-vendor/a-zova
875
875
  devDependencies:
876
876
  clean-package:
@@ -977,7 +977,7 @@ importers:
977
977
  specifier: ^5.0.1
978
978
  version: link:modules/a-rbac
979
979
  zova-module-rest-resource:
980
- specifier: ^5.1.49
980
+ specifier: ^5.1.50
981
981
  version: link:modules/rest-resource
982
982
 
983
983
  src/suite-vendor/a-cabloy/modules/a-rbac:
@@ -1076,7 +1076,7 @@ importers:
1076
1076
  specifier: ^5.1.25
1077
1077
  version: link:modules/a-fetch
1078
1078
  zova-module-a-form:
1079
- specifier: ^5.1.50
1079
+ specifier: ^5.1.51
1080
1080
  version: link:modules/a-form
1081
1081
  zova-module-a-icon:
1082
1082
  specifier: ^5.1.27
@@ -1094,7 +1094,7 @@ importers:
1094
1094
  specifier: ^5.1.36
1095
1095
  version: link:modules/a-model
1096
1096
  zova-module-a-openapi:
1097
- specifier: ^5.1.51
1097
+ specifier: ^5.1.52
1098
1098
  version: link:modules/a-openapi
1099
1099
  zova-module-a-router:
1100
1100
  specifier: ^5.1.34
@@ -1118,7 +1118,7 @@ importers:
1118
1118
  specifier: ^5.1.35
1119
1119
  version: link:modules/a-style
1120
1120
  zova-module-a-table:
1121
- specifier: ^5.1.38
1121
+ specifier: ^5.1.39
1122
1122
  version: link:modules/a-table
1123
1123
  zova-module-a-zod:
1124
1124
  specifier: ^5.1.37
@@ -2311,8 +2311,8 @@ packages:
2311
2311
  '@cabloy/deps@1.1.8':
2312
2312
  resolution: {integrity: sha512-CWaVGSwPI5qLSuRF+WmB+1CwbRe9+PR+nkUmKc9/Dj7sB75qPXLTYACn23T/jIylbDbWCL82LoOa455Vgseyeg==}
2313
2313
 
2314
- '@cabloy/dotenv@1.2.8':
2315
- resolution: {integrity: sha512-1Xn0IsfMVWSZW0Gi7MBGbW6JL8kD7GN/B199RbDlIIy3PbSTdbKF2Gh/NIR2FNCChD1kQaG0FW/mR1tKgMNxbg==}
2314
+ '@cabloy/dotenv@1.2.9':
2315
+ resolution: {integrity: sha512-iR7KWj1YI2SiTjlcSMnZ/wYw/PMcgAJRvOHdWDrwehY8YOuG6uKPTez1hTCR4kfrhiBnZwM/acZvmqjflx18GA==}
2316
2316
 
2317
2317
  '@cabloy/extend@3.2.8':
2318
2318
  resolution: {integrity: sha512-BrXYUtlC1kFY33hNxL/hEaS7wW8TsOuu22k0VCEtzg2iw+USkb4BqONth5Uv2pJcIlDMeWx8A8aUIRF3WQ2ckQ==}
@@ -5138,8 +5138,8 @@ packages:
5138
5138
  capital-case@1.0.4:
5139
5139
  resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
5140
5140
 
5141
- cascade-extend@2.2.8:
5142
- resolution: {integrity: sha512-cs8DkxDoYv0YSFnbZyn/xaaodKgp+iV9xv8IeAWpYRyM5vxIXGKS8Ej0jLwneFFYTaF7juIjOlktOjEidDZURA==}
5141
+ cascade-extend@2.2.9:
5142
+ resolution: {integrity: sha512-YevoTZSywFhLNnHWh9GSzHgrwAJmsDzR0sQeOZ8BG5NlwF8MyH0457ocLVyGgB/m9rTHmRXJkzzvPuDcjpTtfQ==}
5143
5143
 
5144
5144
  ccount@1.1.0:
5145
5145
  resolution: {integrity: sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==}
@@ -8834,9 +8834,9 @@ snapshots:
8834
8834
 
8835
8835
  '@cabloy/deps@1.1.8': {}
8836
8836
 
8837
- '@cabloy/dotenv@1.2.8':
8837
+ '@cabloy/dotenv@1.2.9':
8838
8838
  dependencies:
8839
- cascade-extend: 2.2.8
8839
+ cascade-extend: 2.2.9
8840
8840
  dotenv: 16.6.1
8841
8841
  dotenv-expand: 11.0.7
8842
8842
  globby: 16.2.0
@@ -11389,7 +11389,7 @@ snapshots:
11389
11389
  tslib: 2.8.1
11390
11390
  upper-case-first: 2.0.2
11391
11391
 
11392
- cascade-extend@2.2.8:
11392
+ cascade-extend@2.2.9:
11393
11393
  dependencies:
11394
11394
  '@cabloy/extend': 3.2.8
11395
11395