@mikemajesty/microservice-crud 3.3.10 → 3.3.11
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/package.json +1 -1
- package/potgres.README.md +0 -11
- package/src/templates/postgres/core/entity/entity.js +3 -3
- package/src/templates/postgres/core/repository/repository.js +2 -6
- package/src/templates/postgres/core/use-cases/__tests__/create.spec.js +0 -14
- package/src/templates/postgres/core/use-cases/create.js +3 -12
- package/src/templates/postgres/core/use-cases/delete.js +1 -2
- package/src/templates/postgres/core/use-cases/getByID.js +1 -2
- package/src/templates/postgres/core/use-cases/update.js +2 -3
- package/src/templates/postgres/modules/module.js +8 -10
- package/src/templates/postgres/modules/repository.js +18 -20
- package/src/templates/postgres/schemas/schema.js +16 -7
package/package.json
CHANGED
package/potgres.README.md
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
#### Postgres CRUD
|
|
2
2
|
|
|
3
|
-
### Add Schema to Sequelize.
|
|
4
|
-
|
|
5
|
-
- Access the config.ts file
|
|
6
|
-
```
|
|
7
|
-
src/infra/database/postgres/config.ts
|
|
8
|
-
```
|
|
9
|
-
- Add your Postgres schema in the addModels function.
|
|
10
|
-
```
|
|
11
|
-
sequelizeConfig.addModels([NewSchema]);
|
|
12
|
-
```
|
|
13
|
-
|
|
14
3
|
### Add Module to microservice.
|
|
15
4
|
|
|
16
5
|
- Access the app.module.ts file
|
|
@@ -5,7 +5,7 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
|
|
6
6
|
const getCoreEntity = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
|
-
import { BaseEntity,
|
|
8
|
+
import { BaseEntity, IEntity } from '@/utils/entity';
|
|
9
9
|
|
|
10
10
|
const ID = z.string().uuid();
|
|
11
11
|
const Name = z.string().min(1).max(200).trim();
|
|
@@ -23,12 +23,12 @@ export const ${capitalizeFirstLetter(name)}EntitySchema = z.object({
|
|
|
23
23
|
|
|
24
24
|
type ${capitalizeFirstLetter(name)} = z.infer<typeof ${capitalizeFirstLetter(name)}EntitySchema>;
|
|
25
25
|
|
|
26
|
-
export class ${capitalizeFirstLetter(name)}Entity extends BaseEntity<${capitalizeFirstLetter(name)}Entity>(${capitalizeFirstLetter(name)}EntitySchema) {
|
|
26
|
+
export class ${capitalizeFirstLetter(name)}Entity extends BaseEntity<${capitalizeFirstLetter(name)}Entity>(${capitalizeFirstLetter(name)}EntitySchema) implements IEntity {
|
|
27
27
|
name: string;
|
|
28
28
|
|
|
29
29
|
constructor(entity: ${capitalizeFirstLetter(name)}) {
|
|
30
30
|
super();
|
|
31
|
-
Object.assign(this,
|
|
31
|
+
Object.assign(this, this.validate(entity));
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
`
|
|
@@ -3,17 +3,13 @@ function capitalizeFirstLetter(string) {
|
|
|
3
3
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
const getCoreRepository = (name) => `import {
|
|
7
|
-
|
|
8
|
-
import { IRepository } from '@/infra/repository';
|
|
9
|
-
import { DatabaseOptionsType } from '@/utils/database/sequelize';
|
|
6
|
+
const getCoreRepository = (name) => `import { IRepository } from '@/infra/repository';
|
|
10
7
|
|
|
11
8
|
import { ${capitalizeFirstLetter(name)}Entity } from '../entity/${name}';
|
|
12
9
|
import { ${capitalizeFirstLetter(name)}ListInput, ${capitalizeFirstLetter(name)}ListOutput } from '../use-cases/${name}-list';
|
|
13
10
|
|
|
14
11
|
export abstract class I${capitalizeFirstLetter(name)}Repository extends IRepository<${capitalizeFirstLetter(name)}Entity> {
|
|
15
|
-
abstract paginate
|
|
16
|
-
abstract startSession<TTransaction = Transaction>(): Promise<TTransaction>;
|
|
12
|
+
abstract paginate(input: ${capitalizeFirstLetter(name)}ListInput): Promise<${capitalizeFirstLetter(name)}ListOutput>;
|
|
17
13
|
}
|
|
18
14
|
`
|
|
19
15
|
|
|
@@ -7,7 +7,6 @@ const getCoreUsecaseCreateTest = (name) => `import { Test } from '@nestjs/testin
|
|
|
7
7
|
|
|
8
8
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
9
9
|
import { I${capitalizeFirstLetter(name)}CreateAdapter } from '@/modules/${name}/adapter';
|
|
10
|
-
import { ApiInternalServerException } from '@/utils/exception';
|
|
11
10
|
import { expectZodError, generateUUID } from '@/utils/tests/tests';
|
|
12
11
|
|
|
13
12
|
import { ${capitalizeFirstLetter(name)}Entity } from '../../entity/${name}';
|
|
@@ -64,22 +63,9 @@ describe('${capitalizeFirstLetter(name)}CreateUsecase', () => {
|
|
|
64
63
|
const createOutput: ${capitalizeFirstLetter(name)}CreateOutput = { created: true, id: generateUUID() };
|
|
65
64
|
|
|
66
65
|
repository.create = jest.fn().mockResolvedValue(createOutput);
|
|
67
|
-
repository.startSession = jest.fn().mockResolvedValue({
|
|
68
|
-
commit: jest.fn()
|
|
69
|
-
});
|
|
70
66
|
|
|
71
67
|
await expect(usecase.execute(successInput)).resolves.toEqual(createOutput);
|
|
72
68
|
});
|
|
73
|
-
|
|
74
|
-
test('when transaction throw an error, should expect an error', async () => {
|
|
75
|
-
repository.startSession = jest.fn().mockResolvedValue({
|
|
76
|
-
commit: jest.fn(),
|
|
77
|
-
rollback: jest.fn()
|
|
78
|
-
});
|
|
79
|
-
repository.create = jest.fn().mockRejectedValue(new ApiInternalServerException());
|
|
80
|
-
|
|
81
|
-
await expect(usecase.execute(successInput)).rejects.toThrow(ApiInternalServerException);
|
|
82
|
-
});
|
|
83
69
|
});
|
|
84
70
|
`
|
|
85
71
|
|
|
@@ -7,7 +7,6 @@ const getCoreUsecaseCreate = (name) => `import { z } from 'zod';
|
|
|
7
7
|
|
|
8
8
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
9
9
|
import { CreatedModel } from '@/infra/repository';
|
|
10
|
-
import { DatabaseOptionsType } from '@/utils/database/sequelize';
|
|
11
10
|
import { ValidateSchema } from '@/utils/decorators/validate-schema.decorator';
|
|
12
11
|
|
|
13
12
|
import { I${capitalizeFirstLetter(name)}Repository } from '../repository/${name}';
|
|
@@ -27,19 +26,11 @@ export class ${capitalizeFirstLetter(name)}CreateUsecase {
|
|
|
27
26
|
async execute(input: ${capitalizeFirstLetter(name)}CreateInput): Promise<${capitalizeFirstLetter(name)}CreateOutput> {
|
|
28
27
|
const entity = new ${capitalizeFirstLetter(name)}Entity(input);
|
|
29
28
|
|
|
30
|
-
const
|
|
31
|
-
try {
|
|
32
|
-
const ${name} = await this.${name}Repository.create<DatabaseOptionsType>(entity, { transaction });
|
|
29
|
+
const ${name} = await this.${name}Repository.create(entity);
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
this.loggerServide.info({ message: '${name} created.', obj: { ${name} } });
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return ${name};
|
|
39
|
-
} catch (error) {
|
|
40
|
-
await transaction.rollback();
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
33
|
+
return ${name};
|
|
43
34
|
}
|
|
44
35
|
}
|
|
45
36
|
`
|
|
@@ -6,7 +6,6 @@ function capitalizeFirstLetter(string) {
|
|
|
6
6
|
const getCoreUsecaseDelete = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
8
|
import { I${capitalizeFirstLetter(name)}Repository } from '@/core/${name}/repository/${name}';
|
|
9
|
-
import { DatabaseOptionsType } from '@/utils/database/sequelize';
|
|
10
9
|
import { ValidateSchema } from '@/utils/decorators/validate-schema.decorator';
|
|
11
10
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
12
11
|
|
|
@@ -24,7 +23,7 @@ export class ${capitalizeFirstLetter(name)}DeleteUsecase {
|
|
|
24
23
|
|
|
25
24
|
@ValidateSchema(${capitalizeFirstLetter(name)}DeleteSchema)
|
|
26
25
|
async execute({ id }: ${capitalizeFirstLetter(name)}DeleteInput): Promise<${capitalizeFirstLetter(name)}DeleteOutput> {
|
|
27
|
-
const model = await this.${name}Repository.findById
|
|
26
|
+
const model = await this.${name}Repository.findById(id);
|
|
28
27
|
|
|
29
28
|
if (!model) {
|
|
30
29
|
throw new ApiNotFoundException();
|
|
@@ -6,7 +6,6 @@ function capitalizeFirstLetter(string) {
|
|
|
6
6
|
const getCoreUsecaseGetByID = (name) => `import { z } from 'zod';
|
|
7
7
|
|
|
8
8
|
import { ${capitalizeFirstLetter(name)}EntitySchema } from '@/core/${name}/entity/${name}';
|
|
9
|
-
import { DatabaseOptionsType } from '@/utils/database/sequelize';
|
|
10
9
|
import { ValidateSchema } from '@/utils/decorators/validate-schema.decorator';
|
|
11
10
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
12
11
|
|
|
@@ -25,7 +24,7 @@ export class ${capitalizeFirstLetter(name)}GetByIdUsecase {
|
|
|
25
24
|
|
|
26
25
|
@ValidateSchema(${capitalizeFirstLetter(name)}GetByIdSchema)
|
|
27
26
|
async execute({ id }: ${capitalizeFirstLetter(name)}GetByIDInput): Promise<${capitalizeFirstLetter(name)}GetByIDOutput> {
|
|
28
|
-
const ${name} = await this.${name}Repository.findById
|
|
27
|
+
const ${name} = await this.${name}Repository.findById(id);
|
|
29
28
|
|
|
30
29
|
if (!${name}) {
|
|
31
30
|
throw new ApiNotFoundException();
|
|
@@ -7,7 +7,6 @@ const getCoreUsecaseUpdate = (name) => `import { z } from 'zod';
|
|
|
7
7
|
|
|
8
8
|
import { I${capitalizeFirstLetter(name)}Repository } from '@/core/${name}/repository/${name}';
|
|
9
9
|
import { ILoggerAdapter } from '@/infra/logger';
|
|
10
|
-
import { DatabaseOptionsType } from '@/utils/database/sequelize';
|
|
11
10
|
import { ValidateSchema } from '@/utils/decorators/validate-schema.decorator';
|
|
12
11
|
import { ApiNotFoundException } from '@/utils/exception';
|
|
13
12
|
|
|
@@ -25,7 +24,7 @@ export class ${capitalizeFirstLetter(name)}UpdateUsecase {
|
|
|
25
24
|
|
|
26
25
|
@ValidateSchema(${capitalizeFirstLetter(name)}UpdateSchema)
|
|
27
26
|
async execute(input: ${capitalizeFirstLetter(name)}UpdateInput): Promise<${capitalizeFirstLetter(name)}UpdateOutput> {
|
|
28
|
-
const ${name} = await this.${name}Repository.findById
|
|
27
|
+
const ${name} = await this.${name}Repository.findById(input.id);
|
|
29
28
|
|
|
30
29
|
if (!${name}) {
|
|
31
30
|
throw new ApiNotFoundException();
|
|
@@ -39,7 +38,7 @@ export class ${capitalizeFirstLetter(name)}UpdateUsecase {
|
|
|
39
38
|
|
|
40
39
|
this.loggerServide.info({ message: '${name} updated.', obj: { ${name}: input } });
|
|
41
40
|
|
|
42
|
-
const updated = await this.${name}Repository.findById
|
|
41
|
+
const updated = await this.${name}Repository.findById(entity.id);
|
|
43
42
|
|
|
44
43
|
return new ${capitalizeFirstLetter(name)}Entity(updated);
|
|
45
44
|
}
|
|
@@ -4,7 +4,8 @@ function capitalizeFirstLetter(string) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
const getModule = (name) => `import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
|
7
|
-
import {
|
|
7
|
+
import { getRepositoryToken, TypeOrmModule } from '@nestjs/typeorm';
|
|
8
|
+
import { Repository } from 'typeorm';
|
|
8
9
|
|
|
9
10
|
import { ${capitalizeFirstLetter(name)}Entity } from '@/core/${name}/entity/${name}';
|
|
10
11
|
import { I${capitalizeFirstLetter(name)}Repository } from '@/core/${name}/repository/${name}';
|
|
@@ -14,8 +15,6 @@ import { ${capitalizeFirstLetter(name)}GetByIdUsecase } from '@/core/${name}/use
|
|
|
14
15
|
import { ${capitalizeFirstLetter(name)}ListUsecase } from '@/core/${name}/use-cases/${name}-list';
|
|
15
16
|
import { ${capitalizeFirstLetter(name)}UpdateUsecase } from '@/core/${name}/use-cases/${name}-update';
|
|
16
17
|
import { RedisCacheModule } from '@/infra/cache/redis';
|
|
17
|
-
import { IDataBaseAdapter } from '@/infra/database';
|
|
18
|
-
import { PostgresDatabaseModule } from '@/infra/database/postgres/module';
|
|
19
18
|
import { ${capitalizeFirstLetter(name)}Schema } from '@/infra/database/postgres/schemas/${name}';
|
|
20
19
|
import { ILoggerAdapter, LoggerModule } from '@/infra/logger';
|
|
21
20
|
import { TokenModule } from '@/libs/auth';
|
|
@@ -32,21 +31,20 @@ import { ${capitalizeFirstLetter(name)}Controller } from './controller';
|
|
|
32
31
|
import { ${capitalizeFirstLetter(name)}Repository } from './repository';
|
|
33
32
|
|
|
34
33
|
@Module({
|
|
35
|
-
imports: [TokenModule, LoggerModule,
|
|
34
|
+
imports: [TokenModule, LoggerModule, TypeOrmModule.forFeature([${capitalizeFirstLetter(name)}Schema]), RedisCacheModule],
|
|
36
35
|
controllers: [${capitalizeFirstLetter(name)}Controller],
|
|
37
36
|
providers: [
|
|
38
37
|
{
|
|
39
38
|
provide: I${capitalizeFirstLetter(name)}Repository,
|
|
40
|
-
useFactory: (
|
|
41
|
-
|
|
42
|
-
return new ${capitalizeFirstLetter(name)}Repository(repossitory as ModelCtor<${capitalizeFirstLetter(name)}Schema> & ${capitalizeFirstLetter(name)}Entity);
|
|
39
|
+
useFactory: (repository: Repository<${capitalizeFirstLetter(name)}Schema & ${capitalizeFirstLetter(name)}Entity>) => {
|
|
40
|
+
return new ${capitalizeFirstLetter(name)}Repository(repository);
|
|
43
41
|
},
|
|
44
|
-
inject: [
|
|
42
|
+
inject: [getRepositoryToken(${capitalizeFirstLetter(name)}Schema)]
|
|
45
43
|
},
|
|
46
44
|
{
|
|
47
45
|
provide: I${capitalizeFirstLetter(name)}CreateAdapter,
|
|
48
|
-
useFactory: (
|
|
49
|
-
inject: [
|
|
46
|
+
useFactory: (repository: I${capitalizeFirstLetter(name)}Repository, logger: ILoggerAdapter) => new ${capitalizeFirstLetter(name)}CreateUsecase(repository, logger),
|
|
47
|
+
inject: [I${capitalizeFirstLetter(name)}Repository, ILoggerAdapter]
|
|
50
48
|
},
|
|
51
49
|
{
|
|
52
50
|
provide: I${capitalizeFirstLetter(name)}UpdateAdapter,
|
|
@@ -4,41 +4,39 @@ function capitalizeFirstLetter(string) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
const getModuleRepository = (name) => `import { Injectable } from '@nestjs/common';
|
|
7
|
-
import {
|
|
8
|
-
import { ModelCtor } from 'sequelize-typescript';
|
|
7
|
+
import { FindOptionsWhere, Repository } from 'typeorm';
|
|
9
8
|
|
|
10
9
|
import { ${capitalizeFirstLetter(name)}Entity } from '@/core/${name}/entity/${name}';
|
|
11
10
|
import { I${capitalizeFirstLetter(name)}Repository } from '@/core/${name}/repository/${name}';
|
|
12
11
|
import { ${capitalizeFirstLetter(name)}ListInput, ${capitalizeFirstLetter(name)}ListOutput } from '@/core/${name}/use-cases/${name}-list';
|
|
13
12
|
import { ${capitalizeFirstLetter(name)}Schema } from '@/infra/database/postgres/schemas/${name}';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { ConvertPaginateInputToSequelizeFilter } from '@/utils/decorators/database/postgres/convert-paginate-input-to-sequelize-filter.decorator';
|
|
13
|
+
import { PostgresRepository } from '@/infra/repository/postgres/repository';
|
|
14
|
+
import { ValidatePostgresFilter } from '@/utils/decorators/database/postgres/validate-typeorm-filter.decorator';
|
|
17
15
|
import { ValidateDatabaseSortAllowed } from '@/utils/decorators/database/validate-database-sort-allowed.decorator';
|
|
18
16
|
import { SearchTypeEnum } from '@/utils/decorators/types';
|
|
17
|
+
import { calucaleSkip } from '@/utils/pagination';
|
|
19
18
|
|
|
20
|
-
type Model =
|
|
19
|
+
type Model = ${capitalizeFirstLetter(name)}Schema & ${capitalizeFirstLetter(name)}Entity;
|
|
21
20
|
|
|
22
21
|
@Injectable()
|
|
23
|
-
export class ${capitalizeFirstLetter(name)}Repository extends
|
|
24
|
-
constructor(readonly repository: Model) {
|
|
22
|
+
export class ${capitalizeFirstLetter(name)}Repository extends PostgresRepository<Model> implements I${capitalizeFirstLetter(name)}Repository {
|
|
23
|
+
constructor(readonly repository: Repository<Model>) {
|
|
25
24
|
super(repository);
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
@ValidateDatabaseSortAllowed<${capitalizeFirstLetter(name)}Entity>('createdAt', 'name')
|
|
28
|
+
@ValidatePostgresFilter<${capitalizeFirstLetter(name)}Entity>([{ name: 'name', type: SearchTypeEnum.like }])
|
|
29
|
+
async paginate(input: ${capitalizeFirstLetter(name)}ListInput): Promise<${capitalizeFirstLetter(name)}ListOutput> {
|
|
30
|
+
const skip = calucaleSkip(input);
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const { schema } = DatabaseOptionsSchema.parse(options);
|
|
38
|
-
|
|
39
|
-
const list = await this.repository.schema(schema).findAndCountAll(input);
|
|
32
|
+
const [docs, total] = await this.repository.findAndCount({
|
|
33
|
+
take: input.limit,
|
|
34
|
+
skip,
|
|
35
|
+
order: input.sort,
|
|
36
|
+
where: input.search as FindOptionsWhere<${capitalizeFirstLetter(name)}Entity>
|
|
37
|
+
});
|
|
40
38
|
|
|
41
|
-
return { docs
|
|
39
|
+
return { docs, total, page: input.page, limit: input.limit };
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
`
|
|
@@ -5,18 +5,27 @@ function capitalizeFirstLetter(string) {
|
|
|
5
5
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
const getModuleSchema = (name) => `import {
|
|
8
|
+
const getModuleSchema = (name) => `import { Max, Min } from 'class-validator';
|
|
9
|
+
import { BaseEntity, Column, CreateDateColumn, DeleteDateColumn, Entity, UpdateDateColumn } from 'typeorm';
|
|
9
10
|
|
|
10
|
-
@
|
|
11
|
-
export class ${capitalizeFirstLetter(name)}Schema extends
|
|
12
|
-
@Column({
|
|
11
|
+
@Entity({ name: '${pluralize(name)}' })
|
|
12
|
+
export class ${capitalizeFirstLetter(name)}Schema extends BaseEntity {
|
|
13
|
+
@Column({ type: 'uuid', primary: true })
|
|
13
14
|
id: string;
|
|
14
15
|
|
|
15
|
-
@
|
|
16
|
+
@Min(1)
|
|
17
|
+
@Max(200)
|
|
18
|
+
@Column()
|
|
16
19
|
name: string;
|
|
17
20
|
|
|
18
|
-
@
|
|
19
|
-
|
|
21
|
+
@CreateDateColumn()
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
|
|
24
|
+
@UpdateDateColumn()
|
|
25
|
+
updatedAt: Date;
|
|
26
|
+
|
|
27
|
+
@DeleteDateColumn({ nullable: true })
|
|
28
|
+
deletedAt: Date;
|
|
20
29
|
}
|
|
21
30
|
`
|
|
22
31
|
|