@companix/xeo-server 0.0.2
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/.eslintrc +54 -0
- package/dist/common/decorators.d.ts +3 -0
- package/dist/common/decorators.js +14 -0
- package/dist/common/decorators.js.map +1 -0
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.js +20 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/tokens.d.ts +3 -0
- package/dist/common/tokens.js +14 -0
- package/dist/common/tokens.js.map +1 -0
- package/dist/common/utils.d.ts +2 -0
- package/dist/common/utils.js +19 -0
- package/dist/common/utils.js.map +1 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -0
- package/dist/driver.module.d.ts +7 -0
- package/dist/driver.module.js +41 -0
- package/dist/driver.module.js.map +1 -0
- package/dist/drivers/collection.driver.d.ts +21 -0
- package/dist/drivers/collection.driver.js +101 -0
- package/dist/drivers/collection.driver.js.map +1 -0
- package/dist/drivers/table.driver.d.ts +13 -0
- package/dist/drivers/table.driver.js +79 -0
- package/dist/drivers/table.driver.js.map +1 -0
- package/dist/factories/definitions.factory.d.ts +11 -0
- package/dist/factories/definitions.factory.js +116 -0
- package/dist/factories/definitions.factory.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/mongoose-options.interface.d.ts +12 -0
- package/dist/mongoose-options.interface.js +3 -0
- package/dist/mongoose-options.interface.js.map +1 -0
- package/dist/mongoose.module.d.ts +11 -0
- package/dist/mongoose.module.js +108 -0
- package/dist/mongoose.module.js.map +1 -0
- package/dist/storages/data-source.d.ts +10 -0
- package/dist/storages/data-source.js +34 -0
- package/dist/storages/data-source.js.map +1 -0
- package/jest.cases.config.cjs +14 -0
- package/lib/common/decorators.ts +17 -0
- package/lib/common/index.ts +3 -0
- package/lib/common/tokens.ts +17 -0
- package/lib/common/utils.ts +29 -0
- package/lib/constants.ts +4 -0
- package/lib/driver.module.ts +37 -0
- package/lib/drivers/collection.driver.ts +157 -0
- package/lib/drivers/table.driver.ts +109 -0
- package/lib/factories/definitions.factory.ts +129 -0
- package/lib/index.ts +3 -0
- package/lib/mongoose-options.interface.ts +19 -0
- package/lib/mongoose.module.ts +95 -0
- package/lib/storages/data-source.ts +37 -0
- package/package.json +42 -0
- package/tests/app/bootstrap.ts +16 -0
- package/tests/app/db.ts +22 -0
- package/tests/app/filters.ts +25 -0
- package/tests/app/helpers/is-one-of.ts +58 -0
- package/tests/app/main.ts +3 -0
- package/tests/app/module/app.controller.ts +67 -0
- package/tests/app/module/app.dto.ts +394 -0
- package/tests/app/module/app.module.ts +12 -0
- package/tests/app/module/app.service.ts +76 -0
- package/tests/app/root.module.ts +12 -0
- package/tests/globals.d.ts +6 -0
- package/tests/integrations/cases.test.ts +154 -0
- package/tests/integrations/custom.test.ts +69 -0
- package/tests/unit/definitions.test.ts +31 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +17 -0
- package/tsconfig.test-app.json +10 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { Type } from 'class-transformer'
|
|
2
|
+
import {
|
|
3
|
+
IsArray,
|
|
4
|
+
IsBoolean,
|
|
5
|
+
IsEmail,
|
|
6
|
+
IsIn,
|
|
7
|
+
IsNotEmptyObject,
|
|
8
|
+
IsNumber,
|
|
9
|
+
IsObject,
|
|
10
|
+
IsString,
|
|
11
|
+
ValidateIf,
|
|
12
|
+
ValidateNested
|
|
13
|
+
} from 'class-validator'
|
|
14
|
+
import type { DateFormat, FileFormat } from '@companix/utils-js'
|
|
15
|
+
import { WorkerEntities, DictionaryEntities, RoleEntities, AppKey, AppKeys } from '@companix/xeo-devkit'
|
|
16
|
+
|
|
17
|
+
export class DateFormatDto implements DateFormat {
|
|
18
|
+
@IsNumber()
|
|
19
|
+
year: number
|
|
20
|
+
|
|
21
|
+
@IsNumber()
|
|
22
|
+
month: number
|
|
23
|
+
|
|
24
|
+
@IsNumber()
|
|
25
|
+
day: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class FilmDto implements WorkerEntities.Film {
|
|
29
|
+
@IsString()
|
|
30
|
+
anime: string
|
|
31
|
+
|
|
32
|
+
@IsBoolean()
|
|
33
|
+
isTheater: boolean
|
|
34
|
+
|
|
35
|
+
@IsArray()
|
|
36
|
+
@IsString({ each: true })
|
|
37
|
+
actors: string[]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class ContactsDto implements WorkerEntities.Contacts {
|
|
41
|
+
@IsString()
|
|
42
|
+
phone_base: string
|
|
43
|
+
|
|
44
|
+
@IsBoolean()
|
|
45
|
+
phone_base_verified: boolean
|
|
46
|
+
|
|
47
|
+
@IsString()
|
|
48
|
+
phone_extra: string
|
|
49
|
+
|
|
50
|
+
@IsBoolean()
|
|
51
|
+
phone_extra_verified: boolean
|
|
52
|
+
|
|
53
|
+
@IsString()
|
|
54
|
+
whatsapp_phone: string
|
|
55
|
+
|
|
56
|
+
@IsBoolean()
|
|
57
|
+
whatsapp_verified: boolean
|
|
58
|
+
|
|
59
|
+
@IsString()
|
|
60
|
+
viber_phone: string
|
|
61
|
+
|
|
62
|
+
@IsBoolean()
|
|
63
|
+
viber_verified: boolean
|
|
64
|
+
|
|
65
|
+
@IsString()
|
|
66
|
+
telegram_nickname: string
|
|
67
|
+
|
|
68
|
+
@IsString()
|
|
69
|
+
telegram_phone: string
|
|
70
|
+
|
|
71
|
+
@IsBoolean()
|
|
72
|
+
telegram_phone_verified: boolean
|
|
73
|
+
|
|
74
|
+
@ValidateNested()
|
|
75
|
+
@Type(() => FilmDto)
|
|
76
|
+
film: FilmDto
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export class AboutDto implements WorkerEntities.About {
|
|
80
|
+
@ValidateIf((_, value) => value !== null)
|
|
81
|
+
@IsNumber()
|
|
82
|
+
height: number | null
|
|
83
|
+
|
|
84
|
+
@IsString()
|
|
85
|
+
shoe_size: string
|
|
86
|
+
|
|
87
|
+
@IsString()
|
|
88
|
+
clothing_size: string
|
|
89
|
+
|
|
90
|
+
@IsArray()
|
|
91
|
+
@IsString({ each: true })
|
|
92
|
+
regions: string[]
|
|
93
|
+
|
|
94
|
+
@IsArray()
|
|
95
|
+
@IsString({ each: true })
|
|
96
|
+
kind_of_work: string[]
|
|
97
|
+
|
|
98
|
+
@IsArray()
|
|
99
|
+
@IsString({ each: true })
|
|
100
|
+
employments: string[]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class DocumentsDto implements WorkerEntities.Documents {
|
|
104
|
+
@ValidateIf((_, value) => value !== null)
|
|
105
|
+
@IsIn(AppKeys.Citizenship)
|
|
106
|
+
citizenship: AppKey.Citizenship | null
|
|
107
|
+
|
|
108
|
+
@IsString()
|
|
109
|
+
passport_number: string
|
|
110
|
+
|
|
111
|
+
@IsString()
|
|
112
|
+
passport_serial: string
|
|
113
|
+
|
|
114
|
+
@IsString()
|
|
115
|
+
passport_issued_by: string
|
|
116
|
+
|
|
117
|
+
@ValidateIf((_, value) => value !== null)
|
|
118
|
+
@ValidateNested()
|
|
119
|
+
@Type(() => DateFormatDto)
|
|
120
|
+
passport_issued_date: DateFormat | null
|
|
121
|
+
|
|
122
|
+
@IsString()
|
|
123
|
+
place_of_birth: string
|
|
124
|
+
|
|
125
|
+
@IsString()
|
|
126
|
+
registration_place: string
|
|
127
|
+
|
|
128
|
+
@IsString()
|
|
129
|
+
inn: string
|
|
130
|
+
|
|
131
|
+
@IsString()
|
|
132
|
+
snils: string
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class WorkerBaseDto implements WorkerEntities.BaseWorker {
|
|
136
|
+
@IsNumber()
|
|
137
|
+
workerId: number
|
|
138
|
+
|
|
139
|
+
@IsIn(['office', 'revisor'])
|
|
140
|
+
type: 'office' | 'revisor'
|
|
141
|
+
|
|
142
|
+
@ValidateIf((_, value) => value !== null)
|
|
143
|
+
@IsNumber()
|
|
144
|
+
tgid: number | null
|
|
145
|
+
|
|
146
|
+
@IsNumber()
|
|
147
|
+
createdAt: number
|
|
148
|
+
|
|
149
|
+
@IsObject()
|
|
150
|
+
avatar: FileFormat
|
|
151
|
+
|
|
152
|
+
@IsString()
|
|
153
|
+
name: string
|
|
154
|
+
|
|
155
|
+
@IsString()
|
|
156
|
+
surname: string
|
|
157
|
+
|
|
158
|
+
@IsString()
|
|
159
|
+
patronymic: string
|
|
160
|
+
|
|
161
|
+
@IsEmail()
|
|
162
|
+
email: string
|
|
163
|
+
|
|
164
|
+
@IsIn(AppKeys.Sex)
|
|
165
|
+
sex: AppKey.Sex
|
|
166
|
+
|
|
167
|
+
@IsIn(AppKeys.WorkerStatus)
|
|
168
|
+
status: AppKey.WorkerStatus
|
|
169
|
+
|
|
170
|
+
@ValidateNested()
|
|
171
|
+
@Type(() => DateFormatDto)
|
|
172
|
+
date_birth: DateFormat
|
|
173
|
+
|
|
174
|
+
@ValidateNested()
|
|
175
|
+
@Type(() => DateFormatDto)
|
|
176
|
+
date_employ: DateFormat
|
|
177
|
+
|
|
178
|
+
@ValidateNested()
|
|
179
|
+
@Type(() => ContactsDto)
|
|
180
|
+
contacts: ContactsDto
|
|
181
|
+
|
|
182
|
+
@ValidateNested()
|
|
183
|
+
@Type(() => DocumentsDto)
|
|
184
|
+
documents: DocumentsDto
|
|
185
|
+
|
|
186
|
+
@ValidateNested()
|
|
187
|
+
@Type(() => AboutDto)
|
|
188
|
+
about: AboutDto
|
|
189
|
+
|
|
190
|
+
@IsArray()
|
|
191
|
+
@IsString({ each: true })
|
|
192
|
+
scans: string[]
|
|
193
|
+
|
|
194
|
+
@IsArray()
|
|
195
|
+
@IsString({ each: true })
|
|
196
|
+
bank_cards: string[]
|
|
197
|
+
|
|
198
|
+
@IsArray()
|
|
199
|
+
@IsString({ each: true })
|
|
200
|
+
bank_details: string[]
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export class OfficeProfileDto extends WorkerBaseDto implements WorkerEntities.OfficeProfile {
|
|
204
|
+
@IsIn(['office'])
|
|
205
|
+
type: 'office' = 'office'
|
|
206
|
+
|
|
207
|
+
@IsString()
|
|
208
|
+
password: string
|
|
209
|
+
|
|
210
|
+
@IsArray()
|
|
211
|
+
@IsString({ each: true })
|
|
212
|
+
roles: RoleEntities.Role['value'][]
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export class RevisorProfileDto extends WorkerBaseDto implements WorkerEntities.RevisorProfile {
|
|
216
|
+
@IsIn(['revisor'])
|
|
217
|
+
type: 'revisor' = 'revisor'
|
|
218
|
+
|
|
219
|
+
@IsString()
|
|
220
|
+
password: string
|
|
221
|
+
|
|
222
|
+
@IsIn(AppKeys.RevisorRoles)
|
|
223
|
+
revisor_role: AppKey.RevisorRoles
|
|
224
|
+
|
|
225
|
+
@IsIn(AppKeys.JobType)
|
|
226
|
+
job_type: AppKey.JobType
|
|
227
|
+
|
|
228
|
+
seats: string[]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export class CreateWorkerDto {
|
|
232
|
+
@IsNotEmptyObject()
|
|
233
|
+
@ValidateNested()
|
|
234
|
+
@Type(() => WorkerBaseDto, {
|
|
235
|
+
discriminator: {
|
|
236
|
+
property: 'type',
|
|
237
|
+
subTypes: [
|
|
238
|
+
{ name: 'office', value: OfficeProfileDto },
|
|
239
|
+
{ name: 'revisor', value: RevisorProfileDto }
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
keepDiscriminatorProperty: true
|
|
243
|
+
})
|
|
244
|
+
worker: OfficeProfileDto | RevisorProfileDto
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export class ScanDto implements WorkerEntities.Scan {
|
|
248
|
+
@IsString()
|
|
249
|
+
scanId: string
|
|
250
|
+
|
|
251
|
+
@IsString()
|
|
252
|
+
name: string
|
|
253
|
+
|
|
254
|
+
@IsObject()
|
|
255
|
+
file: FileFormat
|
|
256
|
+
|
|
257
|
+
@IsNumber()
|
|
258
|
+
createdAt: number
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export class CreateScanDto {
|
|
262
|
+
@IsNotEmptyObject()
|
|
263
|
+
@ValidateNested()
|
|
264
|
+
@Type(() => ScanDto)
|
|
265
|
+
scan: ScanDto
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export class BankCardDto implements WorkerEntities.BankCard {
|
|
269
|
+
@IsString()
|
|
270
|
+
cardId: string
|
|
271
|
+
|
|
272
|
+
@IsString()
|
|
273
|
+
bank_name: string
|
|
274
|
+
|
|
275
|
+
@IsString()
|
|
276
|
+
bank_card_number: string
|
|
277
|
+
|
|
278
|
+
@IsString()
|
|
279
|
+
comment: string
|
|
280
|
+
|
|
281
|
+
@IsBoolean()
|
|
282
|
+
is_default_card: boolean
|
|
283
|
+
|
|
284
|
+
@IsObject()
|
|
285
|
+
image: FileFormat
|
|
286
|
+
|
|
287
|
+
@IsNumber()
|
|
288
|
+
createdAt: number
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export class CreateBankCardDto {
|
|
292
|
+
@IsNotEmptyObject()
|
|
293
|
+
@ValidateNested()
|
|
294
|
+
@Type(() => BankCardDto)
|
|
295
|
+
bankCard: BankCardDto
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export class BankDetailDto implements WorkerEntities.BankDetail {
|
|
299
|
+
@IsString()
|
|
300
|
+
detailId: string
|
|
301
|
+
|
|
302
|
+
@IsString()
|
|
303
|
+
recipient_name: string
|
|
304
|
+
|
|
305
|
+
@IsString()
|
|
306
|
+
bank_name: string
|
|
307
|
+
|
|
308
|
+
@IsString()
|
|
309
|
+
recipient_count: string
|
|
310
|
+
|
|
311
|
+
@IsString()
|
|
312
|
+
kor: string
|
|
313
|
+
|
|
314
|
+
@IsString()
|
|
315
|
+
bik: string
|
|
316
|
+
|
|
317
|
+
@IsString()
|
|
318
|
+
kpp: string
|
|
319
|
+
|
|
320
|
+
@IsString()
|
|
321
|
+
inn: string
|
|
322
|
+
|
|
323
|
+
@IsNumber()
|
|
324
|
+
createdAt: number
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export class CreateBankDetailDto {
|
|
328
|
+
@IsNotEmptyObject()
|
|
329
|
+
@ValidateNested()
|
|
330
|
+
@Type(() => BankDetailDto)
|
|
331
|
+
bankDetail: BankDetailDto
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export class RoleDto implements RoleEntities.Role {
|
|
335
|
+
@IsString()
|
|
336
|
+
value: string
|
|
337
|
+
|
|
338
|
+
@IsString()
|
|
339
|
+
title: string
|
|
340
|
+
|
|
341
|
+
@IsNumber()
|
|
342
|
+
createdAt: number
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export class CreateRoleDto {
|
|
346
|
+
@IsNotEmptyObject()
|
|
347
|
+
@ValidateNested()
|
|
348
|
+
@Type(() => RoleDto)
|
|
349
|
+
role: RoleDto
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export class DictionaryDto implements DictionaryEntities.Dictionary {
|
|
353
|
+
@IsIn(AppKeys.Dictionaries)
|
|
354
|
+
dictionary: AppKey.Dictionaries
|
|
355
|
+
|
|
356
|
+
@IsString()
|
|
357
|
+
name: string
|
|
358
|
+
|
|
359
|
+
@IsArray()
|
|
360
|
+
@IsString({ each: true })
|
|
361
|
+
options: DictionaryEntities.Option['value'][]
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export class CreateDictionaryDto {
|
|
365
|
+
@IsNotEmptyObject()
|
|
366
|
+
@ValidateNested()
|
|
367
|
+
@Type(() => DictionaryDto)
|
|
368
|
+
dictionary: DictionaryDto
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export class OptionDto implements DictionaryEntities.Option {
|
|
372
|
+
@IsIn(AppKeys.Dictionaries)
|
|
373
|
+
dictionary: AppKey.Dictionaries
|
|
374
|
+
|
|
375
|
+
@IsString()
|
|
376
|
+
value: string
|
|
377
|
+
|
|
378
|
+
@IsString()
|
|
379
|
+
title: string
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export class CreateOptionDto {
|
|
383
|
+
@IsNotEmptyObject()
|
|
384
|
+
@ValidateNested()
|
|
385
|
+
@Type(() => OptionDto)
|
|
386
|
+
option: OptionDto
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export class UpdateOptionDto {
|
|
390
|
+
@IsNotEmptyObject()
|
|
391
|
+
@ValidateNested()
|
|
392
|
+
@Type(() => OptionDto)
|
|
393
|
+
option: OptionDto
|
|
394
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common'
|
|
2
|
+
import { MongooseDriverModule } from '../../../lib'
|
|
3
|
+
import { AppService } from './app.service'
|
|
4
|
+
import { AppController } from './app.controller'
|
|
5
|
+
import { dataScheme } from '@companix/xeo-devkit'
|
|
6
|
+
|
|
7
|
+
@Module({
|
|
8
|
+
imports: [MongooseDriverModule.forFeature(dataScheme)],
|
|
9
|
+
controllers: [AppController],
|
|
10
|
+
providers: [AppService]
|
|
11
|
+
})
|
|
12
|
+
export class AppModule {}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common'
|
|
2
|
+
import { InjectDataSource } from '../../../lib'
|
|
3
|
+
import { dataScheme, AppScheme } from '@companix/xeo-devkit'
|
|
4
|
+
import { DataSource } from '@companix/xeo-scheme'
|
|
5
|
+
import {
|
|
6
|
+
CreateBankCardDto,
|
|
7
|
+
CreateBankDetailDto,
|
|
8
|
+
CreateDictionaryDto,
|
|
9
|
+
CreateOptionDto,
|
|
10
|
+
CreateRoleDto,
|
|
11
|
+
CreateScanDto,
|
|
12
|
+
CreateWorkerDto,
|
|
13
|
+
UpdateOptionDto
|
|
14
|
+
} from './app.dto'
|
|
15
|
+
import { MongoCollectionDriver } from '../../../lib/drivers/collection.driver'
|
|
16
|
+
|
|
17
|
+
@Injectable()
|
|
18
|
+
export class AppService {
|
|
19
|
+
constructor(
|
|
20
|
+
@InjectDataSource(dataScheme)
|
|
21
|
+
private readonly dataSource: DataSource<AppScheme, MongoCollectionDriver<AppScheme>>
|
|
22
|
+
) {}
|
|
23
|
+
|
|
24
|
+
async addWorker({ worker }: CreateWorkerDto) {
|
|
25
|
+
return this.dataSource.collections.worker.create(worker)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async addScan({ scan }: CreateScanDto) {
|
|
29
|
+
return this.dataSource.collections.scan.create(scan)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async addBankCard({ bankCard }: CreateBankCardDto) {
|
|
33
|
+
return this.dataSource.collections.bankCard.create(bankCard)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async addBankDetail({ bankDetail }: CreateBankDetailDto) {
|
|
37
|
+
return this.dataSource.collections.bankDetail.create(bankDetail)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async addRole({ role }: CreateRoleDto) {
|
|
41
|
+
return this.dataSource.collections.role.create(role)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async addDictionary({ dictionary }: CreateDictionaryDto) {
|
|
45
|
+
return this.dataSource.collections.dictionaries.create(dictionary)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async addOption({ option }: CreateOptionDto) {
|
|
49
|
+
return this.dataSource.collections.options.create(option)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async updateOption({ option }: UpdateOptionDto) {
|
|
53
|
+
return this.dataSource.collections.options.update(option.value, (target) => {
|
|
54
|
+
target.dictionary = option.dictionary
|
|
55
|
+
target.title = option.title
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async getState() {
|
|
60
|
+
return {
|
|
61
|
+
worker: await this.dataSource.collections.worker.getAll(),
|
|
62
|
+
scan: await this.dataSource.collections.scan.getAll(),
|
|
63
|
+
bankCard: await this.dataSource.collections.bankCard.getAll(),
|
|
64
|
+
bankDetail: await this.dataSource.collections.bankDetail.getAll(),
|
|
65
|
+
// role
|
|
66
|
+
role: await this.dataSource.collections.role.getAll(),
|
|
67
|
+
// options
|
|
68
|
+
dictionaries: await this.dataSource.collections.dictionaries.getAll(),
|
|
69
|
+
options: await this.dataSource.collections.options.getAll()
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async getTables() {
|
|
74
|
+
return this.dataSource.driver.tables.getTables()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common'
|
|
2
|
+
import { AppModule } from './module/app.module'
|
|
3
|
+
import { MongooseDriverModule } from '../../lib'
|
|
4
|
+
import { getMongoConnectionOptions, getMongoConnectionURL } from './db'
|
|
5
|
+
|
|
6
|
+
@Module({
|
|
7
|
+
imports: [
|
|
8
|
+
MongooseDriverModule.forRoot(getMongoConnectionURL(), getMongoConnectionOptions()),
|
|
9
|
+
AppModule //
|
|
10
|
+
]
|
|
11
|
+
})
|
|
12
|
+
export class RootModule {}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { writeFile } from 'fs'
|
|
2
|
+
|
|
3
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, test } from '@jest/globals'
|
|
4
|
+
import { DataSource, IndexedTableStore, TableRow, TableStore } from '@companix/xeo-scheme'
|
|
5
|
+
import { getConnectionToken, getDataSourceToken } from '../../lib'
|
|
6
|
+
|
|
7
|
+
import { bootstrap } from '../app/bootstrap'
|
|
8
|
+
import { MongoCollectionDriver } from '../../lib/drivers/collection.driver'
|
|
9
|
+
import { AppScheme, BaseParams, MockKit, cases, createMockKit, dataScheme } from '@companix/xeo-devkit'
|
|
10
|
+
import { Connection } from 'mongoose'
|
|
11
|
+
import { INestApplication } from '@nestjs/common'
|
|
12
|
+
|
|
13
|
+
interface TestOptions {
|
|
14
|
+
params: BaseParams
|
|
15
|
+
commitChanges: (kit: MockKit, dataSource: DataSource<AppScheme>) => Promise<void>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const normalizeCollection = <T>(records: T[]) => {
|
|
19
|
+
return records.map((record) => {
|
|
20
|
+
if (!record || typeof record !== 'object' || Array.isArray(record)) {
|
|
21
|
+
return record
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { _id, __v, ...rest } = record as Record<string, unknown>
|
|
25
|
+
return rest as T
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const normalizeTableState = (tableState: { m1: TableStore; m2: TableStore }) => {
|
|
30
|
+
const normalizeSide = (side: TableStore): TableStore => {
|
|
31
|
+
const normalized: TableStore = {}
|
|
32
|
+
|
|
33
|
+
for (const key of Object.keys(side).sort()) {
|
|
34
|
+
normalized[key] = [...side[key]].sort((a, b) => String(a).localeCompare(String(b)))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return normalized
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
m1: normalizeSide(tableState.m1),
|
|
42
|
+
m2: normalizeSide(tableState.m2)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const getTablesState = async (tables: { [name: string]: TableRow[] }) => {
|
|
47
|
+
const state: BaseParams['expectations']['tables'] = {}
|
|
48
|
+
|
|
49
|
+
for (const table of dataScheme.tables) {
|
|
50
|
+
const indexedStore = new IndexedTableStore(table)
|
|
51
|
+
indexedStore.initialize(tables[table.tableName] ?? [])
|
|
52
|
+
state[table.tableName] = normalizeTableState(indexedStore.getStore())
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return state
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const runTest = async (app: INestApplication<any>, { params, commitChanges }: TestOptions) => {
|
|
59
|
+
const { expectations } = params
|
|
60
|
+
const dataSource = app.get<DataSource<AppScheme, MongoCollectionDriver<AppScheme>>>(
|
|
61
|
+
getDataSourceToken(dataScheme)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
await commitChanges(createMockKit(dataSource), dataSource).catch((error) => {
|
|
65
|
+
expect(error).toEqual(expectations.error)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const snapshot = { result: {} as object, table: {} as object }
|
|
69
|
+
|
|
70
|
+
for (const collection in dataSource.collections) {
|
|
71
|
+
const collectionName = collection as keyof AppScheme
|
|
72
|
+
|
|
73
|
+
await dataSource.collections[collectionName].getAll().then((result) => {
|
|
74
|
+
snapshot.result[collectionName] = result
|
|
75
|
+
expect(normalizeCollection(result)).toEqual(expectations.scheme[collectionName] ?? [])
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const tableRows = await dataSource.driver.tables.getTables()
|
|
80
|
+
const tables = await getTablesState(tableRows)
|
|
81
|
+
|
|
82
|
+
snapshot.table = tableRows
|
|
83
|
+
|
|
84
|
+
for (const table of dataScheme.tables) {
|
|
85
|
+
try {
|
|
86
|
+
expect(tables[table.tableName] ?? { m1: {}, m2: {} }).toEqual(
|
|
87
|
+
normalizeTableState(expectations.tables[table.tableName] ?? { m1: {}, m2: {} })
|
|
88
|
+
)
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw error
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return snapshot
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
describe('DataSource', () => {
|
|
98
|
+
let app: INestApplication
|
|
99
|
+
|
|
100
|
+
const buffer: object[] = []
|
|
101
|
+
|
|
102
|
+
beforeAll(async () => {
|
|
103
|
+
app = await bootstrap(3222)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
beforeEach(async () => {
|
|
107
|
+
const connection = app.get<Connection>(getConnectionToken())
|
|
108
|
+
await connection.dropDatabase()
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
afterAll(async () => {
|
|
112
|
+
const connection = app.get<Connection>(getConnectionToken())
|
|
113
|
+
|
|
114
|
+
await new Promise<void>((resolve) => {
|
|
115
|
+
writeFile(`./tests/${Date.now()}.test.json`, JSON.stringify(buffer), (err) => {
|
|
116
|
+
if (err) {
|
|
117
|
+
console.log('writeFile:', err)
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
resolve()
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
await connection.dropDatabase()
|
|
126
|
+
await app.close()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
for (const item of cases) {
|
|
130
|
+
if (item.type === 'unit') {
|
|
131
|
+
test(item.name, async () => {
|
|
132
|
+
const snapshot = await runTest(app, {
|
|
133
|
+
params: item.params,
|
|
134
|
+
commitChanges: (kit, dataSource) => item.params.execute(kit, dataSource)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
buffer.push({ name: item.name, snapshot })
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (item.type === 'dual') {
|
|
142
|
+
for (const marker of item.markers) {
|
|
143
|
+
test(`${item.name} / ${marker}`, async () => {
|
|
144
|
+
const snapshot = await runTest(app, {
|
|
145
|
+
params: item.params,
|
|
146
|
+
commitChanges: (kit, dataSource) => item.params.execute(kit, dataSource, marker)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
buffer.push({ name: item.name, snapshot })
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|