nestjs-ddd-cli 3.2.2 → 3.3.0
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/README.md +118 -9
- package/ddd.schema.json +11 -1
- package/dist/commands/doctor-enhanced.d.ts +1 -0
- package/dist/commands/doctor-enhanced.js +94 -79
- package/dist/commands/doctor-enhanced.js.map +1 -1
- package/dist/commands/doctor.d.ts +9 -0
- package/dist/commands/doctor.js +68 -21
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/generate-all.js +54 -28
- package/dist/commands/generate-all.js.map +1 -1
- package/dist/commands/generate-controller.d.ts +1 -0
- package/dist/commands/generate-controller.js +71 -0
- package/dist/commands/generate-controller.js.map +1 -0
- package/dist/commands/generate-domain-service.d.ts +1 -1
- package/dist/commands/generate-domain-service.js +6 -4
- package/dist/commands/generate-domain-service.js.map +1 -1
- package/dist/commands/generate-dto.d.ts +4 -0
- package/dist/commands/generate-dto.js +162 -0
- package/dist/commands/generate-dto.js.map +1 -0
- package/dist/commands/generate-entity.js +7 -2
- package/dist/commands/generate-entity.js.map +1 -1
- package/dist/commands/generate-event.js +10 -4
- package/dist/commands/generate-event.js.map +1 -1
- package/dist/commands/generate-migration-deployment.d.ts +15 -0
- package/dist/commands/generate-migration-deployment.js +326 -0
- package/dist/commands/generate-migration-deployment.js.map +1 -0
- package/dist/commands/generate-migration-deployment.spec.d.ts +1 -0
- package/dist/commands/generate-migration-deployment.spec.js +337 -0
- package/dist/commands/generate-migration-deployment.spec.js.map +1 -0
- package/dist/commands/generate-module.js +4 -2
- package/dist/commands/generate-module.js.map +1 -1
- package/dist/commands/generate-query.js +23 -4
- package/dist/commands/generate-query.js.map +1 -1
- package/dist/commands/generate-repository.d.ts +1 -1
- package/dist/commands/generate-repository.js +17 -34
- package/dist/commands/generate-repository.js.map +1 -1
- package/dist/commands/generate-service.js +19 -4
- package/dist/commands/generate-service.js.map +1 -1
- package/dist/commands/generate-usecase.js +12 -31
- package/dist/commands/generate-usecase.js.map +1 -1
- package/dist/commands/generate-value-object.js +3 -14
- package/dist/commands/generate-value-object.js.map +1 -1
- package/dist/commands/init-project.d.ts +3 -0
- package/dist/commands/init-project.js +19 -9
- package/dist/commands/init-project.js.map +1 -1
- package/dist/commands/interactive-scaffold.js +10 -0
- package/dist/commands/interactive-scaffold.js.map +1 -1
- package/dist/commands/migration.d.ts +3 -0
- package/dist/commands/migration.js +83 -48
- package/dist/commands/migration.js.map +1 -1
- package/dist/commands/recipe.d.ts +2 -0
- package/dist/commands/recipe.js +229 -85
- package/dist/commands/recipe.js.map +1 -1
- package/dist/commands/recipes/banklink-connector-contract.recipe.d.ts +1 -0
- package/dist/commands/recipes/banklink-connector-contract.recipe.js +161 -0
- package/dist/commands/recipes/banklink-connector-contract.recipe.js.map +1 -0
- package/dist/commands/recipes/bounded-json-http.recipe.d.ts +2 -0
- package/dist/commands/recipes/bounded-json-http.recipe.js +53 -0
- package/dist/commands/recipes/bounded-json-http.recipe.js.map +1 -0
- package/dist/commands/recipes/business-reference-identifiers.recipe.d.ts +1 -0
- package/dist/commands/recipes/business-reference-identifiers.recipe.js +223 -0
- package/dist/commands/recipes/business-reference-identifiers.recipe.js.map +1 -0
- package/dist/commands/recipes/event-backbone.recipe.d.ts +1 -0
- package/dist/commands/recipes/event-backbone.recipe.js +1118 -0
- package/dist/commands/recipes/event-backbone.recipe.js.map +1 -0
- package/dist/commands/recipes/external-projection-worker.recipe.d.ts +6 -0
- package/dist/commands/recipes/external-projection-worker.recipe.js +211 -0
- package/dist/commands/recipes/external-projection-worker.recipe.js.map +1 -0
- package/dist/commands/recipes/index.d.ts +11 -0
- package/dist/commands/recipes/index.js +11 -0
- package/dist/commands/recipes/index.js.map +1 -1
- package/dist/commands/recipes/jest-cjs-compat.recipe.d.ts +3 -0
- package/dist/commands/recipes/jest-cjs-compat.recipe.js +130 -0
- package/dist/commands/recipes/jest-cjs-compat.recipe.js.map +1 -0
- package/dist/commands/recipes/joi-env.recipe.js +1 -1
- package/dist/commands/recipes/kafka-consumer.recipe.d.ts +1 -0
- package/dist/commands/recipes/kafka-consumer.recipe.js +65 -0
- package/dist/commands/recipes/kafka-consumer.recipe.js.map +1 -0
- package/dist/commands/recipes/oauth2-client-credentials.recipe.d.ts +1 -0
- package/dist/commands/recipes/oauth2-client-credentials.recipe.js +60 -0
- package/dist/commands/recipes/oauth2-client-credentials.recipe.js.map +1 -0
- package/dist/commands/recipes/oauth2-token-introspection.recipe.d.ts +1 -0
- package/dist/commands/recipes/oauth2-token-introspection.recipe.js +67 -0
- package/dist/commands/recipes/oauth2-token-introspection.recipe.js.map +1 -0
- package/dist/commands/recipes/oidc-bff-session.recipe.d.ts +1 -0
- package/dist/commands/recipes/oidc-bff-session.recipe.js +57 -0
- package/dist/commands/recipes/oidc-bff-session.recipe.js.map +1 -0
- package/dist/commands/recipes/oidc-dashboard.recipe.d.ts +1 -0
- package/dist/commands/recipes/oidc-dashboard.recipe.js +463 -0
- package/dist/commands/recipes/oidc-dashboard.recipe.js.map +1 -0
- package/dist/commands/recipes/oidc-resource-server.recipe.d.ts +1 -0
- package/dist/commands/recipes/oidc-resource-server.recipe.js +85 -0
- package/dist/commands/recipes/oidc-resource-server.recipe.js.map +1 -0
- package/dist/commands/recipes/platform-context.recipe.d.ts +1 -0
- package/dist/commands/recipes/platform-context.recipe.js +229 -0
- package/dist/commands/recipes/platform-context.recipe.js.map +1 -0
- package/dist/commands/recipes/platform-parc-authorization.recipe.d.ts +1 -0
- package/dist/commands/recipes/platform-parc-authorization.recipe.js +339 -0
- package/dist/commands/recipes/platform-parc-authorization.recipe.js.map +1 -0
- package/dist/commands/recipes/platform-parc-bound-authorization.recipe.d.ts +1 -0
- package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js +56 -0
- package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js.map +1 -0
- package/dist/commands/recipes/platform-service-access-request-context.recipe.d.ts +1 -0
- package/dist/commands/recipes/platform-service-access-request-context.recipe.js +103 -0
- package/dist/commands/recipes/platform-service-access-request-context.recipe.js.map +1 -0
- package/dist/commands/recipes/platform-service-runtime.recipe.d.ts +1 -0
- package/dist/commands/recipes/platform-service-runtime.recipe.js +415 -0
- package/dist/commands/recipes/platform-service-runtime.recipe.js.map +1 -0
- package/dist/index.js +77 -9
- package/dist/index.js.map +1 -1
- package/dist/templates/ai-context/CLAUDE.md.hbs +39 -3
- package/dist/templates/ai-context/conventions.md.hbs +13 -8
- package/dist/templates/command/create-command.hbs +8 -3
- package/dist/templates/command/delete-command.hbs +1 -1
- package/dist/templates/command/update-command.hbs +1 -1
- package/dist/templates/controller/application-controller.hbs +7 -0
- package/dist/templates/controller/controller.hbs +6 -0
- package/dist/templates/dto/create-dto.hbs +17 -5
- package/dist/templates/dto/filter-dto.hbs +1 -1
- package/dist/templates/dto/response-dto.hbs +1 -1
- package/dist/templates/entity/entity.hbs +4 -0
- package/dist/templates/mapper/mapper.hbs +5 -1
- package/dist/templates/orm-entity/orm-entity.hbs +9 -1
- package/dist/templates/prisma/prisma-mapper.hbs +6 -0
- package/dist/templates/prisma/prisma-repository.hbs +57 -5
- package/dist/templates/prisma/prisma-schema.hbs +2 -0
- package/dist/templates/query/get-all.query.hbs +10 -2
- package/dist/templates/recipes/bounded-json-http/README.md.hbs +36 -0
- package/dist/templates/recipes/external-projection-worker/README.md.hbs +157 -0
- package/dist/templates/recipes/external-projection-worker/canonical-json.ts.hbs +123 -0
- package/dist/templates/recipes/external-projection-worker/enqueuer.ts.hbs +167 -0
- package/dist/templates/recipes/external-projection-worker/index.ts.hbs +6 -0
- package/dist/templates/recipes/external-projection-worker/migration.ts.hbs +88 -0
- package/dist/templates/recipes/external-projection-worker/module.ts.hbs +36 -0
- package/dist/templates/recipes/external-projection-worker/store.ts.hbs +354 -0
- package/dist/templates/recipes/external-projection-worker/types.ts.hbs +134 -0
- package/dist/templates/recipes/external-projection-worker/worker.ts.hbs +296 -0
- package/dist/templates/recipes/kafka-consumer/README.md.hbs +50 -0
- package/dist/templates/recipes/kafka-consumer/kafka-consumer.ts.hbs +135 -0
- package/dist/templates/recipes/kafka-consumer/migration.ts.hbs +17 -0
- package/dist/templates/recipes/oauth2-client-credentials/README.md.hbs +40 -0
- package/dist/templates/recipes/oauth2-client-credentials/client.spec.ts.hbs +234 -0
- package/dist/templates/recipes/oauth2-client-credentials/client.ts.hbs +210 -0
- package/dist/templates/recipes/oauth2-client-credentials/index.ts.hbs +2 -0
- package/dist/templates/recipes/oauth2-client-credentials/module.ts.hbs +58 -0
- package/dist/templates/recipes/oauth2-token-introspection/README.md.hbs +158 -0
- package/dist/templates/recipes/oauth2-token-introspection/client.spec.ts.hbs +350 -0
- package/dist/templates/recipes/oauth2-token-introspection/client.ts.hbs +241 -0
- package/dist/templates/recipes/oauth2-token-introspection/http-client.spec.ts.hbs +411 -0
- package/dist/templates/recipes/oauth2-token-introspection/http-client.ts.hbs +343 -0
- package/dist/templates/recipes/oauth2-token-introspection/index.ts.hbs +3 -0
- package/dist/templates/recipes/oauth2-token-introspection/module.ts.hbs +58 -0
- package/dist/templates/recipes/oidc-bff-session/README.md.hbs +96 -0
- package/dist/templates/recipes/oidc-bff-session/client.test.ts.hbs +663 -0
- package/dist/templates/recipes/oidc-bff-session/client.ts.hbs +635 -0
- package/dist/templates/recipes/oidc-bff-session/index.ts.hbs +3 -0
- package/dist/templates/recipes/oidc-bff-session/store.integration.test.ts.hbs +480 -0
- package/dist/templates/recipes/oidc-bff-session/store.test.ts.hbs +87 -0
- package/dist/templates/recipes/oidc-bff-session/store.ts.hbs +549 -0
- package/dist/templates/recipes/oidc-bff-session/valkey.test.ts.hbs +158 -0
- package/dist/templates/recipes/oidc-bff-session/valkey.ts.hbs +148 -0
- package/dist/templates/recipes/oidc-resource-server/README.md.hbs +74 -0
- package/dist/templates/recipes/oidc-resource-server/index.ts.hbs +2 -0
- package/dist/templates/recipes/oidc-resource-server/module.ts.hbs +51 -0
- package/dist/templates/recipes/oidc-resource-server/verifier.spec.ts.hbs +186 -0
- package/dist/templates/recipes/oidc-resource-server/verifier.ts.hbs +440 -0
- package/dist/templates/recipes/platform-parc-bound-authorization/README.md.hbs +92 -0
- package/dist/templates/recipes/platform-parc-bound-authorization/client.ts.hbs +142 -0
- package/dist/templates/recipes/platform-service-access-request-context/docs.md.hbs +61 -0
- package/dist/templates/recipes/platform-service-access-request-context/env.example.hbs +7 -0
- package/dist/templates/recipes/platform-service-access-request-context/index.ts.hbs +7 -0
- package/dist/templates/recipes/platform-service-access-request-context/request-context-headers.ts.hbs +61 -0
- package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.parser.ts.hbs +132 -0
- package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.types.ts.hbs +40 -0
- package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.client.ts.hbs +45 -0
- package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.config.ts.hbs +142 -0
- package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.guard.ts.hbs +77 -0
- package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.module.ts.hbs +17 -0
- package/dist/templates/repository/repository.hbs +42 -4
- package/dist/templates/resolver/graphql-input.hbs +23 -6
- package/dist/templates/resolver/resolver.hbs +4 -0
- package/dist/templates/service/domain-service.hbs +2 -2
- package/dist/templates/test/controller.spec.hbs +5 -1
- package/dist/templates/test/prisma-repository.spec.hbs +192 -0
- package/dist/templates/test/repository.spec.hbs +40 -1
- package/dist/templates/test/usecase.spec.hbs +23 -4
- package/dist/templates/usecase/application-usecase.hbs +17 -0
- package/dist/templates/usecase/create-usecase.hbs +34 -3
- package/dist/templates/usecase/update-usecase.hbs +15 -1
- package/dist/utils/config.utils.d.ts +2 -0
- package/dist/utils/config.utils.js +14 -2
- package/dist/utils/config.utils.js.map +1 -1
- package/dist/utils/dependency.utils.d.ts +16 -2
- package/dist/utils/dependency.utils.js +100 -12
- package/dist/utils/dependency.utils.js.map +1 -1
- package/dist/utils/field.utils.d.ts +6 -0
- package/dist/utils/field.utils.js +50 -8
- package/dist/utils/field.utils.js.map +1 -1
- package/dist/utils/field.utils.spec.d.ts +1 -0
- package/dist/utils/field.utils.spec.js +38 -0
- package/dist/utils/field.utils.spec.js.map +1 -0
- package/dist/utils/file.utils.d.ts +23 -1
- package/dist/utils/file.utils.js +37 -1
- package/dist/utils/file.utils.js.map +1 -1
- package/dist/utils/naming.utils.js +5 -4
- package/dist/utils/naming.utils.js.map +1 -1
- package/dist/utils/static-recipe.utils.d.ts +4 -0
- package/dist/utils/static-recipe.utils.js +148 -0
- package/dist/utils/static-recipe.utils.js.map +1 -0
- package/package.json +12 -5
|
@@ -5,10 +5,22 @@ import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrast
|
|
|
5
5
|
import { {{entityNamePascal}}OrmEntity } from "@modules/{{moduleNameKebab}}/infrastructure/orm-entities/{{entityNameKebab}}.orm-entity";
|
|
6
6
|
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/application/domain/entities/{{entityNameKebab}}.entity";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const {{entityNameCamel}}OrderFields = [
|
|
9
|
+
"id",
|
|
10
|
+
{{#each fields}}
|
|
11
|
+
"{{#if this.isRelation}}{{this.camelCase}}{{else}}{{this.snakeCase}}{{/if}}",
|
|
12
|
+
{{/each}}
|
|
13
|
+
"isActive",
|
|
14
|
+
"createdAt",
|
|
15
|
+
"updatedAt",
|
|
16
|
+
] as const satisfies readonly (keyof {{entityNamePascal}}OrmEntity)[];
|
|
17
|
+
|
|
18
|
+
export type {{entityNamePascal}}OrderField = (typeof {{entityNameCamel}}OrderFields)[number];
|
|
19
|
+
|
|
20
|
+
export interface {{entityNamePascal}}PaginationOptions {
|
|
9
21
|
skip: number;
|
|
10
22
|
take: number;
|
|
11
|
-
orderBy:
|
|
23
|
+
orderBy: {{entityNamePascal}}OrderField;
|
|
12
24
|
orderDirection: "ASC" | "DESC";
|
|
13
25
|
}
|
|
14
26
|
|
|
@@ -20,6 +32,10 @@ export class {{entityNamePascal}}Repository {
|
|
|
20
32
|
private readonly mapper: {{entityNamePascal}}Mapper,
|
|
21
33
|
) {}
|
|
22
34
|
|
|
35
|
+
static isOrderByField(value: string): value is {{entityNamePascal}}OrderField {
|
|
36
|
+
return {{entityNameCamel}}OrderFields.some((field) => field === value);
|
|
37
|
+
}
|
|
38
|
+
|
|
23
39
|
async create(entity: {{entityNamePascal}}Entity): Promise<{{entityNamePascal}}Entity> {
|
|
24
40
|
const ormEntity = this.mapper.toOrmEntity(entity);
|
|
25
41
|
const savedOrmEntity = await this.repository.save(ormEntity);
|
|
@@ -28,7 +44,11 @@ export class {{entityNamePascal}}Repository {
|
|
|
28
44
|
|
|
29
45
|
async findById(id: string): Promise<{{entityNamePascal}}Entity | null> {
|
|
30
46
|
const ormEntity = await this.repository.findOne({
|
|
47
|
+
{{#if softDelete}}
|
|
31
48
|
where: { id, deletedAt: null } as any,
|
|
49
|
+
{{else}}
|
|
50
|
+
where: { id },
|
|
51
|
+
{{/if}}
|
|
32
52
|
});
|
|
33
53
|
|
|
34
54
|
if (!ormEntity) {
|
|
@@ -39,15 +59,19 @@ export class {{entityNamePascal}}Repository {
|
|
|
39
59
|
}
|
|
40
60
|
|
|
41
61
|
async findAll(): Promise<{{entityNamePascal}}Entity[]> {
|
|
62
|
+
{{#if softDelete}}
|
|
42
63
|
const ormEntities = await this.repository.find({
|
|
43
64
|
where: { deletedAt: null } as any,
|
|
44
65
|
});
|
|
66
|
+
{{else}}
|
|
67
|
+
const ormEntities = await this.repository.find();
|
|
68
|
+
{{/if}}
|
|
45
69
|
|
|
46
70
|
return ormEntities.map((ormEntity) => this.mapper.toDomainEntity(ormEntity));
|
|
47
71
|
}
|
|
48
72
|
|
|
49
73
|
async findAllPaginated(
|
|
50
|
-
options: PaginationOptions,
|
|
74
|
+
options: {{entityNamePascal}}PaginationOptions,
|
|
51
75
|
): Promise<[{{entityNamePascal}}Entity[], number]> {
|
|
52
76
|
const { skip, take, orderBy, orderDirection } = options;
|
|
53
77
|
|
|
@@ -56,7 +80,9 @@ export class {{entityNamePascal}}Repository {
|
|
|
56
80
|
} as FindOptionsOrder<{{entityNamePascal}}OrmEntity>;
|
|
57
81
|
|
|
58
82
|
const [ormEntities, total] = await this.repository.findAndCount({
|
|
83
|
+
{{#if softDelete}}
|
|
59
84
|
where: { deletedAt: null } as any,
|
|
85
|
+
{{/if}}
|
|
60
86
|
skip,
|
|
61
87
|
take,
|
|
62
88
|
order,
|
|
@@ -75,21 +101,33 @@ export class {{entityNamePascal}}Repository {
|
|
|
75
101
|
return entity;
|
|
76
102
|
}
|
|
77
103
|
|
|
104
|
+
{{#if deleteEnabled}}
|
|
78
105
|
async delete(id: string): Promise<void> {
|
|
79
|
-
|
|
106
|
+
{{#if softDelete}}
|
|
80
107
|
await this.repository.update(id, {
|
|
81
108
|
deletedAt: new Date(),
|
|
82
109
|
isActive: false,
|
|
83
110
|
} as any);
|
|
111
|
+
{{else}}
|
|
112
|
+
await this.repository.delete(id);
|
|
113
|
+
{{/if}}
|
|
84
114
|
}
|
|
85
115
|
|
|
116
|
+
{{#if hardDelete}}
|
|
86
117
|
async hardDelete(id: string): Promise<void> {
|
|
87
118
|
await this.repository.delete(id);
|
|
88
119
|
}
|
|
89
120
|
|
|
121
|
+
{{/if}}
|
|
122
|
+
|
|
123
|
+
{{/if}}
|
|
90
124
|
async exists(id: string): Promise<boolean> {
|
|
91
125
|
const count = await this.repository.count({
|
|
126
|
+
{{#if softDelete}}
|
|
92
127
|
where: { id, deletedAt: null } as any,
|
|
128
|
+
{{else}}
|
|
129
|
+
where: { id },
|
|
130
|
+
{{/if}}
|
|
93
131
|
});
|
|
94
132
|
return count > 0;
|
|
95
133
|
}
|
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import { Field, InputType } from "@nestjs/graphql";
|
|
2
|
-
import { IsNotEmpty, IsOptional, IsString, IsBoolean } from "class-validator";
|
|
2
|
+
import { IsDecimal, IsNotEmpty, IsOptional, IsString, IsBoolean } from "class-validator";
|
|
3
3
|
|
|
4
4
|
@InputType()
|
|
5
5
|
export class Create{{entityNamePascal}}Input {
|
|
6
|
-
{{#if
|
|
7
|
-
{{#each
|
|
6
|
+
{{#if hasRequestFields}}
|
|
7
|
+
{{#each requestFields}}
|
|
8
8
|
{{#unless this.isOptional}}
|
|
9
9
|
@Field()
|
|
10
10
|
@IsNotEmpty()
|
|
11
|
+
{{#if this.isMoney}}
|
|
12
|
+
@IsDecimal({ decimal_digits: "0,18", force_decimal: false })
|
|
13
|
+
{{/if}}
|
|
11
14
|
{{this.camelCase}}: {{this.tsType}};
|
|
12
15
|
|
|
13
16
|
{{/unless}}
|
|
14
17
|
{{/each}}
|
|
15
|
-
{{#each
|
|
18
|
+
{{#each requestFields}}
|
|
16
19
|
{{#if this.isOptional}}
|
|
17
20
|
@Field({ nullable: true })
|
|
18
21
|
@IsOptional()
|
|
22
|
+
{{#if this.isMoney}}
|
|
23
|
+
@IsDecimal({ decimal_digits: "0,18", force_decimal: false })
|
|
24
|
+
{{/if}}
|
|
19
25
|
{{this.camelCase}}?: {{this.tsType}};
|
|
20
26
|
|
|
21
27
|
{{/if}}
|
|
22
28
|
{{/each}}
|
|
29
|
+
{{else}}
|
|
30
|
+
{{#if hasFields}}
|
|
31
|
+
// This aggregate has no client-writable scaffold fields.
|
|
23
32
|
{{else}}
|
|
24
33
|
// Add your input fields here
|
|
25
34
|
// Example:
|
|
@@ -28,17 +37,24 @@ export class Create{{entityNamePascal}}Input {
|
|
|
28
37
|
// @IsString()
|
|
29
38
|
// name: string;
|
|
30
39
|
{{/if}}
|
|
40
|
+
{{/if}}
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
@InputType()
|
|
34
44
|
export class Update{{entityNamePascal}}Input {
|
|
35
|
-
{{#if
|
|
36
|
-
{{#each
|
|
45
|
+
{{#if hasRequestFields}}
|
|
46
|
+
{{#each requestFields}}
|
|
37
47
|
@Field({ nullable: true })
|
|
38
48
|
@IsOptional()
|
|
49
|
+
{{#if this.isMoney}}
|
|
50
|
+
@IsDecimal({ decimal_digits: "0,18", force_decimal: false })
|
|
51
|
+
{{/if}}
|
|
39
52
|
{{this.camelCase}}?: {{this.tsType}};
|
|
40
53
|
|
|
41
54
|
{{/each}}
|
|
55
|
+
{{else}}
|
|
56
|
+
{{#if hasFields}}
|
|
57
|
+
// This aggregate has no client-writable scaffold fields.
|
|
42
58
|
{{else}}
|
|
43
59
|
// Add your input fields here
|
|
44
60
|
// Example:
|
|
@@ -46,6 +62,7 @@ export class Update{{entityNamePascal}}Input {
|
|
|
46
62
|
// @IsOptional()
|
|
47
63
|
// @IsString()
|
|
48
64
|
// name?: string;
|
|
65
|
+
{{/if}}
|
|
49
66
|
{{/if}}
|
|
50
67
|
@Field({ nullable: true })
|
|
51
68
|
@IsOptional()
|
|
@@ -2,7 +2,9 @@ import { Args, ID, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
|
2
2
|
import { CommandBus, QueryBus } from "@nestjs/cqrs";
|
|
3
3
|
import { Create{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/create-{{entityNameKebab}}.command";
|
|
4
4
|
import { Update{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/update-{{entityNameKebab}}.command";
|
|
5
|
+
{{#if deleteEnabled}}
|
|
5
6
|
import { Delete{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/delete-{{entityNameKebab}}.command";
|
|
7
|
+
{{/if}}
|
|
6
8
|
import { Get{{entityNamePascal}}ByIdQuery } from "@modules/{{moduleNameKebab}}/application/queries/get-{{entityNameKebab}}-by-id.query";
|
|
7
9
|
import { GetAll{{entityNamePluralPascal}}Query } from "@modules/{{moduleNameKebab}}/application/queries/get-all-{{entityNamePluralKebab}}.query";
|
|
8
10
|
import { Create{{entityNamePascal}}Input } from "./inputs/create-{{entityNameKebab}}.input";
|
|
@@ -51,6 +53,7 @@ export class {{entityNamePascal}}Resolver {
|
|
|
51
53
|
return this.commandBus.execute(command);
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
{{#if deleteEnabled}}
|
|
54
57
|
@Mutation(() => Boolean)
|
|
55
58
|
async delete{{entityNamePascal}}(
|
|
56
59
|
@Args("id", { type: () => ID }) id: string,
|
|
@@ -59,4 +62,5 @@ export class {{entityNamePascal}}Resolver {
|
|
|
59
62
|
await this.commandBus.execute(command);
|
|
60
63
|
return true;
|
|
61
64
|
}
|
|
65
|
+
{{/if}}
|
|
62
66
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Injectable } from '@nestjs/common';
|
|
2
2
|
|
|
3
3
|
@Injectable()
|
|
4
|
-
export class {{
|
|
4
|
+
export class {{entityNamePascal}}Service {
|
|
5
5
|
constructor() {}
|
|
6
6
|
|
|
7
7
|
// Add your domain service methods here
|
|
@@ -10,4 +10,4 @@ export class {{entityName}}Service {
|
|
|
10
10
|
// // Domain validation logic
|
|
11
11
|
// return true;
|
|
12
12
|
// }
|
|
13
|
-
}
|
|
13
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
2
2
|
import { CommandBus, QueryBus } from "@nestjs/cqrs";
|
|
3
|
-
import { {{entityNamePascal}}Controller } from "
|
|
3
|
+
import { {{entityNamePascal}}Controller } from "./{{entityNameKebab}}.controller";
|
|
4
4
|
import { Create{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/create-{{entityNameKebab}}.command";
|
|
5
5
|
import { Update{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/update-{{entityNameKebab}}.command";
|
|
6
|
+
{{#if deleteEnabled}}
|
|
6
7
|
import { Delete{{entityNamePascal}}Command } from "@modules/{{moduleNameKebab}}/application/commands/delete-{{entityNameKebab}}.command";
|
|
8
|
+
{{/if}}
|
|
7
9
|
import { Get{{entityNamePascal}}ByIdQuery } from "@modules/{{moduleNameKebab}}/application/queries/get-{{entityNameKebab}}-by-id.query";
|
|
8
10
|
import { GetAll{{entityNamePluralPascal}}Query } from "@modules/{{moduleNameKebab}}/application/queries/get-all-{{entityNamePluralKebab}}.query";
|
|
9
11
|
|
|
@@ -110,6 +112,7 @@ describe("{{entityNamePascal}}Controller", () => {
|
|
|
110
112
|
});
|
|
111
113
|
});
|
|
112
114
|
|
|
115
|
+
{{#if deleteEnabled}}
|
|
113
116
|
describe("delete", () => {
|
|
114
117
|
it("should delete the {{entityNameCamel}}", async () => {
|
|
115
118
|
commandBus.execute.mockResolvedValue(undefined);
|
|
@@ -121,4 +124,5 @@ describe("{{entityNamePascal}}Controller", () => {
|
|
|
121
124
|
);
|
|
122
125
|
});
|
|
123
126
|
});
|
|
127
|
+
{{/if}}
|
|
124
128
|
});
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { Test, TestingModule } from "@nestjs/testing";
|
|
2
|
+
import { {{entityNamePascal}} as Prisma{{entityNamePascal}} } from "@prisma/client";
|
|
3
|
+
import { PrismaService } from "@prisma/prisma.service";
|
|
4
|
+
import { {{entityNamePascal}}Repository } from "./{{entityNameKebab}}.repository";
|
|
5
|
+
import { {{entityNamePascal}}Mapper } from "../mappers/{{entityNameKebab}}.mapper";
|
|
6
|
+
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/application/domain/entities/{{entityNameKebab}}.entity";
|
|
7
|
+
|
|
8
|
+
describe("{{entityNamePascal}}Repository", () => {
|
|
9
|
+
let repository: {{entityNamePascal}}Repository;
|
|
10
|
+
let mapper: jest.Mocked<{{entityNamePascal}}Mapper>;
|
|
11
|
+
|
|
12
|
+
const prismaDelegate = {
|
|
13
|
+
create: jest.fn(),
|
|
14
|
+
findFirst: jest.fn(),
|
|
15
|
+
findMany: jest.fn(),
|
|
16
|
+
count: jest.fn(),
|
|
17
|
+
update: jest.fn(),
|
|
18
|
+
{{#if deleteEnabled}}
|
|
19
|
+
delete: jest.fn(),
|
|
20
|
+
{{/if}}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const mockPrismaEntity = {
|
|
24
|
+
id: "test-uuid",
|
|
25
|
+
{{#each fields}}
|
|
26
|
+
{{this.snakeCase}}: undefined as never,
|
|
27
|
+
{{/each}}
|
|
28
|
+
is_active: true,
|
|
29
|
+
created_at: new Date(),
|
|
30
|
+
updated_at: new Date(),
|
|
31
|
+
{{#if softDelete}}
|
|
32
|
+
deleted_at: null,
|
|
33
|
+
{{/if}}
|
|
34
|
+
} as Prisma{{entityNamePascal}};
|
|
35
|
+
|
|
36
|
+
const mockDomainEntity = new {{entityNamePascal}}Entity({
|
|
37
|
+
id: "test-uuid",
|
|
38
|
+
{{#each fields}}
|
|
39
|
+
{{this.camelCase}}: undefined as never,
|
|
40
|
+
{{/each}}
|
|
41
|
+
isActive: true,
|
|
42
|
+
createdAt: new Date(),
|
|
43
|
+
updatedAt: new Date(),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
beforeEach(async () => {
|
|
47
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
48
|
+
providers: [
|
|
49
|
+
{{entityNamePascal}}Repository,
|
|
50
|
+
{
|
|
51
|
+
provide: PrismaService,
|
|
52
|
+
useValue: {
|
|
53
|
+
{{entityNameCamel}}: prismaDelegate,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
provide: {{entityNamePascal}}Mapper,
|
|
58
|
+
useValue: {
|
|
59
|
+
toPrismaCreate: jest.fn(),
|
|
60
|
+
toPrismaUpdate: jest.fn(),
|
|
61
|
+
toDomainEntity: jest.fn(),
|
|
62
|
+
toResponseDto: jest.fn(),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
}).compile();
|
|
67
|
+
|
|
68
|
+
repository = module.get<{{entityNamePascal}}Repository>({{entityNamePascal}}Repository);
|
|
69
|
+
mapper = module.get({{entityNamePascal}}Mapper);
|
|
70
|
+
jest.clearAllMocks();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("create", () => {
|
|
74
|
+
it("should create and return a domain entity", async () => {
|
|
75
|
+
mapper.toPrismaCreate.mockReturnValue({});
|
|
76
|
+
prismaDelegate.create.mockResolvedValue(mockPrismaEntity);
|
|
77
|
+
mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
|
|
78
|
+
|
|
79
|
+
const result = await repository.create(mockDomainEntity);
|
|
80
|
+
|
|
81
|
+
expect(prismaDelegate.create).toHaveBeenCalledWith({ data: {} });
|
|
82
|
+
expect(result).toEqual(mockDomainEntity);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("findById", () => {
|
|
87
|
+
it("should return a domain entity when found", async () => {
|
|
88
|
+
prismaDelegate.findFirst.mockResolvedValue(mockPrismaEntity);
|
|
89
|
+
mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
|
|
90
|
+
|
|
91
|
+
const result = await repository.findById("test-uuid");
|
|
92
|
+
|
|
93
|
+
expect(prismaDelegate.findFirst).toHaveBeenCalledWith({
|
|
94
|
+
{{#if softDelete}}
|
|
95
|
+
where: { id: "test-uuid", deleted_at: null },
|
|
96
|
+
{{else}}
|
|
97
|
+
where: { id: "test-uuid" },
|
|
98
|
+
{{/if}}
|
|
99
|
+
});
|
|
100
|
+
expect(result).toEqual(mockDomainEntity);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should return null when the entity is not found", async () => {
|
|
104
|
+
prismaDelegate.findFirst.mockResolvedValue(null);
|
|
105
|
+
|
|
106
|
+
await expect(repository.findById("missing-uuid")).resolves.toBeNull();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("findAllPaginated", () => {
|
|
111
|
+
it("should return paginated entities with a total count", async () => {
|
|
112
|
+
prismaDelegate.findMany.mockResolvedValue([mockPrismaEntity]);
|
|
113
|
+
prismaDelegate.count.mockResolvedValue(1);
|
|
114
|
+
mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
|
|
115
|
+
|
|
116
|
+
const result = await repository.findAllPaginated({
|
|
117
|
+
skip: 0,
|
|
118
|
+
take: 10,
|
|
119
|
+
orderBy: "created_at",
|
|
120
|
+
orderDirection: "DESC",
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
expect(result[0]).toHaveLength(1);
|
|
124
|
+
expect(result[1]).toBe(1);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("update", () => {
|
|
129
|
+
it("should update and return a domain entity", async () => {
|
|
130
|
+
mapper.toPrismaUpdate.mockReturnValue({});
|
|
131
|
+
prismaDelegate.update.mockResolvedValue(mockPrismaEntity);
|
|
132
|
+
mapper.toDomainEntity.mockReturnValue(mockDomainEntity);
|
|
133
|
+
|
|
134
|
+
const result = await repository.update("test-uuid", mockDomainEntity);
|
|
135
|
+
|
|
136
|
+
expect(prismaDelegate.update).toHaveBeenCalledWith({
|
|
137
|
+
where: { id: "test-uuid" },
|
|
138
|
+
data: {},
|
|
139
|
+
});
|
|
140
|
+
expect(result).toEqual(mockDomainEntity);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
{{#if deleteEnabled}}
|
|
145
|
+
describe("delete", () => {
|
|
146
|
+
{{#if softDelete}}
|
|
147
|
+
it("should soft delete the entity", async () => {
|
|
148
|
+
prismaDelegate.update.mockResolvedValue(mockPrismaEntity);
|
|
149
|
+
|
|
150
|
+
await repository.delete("test-uuid");
|
|
151
|
+
|
|
152
|
+
expect(prismaDelegate.update).toHaveBeenCalledWith({
|
|
153
|
+
where: { id: "test-uuid" },
|
|
154
|
+
data: expect.objectContaining({ deleted_at: expect.any(Date) }),
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
{{else}}
|
|
158
|
+
it("should delete the entity", async () => {
|
|
159
|
+
prismaDelegate.delete.mockResolvedValue(mockPrismaEntity);
|
|
160
|
+
|
|
161
|
+
await repository.delete("test-uuid");
|
|
162
|
+
|
|
163
|
+
expect(prismaDelegate.delete).toHaveBeenCalledWith({
|
|
164
|
+
where: { id: "test-uuid" },
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
{{/if}}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
{{#if hardDelete}}
|
|
171
|
+
describe("hardDelete", () => {
|
|
172
|
+
it("should permanently delete the entity after explicit opt-in", async () => {
|
|
173
|
+
prismaDelegate.delete.mockResolvedValue(mockPrismaEntity);
|
|
174
|
+
|
|
175
|
+
await repository.hardDelete("test-uuid");
|
|
176
|
+
|
|
177
|
+
expect(prismaDelegate.delete).toHaveBeenCalledWith({
|
|
178
|
+
where: { id: "test-uuid" },
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
{{/if}}
|
|
184
|
+
{{/if}}
|
|
185
|
+
describe("exists", () => {
|
|
186
|
+
it("should return whether the entity exists", async () => {
|
|
187
|
+
prismaDelegate.count.mockResolvedValue(1);
|
|
188
|
+
|
|
189
|
+
await expect(repository.exists("test-uuid")).resolves.toBe(true);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
2
2
|
import { getRepositoryToken } from "@nestjs/typeorm";
|
|
3
3
|
import { Repository } from "typeorm";
|
|
4
|
-
import { {{entityNamePascal}}Repository } from "
|
|
4
|
+
import { {{entityNamePascal}}Repository } from "./{{entityNameKebab}}.repository";
|
|
5
5
|
import { {{entityNamePascal}}OrmEntity } from "../orm-entities/{{entityNameKebab}}.orm-entity";
|
|
6
6
|
import { {{entityNamePascal}}Mapper } from "../mappers/{{entityNameKebab}}.mapper";
|
|
7
7
|
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/application/domain/entities/{{entityNameKebab}}.entity";
|
|
@@ -13,14 +13,22 @@ describe("{{entityNamePascal}}Repository", () => {
|
|
|
13
13
|
|
|
14
14
|
const mockOrmEntity: {{entityNamePascal}}OrmEntity = {
|
|
15
15
|
id: "test-uuid",
|
|
16
|
+
{{#each fields}}
|
|
17
|
+
{{#if this.isRelation}}{{this.camelCase}}{{else}}{{this.snakeCase}}{{/if}}: undefined as never,
|
|
18
|
+
{{/each}}
|
|
16
19
|
isActive: true,
|
|
17
20
|
createdAt: new Date(),
|
|
18
21
|
updatedAt: new Date(),
|
|
22
|
+
{{#if softDelete}}
|
|
19
23
|
deletedAt: null,
|
|
24
|
+
{{/if}}
|
|
20
25
|
};
|
|
21
26
|
|
|
22
27
|
const mockDomainEntity = new {{entityNamePascal}}Entity({
|
|
23
28
|
id: "test-uuid",
|
|
29
|
+
{{#each fields}}
|
|
30
|
+
{{this.camelCase}}: undefined as never,
|
|
31
|
+
{{/each}}
|
|
24
32
|
isActive: true,
|
|
25
33
|
createdAt: new Date(),
|
|
26
34
|
updatedAt: new Date(),
|
|
@@ -38,7 +46,9 @@ describe("{{entityNamePascal}}Repository", () => {
|
|
|
38
46
|
find: jest.fn(),
|
|
39
47
|
findAndCount: jest.fn(),
|
|
40
48
|
update: jest.fn(),
|
|
49
|
+
{{#if deleteEnabled}}
|
|
41
50
|
delete: jest.fn(),
|
|
51
|
+
{{/if}}
|
|
42
52
|
count: jest.fn(),
|
|
43
53
|
},
|
|
44
54
|
},
|
|
@@ -81,7 +91,11 @@ describe("{{entityNamePascal}}Repository", () => {
|
|
|
81
91
|
const result = await repository.findById("test-uuid");
|
|
82
92
|
|
|
83
93
|
expect(typeOrmRepo.findOne).toHaveBeenCalledWith({
|
|
94
|
+
{{#if softDelete}}
|
|
84
95
|
where: { id: "test-uuid", deletedAt: null },
|
|
96
|
+
{{else}}
|
|
97
|
+
where: { id: "test-uuid" },
|
|
98
|
+
{{/if}}
|
|
85
99
|
});
|
|
86
100
|
expect(result).toEqual(mockDomainEntity);
|
|
87
101
|
});
|
|
@@ -125,7 +139,9 @@ describe("{{entityNamePascal}}Repository", () => {
|
|
|
125
139
|
});
|
|
126
140
|
});
|
|
127
141
|
|
|
142
|
+
{{#if deleteEnabled}}
|
|
128
143
|
describe("delete", () => {
|
|
144
|
+
{{#if softDelete}}
|
|
129
145
|
it("should soft delete the entity", async () => {
|
|
130
146
|
typeOrmRepo.update.mockResolvedValue({ affected: 1 } as any);
|
|
131
147
|
|
|
@@ -136,8 +152,31 @@ describe("{{entityNamePascal}}Repository", () => {
|
|
|
136
152
|
expect.objectContaining({ deletedAt: expect.any(Date) })
|
|
137
153
|
);
|
|
138
154
|
});
|
|
155
|
+
{{else}}
|
|
156
|
+
it("should delete the entity", async () => {
|
|
157
|
+
typeOrmRepo.delete.mockResolvedValue({ affected: 1 } as any);
|
|
158
|
+
|
|
159
|
+
await repository.delete("test-uuid");
|
|
160
|
+
|
|
161
|
+
expect(typeOrmRepo.delete).toHaveBeenCalledWith("test-uuid");
|
|
162
|
+
});
|
|
163
|
+
{{/if}}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
{{#if hardDelete}}
|
|
167
|
+
describe("hardDelete", () => {
|
|
168
|
+
it("should permanently delete the entity after explicit opt-in", async () => {
|
|
169
|
+
typeOrmRepo.delete.mockResolvedValue({ affected: 1 } as any);
|
|
170
|
+
|
|
171
|
+
await repository.hardDelete("test-uuid");
|
|
172
|
+
|
|
173
|
+
expect(typeOrmRepo.delete).toHaveBeenCalledWith("test-uuid");
|
|
174
|
+
});
|
|
139
175
|
});
|
|
140
176
|
|
|
177
|
+
{{/if}}
|
|
178
|
+
|
|
179
|
+
{{/if}}
|
|
141
180
|
describe("exists", () => {
|
|
142
181
|
it("should return true when entity exists", async () => {
|
|
143
182
|
typeOrmRepo.count.mockResolvedValue(1);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
2
2
|
import { NotFoundException } from "@nestjs/common";
|
|
3
|
-
import { Create{{entityNamePascal}}UseCase } from "
|
|
4
|
-
import { Update{{entityNamePascal}}UseCase } from "
|
|
5
|
-
|
|
3
|
+
import { Create{{entityNamePascal}}UseCase } from "./create-{{entityNameKebab}}.use-case";
|
|
4
|
+
import { Update{{entityNamePascal}}UseCase } from "./update-{{entityNameKebab}}.use-case";
|
|
5
|
+
{{#if deleteEnabled}}
|
|
6
|
+
import { Delete{{entityNamePascal}}UseCase } from "./delete-{{entityNameKebab}}.use-case";
|
|
7
|
+
{{/if}}
|
|
6
8
|
import { {{entityNamePascal}}Repository } from "@modules/{{moduleNameKebab}}/infrastructure/repositories/{{entityNameKebab}}.repository";
|
|
7
9
|
import { {{entityNamePascal}}Mapper } from "@modules/{{moduleNameKebab}}/infrastructure/mappers/{{entityNameKebab}}.mapper";
|
|
8
10
|
import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/application/domain/entities/{{entityNameKebab}}.entity";
|
|
@@ -10,7 +12,9 @@ import { {{entityNamePascal}}Entity } from "@modules/{{moduleNameKebab}}/applica
|
|
|
10
12
|
describe("{{entityNamePascal}} Use Cases", () => {
|
|
11
13
|
let createUseCase: Create{{entityNamePascal}}UseCase;
|
|
12
14
|
let updateUseCase: Update{{entityNamePascal}}UseCase;
|
|
15
|
+
{{#if deleteEnabled}}
|
|
13
16
|
let deleteUseCase: Delete{{entityNamePascal}}UseCase;
|
|
17
|
+
{{/if}}
|
|
14
18
|
let repository: jest.Mocked<{{entityNamePascal}}Repository>;
|
|
15
19
|
let mapper: jest.Mocked<{{entityNamePascal}}Mapper>;
|
|
16
20
|
|
|
@@ -33,14 +37,18 @@ describe("{{entityNamePascal}} Use Cases", () => {
|
|
|
33
37
|
providers: [
|
|
34
38
|
Create{{entityNamePascal}}UseCase,
|
|
35
39
|
Update{{entityNamePascal}}UseCase,
|
|
40
|
+
{{#if deleteEnabled}}
|
|
36
41
|
Delete{{entityNamePascal}}UseCase,
|
|
42
|
+
{{/if}}
|
|
37
43
|
{
|
|
38
44
|
provide: {{entityNamePascal}}Repository,
|
|
39
45
|
useValue: {
|
|
40
46
|
create: jest.fn(),
|
|
41
47
|
findById: jest.fn(),
|
|
42
48
|
update: jest.fn(),
|
|
49
|
+
{{#if deleteEnabled}}
|
|
43
50
|
delete: jest.fn(),
|
|
51
|
+
{{/if}}
|
|
44
52
|
},
|
|
45
53
|
},
|
|
46
54
|
{
|
|
@@ -54,7 +62,9 @@ describe("{{entityNamePascal}} Use Cases", () => {
|
|
|
54
62
|
|
|
55
63
|
createUseCase = module.get<Create{{entityNamePascal}}UseCase>(Create{{entityNamePascal}}UseCase);
|
|
56
64
|
updateUseCase = module.get<Update{{entityNamePascal}}UseCase>(Update{{entityNamePascal}}UseCase);
|
|
65
|
+
{{#if deleteEnabled}}
|
|
57
66
|
deleteUseCase = module.get<Delete{{entityNamePascal}}UseCase>(Delete{{entityNamePascal}}UseCase);
|
|
67
|
+
{{/if}}
|
|
58
68
|
repository = module.get({{entityNamePascal}}Repository);
|
|
59
69
|
mapper = module.get({{entityNamePascal}}Mapper);
|
|
60
70
|
});
|
|
@@ -65,7 +75,14 @@ describe("{{entityNamePascal}} Use Cases", () => {
|
|
|
65
75
|
repository.create.mockResolvedValue(mockEntity);
|
|
66
76
|
mapper.toResponseDto.mockReturnValue(mockResponseDto as any);
|
|
67
77
|
|
|
68
|
-
const result = await createUseCase.execute(
|
|
78
|
+
const result = await createUseCase.execute(
|
|
79
|
+
createDto as any{{#if hasServerOwnedFields}},
|
|
80
|
+
{
|
|
81
|
+
{{#each serverOwnedFields}}
|
|
82
|
+
{{this.camelCase}}: undefined as never,
|
|
83
|
+
{{/each}}
|
|
84
|
+
}{{/if}},
|
|
85
|
+
);
|
|
69
86
|
|
|
70
87
|
expect(repository.create).toHaveBeenCalled();
|
|
71
88
|
expect(mapper.toResponseDto).toHaveBeenCalledWith(mockEntity);
|
|
@@ -96,6 +113,7 @@ describe("{{entityNamePascal}} Use Cases", () => {
|
|
|
96
113
|
});
|
|
97
114
|
});
|
|
98
115
|
|
|
116
|
+
{{#if deleteEnabled}}
|
|
99
117
|
describe("Delete{{entityNamePascal}}UseCase", () => {
|
|
100
118
|
it("should delete an existing {{entityNameCamel}}", async () => {
|
|
101
119
|
repository.findById.mockResolvedValue(mockEntity);
|
|
@@ -113,4 +131,5 @@ describe("{{entityNamePascal}} Use Cases", () => {
|
|
|
113
131
|
await expect(deleteUseCase.execute("non-existent")).rejects.toThrow(NotFoundException);
|
|
114
132
|
});
|
|
115
133
|
});
|
|
134
|
+
{{/if}}
|
|
116
135
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
|
|
3
|
+
export interface {{entityNamePascal}}Input {
|
|
4
|
+
// Define validated application input.
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface {{entityNamePascal}}Result {
|
|
8
|
+
// Define the use-case result contract.
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class {{entityNamePascal}}UseCase {
|
|
13
|
+
async execute(input: {{entityNamePascal}}Input): Promise<{{entityNamePascal}}Result> {
|
|
14
|
+
void input;
|
|
15
|
+
throw new Error("{{entityNamePascal}}UseCase is not implemented");
|
|
16
|
+
}
|
|
17
|
+
}
|