vona-cli-set-api 1.1.149 → 1.1.150
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/cli/templates/tools/crudBasic/boilerplate/src/controller/{{resourceName}}.ts_ +7 -7
- package/cli/templates/tools/crudBasic/boilerplate/test/{{resourceName}}.test.ts_ +93 -39
- package/cli/templates/tools/crudBasic/snippets/3-en-us.ts +1 -1
- package/cli/templates/tools/crudBasic/snippets/4-zh-cn.ts +1 -1
- package/dist-cli/templates/tools/crudBasic/snippets/3-en-us.js +1 -1
- package/dist-cli/templates/tools/crudBasic/snippets/4-zh-cn.js +1 -1
- package/package.json +2 -2
|
@@ -27,42 +27,42 @@ export interface IControllerOptions<%=argv.resourceNameCapitalize%> extends IDec
|
|
|
27
27
|
export class Controller<%=argv.resourceNameCapitalize%> extends BeanBase {
|
|
28
28
|
@Web.post('', { summary: $locale('<%=argv.resourceNameCapitalize%>Create') })
|
|
29
29
|
@Api.body(v.tableIdentity())
|
|
30
|
-
@Passport.
|
|
30
|
+
@Passport.rbac()
|
|
31
31
|
async create(@Arg.body() <%=argv.resourceName%>: Dto<%=argv.resourceNameCapitalize%>Create): Promise<TableIdentity> {
|
|
32
32
|
return (await this.scope.service.<%=argv.resourceName%>.create(<%=argv.resourceName%>)).id;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
@Web.get('', { summary: $locale('<%=argv.resourceNameCapitalize%>Select') })
|
|
36
36
|
@Api.body(Dto<%=argv.resourceNameCapitalize%>SelectRes)
|
|
37
|
-
@Passport.
|
|
37
|
+
@Passport.rbac()
|
|
38
38
|
async select(@Arg.filter(Dto<%=argv.resourceNameCapitalize%>SelectReq) params: IQueryParams<Model<%=argv.resourceNameCapitalize%>>): Promise<Dto<%=argv.resourceNameCapitalize%>SelectRes> {
|
|
39
39
|
return await this.scope.service.<%=argv.resourceName%>.select(params);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
@Web.get(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>View') })
|
|
43
43
|
@Api.body(v.optional(), v.object(Dto<%=argv.resourceNameCapitalize%>View))
|
|
44
|
-
@Passport.
|
|
44
|
+
@Passport.rbac()
|
|
45
45
|
async view(@Arg.param('id', v.tableIdentity()) id: TableIdentity): Promise<Dto<%=argv.resourceNameCapitalize%>View | undefined> {
|
|
46
46
|
return await this.scope.service.<%=argv.resourceName%>.view(id);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
@Web.patch(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>Update') })
|
|
50
50
|
@Api.body(z.null())
|
|
51
|
-
@Passport.
|
|
51
|
+
@Passport.rbac()
|
|
52
52
|
async update(@Arg.param('id', v.tableIdentity()) id: TableIdentity, @Arg.body() <%=argv.resourceName%>: Dto<%=argv.resourceNameCapitalize%>Update): Promise<void> {
|
|
53
53
|
await this.scope.service.<%=argv.resourceName%>.update(id, <%=argv.resourceName%>);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
@Web.delete(':id', { summary: $locale('<%=argv.resourceNameCapitalize%>Delete') })
|
|
57
57
|
@Api.body(z.null())
|
|
58
|
-
@Passport.
|
|
58
|
+
@Passport.rbac()
|
|
59
59
|
async delete(@Arg.param('id', v.tableIdentity()) id: TableIdentity): Promise<void> {
|
|
60
60
|
await this.scope.service.<%=argv.resourceName%>.delete(id);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
@Web.post('bulk/delete', { summary: $locale('
|
|
63
|
+
@Web.post('bulk/delete', { summary: $locale('<%=argv.resourceNameCapitalize%>DeleteBulk') })
|
|
64
64
|
@Api.body(z.null())
|
|
65
|
-
@Passport.
|
|
65
|
+
@Passport.rbac({ actionInherit: 'delete' })
|
|
66
66
|
async deleteBulk(@Arg.body() command: Dto<%=argv.resourceNameCapitalize%>DeleteBulk): Promise<void> {
|
|
67
67
|
await this.scope.service.<%=argv.resourceName%>.deleteBulk(command.ids);
|
|
68
68
|
}
|
|
@@ -1,12 +1,74 @@
|
|
|
1
1
|
import type { Dto<%=argv.resourceNameCapitalize%>Create, Dto<%=argv.resourceNameCapitalize%>SelectRes, Dto<%=argv.resourceNameCapitalize%>Update, Entity<%=argv.resourceNameCapitalize%> } from 'vona-module-<%=argv.moduleInfo.relativeName%>';
|
|
2
|
+
|
|
2
3
|
import assert from 'node:assert';
|
|
3
4
|
import { describe, it } from 'node:test';
|
|
5
|
+
import { appMetadata } from 'vona';
|
|
4
6
|
import { app } from 'vona-mock';
|
|
7
|
+
import { SymbolOpenApiOptions } from 'vona-module-a-openapiutils';
|
|
8
|
+
|
|
9
|
+
describe('<%=argv.resourceName%>.test.ts', { concurrency: false }, () => {
|
|
10
|
+
it('action:<%=argv.resourceName%>:openapiMetadata', async () => {
|
|
11
|
+
await app.bean.executor.mockCtx(async () => {
|
|
12
|
+
const controllerBeanFullName = '<%=argv.moduleInfo.relativeName%>.controller.<%=argv.resourceName%>';
|
|
13
|
+
const controller = app.bean.onion.controller
|
|
14
|
+
.getOnionsEnabledCached()
|
|
15
|
+
.find(item => item.beanOptions.beanFullName === controllerBeanFullName)
|
|
16
|
+
?.beanOptions.beanClass;
|
|
17
|
+
if (!controller) throw new Error(`${controllerBeanFullName} not found`);
|
|
18
|
+
|
|
19
|
+
const controllerMetadata = appMetadata.getMetadata<any>(
|
|
20
|
+
SymbolOpenApiOptions,
|
|
21
|
+
controller,
|
|
22
|
+
);
|
|
23
|
+
assert.equal(
|
|
24
|
+
controllerMetadata?.summary?.toString(),
|
|
25
|
+
'<%=argv.moduleInfo.relativeName%>::<%=argv.resourceNameCapitalize%>Controller',
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const expectedSummaries = {
|
|
29
|
+
create: ['post', '<%=argv.moduleActionPathRaw%>', 'Create <%=argv.resourceNameCapitalize%>'],
|
|
30
|
+
select: ['get', '<%=argv.moduleActionPathRaw%>', 'Query <%=argv.resourceNameCapitalize%> List'],
|
|
31
|
+
view: ['get', '<%=argv.moduleActionPathRaw%>/{id}', 'View <%=argv.resourceNameCapitalize%>'],
|
|
32
|
+
update: ['patch', '<%=argv.moduleActionPathRaw%>/{id}', 'Update <%=argv.resourceNameCapitalize%>'],
|
|
33
|
+
delete: ['delete', '<%=argv.moduleActionPathRaw%>/{id}', 'Delete <%=argv.resourceNameCapitalize%>'],
|
|
34
|
+
deleteBulk: ['post', '<%=argv.moduleActionPathRaw%>/bulk/delete', 'Bulk Delete <%=argv.resourceNameCapitalize%>'],
|
|
35
|
+
} as const;
|
|
36
|
+
for (const [action, [method, path, summary]] of Object.entries(expectedSummaries)) {
|
|
37
|
+
const apiJson = await app.bean.openapi.generateJsonOfControllerAction(
|
|
38
|
+
controller,
|
|
39
|
+
action,
|
|
40
|
+
'V31',
|
|
41
|
+
);
|
|
42
|
+
const operation = (apiJson.paths as any)?.[path]?.[method];
|
|
43
|
+
assert.ok(operation, `${action} operation is missing`);
|
|
44
|
+
assert.equal(operation.summary?.toJSON(), summary);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('action:<%=argv.resourceName%>:rbacCatalog', async () => {
|
|
50
|
+
await app.bean.executor.mockCtx(async () => {
|
|
51
|
+
const controllerBeanFullName = '<%=argv.moduleInfo.relativeName%>.controller.<%=argv.resourceName%>';
|
|
52
|
+
const catalog = app.bean.rbacCatalog.getCatalog();
|
|
53
|
+
const expectedInherits = {
|
|
54
|
+
create: undefined,
|
|
55
|
+
select: undefined,
|
|
56
|
+
view: undefined,
|
|
57
|
+
update: undefined,
|
|
58
|
+
delete: undefined,
|
|
59
|
+
deleteBulk: `${controllerBeanFullName}#delete`,
|
|
60
|
+
} as const;
|
|
61
|
+
for (const [action, actionInheritKey] of Object.entries(expectedInherits)) {
|
|
62
|
+
const descriptor = catalog.get(`${controllerBeanFullName}#${action}`);
|
|
63
|
+
assert.ok(descriptor, `${action} RBAC action is missing`);
|
|
64
|
+
assert.equal(descriptor.actionInheritKey, actionInheritKey);
|
|
65
|
+
assert.equal(descriptor.options.dataScope, undefined);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
5
69
|
|
|
6
|
-
describe('<%=argv.resourceName%>.test.ts', () => {
|
|
7
70
|
it('action:<%=argv.resourceName%>', async () => {
|
|
8
71
|
await app.bean.executor.mockCtx(async () => {
|
|
9
|
-
// data
|
|
10
72
|
const data: Dto<%=argv.resourceNameCapitalize%>Create = {
|
|
11
73
|
name: '__Tom__',
|
|
12
74
|
description: 'This is a test',
|
|
@@ -15,48 +77,40 @@ describe('<%=argv.resourceName%>.test.ts', () => {
|
|
|
15
77
|
name: '__TomNew__',
|
|
16
78
|
description: 'This is a test',
|
|
17
79
|
};
|
|
18
|
-
|
|
80
|
+
let <%=argv.resourceName%>Id: Entity<%=argv.resourceNameCapitalize%>['id'] | undefined;
|
|
81
|
+
// sign in as an unrestricted test identity
|
|
19
82
|
await app.bean.passport.signinMock();
|
|
20
83
|
try {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
84
|
+
// create
|
|
85
|
+
<%=argv.resourceName%>Id = await app.bean.executor.performAction('post', '<%=argv.moduleActionPathRaw%>', { body: data });
|
|
86
|
+
assert.equal(!!<%=argv.resourceName%>Id, true);
|
|
87
|
+
// findMany
|
|
88
|
+
const selectRes: Dto<%=argv.resourceNameCapitalize%>SelectRes = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>');
|
|
89
|
+
assert.equal(selectRes.list.findIndex(item => item.name === data.name) > -1, true);
|
|
90
|
+
// update
|
|
91
|
+
const updateRes = await app.bean.executor.performAction('patch', '<%=argv.moduleActionPathRaw%>/:id', {
|
|
92
|
+
params: { id: <%=argv.resourceName%>Id },
|
|
93
|
+
body: dataUpdate,
|
|
94
|
+
});
|
|
95
|
+
assert.equal(updateRes, null);
|
|
96
|
+
// findOne
|
|
97
|
+
let <%=argv.resourceName%>: Entity<%=argv.resourceNameCapitalize%> = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>Id } });
|
|
98
|
+
assert.equal(<%=argv.resourceName%>.name, dataUpdate.name);
|
|
99
|
+
// delete
|
|
100
|
+
const deleteRes = await app.bean.executor.performAction('delete', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>.id } });
|
|
101
|
+
assert.equal(deleteRes, null);
|
|
102
|
+
// findOne
|
|
103
|
+
<%=argv.resourceName%> = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>.id } });
|
|
104
|
+
assert.equal(<%=argv.resourceName%>, undefined);
|
|
32
105
|
} finally {
|
|
106
|
+
if (<%=argv.resourceName%>Id) {
|
|
107
|
+
await app.scope('<%=argv.moduleInfo.relativeName%>').model.<%=argv.resourceName%>.deleteById(
|
|
108
|
+
<%=argv.resourceName%>Id,
|
|
109
|
+
{ disableDeleted: true },
|
|
110
|
+
);
|
|
111
|
+
}
|
|
33
112
|
await app.bean.passport.signout();
|
|
34
113
|
}
|
|
35
|
-
// login as system admin
|
|
36
|
-
await app.bean.passport.signinMock();
|
|
37
|
-
// create
|
|
38
|
-
const <%=argv.resourceName%>Id = await app.bean.executor.performAction('post', '<%=argv.moduleActionPathRaw%>', { body: data });
|
|
39
|
-
assert.equal(!!<%=argv.resourceName%>Id, true);
|
|
40
|
-
// findMany
|
|
41
|
-
const selectRes: Dto<%=argv.resourceNameCapitalize%>SelectRes = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>');
|
|
42
|
-
assert.equal(selectRes.list.findIndex(item => item.name === data.name) > -1, true);
|
|
43
|
-
// update
|
|
44
|
-
const updateRes = await app.bean.executor.performAction('patch', '<%=argv.moduleActionPathRaw%>/:id', {
|
|
45
|
-
params: { id: <%=argv.resourceName%>Id },
|
|
46
|
-
body: dataUpdate,
|
|
47
|
-
});
|
|
48
|
-
assert.equal(updateRes, null);
|
|
49
|
-
// findOne
|
|
50
|
-
let <%=argv.resourceName%>: Entity<%=argv.resourceNameCapitalize%> = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>Id } });
|
|
51
|
-
assert.equal(<%=argv.resourceName%>.name, dataUpdate.name);
|
|
52
|
-
// delete
|
|
53
|
-
const deleteRes = await app.bean.executor.performAction('delete', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>.id } });
|
|
54
|
-
assert.equal(deleteRes, null);
|
|
55
|
-
// findOne
|
|
56
|
-
<%=argv.resourceName%> = await app.bean.executor.performAction('get', '<%=argv.moduleActionPathRaw%>/:id', { params: { id: <%=argv.resourceName%>.id } });
|
|
57
|
-
assert.equal(<%=argv.resourceName%>, undefined);
|
|
58
|
-
// logout
|
|
59
|
-
await app.bean.passport.signout();
|
|
60
114
|
});
|
|
61
115
|
});
|
|
62
116
|
});
|
|
@@ -9,7 +9,6 @@ const __resources = {
|
|
|
9
9
|
Name: 'Name',
|
|
10
10
|
Description: 'Description',
|
|
11
11
|
Operations: 'Operations',
|
|
12
|
-
BulkDelete: 'Bulk Delete',
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
declare module '@cabloy/cli' {
|
|
@@ -40,6 +39,7 @@ export default metadataCustomSnippet({
|
|
|
40
39
|
[`${resource}View`]: `View ${resource}`,
|
|
41
40
|
[`${resource}Update`]: `Update ${resource}`,
|
|
42
41
|
[`${resource}Delete`]: `Delete ${resource}`,
|
|
42
|
+
[`${resource}DeleteBulk`]: `Bulk Delete ${resource}`,
|
|
43
43
|
};
|
|
44
44
|
return locale_transform({ ast, argv, resources });
|
|
45
45
|
},
|
|
@@ -7,7 +7,6 @@ const __resources = {
|
|
|
7
7
|
Name: '名称',
|
|
8
8
|
Description: '描述',
|
|
9
9
|
Operations: '操作',
|
|
10
|
-
BulkDelete: '批量删除',
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
export default metadataCustomSnippet({
|
|
@@ -23,6 +22,7 @@ export default metadataCustomSnippet({
|
|
|
23
22
|
[`${resource}View`]: `查看${resource}`,
|
|
24
23
|
[`${resource}Update`]: `更新${resource}`,
|
|
25
24
|
[`${resource}Delete`]: `删除${resource}`,
|
|
25
|
+
[`${resource}DeleteBulk`]: `批量删除${resource}`,
|
|
26
26
|
};
|
|
27
27
|
return locale_transform({ ast, argv, resources });
|
|
28
28
|
},
|
|
@@ -7,7 +7,6 @@ const __resources = {
|
|
|
7
7
|
Name: 'Name',
|
|
8
8
|
Description: 'Description',
|
|
9
9
|
Operations: 'Operations',
|
|
10
|
-
BulkDelete: 'Bulk Delete',
|
|
11
10
|
};
|
|
12
11
|
export default metadataCustomSnippet({
|
|
13
12
|
file: 'src/config/locale/en-us.ts',
|
|
@@ -30,6 +29,7 @@ export default metadataCustomSnippet({
|
|
|
30
29
|
[`${resource}View`]: `View ${resource}`,
|
|
31
30
|
[`${resource}Update`]: `Update ${resource}`,
|
|
32
31
|
[`${resource}Delete`]: `Delete ${resource}`,
|
|
32
|
+
[`${resource}DeleteBulk`]: `Bulk Delete ${resource}`,
|
|
33
33
|
};
|
|
34
34
|
return locale_transform({ ast, argv, resources });
|
|
35
35
|
},
|
|
@@ -5,7 +5,6 @@ const __resources = {
|
|
|
5
5
|
Name: '名称',
|
|
6
6
|
Description: '描述',
|
|
7
7
|
Operations: '操作',
|
|
8
|
-
BulkDelete: '批量删除',
|
|
9
8
|
};
|
|
10
9
|
export default metadataCustomSnippet({
|
|
11
10
|
file: 'src/config/locale/zh-cn.ts',
|
|
@@ -20,6 +19,7 @@ export default metadataCustomSnippet({
|
|
|
20
19
|
[`${resource}View`]: `查看${resource}`,
|
|
21
20
|
[`${resource}Update`]: `更新${resource}`,
|
|
22
21
|
[`${resource}Delete`]: `删除${resource}`,
|
|
22
|
+
[`${resource}DeleteBulk`]: `批量删除${resource}`,
|
|
23
23
|
};
|
|
24
24
|
return locale_transform({ ast, argv, resources });
|
|
25
25
|
},
|
package/package.json
CHANGED