@comet/api-generator 9.0.0-beta.2 → 9.0.0-beta.3

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 (25) hide show
  1. package/lib/commands/generate/generate-command.js +4 -13
  2. package/lib/commands/generate/generateCrud/build-options.d.ts +1 -1
  3. package/lib/commands/generate/generateCrud/build-options.js +3 -3
  4. package/lib/commands/generate/generateCrud/generate-crud.d.ts +1 -1
  5. package/lib/commands/generate/generateCrud/generate-crud.js +109 -104
  6. package/lib/commands/generate/generateCrud/generate-enum-filter-dto.d.ts +1 -1
  7. package/lib/commands/generate/generateCrud/generate-payload-object-types.d.ts +2 -2
  8. package/lib/commands/generate/generateCrud/generate-payload-object-types.js +2 -3
  9. package/lib/commands/generate/generateCrud/generate-service-hook-call.d.ts +2 -2
  10. package/lib/commands/generate/generateCrud/generate-service-hook-call.js +8 -7
  11. package/lib/commands/generate/generateCrudInput/generate-crud-input.d.ts +2 -2
  12. package/lib/commands/generate/generateCrudInput/generate-crud-input.js +381 -388
  13. package/lib/commands/generate/generateCrudSingle/generate-crud-single.d.ts +2 -2
  14. package/lib/commands/generate/generateCrudSingle/generate-crud-single.js +29 -41
  15. package/lib/commands/generate/generateFiles.js +17 -26
  16. package/lib/commands/generate/utils/build-name-variants.d.ts +1 -1
  17. package/lib/commands/generate/utils/find-hooks-service.d.ts +3 -3
  18. package/lib/commands/generate/utils/find-hooks-service.js +3 -6
  19. package/lib/commands/generate/utils/ts-morph-helper.d.ts +1 -1
  20. package/lib/commands/generate/utils/ts-morph-helper.js +23 -19
  21. package/lib/commands/generate/utils/write-generated-file.js +12 -23
  22. package/lib/commands/generate/utils/write-generated-files.js +4 -16
  23. package/lib/commands/generate/watchMode/handleChildProcess.d.ts +1 -1
  24. package/lib/commands/generate/watchMode/watchMode.js +6 -15
  25. package/package.json +8 -8
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.generateCrudInput = generateCrudInput;
13
4
  const cms_api_1 = require("@comet/cms-api");
@@ -20,14 +11,16 @@ const generate_imports_code_1 = require("../utils/generate-imports-code");
20
11
  const ts_morph_helper_1 = require("../utils/ts-morph-helper");
21
12
  function tsCodeRecordToString(object) {
22
13
  const filteredEntries = Object.entries(object).filter(([key, value]) => value !== undefined);
23
- if (filteredEntries.length == 0)
14
+ if (filteredEntries.length == 0) {
24
15
  return "";
16
+ }
25
17
  return `{${filteredEntries.map(([key, value]) => `${key}: ${value},`).join("\n")}}`;
26
18
  }
27
19
  function findReferenceTargetType(targetMeta, referencedColumnName) {
28
- const referencedColumnProp = targetMeta === null || targetMeta === void 0 ? void 0 : targetMeta.props.find((p) => p.name == referencedColumnName);
29
- if (!referencedColumnProp)
20
+ const referencedColumnProp = targetMeta?.props.find((p) => p.name == referencedColumnName);
21
+ if (!referencedColumnProp) {
30
22
  throw new Error("referencedColumnProp not found");
23
+ }
31
24
  if (referencedColumnProp.type == "uuid") {
32
25
  return "uuid";
33
26
  }
@@ -44,258 +37,230 @@ function findReferenceTargetType(targetMeta, referencedColumnName) {
44
37
  return null;
45
38
  }
46
39
  }
47
- function generateCrudInput(generatorOptions_1, metadata_1) {
48
- return __awaiter(this, arguments, void 0, function* (generatorOptions,
49
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
- metadata, options = {
51
- nested: false,
52
- excludeFields: [],
53
- generateUpdateInput: true,
54
- }) {
55
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
56
- const generatedFiles = [];
57
- const { dedicatedResolverArgProps, targetDirectory } = (0, build_options_1.buildOptions)(metadata, generatorOptions);
58
- const props = metadata.props
59
- .filter((prop) => {
60
- return !prop.embedded;
61
- })
62
- .filter((prop) => {
63
- return (0, cms_api_1.hasCrudFieldFeature)(metadata.class, prop.name, "input");
64
- })
65
- .filter((prop) => {
66
- //filter out props that are dedicatedResolverArgProps
67
- return !dedicatedResolverArgProps.some((dedicatedResolverArgProp) => dedicatedResolverArgProp.name === prop.name);
68
- })
69
- .filter((prop) => !options.excludeFields.includes(prop.name));
70
- let fieldsOut = "";
71
- const imports = [
72
- { name: "IsSlug", importPath: "@comet/cms-api" },
73
- { name: "RootBlockInputScalar", importPath: "@comet/cms-api" },
74
- { name: "IsNullable", importPath: "@comet/cms-api" },
75
- { name: "PartialType", importPath: "@comet/cms-api" },
76
- { name: "BlockInputInterface", importPath: "@comet/cms-api" },
77
- { name: "isBlockInputInterface", importPath: "@comet/cms-api" },
78
- { name: "IsString", importPath: "class-validator" },
79
- { name: "IsNotEmpty", importPath: "class-validator" },
80
- { name: "ValidateNested", importPath: "class-validator" },
81
- { name: "IsNumber", importPath: "class-validator" },
82
- { name: "IsBoolean", importPath: "class-validator" },
83
- { name: "IsDate", importPath: "class-validator" },
84
- { name: "IsDateString", importPath: "class-validator" },
85
- { name: "IsOptional", importPath: "class-validator" },
86
- { name: "IsEnum", importPath: "class-validator" },
87
- { name: "IsUUID", importPath: "class-validator" },
88
- { name: "IsArray", importPath: "class-validator" },
89
- { name: "IsInt", importPath: "class-validator" },
90
- ];
91
- for (const prop of props) {
92
- let type = prop.type;
93
- const fieldName = prop.name;
94
- const definedDecorators = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getDecorators();
95
- const decorators = [];
96
- let isOptional = prop.nullable;
97
- if (prop.name != "position") {
98
- if (!prop.nullable) {
99
- decorators.push("@IsNotEmpty()");
100
- }
101
- else {
102
- decorators.push("@IsNullable()");
103
- }
40
+ async function generateCrudInput(generatorOptions,
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ metadata, options = {
43
+ nested: false,
44
+ excludeFields: [],
45
+ generateUpdateInput: true,
46
+ }) {
47
+ const generatedFiles = [];
48
+ const { dedicatedResolverArgProps, targetDirectory } = (0, build_options_1.buildOptions)(metadata, generatorOptions);
49
+ const props = metadata.props
50
+ .filter((prop) => {
51
+ return !prop.embedded;
52
+ })
53
+ .filter((prop) => {
54
+ return (0, cms_api_1.hasCrudFieldFeature)(metadata.class, prop.name, "input");
55
+ })
56
+ .filter((prop) => {
57
+ //filter out props that are dedicatedResolverArgProps
58
+ return !dedicatedResolverArgProps.some((dedicatedResolverArgProp) => dedicatedResolverArgProp.name === prop.name);
59
+ })
60
+ .filter((prop) => !options.excludeFields.includes(prop.name));
61
+ let fieldsOut = "";
62
+ const imports = [
63
+ { name: "IsSlug", importPath: "@comet/cms-api" },
64
+ { name: "RootBlockInputScalar", importPath: "@comet/cms-api" },
65
+ { name: "IsNullable", importPath: "@comet/cms-api" },
66
+ { name: "PartialType", importPath: "@comet/cms-api" },
67
+ { name: "BlockInputInterface", importPath: "@comet/cms-api" },
68
+ { name: "isBlockInputInterface", importPath: "@comet/cms-api" },
69
+ { name: "IsString", importPath: "class-validator" },
70
+ { name: "IsNotEmpty", importPath: "class-validator" },
71
+ { name: "ValidateNested", importPath: "class-validator" },
72
+ { name: "IsNumber", importPath: "class-validator" },
73
+ { name: "IsBoolean", importPath: "class-validator" },
74
+ { name: "IsDate", importPath: "class-validator" },
75
+ { name: "IsDateString", importPath: "class-validator" },
76
+ { name: "IsOptional", importPath: "class-validator" },
77
+ { name: "IsEnum", importPath: "class-validator" },
78
+ { name: "IsUUID", importPath: "class-validator" },
79
+ { name: "IsArray", importPath: "class-validator" },
80
+ { name: "IsInt", importPath: "class-validator" },
81
+ ];
82
+ for (const prop of props) {
83
+ let type = prop.type;
84
+ const fieldName = prop.name;
85
+ const definedDecorators = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getDecorators();
86
+ const decorators = [];
87
+ let isOptional = prop.nullable;
88
+ if (prop.name != "position") {
89
+ if (!prop.nullable) {
90
+ decorators.push("@IsNotEmpty()");
91
+ }
92
+ else {
93
+ decorators.push("@IsNullable()");
94
+ }
95
+ }
96
+ if (["id", "createdAt", "updatedAt", "scope"].includes(prop.name)) {
97
+ //skip those (TODO find a non-magic solution?)
98
+ continue;
99
+ }
100
+ else if (prop.name == "position") {
101
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
102
+ const defaultValue = initializer == "undefined" || initializer == "null" ? "null" : initializer;
103
+ const fieldOptions = tsCodeRecordToString({ nullable: "true", defaultValue });
104
+ isOptional = true;
105
+ decorators.push(`@IsOptional()`);
106
+ imports.push({ name: "Min", importPath: "class-validator" });
107
+ decorators.push(`@Min(1)`);
108
+ decorators.push("@IsInt()");
109
+ decorators.push(`@Field(() => Int, ${fieldOptions})`);
110
+ type = "number";
111
+ }
112
+ else if (prop.enum) {
113
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
114
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
115
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
116
+ const enumName = (0, ts_morph_helper_1.findEnumName)(prop.name, metadata);
117
+ const importPath = (0, ts_morph_helper_1.findEnumImportPath)(enumName, `${targetDirectory}/dto`, metadata);
118
+ imports.push({ name: enumName, importPath });
119
+ decorators.push(`@IsEnum(${enumName})`);
120
+ decorators.push(`@Field(() => ${enumName}, ${fieldOptions})`);
121
+ type = enumName;
122
+ }
123
+ else if (prop.type === "EnumArrayType") {
124
+ if (prop.nullable) {
125
+ console.warn(`${prop.name}: Nullable enum arrays are not supported`);
104
126
  }
105
- if (["id", "createdAt", "updatedAt", "scope"].includes(prop.name)) {
106
- //skip those (TODO find a non-magic solution?)
127
+ decorators.length = 0; //remove @IsNotEmpty
128
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
129
+ const fieldOptions = tsCodeRecordToString({ defaultValue: initializer });
130
+ const enumName = (0, ts_morph_helper_1.findEnumName)(prop.name, metadata);
131
+ const importPath = (0, ts_morph_helper_1.findEnumImportPath)(enumName, `${targetDirectory}/dto`, metadata);
132
+ imports.push({ name: enumName, importPath });
133
+ decorators.push(`@IsEnum(${enumName}, { each: true })`);
134
+ decorators.push(`@Field(() => [${enumName}], ${fieldOptions})`);
135
+ type = `${enumName}[]`;
136
+ }
137
+ else if (prop.type === "string" || prop.type === "text") {
138
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
139
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
140
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
141
+ decorators.push("@IsString()");
142
+ if (prop.name.startsWith("scope_")) {
107
143
  continue;
108
144
  }
109
- else if (prop.name == "position") {
110
- const initializer = (_a = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _a === void 0 ? void 0 : _a.getText();
111
- const defaultValue = initializer == "undefined" || initializer == "null" ? "null" : initializer;
112
- const fieldOptions = tsCodeRecordToString({ nullable: "true", defaultValue });
113
- isOptional = true;
114
- decorators.push(`@IsOptional()`);
115
- imports.push({ name: "Min", importPath: "class-validator" });
116
- decorators.push(`@Min(1)`);
145
+ else if (prop.name === "slug") {
146
+ //TODO find a non-magic solution
147
+ decorators.push("@IsSlug()");
148
+ }
149
+ decorators.push(`@Field(${fieldOptions})`);
150
+ type = "string";
151
+ }
152
+ else if (constants_1.numberTypes.includes(prop.type)) {
153
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
154
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
155
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
156
+ if (constants_1.integerTypes.includes(prop.columnTypes[0])) {
117
157
  decorators.push("@IsInt()");
118
158
  decorators.push(`@Field(() => Int, ${fieldOptions})`);
119
- type = "number";
120
- }
121
- else if (prop.enum) {
122
- const initializer = (_b = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _b === void 0 ? void 0 : _b.getText();
123
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
124
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
125
- const enumName = (0, ts_morph_helper_1.findEnumName)(prop.name, metadata);
126
- const importPath = (0, ts_morph_helper_1.findEnumImportPath)(enumName, `${targetDirectory}/dto`, metadata);
127
- imports.push({ name: enumName, importPath });
128
- decorators.push(`@IsEnum(${enumName})`);
129
- decorators.push(`@Field(() => ${enumName}, ${fieldOptions})`);
130
- type = enumName;
131
- }
132
- else if (prop.type === "EnumArrayType") {
133
- if (prop.nullable) {
134
- console.warn(`${prop.name}: Nullable enum arrays are not supported`);
135
- }
136
- decorators.length = 0; //remove @IsNotEmpty
137
- const initializer = (_c = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _c === void 0 ? void 0 : _c.getText();
138
- const fieldOptions = tsCodeRecordToString({ defaultValue: initializer });
139
- const enumName = (0, ts_morph_helper_1.findEnumName)(prop.name, metadata);
140
- const importPath = (0, ts_morph_helper_1.findEnumImportPath)(enumName, `${targetDirectory}/dto`, metadata);
141
- imports.push({ name: enumName, importPath });
142
- decorators.push(`@IsEnum(${enumName}, { each: true })`);
143
- decorators.push(`@Field(() => [${enumName}], ${fieldOptions})`);
144
- type = `${enumName}[]`;
145
159
  }
146
- else if (prop.type === "string" || prop.type === "text") {
147
- const initializer = (_d = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _d === void 0 ? void 0 : _d.getText();
148
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
149
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
150
- decorators.push("@IsString()");
151
- if (prop.name.startsWith("scope_")) {
152
- continue;
153
- }
154
- else if (prop.name === "slug") {
155
- //TODO find a non-magic solution
156
- decorators.push("@IsSlug()");
157
- }
160
+ else {
161
+ decorators.push("@IsNumber()");
158
162
  decorators.push(`@Field(${fieldOptions})`);
159
- type = "string";
160
163
  }
161
- else if (constants_1.numberTypes.includes(prop.type)) {
162
- const initializer = (_e = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _e === void 0 ? void 0 : _e.getText();
163
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
164
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
165
- if (constants_1.integerTypes.includes(prop.columnTypes[0])) {
166
- decorators.push("@IsInt()");
167
- decorators.push(`@Field(() => Int, ${fieldOptions})`);
168
- }
169
- else {
170
- decorators.push("@IsNumber()");
171
- decorators.push(`@Field(${fieldOptions})`);
172
- }
173
- type = "number";
164
+ type = "number";
165
+ }
166
+ else if (prop.type === "DateType") {
167
+ // ISO Date without time
168
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
169
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
170
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
171
+ decorators.push("@IsDateString()");
172
+ decorators.push(`@Field(() => GraphQLLocalDate, ${fieldOptions})`);
173
+ type = "string";
174
+ }
175
+ else if (prop.type === "Date") {
176
+ // DateTime
177
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
178
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
179
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
180
+ decorators.push("@IsDate()");
181
+ decorators.push(`@Field(${fieldOptions})`);
182
+ type = "Date";
183
+ }
184
+ else if (prop.type === "BooleanType" || prop.type === "boolean") {
185
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
186
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
187
+ const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
188
+ decorators.push("@IsBoolean()");
189
+ decorators.push(`@Field(${fieldOptions})`);
190
+ type = "boolean";
191
+ }
192
+ else if (prop.type === "RootBlockType") {
193
+ const blockName = (0, ts_morph_helper_1.findBlockName)(prop.name, metadata);
194
+ const importPath = (0, ts_morph_helper_1.findBlockImportPath)(blockName, `${targetDirectory}/dto`, metadata);
195
+ imports.push({ name: blockName, importPath });
196
+ decorators.push(`@Field(() => RootBlockInputScalar(${blockName})${prop.nullable ? ", { nullable: true }" : ""})`);
197
+ decorators.push(`@Transform(({ value }) => (isBlockInputInterface(value) ? value : ${blockName}.blockInputFactory(value)), { toClassOnly: true })`);
198
+ decorators.push("@ValidateNested()");
199
+ type = "BlockInputInterface";
200
+ }
201
+ else if (prop.kind == "m:1") {
202
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
203
+ const defaultValueNull = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined);
204
+ const fieldOptions = tsCodeRecordToString({
205
+ nullable: prop.nullable ? "true" : undefined,
206
+ defaultValue: defaultValueNull ? "null" : undefined,
207
+ });
208
+ decorators.push(`@Field(() => ID, ${fieldOptions})`);
209
+ if (prop.referencedColumnNames.length > 1) {
210
+ console.warn(`${prop.name}: Composite keys are not supported`);
211
+ continue;
174
212
  }
175
- else if (prop.type === "DateType") {
176
- // ISO Date without time
177
- const initializer = (_f = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _f === void 0 ? void 0 : _f.getText();
178
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
179
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
180
- decorators.push("@IsDateString()");
181
- decorators.push(`@Field(() => GraphQLLocalDate, ${fieldOptions})`);
213
+ const refType = findReferenceTargetType(prop.targetMeta, prop.referencedColumnNames[0]);
214
+ if (refType == "uuid") {
182
215
  type = "string";
216
+ decorators.push("@IsUUID()");
183
217
  }
184
- else if (prop.type === "Date") {
185
- // DateTime
186
- const initializer = (_g = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _g === void 0 ? void 0 : _g.getText();
187
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
188
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
189
- decorators.push("@IsDate()");
190
- decorators.push(`@Field(${fieldOptions})`);
191
- type = "Date";
192
- }
193
- else if (prop.type === "BooleanType" || prop.type === "boolean") {
194
- const initializer = (_h = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _h === void 0 ? void 0 : _h.getText();
195
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined) ? "null" : initializer;
196
- const fieldOptions = tsCodeRecordToString({ nullable: prop.nullable ? "true" : undefined, defaultValue });
197
- decorators.push("@IsBoolean()");
198
- decorators.push(`@Field(${fieldOptions})`);
199
- type = "boolean";
218
+ else if (refType == "string") {
219
+ type = "string";
220
+ decorators.push("@IsString()");
200
221
  }
201
- else if (prop.type === "RootBlockType") {
202
- const blockName = (0, ts_morph_helper_1.findBlockName)(prop.name, metadata);
203
- const importPath = (0, ts_morph_helper_1.findBlockImportPath)(blockName, `${targetDirectory}/dto`, metadata);
204
- imports.push({ name: blockName, importPath });
205
- decorators.push(`@Field(() => RootBlockInputScalar(${blockName})${prop.nullable ? ", { nullable: true }" : ""})`);
206
- decorators.push(`@Transform(({ value }) => (isBlockInputInterface(value) ? value : ${blockName}.blockInputFactory(value)), { toClassOnly: true })`);
207
- decorators.push("@ValidateNested()");
208
- type = "BlockInputInterface";
222
+ else if (refType == "integer") {
223
+ type = "number";
224
+ decorators.push("@Transform(({ value }) => (value ? parseInt(value) : null))");
225
+ decorators.push("@IsInt()");
209
226
  }
210
- else if (prop.kind == "m:1") {
211
- const initializer = (_j = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _j === void 0 ? void 0 : _j.getText();
212
- const defaultValueNull = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined);
213
- const fieldOptions = tsCodeRecordToString({
214
- nullable: prop.nullable ? "true" : undefined,
215
- defaultValue: defaultValueNull ? "null" : undefined,
216
- });
217
- decorators.push(`@Field(() => ID, ${fieldOptions})`);
218
- if (prop.referencedColumnNames.length > 1) {
219
- console.warn(`${prop.name}: Composite keys are not supported`);
220
- continue;
221
- }
222
- const refType = findReferenceTargetType(prop.targetMeta, prop.referencedColumnNames[0]);
223
- if (refType == "uuid") {
224
- type = "string";
225
- decorators.push("@IsUUID()");
226
- }
227
- else if (refType == "string") {
228
- type = "string";
229
- decorators.push("@IsString()");
230
- }
231
- else if (refType == "integer") {
232
- type = "number";
233
- decorators.push("@Transform(({ value }) => (value ? parseInt(value) : null))");
234
- decorators.push("@IsInt()");
235
- }
236
- else {
237
- console.warn(`${prop.name}: Unsupported referenced type`);
238
- continue;
239
- }
227
+ else {
228
+ console.warn(`${prop.name}: Unsupported referenced type`);
229
+ continue;
240
230
  }
241
- else if (prop.kind == "1:m") {
242
- if (prop.orphanRemoval) {
243
- //if orphanRemoval is enabled, we need to generate a nested input type
244
- decorators.length = 0;
245
- if (!prop.targetMeta)
246
- throw new Error("No targetMeta");
247
- const inputNameClassName = `${metadata.className}Nested${prop.targetMeta.className}Input`;
248
- {
249
- const excludeFields = prop.targetMeta.props.filter((p) => p.kind == "m:1" && p.targetMeta == metadata).map((p) => p.name);
250
- const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
251
- const { fileNameSingular: targetFileNameSingular } = (0, build_name_variants_1.buildNameVariants)(prop.targetMeta);
252
- const fileName = `dto/${fileNameSingular}-nested-${targetFileNameSingular}.input.ts`;
253
- const nestedInputFiles = yield generateCrudInput(generatorOptions, prop.targetMeta, {
254
- nested: true,
255
- fileName,
256
- className: inputNameClassName,
257
- excludeFields,
258
- });
259
- generatedFiles.push(...nestedInputFiles);
260
- imports.push({
261
- name: inputNameClassName,
262
- importPath: nestedInputFiles[nestedInputFiles.length - 1].name.replace(/^dto/, ".").replace(/\.ts$/, ""),
263
- });
264
- }
265
- decorators.push(`@Field(() => [${inputNameClassName}], {${prop.nullable ? "nullable: true" : "defaultValue: []"}})`);
266
- decorators.push(`@IsArray()`);
267
- decorators.push(`@Type(() => ${inputNameClassName})`);
268
- type = `${inputNameClassName}[]`;
231
+ }
232
+ else if (prop.kind == "1:m") {
233
+ if (prop.orphanRemoval) {
234
+ //if orphanRemoval is enabled, we need to generate a nested input type
235
+ decorators.length = 0;
236
+ if (!prop.targetMeta) {
237
+ throw new Error("No targetMeta");
269
238
  }
270
- else {
271
- //if orphanRemoval is disabled, we reference the id in input
272
- decorators.length = 0;
273
- decorators.push(`@Field(() => [ID], {${prop.nullable ? "nullable: true" : "defaultValue: []"}})`);
274
- decorators.push(`@IsArray()`);
275
- if (prop.referencedColumnNames.length > 1) {
276
- console.warn(`${prop.name}: Composite keys are not supported`);
277
- continue;
278
- }
279
- const refType = findReferenceTargetType(prop.targetMeta, prop.referencedColumnNames[0]);
280
- if (refType == "uuid") {
281
- type = "string[]";
282
- decorators.push("@IsUUID(undefined, { each: true })");
283
- }
284
- else if (refType == "string") {
285
- type = "string[]";
286
- decorators.push("@IsString({ each: true })");
287
- }
288
- else if (refType == "integer") {
289
- type = "number[]";
290
- decorators.push("@Transform(({ value }) => value.map((id: string) => parseInt(id)))");
291
- decorators.push("@IsInt({ each: true })");
292
- }
293
- else {
294
- console.warn(`${prop.name}: Unsupported referenced type`);
295
- }
239
+ const inputNameClassName = `${metadata.className}Nested${prop.targetMeta.className}Input`;
240
+ {
241
+ const excludeFields = prop.targetMeta.props.filter((p) => p.kind == "m:1" && p.targetMeta == metadata).map((p) => p.name);
242
+ const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
243
+ const { fileNameSingular: targetFileNameSingular } = (0, build_name_variants_1.buildNameVariants)(prop.targetMeta);
244
+ const fileName = `dto/${fileNameSingular}-nested-${targetFileNameSingular}.input.ts`;
245
+ const nestedInputFiles = await generateCrudInput(generatorOptions, prop.targetMeta, {
246
+ nested: true,
247
+ fileName,
248
+ className: inputNameClassName,
249
+ excludeFields,
250
+ });
251
+ generatedFiles.push(...nestedInputFiles);
252
+ imports.push({
253
+ name: inputNameClassName,
254
+ importPath: nestedInputFiles[nestedInputFiles.length - 1].name.replace(/^dto/, ".").replace(/\.ts$/, ""),
255
+ });
296
256
  }
257
+ decorators.push(`@Field(() => [${inputNameClassName}], {${prop.nullable ? "nullable: true" : "defaultValue: []"}})`);
258
+ decorators.push(`@IsArray()`);
259
+ decorators.push(`@Type(() => ${inputNameClassName})`);
260
+ type = `${inputNameClassName}[]`;
297
261
  }
298
- else if (prop.kind == "m:n") {
262
+ else {
263
+ //if orphanRemoval is disabled, we reference the id in input
299
264
  decorators.length = 0;
300
265
  decorators.push(`@Field(() => [ID], {${prop.nullable ? "nullable: true" : "defaultValue: []"}})`);
301
266
  decorators.push(`@IsArray()`);
@@ -315,169 +280,198 @@ function generateCrudInput(generatorOptions_1, metadata_1) {
315
280
  else if (refType == "integer") {
316
281
  type = "number[]";
317
282
  decorators.push("@Transform(({ value }) => value.map((id: string) => parseInt(id)))");
283
+ decorators.push("@IsInt({ each: true })");
318
284
  }
319
285
  else {
320
286
  console.warn(`${prop.name}: Unsupported referenced type`);
321
287
  }
322
288
  }
323
- else if (prop.kind == "1:1") {
324
- if (!prop.targetMeta)
325
- throw new Error("No targetMeta");
326
- const inputNameClassName = `${metadata.className}Nested${prop.targetMeta.className}Input`;
327
- {
328
- const excludeFields = prop.targetMeta.props.filter((p) => p.kind == "1:1" && p.targetMeta == metadata).map((p) => p.name);
329
- const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
330
- const { fileNameSingular: targetFileNameSingular } = (0, build_name_variants_1.buildNameVariants)(prop.targetMeta);
331
- const fileName = `dto/${fileNameSingular}-nested-${targetFileNameSingular}.input.ts`;
332
- const nestedInputFiles = yield generateCrudInput(generatorOptions, prop.targetMeta, {
333
- nested: true,
334
- fileName,
335
- className: inputNameClassName,
336
- excludeFields,
337
- });
338
- generatedFiles.push(...nestedInputFiles);
339
- imports.push({
340
- name: inputNameClassName,
341
- importPath: nestedInputFiles[nestedInputFiles.length - 1].name.replace(/^dto/, ".").replace(/\.ts$/, ""),
342
- });
343
- }
344
- decorators.push(`@Field(() => ${inputNameClassName}${prop.nullable ? ", { nullable: true }" : ""})`);
345
- decorators.push(`@Type(() => ${inputNameClassName})`);
346
- decorators.push("@ValidateNested()");
347
- type = `${inputNameClassName}`;
289
+ }
290
+ else if (prop.kind == "m:n") {
291
+ decorators.length = 0;
292
+ decorators.push(`@Field(() => [ID], {${prop.nullable ? "nullable: true" : "defaultValue: []"}})`);
293
+ decorators.push(`@IsArray()`);
294
+ if (prop.referencedColumnNames.length > 1) {
295
+ console.warn(`${prop.name}: Composite keys are not supported`);
296
+ continue;
297
+ }
298
+ const refType = findReferenceTargetType(prop.targetMeta, prop.referencedColumnNames[0]);
299
+ if (refType == "uuid") {
300
+ type = "string[]";
301
+ decorators.push("@IsUUID(undefined, { each: true })");
302
+ }
303
+ else if (refType == "string") {
304
+ type = "string[]";
305
+ decorators.push("@IsString({ each: true })");
306
+ }
307
+ else if (refType == "integer") {
308
+ type = "number[]";
309
+ decorators.push("@Transform(({ value }) => value.map((id: string) => parseInt(id)))");
310
+ }
311
+ else {
312
+ console.warn(`${prop.name}: Unsupported referenced type`);
313
+ }
314
+ }
315
+ else if (prop.kind == "1:1") {
316
+ if (!prop.targetMeta) {
317
+ throw new Error("No targetMeta");
318
+ }
319
+ const inputNameClassName = `${metadata.className}Nested${prop.targetMeta.className}Input`;
320
+ {
321
+ const excludeFields = prop.targetMeta.props.filter((p) => p.kind == "1:1" && p.targetMeta == metadata).map((p) => p.name);
322
+ const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
323
+ const { fileNameSingular: targetFileNameSingular } = (0, build_name_variants_1.buildNameVariants)(prop.targetMeta);
324
+ const fileName = `dto/${fileNameSingular}-nested-${targetFileNameSingular}.input.ts`;
325
+ const nestedInputFiles = await generateCrudInput(generatorOptions, prop.targetMeta, {
326
+ nested: true,
327
+ fileName,
328
+ className: inputNameClassName,
329
+ excludeFields,
330
+ });
331
+ generatedFiles.push(...nestedInputFiles);
332
+ imports.push({
333
+ name: inputNameClassName,
334
+ importPath: nestedInputFiles[nestedInputFiles.length - 1].name.replace(/^dto/, ".").replace(/\.ts$/, ""),
335
+ });
348
336
  }
349
- else if (prop.type == "JsonType" || prop.embeddable || prop.type == "ArrayType") {
350
- const tsProp = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata);
351
- let tsType = tsProp.getType();
352
- if (tsType.isUnion() && tsType.getUnionTypes().length == 2 && tsType.getUnionTypes()[0].getText() == "undefined") {
353
- // undefinded | type (or prop?: type) -> type
354
- tsType = tsType.getUnionTypes()[1];
337
+ decorators.push(`@Field(() => ${inputNameClassName}${prop.nullable ? ", { nullable: true }" : ""})`);
338
+ decorators.push(`@Type(() => ${inputNameClassName})`);
339
+ decorators.push("@ValidateNested()");
340
+ type = `${inputNameClassName}`;
341
+ }
342
+ else if (prop.type == "JsonType" || prop.embeddable || prop.type == "ArrayType") {
343
+ const tsProp = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata);
344
+ let tsType = tsProp.getType();
345
+ if (tsType.isUnion() && tsType.getUnionTypes().length == 2 && tsType.getUnionTypes()[0].getText() == "undefined") {
346
+ // undefinded | type (or prop?: type) -> type
347
+ tsType = tsType.getUnionTypes()[1];
348
+ }
349
+ type = tsType.getText(tsProp);
350
+ if (tsType.isArray()) {
351
+ const initializer = tsProp.getInitializer()?.getText();
352
+ const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined)
353
+ ? "null"
354
+ : initializer == "[]"
355
+ ? "[]"
356
+ : undefined;
357
+ const fieldOptions = tsCodeRecordToString({
358
+ nullable: prop.nullable ? "true" : undefined,
359
+ defaultValue: defaultValue,
360
+ });
361
+ decorators.push(`@IsArray()`);
362
+ if (type == "string[]") {
363
+ decorators.push(`@Field(() => [String], ${fieldOptions})`);
364
+ decorators.push("@IsString({ each: true })");
355
365
  }
356
- type = tsType.getText(tsProp);
357
- if (tsType.isArray()) {
358
- const initializer = (_k = tsProp.getInitializer()) === null || _k === void 0 ? void 0 : _k.getText();
359
- const defaultValue = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined)
360
- ? "null"
361
- : initializer == "[]"
362
- ? "[]"
363
- : undefined;
364
- const fieldOptions = tsCodeRecordToString({
365
- nullable: prop.nullable ? "true" : undefined,
366
- defaultValue: defaultValue,
367
- });
368
- decorators.push(`@IsArray()`);
369
- if (type == "string[]") {
370
- decorators.push(`@Field(() => [String], ${fieldOptions})`);
371
- decorators.push("@IsString({ each: true })");
372
- }
373
- else if (type == "number[]") {
374
- decorators.push(`@Field(() => [Number], ${fieldOptions})`);
375
- decorators.push("@IsNumber({ each: true })");
376
- }
377
- else if (type == "boolean[]") {
378
- decorators.push(`@Field(() => [Boolean], ${fieldOptions})`);
379
- decorators.push("@IsBoolean({ each: true })");
380
- }
381
- else if (tsType.getArrayElementTypeOrThrow().isClass()) {
382
- const nestedClassName = tsType.getArrayElementTypeOrThrow().getText(tsProp);
383
- const importPath = (0, ts_morph_helper_1.findInputClassImportPath)(nestedClassName, `${targetDirectory}/dto`, metadata);
384
- imports.push({ name: nestedClassName, importPath });
385
- decorators.push(`@ValidateNested()`);
386
- decorators.push(`@Type(() => ${nestedClassName})`);
387
- decorators.push(`@Field(() => [${nestedClassName}], ${fieldOptions})`);
388
- }
389
- else {
390
- const typeNode = tsProp.getTypeNodeOrThrow().asKindOrThrow(ts_morph_1.SyntaxKind.ArrayType);
391
- const elementTypeNode = typeNode.getElementTypeNode();
392
- if (elementTypeNode.isKind(ts_morph_1.SyntaxKind.TypeReference)) {
393
- // if the element type is a type reference, we need to find the import path
394
- const { importPath } = (0, ts_morph_helper_1.findImportPath)(elementTypeNode.getText(), `${targetDirectory}/dto`, metadata);
395
- if (importPath) {
396
- imports.push({ name: elementTypeNode.getText(), importPath });
397
- }
398
- }
399
- decorators.push(`@Field(() => [GraphQLJSONObject], ${fieldOptions}) // Warning: this input is not validated properly`);
400
- }
366
+ else if (type == "number[]") {
367
+ decorators.push(`@Field(() => [Number], ${fieldOptions})`);
368
+ decorators.push("@IsNumber({ each: true })");
369
+ }
370
+ else if (type == "boolean[]") {
371
+ decorators.push(`@Field(() => [Boolean], ${fieldOptions})`);
372
+ decorators.push("@IsBoolean({ each: true })");
401
373
  }
402
- else if (tsType.isClass()) {
403
- const nestedClassName = tsType.getText(tsProp);
374
+ else if (tsType.getArrayElementTypeOrThrow().isClass()) {
375
+ const nestedClassName = tsType.getArrayElementTypeOrThrow().getText(tsProp);
404
376
  const importPath = (0, ts_morph_helper_1.findInputClassImportPath)(nestedClassName, `${targetDirectory}/dto`, metadata);
405
377
  imports.push({ name: nestedClassName, importPath });
406
378
  decorators.push(`@ValidateNested()`);
407
379
  decorators.push(`@Type(() => ${nestedClassName})`);
408
- decorators.push(`@Field(() => ${nestedClassName}${prop.nullable ? ", { nullable: true }" : ""})`);
380
+ decorators.push(`@Field(() => [${nestedClassName}], ${fieldOptions})`);
409
381
  }
410
382
  else {
411
- const typeNode = tsProp.getTypeNodeOrThrow();
412
- if (typeNode.isKind(ts_morph_1.SyntaxKind.TypeReference)) {
383
+ const typeNode = tsProp.getTypeNodeOrThrow().asKindOrThrow(ts_morph_1.SyntaxKind.ArrayType);
384
+ const elementTypeNode = typeNode.getElementTypeNode();
385
+ if (elementTypeNode.isKind(ts_morph_1.SyntaxKind.TypeReference)) {
413
386
  // if the element type is a type reference, we need to find the import path
414
- const { importPath } = (0, ts_morph_helper_1.findImportPath)(typeNode.getText(), `${targetDirectory}/dto`, metadata);
387
+ const { importPath } = (0, ts_morph_helper_1.findImportPath)(elementTypeNode.getText(), `${targetDirectory}/dto`, metadata);
415
388
  if (importPath) {
416
- imports.push({ name: typeNode.getText(), importPath });
389
+ imports.push({ name: elementTypeNode.getText(), importPath });
417
390
  }
418
391
  }
419
- decorators.push(`@Field(() => GraphQLJSONObject${prop.nullable ? ", { nullable: true }" : ""}) // Warning: this input is not validated properly`);
392
+ decorators.push(`@Field(() => [GraphQLJSONObject], ${fieldOptions}) // Warning: this input is not validated properly`);
420
393
  }
421
394
  }
422
- else if (prop.type == "uuid") {
423
- const initializer = (_l = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()) === null || _l === void 0 ? void 0 : _l.getText();
424
- const defaultValueNull = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined);
425
- const fieldOptions = tsCodeRecordToString({
426
- nullable: prop.nullable ? "true" : undefined,
427
- defaultValue: defaultValueNull ? "null" : undefined,
428
- });
429
- decorators.push(`@Field(() => ID, ${fieldOptions})`);
430
- decorators.push("@IsUUID()");
431
- type = "string";
432
- }
433
- else if ((0, ts_morph_helper_1.getFieldDecoratorClassName)(prop.name, metadata)) {
434
- //for custom mikro-orm type
435
- const className = (0, ts_morph_helper_1.getFieldDecoratorClassName)(prop.name, metadata);
436
- const importPath = (0, ts_morph_helper_1.findInputClassImportPath)(className, `${targetDirectory}/dto`, metadata);
437
- imports.push({ name: className, importPath });
395
+ else if (tsType.isClass()) {
396
+ const nestedClassName = tsType.getText(tsProp);
397
+ const importPath = (0, ts_morph_helper_1.findInputClassImportPath)(nestedClassName, `${targetDirectory}/dto`, metadata);
398
+ imports.push({ name: nestedClassName, importPath });
438
399
  decorators.push(`@ValidateNested()`);
439
- decorators.push(`@Type(() => ${className})`);
440
- decorators.push(`@Field(() => ${className}${prop.nullable ? ", { nullable: true }" : ""})`);
441
- type = className;
400
+ decorators.push(`@Type(() => ${nestedClassName})`);
401
+ decorators.push(`@Field(() => ${nestedClassName}${prop.nullable ? ", { nullable: true }" : ""})`);
442
402
  }
443
403
  else {
444
- console.warn(`${prop.name}: unsupported type ${type}`);
404
+ const typeNode = tsProp.getTypeNodeOrThrow();
405
+ if (typeNode.isKind(ts_morph_1.SyntaxKind.TypeReference)) {
406
+ // if the element type is a type reference, we need to find the import path
407
+ const { importPath } = (0, ts_morph_helper_1.findImportPath)(typeNode.getText(), `${targetDirectory}/dto`, metadata);
408
+ if (importPath) {
409
+ imports.push({ name: typeNode.getText(), importPath });
410
+ }
411
+ }
412
+ decorators.push(`@Field(() => GraphQLJSONObject${prop.nullable ? ", { nullable: true }" : ""}) // Warning: this input is not validated properly`);
413
+ }
414
+ }
415
+ else if (prop.type == "uuid") {
416
+ const initializer = (0, ts_morph_helper_1.morphTsProperty)(prop.name, metadata).getInitializer()?.getText();
417
+ const defaultValueNull = prop.nullable && (initializer == "undefined" || initializer == "null" || initializer === undefined);
418
+ const fieldOptions = tsCodeRecordToString({
419
+ nullable: prop.nullable ? "true" : undefined,
420
+ defaultValue: defaultValueNull ? "null" : undefined,
421
+ });
422
+ decorators.push(`@Field(() => ID, ${fieldOptions})`);
423
+ decorators.push("@IsUUID()");
424
+ type = "string";
425
+ }
426
+ else if ((0, ts_morph_helper_1.getFieldDecoratorClassName)(prop.name, metadata)) {
427
+ //for custom mikro-orm type
428
+ const className = (0, ts_morph_helper_1.getFieldDecoratorClassName)(prop.name, metadata);
429
+ const importPath = (0, ts_morph_helper_1.findInputClassImportPath)(className, `${targetDirectory}/dto`, metadata);
430
+ imports.push({ name: className, importPath });
431
+ decorators.push(`@ValidateNested()`);
432
+ decorators.push(`@Type(() => ${className})`);
433
+ decorators.push(`@Field(() => ${className}${prop.nullable ? ", { nullable: true }" : ""})`);
434
+ type = className;
435
+ }
436
+ else {
437
+ console.warn(`${prop.name}: unsupported type ${type}`);
438
+ continue;
439
+ }
440
+ const classValidatorValidators = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(metadata.class, prop.name, false, false, undefined);
441
+ for (const validator of classValidatorValidators) {
442
+ if (validator.propertyName !== prop.name) {
445
443
  continue;
446
444
  }
447
- const classValidatorValidators = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(metadata.class, prop.name, false, false, undefined);
448
- for (const validator of classValidatorValidators) {
449
- if (validator.propertyName !== prop.name)
450
- continue;
451
- const constraints = (0, class_validator_1.getMetadataStorage)().getTargetValidatorConstraints(validator.constraintCls);
452
- for (const constraint of constraints) {
453
- const decorator = definedDecorators.find((decorator) => {
454
- return (
455
- // ignore casing since class validator is inconsistent with casing
456
- decorator.getName().toUpperCase() === constraint.name.toUpperCase() ||
457
- // some class validator decorators have a prefix "Is" but not in the constraint name
458
- `Is${decorator.getName()}`.toUpperCase() === constraint.name.toUpperCase());
459
- });
460
- if (decorator) {
461
- const importPath = (0, ts_morph_helper_1.findValidatorImportPath)(decorator.getName(), targetDirectory, metadata);
462
- if (importPath) {
463
- imports.push({ name: decorator.getName(), importPath });
464
- if (!decorators.includes(decorator.getText())) {
465
- decorators.unshift(decorator.getText());
466
- }
445
+ const constraints = (0, class_validator_1.getMetadataStorage)().getTargetValidatorConstraints(validator.constraintCls);
446
+ for (const constraint of constraints) {
447
+ const decorator = definedDecorators.find((decorator) => {
448
+ return (
449
+ // ignore casing since class validator is inconsistent with casing
450
+ decorator.getName().toUpperCase() === constraint.name.toUpperCase() ||
451
+ // some class validator decorators have a prefix "Is" but not in the constraint name
452
+ `Is${decorator.getName()}`.toUpperCase() === constraint.name.toUpperCase());
453
+ });
454
+ if (decorator) {
455
+ const importPath = (0, ts_morph_helper_1.findValidatorImportPath)(decorator.getName(), targetDirectory, metadata);
456
+ if (importPath) {
457
+ imports.push({ name: decorator.getName(), importPath });
458
+ if (!decorators.includes(decorator.getText())) {
459
+ decorators.unshift(decorator.getText());
467
460
  }
468
461
  }
469
- else {
470
- console.warn(`Decorator import for constraint ${constraint.name} not found`);
471
- }
462
+ }
463
+ else {
464
+ console.warn(`Decorator import for constraint ${constraint.name} not found`);
472
465
  }
473
466
  }
474
- fieldsOut += `${decorators.join("\n")}
467
+ }
468
+ fieldsOut += `${decorators.join("\n")}
475
469
  ${fieldName}${isOptional ? "?" : ""}: ${type};
476
470
 
477
471
  `;
478
- }
479
- const className = (_m = options.className) !== null && _m !== void 0 ? _m : `${metadata.className}Input`;
480
- const inputOut = `import { Field, InputType, ID, Int } from "@nestjs/graphql";
472
+ }
473
+ const className = options.className ?? `${metadata.className}Input`;
474
+ const inputOut = `import { Field, InputType, ID, Int } from "@nestjs/graphql";
481
475
  import { Transform, Type } from "class-transformer";
482
476
  import { GraphQLJSONObject, GraphQLLocalDate } from "graphql-scalars";
483
477
  ${(0, generate_imports_code_1.generateImportsCode)(imports)}
@@ -488,19 +482,18 @@ export class ${className} {
488
482
  }
489
483
 
490
484
  ${options.generateUpdateInput && !options.nested
491
- ? `
485
+ ? `
492
486
  @InputType()
493
487
  export class ${className.replace(/Input$/, "")}UpdateInput extends PartialType(${className}) {}
494
488
  `
495
- : ""}
489
+ : ""}
496
490
  `;
497
- const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
498
- const fileName = (_o = options.fileName) !== null && _o !== void 0 ? _o : `dto/${fileNameSingular}.input.ts`;
499
- generatedFiles.push({
500
- name: fileName,
501
- content: inputOut,
502
- type: "input",
503
- });
504
- return generatedFiles;
491
+ const { fileNameSingular } = (0, build_name_variants_1.buildNameVariants)(metadata);
492
+ const fileName = options.fileName ?? `dto/${fileNameSingular}.input.ts`;
493
+ generatedFiles.push({
494
+ name: fileName,
495
+ content: inputOut,
496
+ type: "input",
505
497
  });
498
+ return generatedFiles;
506
499
  }