vona-module-test-vona 5.0.39 → 5.0.42

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 (123) hide show
  1. package/dist/.metadata/index.d.ts +62 -29
  2. package/dist/controller/dtoTest.d.ts +1 -1
  3. package/dist/index.js +401 -158
  4. package/dist/service/category.d.ts +5 -0
  5. package/dist/service/order.d.ts +4 -0
  6. package/dist/service/post.d.ts +4 -2
  7. package/dist/service/user.d.ts +4 -0
  8. package/package.json +4 -2
  9. package/src/.metadata/index.ts +1771 -0
  10. package/src/.metadata/this.ts +2 -0
  11. package/src/bean/aop.regExp.ts +30 -0
  12. package/src/bean/aop.simple.ts +58 -0
  13. package/src/bean/aopMethod.test.ts +42 -0
  14. package/src/bean/bean.testCtx.ts +55 -0
  15. package/src/bean/broadcast.test.ts +22 -0
  16. package/src/bean/cacheMem.test.ts +7 -0
  17. package/src/bean/cacheRedis.post.ts +10 -0
  18. package/src/bean/cacheRedis.test.ts +7 -0
  19. package/src/bean/event.helloEcho.ts +8 -0
  20. package/src/bean/eventListener.helloEcho.ts +21 -0
  21. package/src/bean/meta.version.ts +81 -0
  22. package/src/bean/queue.test.ts +18 -0
  23. package/src/bean/schedule.test.ts +12 -0
  24. package/src/bean/schedule.test3.ts +12 -0
  25. package/src/bean/summerCache.test.ts +29 -0
  26. package/src/config/config.ts +5 -0
  27. package/src/config/locale/en-us.ts +19 -0
  28. package/src/config/locale/zh-cn.ts +17 -0
  29. package/src/controller/bean.ts +95 -0
  30. package/src/controller/cacheMem.ts +63 -0
  31. package/src/controller/cacheRedis.ts +55 -0
  32. package/src/controller/dtoTest.ts +63 -0
  33. package/src/controller/guardPassport.ts +25 -0
  34. package/src/controller/onion.ts +92 -0
  35. package/src/controller/passport.ts +48 -0
  36. package/src/controller/performAction.ts +18 -0
  37. package/src/controller/queue.ts +25 -0
  38. package/src/controller/summer.ts +125 -0
  39. package/src/controller/tail.ts +32 -0
  40. package/src/controller/transaction.ts +29 -0
  41. package/src/controller/upload.ts +57 -0
  42. package/src/dto/categoryTree.ts +8 -0
  43. package/src/dto/orderCreate.ts +10 -0
  44. package/src/dto/orderResult.ts +9 -0
  45. package/src/dto/orderUpdate.ts +9 -0
  46. package/src/dto/postCreate.ts +9 -0
  47. package/src/dto/profile.ts +14 -0
  48. package/src/dto/roleLazy.ts +15 -0
  49. package/src/dto/user.ts +19 -0
  50. package/src/dto/userCreate.ts +8 -0
  51. package/src/dto/userLazy.ts +18 -0
  52. package/src/dto/userUpdate.ts +8 -0
  53. package/src/entity/category.ts +14 -0
  54. package/src/entity/order.ts +18 -0
  55. package/src/entity/post.ts +17 -0
  56. package/src/entity/postContent.ts +14 -0
  57. package/src/entity/product.ts +24 -0
  58. package/src/entity/role.ts +11 -0
  59. package/src/entity/roleUser.ts +14 -0
  60. package/src/entity/test.ts +18 -0
  61. package/src/entity/user.ts +17 -0
  62. package/src/index.ts +1 -0
  63. package/src/model/category.ts +20 -0
  64. package/src/model/categoryChain.ts +16 -0
  65. package/src/model/order.ts +26 -0
  66. package/src/model/orderStats.ts +27 -0
  67. package/src/model/post.ts +16 -0
  68. package/src/model/postContent.ts +17 -0
  69. package/src/model/product.ts +8 -0
  70. package/src/model/role.ts +15 -0
  71. package/src/model/roleUser.ts +8 -0
  72. package/src/model/test.ts +8 -0
  73. package/src/model/testDynamicTable.ts +21 -0
  74. package/src/model/user.ts +21 -0
  75. package/src/model/userStats.ts +15 -0
  76. package/src/model/userStatsGroup.ts +15 -0
  77. package/src/service/aopMethod.ts +38 -0
  78. package/src/service/caching.ts +75 -0
  79. package/src/service/category.ts +72 -0
  80. package/src/service/order.ts +65 -0
  81. package/src/service/post.ts +219 -0
  82. package/src/service/test.ts +9 -0
  83. package/src/service/testApp.ts +13 -0
  84. package/src/service/testClass.ts +15 -0
  85. package/src/service/testData.ts +67 -0
  86. package/src/service/transaction.ts +20 -0
  87. package/src/service/user.ts +68 -0
  88. package/test/aopMethod.test.ts +21 -0
  89. package/test/authSimple.test.ts +45 -0
  90. package/test/bean.test.ts +16 -0
  91. package/test/broadcast.test.ts +17 -0
  92. package/test/cache/cacheMem.test.ts +10 -0
  93. package/test/cache/cacheRedis.test.ts +10 -0
  94. package/test/cache/caching.test.ts +58 -0
  95. package/test/cache/summer.test.ts +10 -0
  96. package/test/database/database.test.ts +127 -0
  97. package/test/database/dtoAggregate.test.ts +44 -0
  98. package/test/database/dtoGet.test.ts +61 -0
  99. package/test/database/dtoGroup.test.ts +44 -0
  100. package/test/database/dtoLazy.test.ts +45 -0
  101. package/test/database/dtoMutate.test.ts +56 -0
  102. package/test/database/modelAggregate.test.ts +197 -0
  103. package/test/database/modelCache.test.ts +37 -0
  104. package/test/database/modelGeneral.test.ts +18 -0
  105. package/test/database/modelGroup.test.ts +211 -0
  106. package/test/database/modelRelations.test.ts +203 -0
  107. package/test/database/modelRelationsJoins.test.ts +39 -0
  108. package/test/database/modelRelationsMutate.test.ts +354 -0
  109. package/test/database/modelWhere.test.ts +138 -0
  110. package/test/database/orm.test.ts +22 -0
  111. package/test/database/transaction.test.ts +142 -0
  112. package/test/event.test.ts +14 -0
  113. package/test/guardPassport.test.ts +44 -0
  114. package/test/jwt.test.ts +27 -0
  115. package/test/locale.test.ts +51 -0
  116. package/test/passport.test.ts +57 -0
  117. package/test/queue.test.ts +11 -0
  118. package/test/tail.test.ts +21 -0
  119. package/test/upload.test.ts +58 -0
  120. package/test/utils/cabloyUtils.test.ts +22 -0
  121. package/test/utils/celjs.test.ts +26 -0
  122. package/test/utils/mappedTypes.test.ts +65 -0
  123. package/test/utils/performAction.test.ts +28 -0
@@ -0,0 +1,58 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+
5
+ describe('caching.test.ts', () => {
6
+ it('action:caching', async () => {
7
+ await app.bean.executor.mockCtx(async () => {
8
+ const scopeTest = app.bean.scope('test-vona');
9
+ // get: cacheKeyFn(string)
10
+ const res = await scopeTest.service.caching.get(2);
11
+ assert.equal(res.id, 2);
12
+ // get: cacheKeyFn(function)
13
+ const res2 = await scopeTest.service.caching.get2(2);
14
+ assert.equal(res.id, res2.id);
15
+ // get: cacheKey(celjs expression)
16
+ const res3 = await scopeTest.service.caching.get3(2);
17
+ assert.equal(res.id, res3.id);
18
+ // get: cacheKey(default)
19
+ const res4 = await scopeTest.service.caching.get4(2);
20
+ assert.equal(res.id, res4.id);
21
+ // get: cacheKey(default) not hit cache
22
+ const res5 = await scopeTest.service.caching.get4(5);
23
+ assert.equal(res5, undefined);
24
+ // set: cacheKeyFn/cacheValueFn
25
+ await scopeTest.service.caching.set(2, { ...res, name: `${res.name}!` });
26
+ // get again
27
+ const res6 = await scopeTest.service.caching.get4(2);
28
+ assert.equal(res.id, res6.id);
29
+ assert.equal(`${res.name}!`, res6.name);
30
+ // set: cacheKey/cacheValue
31
+ await scopeTest.service.caching.set2(2, { ...res, name: `${res.name}!` });
32
+ // get again
33
+ const res7 = await scopeTest.service.caching.get4(2);
34
+ assert.equal(res.id, res7.id);
35
+ assert.equal(`${res.name}!`, res7.name);
36
+ // set: no cacheValue/cacheValueFn
37
+ await scopeTest.service.caching.set3(2, { ...res, name: `${res.name}!` });
38
+ // get again
39
+ const res8 = await scopeTest.service.caching.get4(2);
40
+ assert.equal(res.id, res8.id);
41
+ assert.equal(`${res.name}!`, res8.name);
42
+ // del
43
+ await scopeTest.service.caching.del(2);
44
+ // get again
45
+ const res9 = await scopeTest.service.caching.get4(2);
46
+ assert.equal(res9, undefined);
47
+ // cache again
48
+ const res10 = await scopeTest.service.caching.get(2);
49
+ assert.equal(res10.id, 2);
50
+ const res11 = await scopeTest.service.caching.get4(2);
51
+ assert.equal(res11.id, 2);
52
+ // clear
53
+ await scopeTest.service.caching.clear();
54
+ const res12 = await scopeTest.service.caching.get4(2);
55
+ assert.equal(res12, undefined);
56
+ });
57
+ });
58
+ });
@@ -0,0 +1,10 @@
1
+ import { describe, it } from 'node:test';
2
+ import { app } from 'vona-mock';
3
+
4
+ describe('summer.test.ts', () => {
5
+ it('action:summer', async () => {
6
+ await app.bean.executor.mockCtx(async () => {
7
+ await app.bean.executor.performAction('post', '/test/vona/summer');
8
+ });
9
+ });
10
+ });
@@ -0,0 +1,127 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { catchError } from '@cabloy/utils';
4
+ import moment from 'moment';
5
+ import { app } from 'vona-mock';
6
+
7
+ describe('database.test.ts', () => {
8
+ it('action:database:switchClient', async () => {
9
+ await app.bean.executor.mockCtx(async () => {
10
+ const scopeDatabase = app.bean.scope('a-orm');
11
+ const defaultClientName = scopeDatabase.service.database.getDefaultClientName();
12
+ // current
13
+ assert.equal(app.ctx.db.clientName, defaultClientName);
14
+ // switch
15
+ const clientNames = Object.keys(app.config.database.clients);
16
+ const clientName2 = clientNames.find(item => item !== defaultClientName);
17
+ await app.bean.database.switchDb(async () => {
18
+ assert.equal(app.ctx.db.clientName, clientName2);
19
+ }, { clientName: clientName2 as any });
20
+ // restore
21
+ assert.equal(app.ctx.db.clientName, defaultClientName);
22
+ });
23
+ });
24
+ it('action:model:clientName', async () => {
25
+ await app.bean.executor.mockCtx(async () => {
26
+ // scope
27
+ const scopeTest = app.bean.scope('test-vona');
28
+ const modelTest = scopeTest.model.test;
29
+ assert.equal(modelTest.options.client, 'default');
30
+ const modelTest2 = scopeTest.model.test;
31
+ assert.equal(modelTest, modelTest2);
32
+ });
33
+ });
34
+ it('action:model:clientNameDynamic:transaction:fail', async () => {
35
+ await app.bean.executor.mockCtx(async () => {
36
+ // scope
37
+ const scopeTest = app.bean.scope('test-vona');
38
+ const entityTest = await scopeTest.model.test.insert({ title: 'clientNameDynamic:fail' });
39
+ assert.equal(entityTest.title, 'clientNameDynamic:fail');
40
+ await catchError(async () => {
41
+ const db = app.bean.database.getDb({ clientName: 'default' });
42
+ await db.transaction.begin(async () => {
43
+ const modelTest = scopeTest.model.test.newInstance(db);
44
+ assert.equal(modelTest.options.client, 'default');
45
+ await modelTest.update({ id: entityTest.id, title: 'clientNameDynamic:fail_1' });
46
+ throw new Error('rollback');
47
+ });
48
+ });
49
+ const entityTest2 = await scopeTest.model.test.get({ id: entityTest.id });
50
+ assert.equal(entityTest2?.title, 'clientNameDynamic:fail');
51
+ // delete
52
+ await scopeTest.model.test.delete({ id: entityTest.id });
53
+ });
54
+ });
55
+ it('action:model:clientNameDynamic:transaction:success', async () => {
56
+ await app.bean.executor.mockCtx(async () => {
57
+ // scope
58
+ const scopeTest = app.bean.scope('test-vona');
59
+ const entityTest = await scopeTest.model.test.insert({ title: 'clientNameDynamic:success' });
60
+ assert.equal(entityTest.title, 'clientNameDynamic:success');
61
+ const db = app.bean.database.getDb({ clientName: 'default' });
62
+ await db.transaction.begin(async () => {
63
+ const modelTest = scopeTest.model.test.newInstance(db);
64
+ assert.equal(modelTest.options.client, 'default');
65
+ await modelTest.update({ id: entityTest.id, title: 'clientNameDynamic:success_1' });
66
+ });
67
+ const entityTest2 = await scopeTest.model.test.get({ id: entityTest.id });
68
+ assert.equal(entityTest2?.title, 'clientNameDynamic:success_1');
69
+ // delete
70
+ await scopeTest.model.test.delete({ id: entityTest.id });
71
+ });
72
+ });
73
+ it('action:database:transaction:compensate', async () => {
74
+ await app.bean.executor.mockCtx(async () => {
75
+ // scope
76
+ const scopeTest = app.bean.scope('test-vona');
77
+ const entityTest = await scopeTest.model.test.insert({ title: 'transaction:compensate:fail' });
78
+ assert.equal(entityTest.title, 'transaction:compensate:fail');
79
+ await catchError(async () => {
80
+ const db = app.bean.database.getDb({ clientName: 'default' });
81
+ await db.transaction.begin(async () => {
82
+ const modelTest = scopeTest.model.test.newInstance(db);
83
+ assert.equal(modelTest.options.client, 'default');
84
+ await modelTest.update({ id: entityTest.id, title: 'transaction:compensate:fail_1' });
85
+ // let cache take effect
86
+ await modelTest.get({ id: entityTest.id });
87
+ throw new Error('rollback');
88
+ });
89
+ });
90
+ const entityTest2 = await scopeTest.model.test.get({ id: entityTest.id });
91
+ assert.equal(entityTest2?.title, 'transaction:compensate:fail');
92
+ // delete
93
+ await scopeTest.model.test.delete({ id: entityTest.id });
94
+ });
95
+ });
96
+ it('action:model:dynamicTableName', async () => {
97
+ await app.bean.executor.mockCtx(async () => {
98
+ // scope
99
+ const scopeTest = app.bean.scope('test-vona');
100
+ const entityTest = scopeTest.entity.test;
101
+ const modelTest = scopeTest.model.testDynamicTable;
102
+ // tableName
103
+ const tableName = `${entityTest.$table}_${moment().format('YYYYMMDD')}`;
104
+ // create table
105
+ await app.bean.model.createTable(tableName, table => {
106
+ table.basicFields();
107
+ table.string(entityTest.title, 255);
108
+ table.string(entityTest.description, 255);
109
+ });
110
+ // insert
111
+ const item = await modelTest.insert({ title: 'title', description: 'description' });
112
+ // get
113
+ const item2 = await modelTest.get({ id: item.id });
114
+ assert.equal(item2?.id, item.id);
115
+ // get by tableName
116
+ const item3 = await app.bean.model.get(tableName as any, { id: item.id });
117
+ assert.equal(item3.id, item.id);
118
+ // delete
119
+ await modelTest.delete({ id: item.id });
120
+ // get by tableName
121
+ const item4 = await app.bean.model.get(tableName as any, { id: item.id });
122
+ assert.equal(item4, undefined);
123
+ // drop table
124
+ await app.bean.model.dropTable(tableName);
125
+ });
126
+ });
127
+ });
@@ -0,0 +1,44 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+ import { getTargetDecoratorRules } from 'vona-module-a-openapi';
5
+ import { $Dto } from 'vona-module-a-orm';
6
+ import { ModelUserStats } from 'vona-module-test-vona';
7
+
8
+ describe('dtoAggregate.test.ts', () => {
9
+ it('action:dtoAggregate', async () => {
10
+ await app.bean.executor.mockCtx(async () => {
11
+ await app.bean.executor.mockCtx(async () => {
12
+ // aggr
13
+ const DtoUserAggr = $Dto.aggregate('test-vona:user', {
14
+ count: ['*', 'age'],
15
+ sum: ['age'],
16
+ avg: 'age',
17
+ // max: 'age',
18
+ // min: 'age',
19
+ });
20
+ let rules: any;
21
+ rules = getTargetDecoratorRules(DtoUserAggr.prototype);
22
+ assert.equal(rules.count_all._def.typeName, 'ZodOptional');
23
+ assert.equal(rules.count_all._def.innerType._def.typeName, 'ZodUnion');
24
+ assert.equal(rules.count_all._def.innerType._def.options[0]._def.typeName, 'ZodString');
25
+ assert.equal(rules.count_all._def.innerType._def.options[1]._def.typeName, 'ZodNumber');
26
+ assert.equal(rules.count_age._def.typeName, 'ZodOptional');
27
+ assert.equal(rules.sum_age._def.typeName, 'ZodOptional');
28
+ assert.equal(rules.avg_age._def.typeName, 'ZodOptional');
29
+ assert.equal(rules.max_age, undefined);
30
+ assert.equal(rules.min_age, undefined);
31
+ // aggr: usersStats: posts: autoload
32
+ const DtoUserStats = $Dto.get(() => ModelUserStats, {
33
+ columns: 'name',
34
+ include: { roles: true },
35
+ });
36
+ rules = getTargetDecoratorRules(DtoUserStats.prototype);
37
+ assert.equal(rules.name._def.typeName, 'ZodString');
38
+ assert.equal(rules.iid, undefined);
39
+ assert.equal(rules.posts._def.typeName, 'ZodOptional');
40
+ assert.equal(rules.roles._def.typeName, 'ZodOptional');
41
+ });
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,61 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+ import { getTargetDecoratorRules } from 'vona-module-a-openapi';
5
+ import { $Dto, $relationDynamic } from 'vona-module-a-orm';
6
+ import { ModelPost, ModelPostContent, ModelRole, ModelRoleUser, ModelUser } from 'vona-module-test-vona';
7
+
8
+ describe('dtoGet.test.ts', () => {
9
+ it('action:dtoGet', async () => {
10
+ await app.bean.executor.mockCtx(async () => {
11
+ await app.bean.executor.mockCtx(async () => {
12
+ const DtoPostNew = $Dto.get(ModelPost, {
13
+ columns: ['id', 'title', 'userId'],
14
+ include: {
15
+ postContent: {
16
+ columns: ['id', 'content'],
17
+ include: {
18
+ post: { include: { user: { columns: ['id'] } } },
19
+ },
20
+ with: {
21
+ post3: $relationDynamic.belongsTo(() => ModelPostContent, () => ModelPost, 'postId', {
22
+ include: {
23
+ postContent: true,
24
+ },
25
+ }),
26
+ },
27
+ },
28
+ },
29
+ with: {
30
+ user3: $relationDynamic.belongsTo(ModelPost, () => ModelUser, 'userId', {
31
+ include: { posts: true },
32
+ with: { roles: $relationDynamic.belongsToMany(() => ModelRoleUser, () => ModelRole, 'userId', 'roleId') },
33
+ columns: ['id', 'name'],
34
+ }),
35
+ },
36
+ });
37
+ const rules: any = getTargetDecoratorRules(DtoPostNew.prototype);
38
+ assert.equal(['ZodString', 'ZodNumber'].includes(rules.id._def.typeName), true);
39
+ assert.equal(rules.title._def.typeName, 'ZodString');
40
+ assert.equal(['ZodString', 'ZodNumber'].includes(rules.userId._def.typeName), true);
41
+ assert.equal(rules.iid, undefined);
42
+ assert.equal(rules.postContent._def.typeName, 'ZodOptional');
43
+ assert.equal(rules.user._def.typeName, 'ZodOptional');
44
+ assert.equal(rules.user3._def.typeName, 'ZodOptional');
45
+ });
46
+ });
47
+ });
48
+ it('action:dtoGet:categoryTree', async () => {
49
+ await app.bean.executor.mockCtx(async () => {
50
+ await app.bean.executor.mockCtx(async () => {
51
+ const DtoCategoryTree = $Dto.get('test-vona:category', { columns: ['id', 'name'], include: { children: { columns: ['id'] } } });
52
+ const rules: any = getTargetDecoratorRules(DtoCategoryTree.prototype);
53
+ assert.equal(rules.children._def.typeName, 'ZodEffects');
54
+ assert.equal(rules.iid, undefined);
55
+ const DtoCategoryChain = $Dto.get('test-vona:categoryChain', { columns: ['id', 'name', 'categoryIdParent'] });
56
+ const _apiJson = await app.bean.scope('a-openapi').service.openapi.generateJsonOfClass(DtoCategoryChain);
57
+ // console.log(JSON.stringify(apiJson.components));
58
+ });
59
+ });
60
+ });
61
+ });
@@ -0,0 +1,44 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+ import { getTargetDecoratorRules } from 'vona-module-a-openapi';
5
+ import { $Dto } from 'vona-module-a-orm';
6
+ import { ModelUserStatsGroup } from 'vona-module-test-vona';
7
+
8
+ describe('dtoGroup.test.ts', () => {
9
+ it('action:dtoGroup', async () => {
10
+ await app.bean.executor.mockCtx(async () => {
11
+ await app.bean.executor.mockCtx(async () => {
12
+ const DtoUserAggr = $Dto.group('test-vona:user', ['name'], {
13
+ count: ['*', 'age'],
14
+ sum: ['age'],
15
+ avg: 'age',
16
+ // max: 'age',
17
+ // min: 'age',
18
+ });
19
+ let rules: any;
20
+ rules = getTargetDecoratorRules(DtoUserAggr.prototype);
21
+ assert.equal(rules.name._def.typeName, 'ZodString');
22
+ assert.equal(rules.count_all._def.typeName, 'ZodOptional');
23
+ assert.equal(rules.count_all._def.innerType._def.typeName, 'ZodUnion');
24
+ assert.equal(rules.count_all._def.innerType._def.options[0]._def.typeName, 'ZodString');
25
+ assert.equal(rules.count_all._def.innerType._def.options[1]._def.typeName, 'ZodNumber');
26
+ assert.equal(rules.count_age._def.typeName, 'ZodOptional');
27
+ assert.equal(rules.sum_age._def.typeName, 'ZodOptional');
28
+ assert.equal(rules.avg_age._def.typeName, 'ZodOptional');
29
+ assert.equal(rules.max_age, undefined);
30
+ assert.equal(rules.min_age, undefined);
31
+ // group: userStats: posts: autoload
32
+ const DtoUserStats = $Dto.get(() => ModelUserStatsGroup, {
33
+ columns: 'name',
34
+ include: { roles: true },
35
+ });
36
+ rules = getTargetDecoratorRules(DtoUserStats.prototype);
37
+ assert.equal(rules.name._def.typeName, 'ZodString');
38
+ assert.equal(rules.iid, undefined);
39
+ assert.equal(rules.posts._def.typeName, 'ZodEffects');
40
+ assert.equal(rules.roles._def.typeName, 'ZodEffects');
41
+ });
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,45 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { OpenApiGeneratorV31, OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
4
+ import { appResource, cast } from 'vona';
5
+ import { app } from 'vona-mock';
6
+ import { $schema } from 'vona-module-a-openapi';
7
+ import { DtoUserLazy } from 'vona-module-test-vona';
8
+
9
+ describe('dtoLazy.test.ts', () => {
10
+ it('action:dtoLazy', async () => {
11
+ await app.bean.executor.mockCtx(async () => {
12
+ const data = {
13
+ name: 'kevin',
14
+ other: 'other',
15
+ user: {
16
+ id: 1,
17
+ name: 'tom',
18
+ married: 1,
19
+ },
20
+ roles: [{ id: 2, name: 'admin' }],
21
+ };
22
+ const schema = $schema(DtoUserLazy);
23
+ const res = await schema.parseAsync(data);
24
+ assert.equal(res.name, 'kevin');
25
+ assert.equal(cast(res).other, undefined);
26
+ assert.equal(res.user?.name, 'tom');
27
+ assert.equal(cast(res.user)?.married, undefined);
28
+ assert.equal(res.roles?.length, 1);
29
+ assert.equal(res.roles?.[0].name, 'admin');
30
+ assert.equal(cast(res.roles?.[0])?.id, undefined);
31
+ });
32
+ });
33
+ it('action:openapi', async () => {
34
+ await app.bean.executor.mockCtx(async () => {
35
+ const registry = new OpenAPIRegistry();
36
+ const beanOptions = appResource.getBean(DtoUserLazy)!;
37
+ const schema = $schema(beanOptions.beanClass);
38
+ registry.register(beanOptions.beanFullName, schema);
39
+ const generator = new OpenApiGeneratorV31(registry.definitions);
40
+ const apiObj = generator.generateDocument(app.bean.scope('a-openapi').config.generateDocument.V31);
41
+ assert.equal(cast(apiObj).components.schemas['test-vona.dto.userLazy'].properties.user.$ref, '#/components/schemas/test-vona.dto.userLazy');
42
+ assert.equal(cast(apiObj).components.schemas['test-vona.dto.roleLazy'].properties.users.items.$ref, '#/components/schemas/test-vona.dto.userLazy');
43
+ });
44
+ });
45
+ });
@@ -0,0 +1,56 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { app } from 'vona-mock';
4
+ import { getTargetDecoratorRules } from 'vona-module-a-openapi';
5
+ import { $Dto, $relationDynamic } from 'vona-module-a-orm';
6
+ import { ModelPost } from 'vona-module-test-vona';
7
+
8
+ describe('dtoMutate.test.ts', () => {
9
+ it('action:dtoMutate', async () => {
10
+ await app.bean.executor.mockCtx(async () => {
11
+ await app.bean.executor.mockCtx(async () => {
12
+ // create
13
+ const DtoUserCreate = $Dto.create('test-vona:user', {
14
+ include: { posts: true },
15
+ });
16
+ let rules: any;
17
+ rules = getTargetDecoratorRules(DtoUserCreate.prototype);
18
+ assert.equal(rules.name._def.typeName, 'ZodString');
19
+ assert.equal(rules.id, undefined);
20
+ assert.equal(rules.iid, undefined);
21
+ assert.equal(rules.deleted, undefined);
22
+ assert.equal(rules.createdAt, undefined);
23
+ assert.equal(rules.updatedAt, undefined);
24
+ assert.equal(rules.posts._def.typeName, 'ZodOptional');
25
+ // update
26
+ const DtoUserUpdate = $Dto.update('test-vona:user', {
27
+ with: {
28
+ posts: $relationDynamic.hasMany(() => ModelPost, 'userId', { columns: ['id', 'title'] }),
29
+ },
30
+ });
31
+ rules = getTargetDecoratorRules(DtoUserUpdate.prototype);
32
+ assert.equal(rules.name._def.typeName, 'ZodString'); // ZodOptional
33
+ assert.equal(rules.id, undefined);
34
+ assert.equal(rules.iid, undefined);
35
+ assert.equal(rules.deleted, undefined);
36
+ assert.equal(rules.createdAt, undefined);
37
+ assert.equal(rules.updatedAt, undefined);
38
+ assert.equal(rules.posts._def.typeName, 'ZodOptional');
39
+ // create: not mutate post(belongsTo)
40
+ const DtoPostCreate = $Dto.create('test-vona:post', {
41
+ include: {
42
+ postContent: true,
43
+ user: true,
44
+ },
45
+ });
46
+ rules = getTargetDecoratorRules(DtoPostCreate.prototype);
47
+ assert.equal(rules.title._def.typeName, 'ZodString'); // ZodOptional
48
+ assert.equal(rules.stars._def.typeName, 'ZodOptional');
49
+ assert.equal(['ZodString', 'ZodNumber'].includes(rules.userId._def.typeName), true);
50
+ assert.equal(rules.postContent._def.typeName, 'ZodOptional');
51
+ assert.equal(rules.user, undefined);
52
+ assert.equal(rules.id, undefined);
53
+ });
54
+ });
55
+ });
56
+ });
@@ -0,0 +1,197 @@
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
3
+ import { cast } from 'vona';
4
+ import { app } from 'vona-mock';
5
+ import { $relationDynamic } from 'vona-module-a-orm';
6
+ import { ModelPost, ModelRole, ModelRoleUser } from 'vona-module-test-vona';
7
+
8
+ describe('modelAggregate.test.ts', () => {
9
+ it('action:modelAggregate', async () => {
10
+ await app.bean.executor.mockCtx(async () => {
11
+ const prefix = 'action:modelAggregate';
12
+ // scope
13
+ const scopeTest = app.bean.scope('test-vona');
14
+ // insert: roles
15
+ const roles = await scopeTest.model.role.insertBulk([
16
+ { name: `${prefix}:family` },
17
+ { name: `${prefix}:friend` },
18
+ ]);
19
+ assert.equal(roles.length, 2);
20
+ assert.equal(roles[0].id !== undefined, true);
21
+ // create: users
22
+ const users = await scopeTest.model.user.insertBulk([
23
+ {
24
+ name: `${prefix}:tom`,
25
+ age: 3,
26
+ posts: [
27
+ {
28
+ title: `${prefix}:postApple`,
29
+ stars: 2,
30
+ postContent: {
31
+ content: `${prefix}:postContentApple`,
32
+ },
33
+ },
34
+ {
35
+ title: `${prefix}:postApple2`,
36
+ stars: 3,
37
+ postContent: {
38
+ content: `${prefix}:postContentApple2`,
39
+ },
40
+ },
41
+ ],
42
+ roles: [{
43
+ id: roles[0].id,
44
+ }],
45
+ },
46
+ {
47
+ name: `${prefix}:jimmy`,
48
+ age: 5,
49
+ posts: [{
50
+ title: `${prefix}:postPear`,
51
+ stars: 4,
52
+ postContent: {
53
+ content: `${prefix}:postContentPear`,
54
+ },
55
+ }],
56
+ },
57
+ { name: `${prefix}:mike` },
58
+ ], {
59
+ include: {
60
+ posts: { include: { postContent: true } },
61
+ roles: true,
62
+ },
63
+ });
64
+ // count: user
65
+ const userCount = await scopeTest.model.user.count({
66
+ column: '*',
67
+ where: {
68
+ name: { _startsWith_: `${prefix}:` },
69
+ },
70
+ });
71
+ assert.equal(userCount, 3);
72
+ // aggr: user
73
+ const userStats = await scopeTest.model.user.aggregate({
74
+ aggrs: {
75
+ count: ['*', 'age'],
76
+ sum: ['age'],
77
+ avg: 'age',
78
+ max: 'age',
79
+ },
80
+ where: {
81
+ name: { _startsWith_: `${prefix}:` },
82
+ },
83
+ });
84
+ assert.equal(userStats.count_all, 3);
85
+ assert.equal(userStats.count_age, 2);
86
+ assert.equal(userStats.sum_age, 8);
87
+ assert.equal(userStats.avg_age, 4);
88
+ assert.equal(userStats.max_age, 5);
89
+ // aggr: usersStats: posts: autoload
90
+ const usersStats = await scopeTest.model.userStats.select({
91
+ where: {
92
+ id: users.map(item => item.id),
93
+ },
94
+ orders: [['id', 'asc']],
95
+ include: {
96
+ roles: true,
97
+ },
98
+ });
99
+ assert.equal(usersStats.length, 3);
100
+ assert.equal(usersStats[0].posts?.count_all, 2);
101
+ assert.equal(usersStats[0].posts?.count_title, 2);
102
+ assert.equal(usersStats[0].posts?.sum_stars, 5);
103
+ assert.equal(usersStats[0].roles?.count_all, 1);
104
+ // aggr: usersStats: posts: mixed
105
+ const usersStats2 = await scopeTest.model.userStats.select({
106
+ where: {
107
+ id: users.map(item => item.id),
108
+ },
109
+ orders: [['id', 'asc']],
110
+ include: {
111
+ posts: { aggrs: { count: '*' } },
112
+ roles: true,
113
+ },
114
+ });
115
+ assert.equal(usersStats2.length, 3);
116
+ assert.equal(usersStats2[0].posts?.count_all, 2);
117
+ assert.equal(cast(usersStats2[0].posts).count_title, undefined);
118
+ assert.equal(usersStats2[0].posts?.sum_stars, 5);
119
+ assert.equal(usersStats2[0].roles?.count_all, 1);
120
+ // aggr: usersStats: posts: disable
121
+ const usersStats3 = await scopeTest.model.userStats.select({
122
+ where: {
123
+ id: users.map(item => item.id),
124
+ },
125
+ orders: [['id', 'asc']],
126
+ include: {
127
+ posts: {
128
+ aggrs: {
129
+ count: ['*'],
130
+ sum: [],
131
+ },
132
+ },
133
+ roles: true,
134
+ },
135
+ });
136
+ assert.equal(usersStats3.length, 3);
137
+ assert.equal(usersStats3[0].posts?.count_all, 2);
138
+ assert.equal(cast(usersStats3[0].posts).count_title, undefined);
139
+ assert.equal(cast(usersStats3[0].posts).sum_stars, undefined);
140
+ assert.equal(usersStats3[0].roles?.count_all, 1);
141
+ // aggr: usersStats: with
142
+ const usersStats4 = await scopeTest.model.userStats.select({
143
+ where: {
144
+ id: users.map(item => item.id),
145
+ },
146
+ orders: [['id', 'asc']],
147
+ include: {
148
+ posts: false,
149
+ roles: false,
150
+ },
151
+ with: {
152
+ posts: $relationDynamic.hasMany(() => ModelPost, 'userId', {
153
+ aggrs: { count: '*' },
154
+ }),
155
+ roles: $relationDynamic.belongsToMany(() => ModelRoleUser, () => ModelRole, 'userId', 'roleId', {
156
+ aggrs: { count: '*' },
157
+ }),
158
+ },
159
+ });
160
+ assert.equal(usersStats4.length, 3);
161
+ assert.equal(usersStats4[0].posts?.count_all, 2);
162
+ assert.equal(cast(usersStats4[0].posts).count_title, undefined);
163
+ assert.equal(cast(usersStats4[0].posts).sum_stars, undefined);
164
+ assert.equal(usersStats4[0].roles?.count_all, 1);
165
+ // aggr: get
166
+ const userStats4 = await scopeTest.model.userStats.get({
167
+ id: users[0].id,
168
+ }, {
169
+ include: {
170
+ posts: false,
171
+ roles: false,
172
+ },
173
+ with: {
174
+ posts: $relationDynamic.hasMany(() => ModelPost, 'userId', {
175
+ aggrs: { count: '*' },
176
+ }),
177
+ roles: $relationDynamic.belongsToMany(() => ModelRoleUser, () => ModelRole, 'userId', 'roleId', {
178
+ aggrs: { count: '*' },
179
+ }),
180
+ },
181
+ });
182
+ assert.equal(userStats4?.posts?.count_all, 2);
183
+ assert.equal(cast(userStats4?.posts).count_title, undefined);
184
+ assert.equal(cast(userStats4?.posts).sum_stars, undefined);
185
+ assert.equal(userStats4?.roles?.count_all, 1);
186
+ // delete: users
187
+ await scopeTest.model.user.deleteBulk(users.map(item => item.id), {
188
+ include: {
189
+ posts: { include: { postContent: true } },
190
+ roles: true,
191
+ },
192
+ });
193
+ // delete: roles
194
+ await scopeTest.model.role.deleteBulk(roles.map(item => item.id));
195
+ });
196
+ });
197
+ });