vona-module-test-vona 5.0.49 → 5.0.50
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/dist/.metadata/index.d.ts +7 -0
- package/dist/controller/order.d.ts +5 -1
- package/dist/controller/post.d.ts +3 -2
- package/dist/dto/orderCreate.d.ts +1 -1
- package/dist/dto/orderQuery.d.ts +9 -0
- package/dist/dto/orderUpdate.d.ts +1 -1
- package/dist/dto/postCreate.d.ts +1 -1
- package/dist/dto/signin.d.ts +2 -0
- package/dist/dto/userCreate.d.ts +1 -1
- package/dist/dto/userUpdate.d.ts +1 -1
- package/dist/index.js +380 -325
- package/dist/service/post.d.ts +2 -2
- package/package.json +1 -1
- package/src/.metadata/index.ts +8 -0
- package/src/config/locale/en-us.ts +1 -1
- package/src/config/locale/zh-cn.ts +1 -1
- package/src/controller/captcha.ts +2 -2
- package/src/controller/onion.ts +1 -1
- package/src/controller/order.ts +25 -3
- package/src/controller/post.ts +5 -4
- package/src/controller/upload.ts +4 -5
- package/src/dto/orderQuery.ts +28 -0
- package/src/dto/postQuery.ts +7 -8
- package/src/dto/signin.ts +4 -0
- package/test/authSimple.test.ts +1 -0
- package/test/captcha.test.ts +49 -2
- package/test/database/dtoAggregate.test.ts +14 -11
- package/test/database/dtoGet.test.ts +10 -9
- package/test/database/dtoGroup.test.ts +15 -12
- package/test/database/dtoLazy.test.ts +1 -1
- package/test/database/dtoMutate.test.ts +10 -9
- package/test/database/dtoQuery.test.ts +3 -2
- package/test/database/modelWhere.test.ts +1 -0
- package/test/mail.test.ts +14 -0
package/dist/service/post.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare class ServicePost extends BeanBase {
|
|
|
9
9
|
};
|
|
10
10
|
with?: Record<string, unknown>;
|
|
11
11
|
distinct?: boolean | keyof import("vona-module-test-vona").EntityPost | (keyof import("vona-module-test-vona").EntityPost)[] | undefined;
|
|
12
|
-
columns?: "
|
|
12
|
+
columns?: "title" | "id" | "iid" | "createdAt" | "updatedAt" | "deleted" | "*" | "userId" | "stars" | ("title" | "id" | "iid" | "createdAt" | "updatedAt" | "deleted" | "*" | "userId" | "stars")[] | undefined;
|
|
13
13
|
where?: import("vona-module-a-orm").TypeModelWhereInner<{
|
|
14
14
|
"testVonaPostContent.content": string;
|
|
15
15
|
"testVonaPostContent.postId": TableIdentity;
|
|
@@ -100,7 +100,7 @@ export declare class ServicePost extends BeanBase {
|
|
|
100
100
|
};
|
|
101
101
|
}, undefined, 50>[]>;
|
|
102
102
|
select2(): Promise<import("vona-module-a-orm").TypeModelRelationResult_Normal<import("vona-module-test-vona").EntityPost, ModelPost, {
|
|
103
|
-
columns: ("
|
|
103
|
+
columns: ("title" | "id" | "userId")[];
|
|
104
104
|
where: {
|
|
105
105
|
id: {
|
|
106
106
|
_gt_: number;
|
package/package.json
CHANGED
package/src/.metadata/index.ts
CHANGED
|
@@ -1330,6 +1330,7 @@ export interface IModuleSummerCache {
|
|
|
1330
1330
|
/** dto: begin */
|
|
1331
1331
|
export * from '../dto/categoryTree.ts';
|
|
1332
1332
|
export * from '../dto/orderCreate.ts';
|
|
1333
|
+
export * from '../dto/orderQuery.ts';
|
|
1333
1334
|
export * from '../dto/orderResult.ts';
|
|
1334
1335
|
export * from '../dto/orderUpdate.ts';
|
|
1335
1336
|
export * from '../dto/postCreate.ts';
|
|
@@ -1344,6 +1345,7 @@ export * from '../dto/userLazy.ts';
|
|
|
1344
1345
|
export * from '../dto/userUpdate.ts';
|
|
1345
1346
|
import type { IDtoOptionsCategoryTree } from '../dto/categoryTree.ts';
|
|
1346
1347
|
import type { IDtoOptionsOrderCreate } from '../dto/orderCreate.ts';
|
|
1348
|
+
import type { IDtoOptionsOrderQuery } from '../dto/orderQuery.ts';
|
|
1347
1349
|
import type { IDtoOptionsOrderResult } from '../dto/orderResult.ts';
|
|
1348
1350
|
import type { IDtoOptionsOrderUpdate } from '../dto/orderUpdate.ts';
|
|
1349
1351
|
import type { IDtoOptionsPostCreate } from '../dto/postCreate.ts';
|
|
@@ -1362,6 +1364,7 @@ declare module 'vona-module-a-web' {
|
|
|
1362
1364
|
export interface IDtoRecord {
|
|
1363
1365
|
'test-vona:categoryTree': IDtoOptionsCategoryTree;
|
|
1364
1366
|
'test-vona:orderCreate': IDtoOptionsOrderCreate;
|
|
1367
|
+
'test-vona:orderQuery': IDtoOptionsOrderQuery;
|
|
1365
1368
|
'test-vona:orderResult': IDtoOptionsOrderResult;
|
|
1366
1369
|
'test-vona:orderUpdate': IDtoOptionsOrderUpdate;
|
|
1367
1370
|
'test-vona:postCreate': IDtoOptionsPostCreate;
|
|
@@ -1385,6 +1388,7 @@ declare module 'vona-module-test-vona' {
|
|
|
1385
1388
|
/** dto: begin */
|
|
1386
1389
|
import type { DtoCategoryTree } from '../dto/categoryTree.ts';
|
|
1387
1390
|
import type { DtoOrderCreate } from '../dto/orderCreate.ts';
|
|
1391
|
+
import type { DtoOrderQuery } from '../dto/orderQuery.ts';
|
|
1388
1392
|
import type { DtoOrderResult } from '../dto/orderResult.ts';
|
|
1389
1393
|
import type { DtoOrderUpdate } from '../dto/orderUpdate.ts';
|
|
1390
1394
|
import type { DtoPostCreate } from '../dto/postCreate.ts';
|
|
@@ -1407,6 +1411,10 @@ declare module 'vona-module-test-vona' {
|
|
|
1407
1411
|
fields?: TypeEntityOptionsFields<DtoOrderCreate, IDtoOptionsOrderCreate[TypeSymbolKeyFieldsMore]>;
|
|
1408
1412
|
}
|
|
1409
1413
|
|
|
1414
|
+
export interface IDtoOptionsOrderQuery {
|
|
1415
|
+
fields?: TypeEntityOptionsFields<DtoOrderQuery, IDtoOptionsOrderQuery[TypeSymbolKeyFieldsMore]>;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1410
1418
|
export interface IDtoOptionsOrderResult {
|
|
1411
1419
|
fields?: TypeEntityOptionsFields<DtoOrderResult, IDtoOptionsOrderResult[TypeSymbolKeyFieldsMore]>;
|
|
1412
1420
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
2
2
|
import { BeanBase } from 'vona';
|
|
3
|
-
import {
|
|
3
|
+
import { Captcha } from 'vona-module-a-captcha';
|
|
4
4
|
import { Passport } from 'vona-module-a-user';
|
|
5
5
|
import { Arg, Controller, Web } from 'vona-module-a-web';
|
|
6
6
|
import { DtoSignin } from '../dto/signin.ts';
|
|
@@ -11,7 +11,7 @@ export interface IControllerOptionsCaptcha extends IDecoratorControllerOptions {
|
|
|
11
11
|
export class ControllerCaptcha extends BeanBase {
|
|
12
12
|
@Web.post('signin')
|
|
13
13
|
@Passport.public()
|
|
14
|
-
@
|
|
14
|
+
@Captcha.verify({ scene: 'a-captchasimple:simple' })
|
|
15
15
|
async signin(@Arg.body() _user: DtoSignin) {
|
|
16
16
|
}
|
|
17
17
|
}
|
package/src/controller/onion.ts
CHANGED
|
@@ -42,7 +42,7 @@ export class ControllerOnion extends BeanBase {
|
|
|
42
42
|
@Web.post('echo2/:userId/:userName')
|
|
43
43
|
// @Aspect.middlewareGlobal('a-core:gate', { gate: { mode: 'dev' } })
|
|
44
44
|
@Aspect.guardGlobal('a-user:passport', { public: true })
|
|
45
|
-
// echo2(@Arg.query(v.object(DtoUser, {
|
|
45
|
+
// echo2(@Arg.query(v.object(DtoUser, { loose: false, strict: false })) book: Partial<DtoUser>) {
|
|
46
46
|
echo2(
|
|
47
47
|
@Arg.param('userId', v.title($locale('UserId')), v.example('example:1')) _userId: number,
|
|
48
48
|
@Arg.param('userName', v.title($locale('UserId')), v.example('example:1')) _userName: string,
|
package/src/controller/order.ts
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { VonaContext } from 'vona';
|
|
2
|
+
import type { IQueryParams } from 'vona-module-a-orm';
|
|
3
|
+
import type { IDecoratorControllerOptions, IPipeOptionsQueryTransformInfo } from 'vona-module-a-web';
|
|
4
|
+
import type { ModelOrder } from '../model/order.ts';
|
|
2
5
|
import { BeanBase } from 'vona';
|
|
3
6
|
import { Api, v } from 'vona-module-a-openapi';
|
|
4
|
-
import { Controller, Web } from 'vona-module-a-web';
|
|
7
|
+
import { Arg, Controller, Web } from 'vona-module-a-web';
|
|
8
|
+
import { DtoOrderCreate } from '../dto/orderCreate.ts';
|
|
9
|
+
import { DtoOrderQuery } from '../dto/orderQuery.ts';
|
|
5
10
|
import { DtoOrderResult } from '../dto/orderResult.ts';
|
|
6
11
|
|
|
7
12
|
export interface IControllerOptionsOrder extends IDecoratorControllerOptions {}
|
|
8
13
|
|
|
14
|
+
function myCustomQueryTransform(_ctx: VonaContext, info: IPipeOptionsQueryTransformInfo): boolean | undefined {
|
|
15
|
+
if (info.key === 'userName') {
|
|
16
|
+
info.params.where[info.fullName] = info.value;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
@Controller<IControllerOptionsOrder>('order')
|
|
10
23
|
export class ControllerOrder extends BeanBase {
|
|
24
|
+
@Web.post('create')
|
|
25
|
+
@Api.body(DtoOrderResult)
|
|
26
|
+
async create(@Arg.body(DtoOrderCreate) data: DtoOrderCreate) {
|
|
27
|
+
return await this.scope.model.order.insert(data);
|
|
28
|
+
}
|
|
29
|
+
|
|
11
30
|
@Web.get('findAll')
|
|
12
31
|
@Api.body(v.array(DtoOrderResult))
|
|
13
|
-
async findAll(
|
|
32
|
+
async findAll(
|
|
33
|
+
@Arg.queryPro(DtoOrderQuery, myCustomQueryTransform) params: IQueryParams<ModelOrder>,
|
|
34
|
+
): Promise<DtoOrderResult[]> {
|
|
14
35
|
return this.scope.model.order.select({
|
|
36
|
+
...params,
|
|
15
37
|
include: {
|
|
16
38
|
products: true,
|
|
17
39
|
},
|
package/src/controller/post.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IQueryParams } from 'vona-module-a-orm';
|
|
2
|
-
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
2
|
+
import type { IDecoratorControllerOptions, IPipeOptionsQueryTransformInfo } from 'vona-module-a-web';
|
|
3
3
|
import type { ModelPost } from '../model/post.ts';
|
|
4
4
|
import { BeanBase } from 'vona';
|
|
5
5
|
import { Api } from 'vona-module-a-openapi';
|
|
@@ -19,13 +19,14 @@ export class ControllerPost extends BeanBase {
|
|
|
19
19
|
return params;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
findManyQueryTransform(_info: IPipeOptionsQueryTransformInfo): boolean | undefined {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
@Web.get('findMany')
|
|
23
27
|
@Api.body(DtoPostQueryRes)
|
|
24
28
|
@Passport.public()
|
|
25
29
|
async findMany(@Arg.queryPro(DtoPostQuery) params: IQueryParams<ModelPost>) {
|
|
26
|
-
if (!params.orders) {
|
|
27
|
-
params.orders = [['testVonaPost.createdAt', 'desc']];
|
|
28
|
-
}
|
|
29
30
|
return await this.scope.service.post.findMany(params);
|
|
30
31
|
}
|
|
31
32
|
}
|
package/src/controller/upload.ts
CHANGED
|
@@ -2,9 +2,8 @@ import type { IUploadField, IUploadFile } from 'vona-module-a-upload';
|
|
|
2
2
|
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
3
3
|
import assert from 'node:assert';
|
|
4
4
|
import { BeanBase } from 'vona';
|
|
5
|
-
import { Aspect } from 'vona-module-a-aspect';
|
|
6
5
|
import { Api, v } from 'vona-module-a-openapi';
|
|
7
|
-
import { SymbolUploadValue } from 'vona-module-a-upload';
|
|
6
|
+
import { File, SymbolUploadValue } from 'vona-module-a-upload';
|
|
8
7
|
import { Passport } from 'vona-module-a-user';
|
|
9
8
|
import { Arg, Controller, Web } from 'vona-module-a-web';
|
|
10
9
|
import { z } from 'zod';
|
|
@@ -15,7 +14,7 @@ export interface IControllerOptionsUpload extends IDecoratorControllerOptions {}
|
|
|
15
14
|
export class ControllerUpload extends BeanBase {
|
|
16
15
|
@Web.post('fields')
|
|
17
16
|
@Passport.public()
|
|
18
|
-
@
|
|
17
|
+
@File.upload()
|
|
19
18
|
@Api.contentType('application/json')
|
|
20
19
|
fields(
|
|
21
20
|
@Arg.fields() fields: IUploadField[],
|
|
@@ -30,7 +29,7 @@ export class ControllerUpload extends BeanBase {
|
|
|
30
29
|
|
|
31
30
|
@Web.post('file')
|
|
32
31
|
@Passport.public()
|
|
33
|
-
@
|
|
32
|
+
@File.upload()
|
|
34
33
|
@Api.contentType('application/json')
|
|
35
34
|
file(@Arg.field('name', v.default('zhennann')) name: string, @Arg.file('welcome') file: IUploadFile) {
|
|
36
35
|
assert.equal(name, 'zhennann');
|
|
@@ -40,7 +39,7 @@ export class ControllerUpload extends BeanBase {
|
|
|
40
39
|
|
|
41
40
|
@Web.post('files')
|
|
42
41
|
@Passport.public()
|
|
43
|
-
@
|
|
42
|
+
@File.upload()
|
|
44
43
|
@Api.contentType('application/json')
|
|
45
44
|
files(
|
|
46
45
|
@Arg.files(v.title('more files')) files: IUploadFile[],
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { IDecoratorDtoOptions } from 'vona-module-a-web';
|
|
2
|
+
import { Api, v } from 'vona-module-a-openapi';
|
|
3
|
+
import { $Dto, $tableName } from 'vona-module-a-orm';
|
|
4
|
+
import { Dto } from 'vona-module-a-web';
|
|
5
|
+
import { EntityOrder } from '../entity/order.ts';
|
|
6
|
+
import { EntityUser } from '../entity/user.ts';
|
|
7
|
+
|
|
8
|
+
export interface IDtoOptionsOrderQuery extends IDecoratorDtoOptions {}
|
|
9
|
+
|
|
10
|
+
@Dto<IDtoOptionsOrderQuery>({
|
|
11
|
+
openapi: {
|
|
12
|
+
query: {
|
|
13
|
+
table: $tableName(EntityOrder),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
export class DtoOrderQuery
|
|
18
|
+
extends $Dto.query(EntityOrder, ['orderNo', 'remark']) {
|
|
19
|
+
@Api.field(v.optional(), v.openapi({
|
|
20
|
+
query: {
|
|
21
|
+
table: $tableName(EntityUser),
|
|
22
|
+
joinType: 'innerJoin',
|
|
23
|
+
joinOn: ['userId', 'testVonaUser.id'],
|
|
24
|
+
originalName: 'name',
|
|
25
|
+
},
|
|
26
|
+
}))
|
|
27
|
+
userName?: string;
|
|
28
|
+
}
|
package/src/dto/postQuery.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import type { IDecoratorDtoOptions } from 'vona-module-a-web';
|
|
2
2
|
import { Api, v } from 'vona-module-a-openapi';
|
|
3
|
-
import { $Dto } from 'vona-module-a-orm';
|
|
3
|
+
import { $Dto, $tableName } from 'vona-module-a-orm';
|
|
4
4
|
import { Dto } from 'vona-module-a-web';
|
|
5
5
|
import { EntityPost } from '../entity/post.ts';
|
|
6
6
|
|
|
7
7
|
export interface IDtoOptionsPostQuery extends IDecoratorDtoOptions {}
|
|
8
8
|
|
|
9
|
-
@Dto<IDtoOptionsPostQuery>(
|
|
9
|
+
@Dto<IDtoOptionsPostQuery>({
|
|
10
|
+
openapi: { query: { table: $tableName(EntityPost) } },
|
|
11
|
+
})
|
|
10
12
|
export class DtoPostQuery extends $Dto.queryPage(EntityPost, ['title']) {
|
|
11
13
|
@Api.field(v.optional(), v.openapi({
|
|
12
14
|
query: {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
table: 'testVonaUser',
|
|
16
|
-
on: ['userId', 'testVonaUser.id'],
|
|
17
|
-
},
|
|
15
|
+
table: 'testVonaUser',
|
|
16
|
+
joinOn: ['userId', 'testVonaUser.id'],
|
|
18
17
|
originalName: 'name',
|
|
19
|
-
op: '
|
|
18
|
+
op: '_eqI_',
|
|
20
19
|
},
|
|
21
20
|
}))
|
|
22
21
|
userName?: string;
|
package/src/dto/signin.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DtoCaptchaVerify } from 'vona-module-a-captcha';
|
|
1
2
|
import type { IDecoratorDtoOptions } from 'vona-module-a-web';
|
|
2
3
|
import { Api, v } from 'vona-module-a-openapi';
|
|
3
4
|
import { Dto } from 'vona-module-a-web';
|
|
@@ -11,4 +12,7 @@ export class DtoSignin {
|
|
|
11
12
|
|
|
12
13
|
@Api.field(v.min(3))
|
|
13
14
|
password: string;
|
|
15
|
+
|
|
16
|
+
@Api.field(v.captcha({ scene: 'a-captchasimple:simple' }))
|
|
17
|
+
captcha: DtoCaptchaVerify;
|
|
14
18
|
}
|
package/test/authSimple.test.ts
CHANGED
package/test/captcha.test.ts
CHANGED
|
@@ -8,7 +8,7 @@ describe('captcha.test.ts', () => {
|
|
|
8
8
|
// scene/provider
|
|
9
9
|
const sceneName = 'a-captchasimple:simple';
|
|
10
10
|
const providerName = 'a-captchasimple:imageText';
|
|
11
|
-
it('action:captcha', async () => {
|
|
11
|
+
it('action:captcha:error', async () => {
|
|
12
12
|
await app.bean.executor.mockCtx(async () => {
|
|
13
13
|
// create
|
|
14
14
|
const captcha = await app.bean.captcha.create(sceneName);
|
|
@@ -21,12 +21,27 @@ describe('captcha.test.ts', () => {
|
|
|
21
21
|
// verify: false
|
|
22
22
|
const verifiedFalse = await app.bean.captcha.verify(captcha.id, `${token}!`, sceneName);
|
|
23
23
|
assert.equal(verifiedFalse, false);
|
|
24
|
+
// verify: false
|
|
25
|
+
const verifiedFalse2 = await app.bean.captcha.verify(captcha.id, token, sceneName);
|
|
26
|
+
assert.equal(verifiedFalse2, false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('action:captcha:ok', async () => {
|
|
30
|
+
await app.bean.executor.mockCtx(async () => {
|
|
31
|
+
// create
|
|
32
|
+
const captcha = await app.bean.captcha.create(sceneName);
|
|
33
|
+
assert.equal(captcha.provider, providerName);
|
|
34
|
+
// get
|
|
35
|
+
const captchaData = await app.bean.captcha.getCaptchaData(captcha.id);
|
|
36
|
+
assert.equal(captchaData?.provider, providerName);
|
|
37
|
+
// token
|
|
38
|
+
const token = captchaData?.token;
|
|
24
39
|
// verify: true
|
|
25
40
|
const verifiedTrue = await app.bean.captcha.verify(captcha.id, token, sceneName);
|
|
26
41
|
assert.equal(verifiedTrue, true);
|
|
27
42
|
});
|
|
28
43
|
});
|
|
29
|
-
it('action:captcha api', async () => {
|
|
44
|
+
it('action:captcha api:error', async () => {
|
|
30
45
|
await app.bean.executor.mockCtx(async () => {
|
|
31
46
|
// create
|
|
32
47
|
const captcha: ICaptchaData = await app.bean.executor.performAction('post', '/captcha/create', {
|
|
@@ -56,6 +71,38 @@ describe('captcha.test.ts', () => {
|
|
|
56
71
|
});
|
|
57
72
|
});
|
|
58
73
|
assert.equal(error?.code, 403);
|
|
74
|
+
// verifyImmediate: error again
|
|
75
|
+
const [_2, error2] = await catchError(() => {
|
|
76
|
+
return app.bean.executor.performAction('post', '/captcha/verifyImmediate', {
|
|
77
|
+
body: {
|
|
78
|
+
id: captcha2.id,
|
|
79
|
+
token: captchaData?.token,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
assert.equal(error2?.code, 403);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
it('action:captcha api:ok', async () => {
|
|
87
|
+
await app.bean.executor.mockCtx(async () => {
|
|
88
|
+
// create
|
|
89
|
+
const captcha: ICaptchaData = await app.bean.executor.performAction('post', '/captcha/create', {
|
|
90
|
+
body: {
|
|
91
|
+
scene: sceneName,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
assert.equal(captcha.provider, providerName);
|
|
95
|
+
// refresh
|
|
96
|
+
const captcha2: ICaptchaData = await app.bean.executor.performAction('post', '/captcha/refresh', {
|
|
97
|
+
body: {
|
|
98
|
+
id: captcha.id,
|
|
99
|
+
scene: sceneName,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
assert.equal(captcha2.provider, providerName);
|
|
103
|
+
assert.equal(captcha2.id, captcha.id);
|
|
104
|
+
// get token
|
|
105
|
+
const captchaData = await app.bean.captcha.getCaptchaData(captcha2.id);
|
|
59
106
|
// verifyImmediate: ok
|
|
60
107
|
const tokenSecondary = await app.bean.executor.performAction('post', '/captcha/verifyImmediate', {
|
|
61
108
|
body: {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { TypeDecoratorRules } from 'vona-module-a-openapiutils';
|
|
2
|
+
import type z from 'zod';
|
|
1
3
|
import assert from 'node:assert';
|
|
2
4
|
import { describe, it } from 'node:test';
|
|
3
5
|
import { app } from 'vona-mock';
|
|
@@ -16,15 +18,16 @@ describe('dtoAggregate.test.ts', () => {
|
|
|
16
18
|
// max: 'age',
|
|
17
19
|
// min: 'age',
|
|
18
20
|
});
|
|
19
|
-
let rules:
|
|
21
|
+
let rules: TypeDecoratorRules;
|
|
20
22
|
rules = getTargetDecoratorRules(DtoUserAggr.prototype);
|
|
21
|
-
assert.equal(rules.count_all
|
|
22
|
-
|
|
23
|
-
assert.equal(
|
|
24
|
-
assert.equal(
|
|
25
|
-
assert.equal(
|
|
26
|
-
assert.equal(rules.
|
|
27
|
-
assert.equal(rules.
|
|
23
|
+
assert.equal(rules.count_all?.type === 'optional', true);
|
|
24
|
+
const rule_count_all = (rules.count_all as z.ZodOptional)?.def.innerType as z.ZodUnion;
|
|
25
|
+
assert.equal(rule_count_all.type === 'union', true);
|
|
26
|
+
assert.equal((rule_count_all.def.options[0] as z.ZodType).type === 'string', true);
|
|
27
|
+
assert.equal((rule_count_all.def.options[1] as z.ZodType).type === 'number', true);
|
|
28
|
+
assert.equal(rules.count_age?.type === 'optional', true);
|
|
29
|
+
assert.equal(rules.sum_age?.type === 'optional', true);
|
|
30
|
+
assert.equal(rules.avg_age?.type === 'optional', true);
|
|
28
31
|
assert.equal(rules.max_age, undefined);
|
|
29
32
|
assert.equal(rules.min_age, undefined);
|
|
30
33
|
// aggr: usersStats: posts: autoload
|
|
@@ -33,10 +36,10 @@ describe('dtoAggregate.test.ts', () => {
|
|
|
33
36
|
include: { roles: true },
|
|
34
37
|
});
|
|
35
38
|
rules = getTargetDecoratorRules(DtoUserStats.prototype);
|
|
36
|
-
assert.equal(rules.name
|
|
39
|
+
assert.equal(rules.name?.type === 'string', true);
|
|
37
40
|
assert.equal(rules.iid, undefined);
|
|
38
|
-
assert.equal(rules.posts
|
|
39
|
-
assert.equal(rules.roles
|
|
41
|
+
assert.equal(rules.posts?.type === 'optional', true);
|
|
42
|
+
assert.equal(rules.roles?.type === 'optional', true);
|
|
40
43
|
});
|
|
41
44
|
});
|
|
42
45
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TypeDecoratorRules } from 'vona-module-a-openapiutils';
|
|
1
2
|
import assert from 'node:assert';
|
|
2
3
|
import { describe, it } from 'node:test';
|
|
3
4
|
import { app } from 'vona-mock';
|
|
@@ -33,21 +34,21 @@ describe('dtoGet.test.ts', () => {
|
|
|
33
34
|
}),
|
|
34
35
|
},
|
|
35
36
|
});
|
|
36
|
-
const rules:
|
|
37
|
-
assert.equal(['
|
|
38
|
-
assert.equal(rules.title
|
|
39
|
-
assert.equal(['
|
|
37
|
+
const rules: TypeDecoratorRules = getTargetDecoratorRules(DtoPostNew.prototype);
|
|
38
|
+
assert.equal(['string', 'number'].includes(rules.id?.type as string), true);
|
|
39
|
+
assert.equal(rules.title?.type === 'string', true);
|
|
40
|
+
assert.equal(['string', 'number'].includes(rules.userId?.type as string), true);
|
|
40
41
|
assert.equal(rules.iid, undefined);
|
|
41
|
-
assert.equal(rules.postContent
|
|
42
|
-
assert.equal(rules.user
|
|
43
|
-
assert.equal(rules.user3
|
|
42
|
+
assert.equal(rules.postContent?.type === 'optional', true);
|
|
43
|
+
assert.equal(rules.user?.type === 'optional', true);
|
|
44
|
+
assert.equal(rules.user3?.type === 'optional', true);
|
|
44
45
|
});
|
|
45
46
|
});
|
|
46
47
|
it('action:dtoGet:categoryTree', async () => {
|
|
47
48
|
await app.bean.executor.mockCtx(async () => {
|
|
48
49
|
const DtoCategoryTree = $Dto.get('test-vona:category', { columns: ['id', 'name'], include: { children: { columns: ['id'] } } });
|
|
49
|
-
const rules:
|
|
50
|
-
assert.equal(rules.children
|
|
50
|
+
const rules: TypeDecoratorRules = getTargetDecoratorRules(DtoCategoryTree.prototype);
|
|
51
|
+
assert.equal(rules.children?.type === 'pipe', true);
|
|
51
52
|
assert.equal(rules.iid, undefined);
|
|
52
53
|
const DtoCategoryChain = $Dto.get('test-vona:categoryChain', { columns: ['id', 'name', 'categoryIdParent'] });
|
|
53
54
|
const _apiJson = await app.bean.scope('a-openapi').service.openapi.generateJsonOfClass(DtoCategoryChain);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { TypeDecoratorRules } from 'vona-module-a-openapiutils';
|
|
2
|
+
import type z from 'zod';
|
|
1
3
|
import assert from 'node:assert';
|
|
2
4
|
import { describe, it } from 'node:test';
|
|
3
5
|
import { app } from 'vona-mock';
|
|
@@ -15,16 +17,17 @@ describe('dtoGroup.test.ts', () => {
|
|
|
15
17
|
// max: 'age',
|
|
16
18
|
// min: 'age',
|
|
17
19
|
});
|
|
18
|
-
let rules:
|
|
20
|
+
let rules: TypeDecoratorRules;
|
|
19
21
|
rules = getTargetDecoratorRules(DtoUserAggr.prototype);
|
|
20
|
-
assert.equal(rules.name
|
|
21
|
-
assert.equal(rules.count_all
|
|
22
|
-
|
|
23
|
-
assert.equal(
|
|
24
|
-
assert.equal(
|
|
25
|
-
assert.equal(
|
|
26
|
-
assert.equal(rules.
|
|
27
|
-
assert.equal(rules.
|
|
22
|
+
assert.equal(rules.name?.type === 'string', true);
|
|
23
|
+
assert.equal(rules.count_all?.type === 'optional', true);
|
|
24
|
+
const rule_count_all = (rules.count_all as z.ZodOptional)?.def.innerType as z.ZodUnion;
|
|
25
|
+
assert.equal(rule_count_all.type === 'union', true);
|
|
26
|
+
assert.equal((rule_count_all.def.options[0] as z.ZodType).type === 'string', true);
|
|
27
|
+
assert.equal((rule_count_all.def.options[1] as z.ZodType).type === 'number', true);
|
|
28
|
+
assert.equal(rules.count_age?.type === 'optional', true);
|
|
29
|
+
assert.equal(rules.sum_age?.type === 'optional', true);
|
|
30
|
+
assert.equal(rules.avg_age?.type === 'optional', true);
|
|
28
31
|
assert.equal(rules.max_age, undefined);
|
|
29
32
|
assert.equal(rules.min_age, undefined);
|
|
30
33
|
// group: userStats: posts: autoload
|
|
@@ -33,10 +36,10 @@ describe('dtoGroup.test.ts', () => {
|
|
|
33
36
|
include: { roles: true },
|
|
34
37
|
});
|
|
35
38
|
rules = getTargetDecoratorRules(DtoUserStats.prototype);
|
|
36
|
-
assert.equal(rules.name
|
|
39
|
+
assert.equal(rules.name?.type === 'string', true);
|
|
37
40
|
assert.equal(rules.iid, undefined);
|
|
38
|
-
assert.equal(rules.posts
|
|
39
|
-
assert.equal(rules.roles
|
|
41
|
+
assert.equal(rules.posts?.type === 'pipe', true);
|
|
42
|
+
assert.equal(rules.roles?.type === 'pipe', true);
|
|
40
43
|
});
|
|
41
44
|
});
|
|
42
45
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { describe, it } from 'node:test';
|
|
3
|
-
import { OpenApiGeneratorV31, OpenAPIRegistry } from '@
|
|
3
|
+
import { OpenApiGeneratorV31, OpenAPIRegistry } from '@cabloy/zod-to-openapi';
|
|
4
4
|
import { appResource, cast } from 'vona';
|
|
5
5
|
import { app } from 'vona-mock';
|
|
6
6
|
import { $schema } from 'vona-module-a-openapi';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TypeDecoratorRules } from 'vona-module-a-openapiutils';
|
|
1
2
|
import assert from 'node:assert';
|
|
2
3
|
import { describe, it } from 'node:test';
|
|
3
4
|
import { app } from 'vona-mock';
|
|
@@ -12,15 +13,15 @@ describe('dtoMutate.test.ts', () => {
|
|
|
12
13
|
const DtoUserCreate = $Dto.create('test-vona:user', {
|
|
13
14
|
include: { posts: true },
|
|
14
15
|
});
|
|
15
|
-
let rules:
|
|
16
|
+
let rules: TypeDecoratorRules;
|
|
16
17
|
rules = getTargetDecoratorRules(DtoUserCreate.prototype);
|
|
17
|
-
assert.equal(rules.name
|
|
18
|
+
assert.equal(rules.name?.type === 'string', true);
|
|
18
19
|
assert.equal(rules.id, undefined);
|
|
19
20
|
assert.equal(rules.iid, undefined);
|
|
20
21
|
assert.equal(rules.deleted, undefined);
|
|
21
22
|
assert.equal(rules.createdAt, undefined);
|
|
22
23
|
assert.equal(rules.updatedAt, undefined);
|
|
23
|
-
assert.equal(rules.posts
|
|
24
|
+
assert.equal(rules.posts?.type === 'optional', true);
|
|
24
25
|
// update
|
|
25
26
|
const DtoUserUpdate = $Dto.update('test-vona:user', {
|
|
26
27
|
with: {
|
|
@@ -28,13 +29,13 @@ describe('dtoMutate.test.ts', () => {
|
|
|
28
29
|
},
|
|
29
30
|
});
|
|
30
31
|
rules = getTargetDecoratorRules(DtoUserUpdate.prototype);
|
|
31
|
-
assert.equal(rules.name
|
|
32
|
+
assert.equal(rules.name?.type === 'string', true); // ZodOptional
|
|
32
33
|
assert.equal(rules.id, undefined);
|
|
33
34
|
assert.equal(rules.iid, undefined);
|
|
34
35
|
assert.equal(rules.deleted, undefined);
|
|
35
36
|
assert.equal(rules.createdAt, undefined);
|
|
36
37
|
assert.equal(rules.updatedAt, undefined);
|
|
37
|
-
assert.equal(rules.posts
|
|
38
|
+
assert.equal(rules.posts?.type === 'optional', true);
|
|
38
39
|
// create: not mutate post(belongsTo)
|
|
39
40
|
const DtoPostCreate = $Dto.create('test-vona:post', {
|
|
40
41
|
include: {
|
|
@@ -43,10 +44,10 @@ describe('dtoMutate.test.ts', () => {
|
|
|
43
44
|
},
|
|
44
45
|
});
|
|
45
46
|
rules = getTargetDecoratorRules(DtoPostCreate.prototype);
|
|
46
|
-
assert.equal(rules.title
|
|
47
|
-
assert.equal(rules.stars
|
|
48
|
-
assert.equal(['
|
|
49
|
-
assert.equal(rules.postContent
|
|
47
|
+
assert.equal(rules.title?.type === 'string', true); // ZodOptional
|
|
48
|
+
assert.equal(rules.stars?.type === 'optional', true);
|
|
49
|
+
assert.equal(['string', 'number'].includes(rules.userId?.type as string), true);
|
|
50
|
+
assert.equal(rules.postContent?.type === 'optional', true);
|
|
50
51
|
assert.equal(rules.user, undefined);
|
|
51
52
|
assert.equal(rules.id, undefined);
|
|
52
53
|
});
|
|
@@ -16,7 +16,8 @@ describe('dtoQuery.test.ts', () => {
|
|
|
16
16
|
_gt_: 12,
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
|
-
orders: [['
|
|
19
|
+
// orders: [['userName', 'asc']],
|
|
20
|
+
// orders: [['testVonaPost.createdAt', 'asc']],
|
|
20
21
|
pageNo: 2,
|
|
21
22
|
pageSize: 30,
|
|
22
23
|
title: 'ai',
|
|
@@ -27,7 +28,7 @@ describe('dtoQuery.test.ts', () => {
|
|
|
27
28
|
assert.deepEqual(resEcho.where, {
|
|
28
29
|
'stars': { _gt_: 12 },
|
|
29
30
|
'title': { _includesI_: 'ai' },
|
|
30
|
-
'testVonaUser.name': 'tom',
|
|
31
|
+
'testVonaUser.name': { _eqI_: 'tom' },
|
|
31
32
|
});
|
|
32
33
|
assert.deepEqual(resEcho.orders, [['testVonaPost.createdAt', 'desc']]);
|
|
33
34
|
assert.equal(resEcho.offset, 30);
|
|
@@ -6,6 +6,7 @@ import { app } from 'vona-mock';
|
|
|
6
6
|
describe('modelWhere.test.ts', () => {
|
|
7
7
|
it('action:modelWhere', async () => {
|
|
8
8
|
await app.bean.executor.mockCtx(async () => {
|
|
9
|
+
if (app.bean.database.current.dialectName !== 'pg') return;
|
|
9
10
|
const scopeTest = app.bean.scope('test-vona');
|
|
10
11
|
// ref
|
|
11
12
|
let builder = scopeTest.model.post.builder();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import { app } from 'vona-mock';
|
|
3
|
+
|
|
4
|
+
describe('mail.test.ts', () => {
|
|
5
|
+
it('action:mail', async () => {
|
|
6
|
+
await app.bean.executor.mockCtx(async () => {
|
|
7
|
+
await app.bean.mail.send({
|
|
8
|
+
to: 'someone@cabloy.com',
|
|
9
|
+
subject: 'this is a test mail',
|
|
10
|
+
text: 'message body!',
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
});
|