cabloy 5.1.248 → 5.1.250
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cabloy-version +1 -1
- package/.github/workflows/create-cabloy.yml +50 -3
- package/.vscode/settings.json +1 -2
- package/CHANGELOG.md +31 -0
- package/package.json +1 -7
- package/repo-agent-governance/managed-assets.json +12 -12
- package/repo-agent-governance/skills/cabloy-spec-execution/references/status-and-evidence.md +1 -1
- package/repo-agent-governance/skills/cabloy-spec-generation/references/canonical-spec-input.md +1 -1
- package/repo-agent-governance/skills/cabloy-spec-generation/references/repo-specs-document-set.md +2 -2
- package/repo-agent-governance/skills/cabloy-spec-generation/references/traceability-and-status-rules.md +1 -1
- package/repo-agent-governance/tools/spec-charts/generate-implementation-charts.mjs +73 -22
- package/repo-agent-governance/tools/spec-charts/generate-implementation-charts.test.mjs +98 -7
- package/repo-docs/ai/playbook-spec-execution.md +1 -1
- package/repo-docs/backend/crud-workflow.md +92 -1
- package/repo-docs/backend/dto-guide.md +16 -1
- package/repo-docs/backend/dto-infer-generation.md +23 -5
- package/repo-docs/backend/orm-aggregate-group-guide.md +32 -0
- package/repo-docs/backend/validation-guide.md +38 -2
- package/repo-e2e/specs/cabloy-basic.spec.ts +9 -2
- package/vona/package.original.json +1 -7
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/aggregate/src/dto/{{resourceName}}AggregateRes.tsx_ +11 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/common/src/lib/{{resourceName}}Analysis.ts_ +14 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/common/test/{{resourceName}}Analysis.test.ts_ +81 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudAnalysis/group/src/dto/{{resourceName}}GroupResItem.tsx_ +11 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/controller/{{resourceName}}.ts_ +18 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}SelectReq.tsx_ +2 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/service/{{resourceName}}.ts_ +14 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/test/{{resourceName}}.test.ts_ +4 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/3-en-us.ts +2 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +2 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/controller/{{resourceName}}.ts_ +18 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}SelectReq.tsx_ +2 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/service/{{resourceName}}.ts_ +14 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/test/{{resourceName}}.test.ts_ +1 -1
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/3-en-us.ts +2 -0
- package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/snippets/4-zh-cn.ts +2 -0
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudBasic.ts +2 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudStart.ts +2 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts +9 -1
- package/vona/packages-cli/cli-set-api/src/lib/crudAnalysis.ts +11 -0
- package/vona/packages-cli/cli-set-api/test/crudAnalysis.test.ts +385 -0
- package/vona/packages-utils/babel-plugin-vona-bean-module/package.json +1 -1
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +76 -1008
- package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +18 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/controller/student.ts +28 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentAggregateRes.tsx +11 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentGroupResItem.tsx +11 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/lib/studentAnalysis.ts +12 -0
- package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +22 -1
- package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +4 -0
- package/vona/src/suite/a-training/modules/training-student/test/studentAnalysis.test.ts +422 -0
- package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
- package/vona/src/suite-vendor/a-captcha/modules/a-captcha/package.json +1 -1
- package/vona/src/suite-vendor/a-captcha/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-hmr/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-locale/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-openapi/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/utils.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/.metadata/index.ts +26 -26
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/aggregateResult.ts +53 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/controls.ts +163 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/execute.ts +49 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/index.ts +3 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/analysis/policy.ts +140 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_cache.ts +4 -2
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/bean.model/bean.model_crud_inner.ts +8 -3
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dto.ts +3 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAggregate.ts +4 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoAnalysis.ts +34 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/analysis.ts +137 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/relationsAggr.ts +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/test/aggregateResult.test.ts +81 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/test/analysis.test.ts +208 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/test/analysis.types.test.ts +112 -0
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-queue/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ratelimit/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/.metadata/index.ts +40 -40
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/bean/pipe.filter.ts +44 -3
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/analysisFilter.ts +69 -0
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/arguments.ts +6 -4
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/types/dto.ts +2 -1
- package/vona/src/suite-vendor/a-vona/modules/a-web/src/types/filter.ts +7 -2
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/package.original.json +0 -6
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/package.json +2 -2
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-utils/zova-vite/package.json +1 -1
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/pnpm-lock.yaml +11 -963
- package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.header.tsx +4 -1
- package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/render.tabs.tsx +2 -2
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +16 -2
- package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +201 -7
- package/zova/src/suite/a-training/modules/training-student/src/api/trainingStudent.ts +42 -0
- package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +10 -0
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssrserver/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +5 -5
- package/vona/.textlintrc.json +0 -19
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableIdentity } from 'table-identity';
|
|
2
|
-
import type { IQueryParams } from 'vona-module-a-orm';
|
|
2
|
+
import type { IQueryParams, TypeAnalysisGroupParams, TypeAnalysisAggregateParams } from 'vona-module-a-orm';
|
|
3
3
|
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
4
4
|
|
|
5
5
|
import { BeanBase } from 'vona';
|
|
@@ -17,6 +17,9 @@ import { Dto<%=argv.resourceNameCapitalize%>SelectReq } from '../dto/<%=argv.res
|
|
|
17
17
|
import { Dto<%=argv.resourceNameCapitalize%>SelectRes } from '../dto/<%=argv.resourceName%>SelectRes.tsx';
|
|
18
18
|
import { Dto<%=argv.resourceNameCapitalize%>Update } from '../dto/<%=argv.resourceName%>Update.tsx';
|
|
19
19
|
import { Dto<%=argv.resourceNameCapitalize%>View } from '../dto/<%=argv.resourceName%>View.tsx';
|
|
20
|
+
import { Dto<%=argv.resourceNameCapitalize%>GroupResItem } from '../dto/<%=argv.resourceName%>GroupResItem.tsx';
|
|
21
|
+
import { Dto<%=argv.resourceNameCapitalize%>AggregateRes } from '../dto/<%=argv.resourceName%>AggregateRes.tsx';
|
|
22
|
+
import type { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
20
23
|
|
|
21
24
|
export interface IControllerOptions<%=argv.resourceNameCapitalize%> extends IDecoratorControllerOptions {}
|
|
22
25
|
|
|
@@ -39,6 +42,20 @@ export class Controller<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
|
39
42
|
return await this.scope.service.<%=argv.resourceName%>.select(params);
|
|
40
43
|
}
|
|
41
44
|
|
|
45
|
+
@Web.get('group', { summary: $locale('<%=argv.resourceNameCapitalize%>Group') })
|
|
46
|
+
@Api.body(v.array(v.object(Dto<%=argv.resourceNameCapitalize%>GroupResItem)))
|
|
47
|
+
@Passport.rbac({ actionInherit: 'select' })
|
|
48
|
+
async group(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq, { mode: 'group' }) params: TypeAnalysisGroupParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>GroupResItem[]> {
|
|
49
|
+
return await this.scope.service.<%=argv.resourceName%>.group(params);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Web.get('aggregate', { summary: $locale('<%=argv.resourceNameCapitalize%>Aggregate') })
|
|
53
|
+
@Api.body(Dto<%=argv.resourceNameCapitalize%>AggregateRes)
|
|
54
|
+
@Passport.rbac({ actionInherit: 'select' })
|
|
55
|
+
async aggregate(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq, { mode: 'aggregate' }) params: TypeAnalysisAggregateParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>AggregateRes> {
|
|
56
|
+
return await this.scope.service.<%=argv.resourceName%>.aggregate(params);
|
|
57
|
+
}
|
|
58
|
+
|
|
42
59
|
@Web.get(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>View') })
|
|
43
60
|
@Api.body(v.optional(), v.object(Dto<%=argv.resourceNameCapitalize%>View))
|
|
44
61
|
@Passport.rbac()
|
|
@@ -7,10 +7,12 @@ import z from 'zod';
|
|
|
7
7
|
import { ZovaRender } from 'zova-rest-cabloy-basic-admin';
|
|
8
8
|
|
|
9
9
|
import { Entity<%=argv.resourceNameCapitalize%> } from '../entity/<%=argv.resourceName%>.tsx';
|
|
10
|
+
import { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
10
11
|
|
|
11
12
|
export interface IDtoOptions<%=argv.resourceNameCapitalize%>SelectReq extends IDecoratorDtoOptions {}
|
|
12
13
|
|
|
13
14
|
@Dto<IDtoOptions<%=argv.resourceNameCapitalize%>SelectReq>({
|
|
15
|
+
analysis: <%=argv.resourceName%>Analysis,
|
|
14
16
|
openapi: { filter: { table: '<%=argv.moduleResourceName%>' } },
|
|
15
17
|
fields: {
|
|
16
18
|
name: $makeSchema(v.optional(), z.string()),
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { TableIdentity } from 'table-identity';
|
|
2
|
-
import type { IQueryParams } from 'vona-module-a-orm';
|
|
2
|
+
import type { IQueryParams, TypeAnalysisGroupParams, TypeAnalysisAggregateParams } from 'vona-module-a-orm';
|
|
3
3
|
|
|
4
4
|
import { BeanBase } from 'vona';
|
|
5
5
|
import { Service } from 'vona-module-a-bean';
|
|
6
6
|
import { Core } from 'vona-module-a-core';
|
|
7
|
+
import { $executeAnalysisGroup, $executeAnalysisAggregate } from 'vona-module-a-orm';
|
|
7
8
|
|
|
8
9
|
import type { Dto<%=argv.resourceNameCapitalize%>Create } from '../dto/<%=argv.resourceName%>Create.tsx';
|
|
9
10
|
import type { Dto<%=argv.resourceNameCapitalize%>SelectRes } from '../dto/<%=argv.resourceName%>SelectRes.tsx';
|
|
@@ -11,6 +12,10 @@ import type { Dto<%=argv.resourceNameCapitalize%>Update } from '../dto/<%=argv.r
|
|
|
11
12
|
import type { Dto<%=argv.resourceNameCapitalize%>View } from '../dto/<%=argv.resourceName%>View.tsx';
|
|
12
13
|
import type { Entity<%=argv.resourceNameCapitalize%> } from '../entity/<%=argv.resourceName%>.tsx';
|
|
13
14
|
import type { Model<%=argv.resourceNameCapitalize%> } from '../model/<%=argv.resourceName%>.ts';
|
|
15
|
+
import type { Dto<%=argv.resourceNameCapitalize%>GroupResItem } from '../dto/<%=argv.resourceName%>GroupResItem.tsx';
|
|
16
|
+
import type { Dto<%=argv.resourceNameCapitalize%>AggregateRes } from '../dto/<%=argv.resourceName%>AggregateRes.tsx';
|
|
17
|
+
|
|
18
|
+
import { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
14
19
|
|
|
15
20
|
@Service()
|
|
16
21
|
export class Service<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
@@ -22,6 +27,14 @@ export class Service<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
|
22
27
|
return await this.scope.model.<%=argv.resourceName%>.selectAndCount(params);
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
async group(params?: TypeAnalysisGroupParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>GroupResItem[]> {
|
|
31
|
+
return await $executeAnalysisGroup(this.scope.model.<%=argv.resourceName%>, <%=argv.resourceName%>Analysis, params);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async aggregate(params?: TypeAnalysisAggregateParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>AggregateRes> {
|
|
35
|
+
return await $executeAnalysisAggregate(this.scope.model.<%=argv.resourceName%>, <%=argv.resourceName%>Analysis, params);
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
async view(id: TableIdentity): Promise<Dto<%=argv.resourceNameCapitalize%>View | undefined> {
|
|
26
39
|
return await this.scope.model.<%=argv.resourceName%>.getById(id);
|
|
27
40
|
}
|
|
@@ -29,6 +29,8 @@ describe('<%=argv.resourceName%>.test.ts', { concurrency: false }, () => {
|
|
|
29
29
|
const expectedSummaries = {
|
|
30
30
|
create: ['post', moduleApiPath, 'Create <%=argv.resourceNameCapitalize%>'],
|
|
31
31
|
select: ['get', moduleApiPath, 'Query <%=argv.resourceNameCapitalize%> List'],
|
|
32
|
+
group: ['get', `${moduleApiPath}/group`, 'Group <%=argv.resourceNameCapitalize%>'],
|
|
33
|
+
aggregate: ['get', `${moduleApiPath}/aggregate`, 'Aggregate <%=argv.resourceNameCapitalize%>'],
|
|
32
34
|
view: ['get', `${moduleApiPath}/{id}`, 'View <%=argv.resourceNameCapitalize%>'],
|
|
33
35
|
update: ['patch', `${moduleApiPath}/{id}`, 'Update <%=argv.resourceNameCapitalize%>'],
|
|
34
36
|
delete: ['delete', `${moduleApiPath}/{id}`, 'Delete <%=argv.resourceNameCapitalize%>'],
|
|
@@ -54,6 +56,8 @@ describe('<%=argv.resourceName%>.test.ts', { concurrency: false }, () => {
|
|
|
54
56
|
const expectedInherits = {
|
|
55
57
|
create: undefined,
|
|
56
58
|
select: undefined,
|
|
59
|
+
group: `${controllerBeanFullName}#select`,
|
|
60
|
+
aggregate: `${controllerBeanFullName}#select`,
|
|
57
61
|
view: undefined,
|
|
58
62
|
update: undefined,
|
|
59
63
|
delete: undefined,
|
|
@@ -40,6 +40,8 @@ export default metadataCustomSnippet({
|
|
|
40
40
|
[`${resource}Update`]: `Update ${resource}`,
|
|
41
41
|
[`${resource}Delete`]: `Delete ${resource}`,
|
|
42
42
|
[`${resource}DeleteBulk`]: `Bulk Delete ${resource}`,
|
|
43
|
+
[`${resource}Group`]: `Group ${resource}`,
|
|
44
|
+
[`${resource}Aggregate`]: `Aggregate ${resource}`,
|
|
43
45
|
};
|
|
44
46
|
return locale_transform({ ast, argv, resources });
|
|
45
47
|
},
|
|
@@ -23,6 +23,8 @@ export default metadataCustomSnippet({
|
|
|
23
23
|
[`${resource}Update`]: `更新${resource}`,
|
|
24
24
|
[`${resource}Delete`]: `删除${resource}`,
|
|
25
25
|
[`${resource}DeleteBulk`]: `批量删除${resource}`,
|
|
26
|
+
[`${resource}Group`]: `${resource}分组统计`,
|
|
27
|
+
[`${resource}Aggregate`]: `${resource}汇总统计`,
|
|
26
28
|
};
|
|
27
29
|
return locale_transform({ ast, argv, resources });
|
|
28
30
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableIdentity } from 'table-identity';
|
|
2
|
-
import type { IQueryParams } from 'vona-module-a-orm';
|
|
2
|
+
import type { IQueryParams, TypeAnalysisGroupParams, TypeAnalysisAggregateParams } from 'vona-module-a-orm';
|
|
3
3
|
import type { IRbacScopeAccess } from 'vona-module-a-rbac';
|
|
4
4
|
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
5
5
|
|
|
@@ -18,6 +18,9 @@ import { Dto<%=argv.resourceNameCapitalize%>SelectReq } from '../dto/<%=argv.res
|
|
|
18
18
|
import { Dto<%=argv.resourceNameCapitalize%>SelectRes } from '../dto/<%=argv.resourceName%>SelectRes.tsx';
|
|
19
19
|
import { Dto<%=argv.resourceNameCapitalize%>Update } from '../dto/<%=argv.resourceName%>Update.tsx';
|
|
20
20
|
import { Dto<%=argv.resourceNameCapitalize%>View } from '../dto/<%=argv.resourceName%>View.tsx';
|
|
21
|
+
import { Dto<%=argv.resourceNameCapitalize%>GroupResItem } from '../dto/<%=argv.resourceName%>GroupResItem.tsx';
|
|
22
|
+
import { Dto<%=argv.resourceNameCapitalize%>AggregateRes } from '../dto/<%=argv.resourceName%>AggregateRes.tsx';
|
|
23
|
+
import type { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
21
24
|
|
|
22
25
|
export interface IControllerOptions<%=argv.resourceNameCapitalize%> extends IDecoratorControllerOptions {}
|
|
23
26
|
|
|
@@ -40,6 +43,20 @@ export class Controller<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
|
40
43
|
return await this.scope.service.<%=argv.resourceName%>.select(params);
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
@Web.get('group', { summary: $locale('<%=argv.resourceNameCapitalize%>Group') })
|
|
47
|
+
@Api.body(v.array(v.object(Dto<%=argv.resourceNameCapitalize%>GroupResItem)))
|
|
48
|
+
@Passport.rbac({ actionInherit: 'select' })
|
|
49
|
+
async group(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq, { mode: 'group' }) params: TypeAnalysisGroupParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>GroupResItem[]> {
|
|
50
|
+
return await this.scope.service.<%=argv.resourceName%>.group(params);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Web.get('aggregate', { summary: $locale('<%=argv.resourceNameCapitalize%>Aggregate') })
|
|
54
|
+
@Api.body(Dto<%=argv.resourceNameCapitalize%>AggregateRes)
|
|
55
|
+
@Passport.rbac({ actionInherit: 'select' })
|
|
56
|
+
async aggregate(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq, { mode: 'aggregate' }) params: TypeAnalysisAggregateParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>AggregateRes> {
|
|
57
|
+
return await this.scope.service.<%=argv.resourceName%>.aggregate(params);
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
@Web.get(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>View') })
|
|
44
61
|
@Api.body(v.optional(), v.object(Dto<%=argv.resourceNameCapitalize%>View))
|
|
45
62
|
@Passport.rbac()
|
|
@@ -7,10 +7,12 @@ import z from 'zod';
|
|
|
7
7
|
import { ZovaRender } from 'zova-rest-cabloy-start-admin';
|
|
8
8
|
|
|
9
9
|
import { Entity<%=argv.resourceNameCapitalize%> } from '../entity/<%=argv.resourceName%>.tsx';
|
|
10
|
+
import { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
10
11
|
|
|
11
12
|
export interface IDtoOptions<%=argv.resourceNameCapitalize%>SelectReq extends IDecoratorDtoOptions {}
|
|
12
13
|
|
|
13
14
|
@Dto<IDtoOptions<%=argv.resourceNameCapitalize%>SelectReq>({
|
|
15
|
+
analysis: <%=argv.resourceName%>Analysis,
|
|
14
16
|
openapi: { filter: { table: '<%=argv.moduleResourceName%>' } },
|
|
15
17
|
fields: {
|
|
16
18
|
name: $makeSchema(v.optional(), z.string()),
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { TableIdentity } from 'table-identity';
|
|
2
|
-
import type { IQueryParams } from 'vona-module-a-orm';
|
|
2
|
+
import type { IQueryParams, TypeAnalysisGroupParams, TypeAnalysisAggregateParams } from 'vona-module-a-orm';
|
|
3
3
|
|
|
4
4
|
import { BeanBase } from 'vona';
|
|
5
5
|
import { Service } from 'vona-module-a-bean';
|
|
6
6
|
import { Core } from 'vona-module-a-core';
|
|
7
|
+
import { $executeAnalysisGroup, $executeAnalysisAggregate } from 'vona-module-a-orm';
|
|
7
8
|
|
|
8
9
|
import type { Dto<%=argv.resourceNameCapitalize%>Create } from '../dto/<%=argv.resourceName%>Create.tsx';
|
|
9
10
|
import type { Dto<%=argv.resourceNameCapitalize%>SelectRes } from '../dto/<%=argv.resourceName%>SelectRes.tsx';
|
|
@@ -11,6 +12,10 @@ import type { Dto<%=argv.resourceNameCapitalize%>Update } from '../dto/<%=argv.r
|
|
|
11
12
|
import type { Dto<%=argv.resourceNameCapitalize%>View } from '../dto/<%=argv.resourceName%>View.tsx';
|
|
12
13
|
import type { Entity<%=argv.resourceNameCapitalize%> } from '../entity/<%=argv.resourceName%>.tsx';
|
|
13
14
|
import type { Model<%=argv.resourceNameCapitalize%> } from '../model/<%=argv.resourceName%>.ts';
|
|
15
|
+
import type { Dto<%=argv.resourceNameCapitalize%>GroupResItem } from '../dto/<%=argv.resourceName%>GroupResItem.tsx';
|
|
16
|
+
import type { Dto<%=argv.resourceNameCapitalize%>AggregateRes } from '../dto/<%=argv.resourceName%>AggregateRes.tsx';
|
|
17
|
+
|
|
18
|
+
import { <%=argv.resourceName%>Analysis } from '../lib/<%=argv.resourceName%>Analysis.ts';
|
|
14
19
|
|
|
15
20
|
@Service()
|
|
16
21
|
export class Service<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
@@ -22,6 +27,14 @@ export class Service<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
|
22
27
|
return await this.scope.model.<%=argv.resourceName%>.selectAndCount(params);
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
async group(params?: TypeAnalysisGroupParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>GroupResItem[]> {
|
|
31
|
+
return await $executeAnalysisGroup(this.scope.model.<%=argv.resourceName%>, <%=argv.resourceName%>Analysis, params);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async aggregate(params?: TypeAnalysisAggregateParams<typeof <%=argv.resourceName%>Analysis>): Promise<Dto<%=argv.resourceNameCapitalize%>AggregateRes> {
|
|
35
|
+
return await $executeAnalysisAggregate(this.scope.model.<%=argv.resourceName%>, <%=argv.resourceName%>Analysis, params);
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
async view(id: TableIdentity): Promise<Dto<%=argv.resourceNameCapitalize%>View | undefined> {
|
|
26
39
|
return await this.scope.model.<%=argv.resourceName%>.getById(id);
|
|
27
40
|
}
|
|
@@ -19,7 +19,7 @@ describe('<%=argv.resourceName%>.test.ts', () => {
|
|
|
19
19
|
await app.bean.passport.signinMock();
|
|
20
20
|
try {
|
|
21
21
|
app.bean.passport.current!.roles = [];
|
|
22
|
-
const actions = ['create', 'select', 'view', 'update', 'delete'];
|
|
22
|
+
const actions = ['create', 'select', 'view', 'update', 'delete', 'group', 'aggregate'];
|
|
23
23
|
const permissions = await Promise.all(
|
|
24
24
|
actions.map(action =>
|
|
25
25
|
app.bean.permission.retrievePermissionAction(
|
|
@@ -40,6 +40,8 @@ export default metadataCustomSnippet({
|
|
|
40
40
|
[`${resource}View`]: `View ${resource}`,
|
|
41
41
|
[`${resource}Update`]: `Update ${resource}`,
|
|
42
42
|
[`${resource}Delete`]: `Delete ${resource}`,
|
|
43
|
+
[`${resource}Group`]: `Group ${resource}`,
|
|
44
|
+
[`${resource}Aggregate`]: `Aggregate ${resource}`,
|
|
43
45
|
};
|
|
44
46
|
return locale_transform({ ast, argv, resources });
|
|
45
47
|
},
|
|
@@ -23,6 +23,8 @@ export default metadataCustomSnippet({
|
|
|
23
23
|
[`${resource}View`]: `查看${resource}`,
|
|
24
24
|
[`${resource}Update`]: `更新${resource}`,
|
|
25
25
|
[`${resource}Delete`]: `删除${resource}`,
|
|
26
|
+
[`${resource}Group`]: `${resource}分组统计`,
|
|
27
|
+
[`${resource}Aggregate`]: `${resource}汇总统计`,
|
|
26
28
|
};
|
|
27
29
|
return locale_transform({ ast, argv, resources });
|
|
28
30
|
},
|
|
@@ -5,6 +5,7 @@ import { combineApiPathControllerAndActionRaw } from '@cabloy/utils';
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
|
|
8
|
+
import { renderCrudAnalysis } from '../crudAnalysis.ts';
|
|
8
9
|
import { __ThisSetName__ } from '../this.ts';
|
|
9
10
|
|
|
10
11
|
declare module '@cabloy/cli' {
|
|
@@ -55,6 +56,7 @@ export class CliToolsCrudBasic extends BeanCliBase {
|
|
|
55
56
|
snippetsPath: 'tools/crudBasic/snippets',
|
|
56
57
|
boilerplatePath: 'tools/crudBasic/boilerplate',
|
|
57
58
|
});
|
|
59
|
+
await renderCrudAnalysis(this, targetDir, __ThisSetName__);
|
|
58
60
|
// tools.metadata
|
|
59
61
|
if (!argv.nometadata) {
|
|
60
62
|
await this.helper.invokeCli([':tools:metadata', moduleName], { cwd: argv.projectPath });
|
|
@@ -5,6 +5,7 @@ import { combineApiPathControllerAndActionRaw } from '@cabloy/utils';
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
|
|
8
|
+
import { renderCrudAnalysis } from '../crudAnalysis.ts';
|
|
8
9
|
import { __ThisSetName__ } from '../this.ts';
|
|
9
10
|
|
|
10
11
|
declare module '@cabloy/cli' {
|
|
@@ -55,6 +56,7 @@ export class CliToolsCrudStart extends BeanCliBase {
|
|
|
55
56
|
snippetsPath: 'tools/crudStart/snippets',
|
|
56
57
|
boilerplatePath: 'tools/crudStart/boilerplate',
|
|
57
58
|
});
|
|
59
|
+
await renderCrudAnalysis(this, targetDir, __ThisSetName__);
|
|
58
60
|
// tools.metadata
|
|
59
61
|
if (!argv.nometadata) {
|
|
60
62
|
await this.helper.invokeCli([':tools:metadata', moduleName], { cwd: argv.projectPath });
|
|
@@ -613,6 +613,8 @@ export class CliToolsMasterDetail extends BeanCliBase {
|
|
|
613
613
|
service: path.join(detailRoot, 'src/service', `${argv.detailResourceName}.ts`),
|
|
614
614
|
dtoDir: path.join(detailRoot, 'src/dto'),
|
|
615
615
|
test: path.join(detailRoot, 'test', `${argv.detailResourceName}.test.ts`),
|
|
616
|
+
analysisTest: path.join(detailRoot, 'test', `${argv.detailResourceName}Analysis.test.ts`),
|
|
617
|
+
analysis: path.join(detailRoot, 'src/lib', `${argv.detailResourceName}Analysis.ts`),
|
|
616
618
|
metaVersion: path.join(detailRoot, 'src/bean', 'meta.version.ts'),
|
|
617
619
|
metaIndex: path.join(detailRoot, 'src/bean', 'meta.index.ts'),
|
|
618
620
|
};
|
|
@@ -627,7 +629,13 @@ export class CliToolsMasterDetail extends BeanCliBase {
|
|
|
627
629
|
|
|
628
630
|
private _removeStandaloneDetailSurface() {
|
|
629
631
|
const files = this._detailPaths();
|
|
630
|
-
for (const file of [
|
|
632
|
+
for (const file of [
|
|
633
|
+
files.controller,
|
|
634
|
+
files.service,
|
|
635
|
+
files.test,
|
|
636
|
+
files.analysisTest,
|
|
637
|
+
files.analysis,
|
|
638
|
+
]) {
|
|
631
639
|
if (fs.existsSync(file)) {
|
|
632
640
|
fs.rmSync(file, { force: true });
|
|
633
641
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BeanCliBase } from '@cabloy/cli';
|
|
2
|
+
|
|
3
|
+
export async function renderCrudAnalysis(cli: BeanCliBase, targetDir: string, setName: string) {
|
|
4
|
+
for (const part of ['common', 'group', 'aggregate']) {
|
|
5
|
+
await cli.template.renderBoilerplateAndSnippets({
|
|
6
|
+
targetDir,
|
|
7
|
+
setName,
|
|
8
|
+
boilerplatePath: `tools/crudAnalysis/${part}`,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|