@k0lyan/nestjs-prisma-graphql-generator 0.2.0 → 0.2.1
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/dist/generator/generate-grouped-fast.d.ts +9 -0
- package/dist/generator/generate-grouped-fast.d.ts.map +1 -0
- package/dist/generator/generate-grouped-fast.js +689 -0
- package/dist/generator/generate-grouped-fast.js.map +1 -0
- package/dist/generator/generate.js +3 -3
- package/dist/generator/generate.js.map +1 -1
- package/package.json +1 -1
- package/dist/generator/generate-grouped.d.ts +0 -20
- package/dist/generator/generate-grouped.d.ts.map +0 -1
- package/dist/generator/generate-grouped.js +0 -862
- package/dist/generator/generate-grouped.js.map +0 -1
|
@@ -1,862 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateCodeGrouped = generateCodeGrouped;
|
|
7
|
-
const ts_morph_1 = require("ts-morph");
|
|
8
|
-
const types_1 = require("./dmmf/types");
|
|
9
|
-
const transformer_1 = require("./dmmf/transformer");
|
|
10
|
-
const pluralize_1 = __importDefault(require("pluralize"));
|
|
11
|
-
/**
|
|
12
|
-
* Generate code with files grouped by model
|
|
13
|
-
*
|
|
14
|
-
* Output structure:
|
|
15
|
-
* - enums/ (shared enums)
|
|
16
|
-
* - common/ (AffectedRows, etc.)
|
|
17
|
-
* - {ModelName}/ (per-model folder)
|
|
18
|
-
* - model.ts (ObjectType)
|
|
19
|
-
* - inputs.ts (all inputs for this model)
|
|
20
|
-
* - args.ts (all args for this model)
|
|
21
|
-
* - resolver.ts (resolver)
|
|
22
|
-
* - index.ts (re-exports)
|
|
23
|
-
* - helpers.ts
|
|
24
|
-
* - index.ts
|
|
25
|
-
*/
|
|
26
|
-
async function generateCodeGrouped(dmmf, config) {
|
|
27
|
-
const project = new ts_morph_1.Project({
|
|
28
|
-
useInMemoryFileSystem: true,
|
|
29
|
-
compilerOptions: {
|
|
30
|
-
declaration: true,
|
|
31
|
-
strict: true,
|
|
32
|
-
experimentalDecorators: true,
|
|
33
|
-
emitDecoratorMetadata: true,
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
const allFiles = new Map();
|
|
37
|
-
// Generate shared enums
|
|
38
|
-
const enumFiles = generateEnumsGrouped(project, dmmf);
|
|
39
|
-
for (const [path, file] of enumFiles) {
|
|
40
|
-
allFiles.set(path, file);
|
|
41
|
-
}
|
|
42
|
-
// Generate common types
|
|
43
|
-
const commonFiles = generateCommonTypesGrouped(project);
|
|
44
|
-
for (const [path, file] of commonFiles) {
|
|
45
|
-
allFiles.set(path, file);
|
|
46
|
-
}
|
|
47
|
-
// Generate helpers
|
|
48
|
-
const helpersFile = generateHelpersGrouped(project, config);
|
|
49
|
-
allFiles.set('helpers.ts', helpersFile);
|
|
50
|
-
// Generate per-model files
|
|
51
|
-
for (const model of dmmf.models) {
|
|
52
|
-
const modelFiles = generateModelGrouped(project, model, dmmf, config);
|
|
53
|
-
for (const [path, file] of modelFiles) {
|
|
54
|
-
allFiles.set(path, file);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Generate root index
|
|
58
|
-
const indexFile = project.createSourceFile('index.ts', '', { overwrite: true });
|
|
59
|
-
generateRootIndexGrouped(indexFile, dmmf, config);
|
|
60
|
-
allFiles.set('index.ts', indexFile);
|
|
61
|
-
// Convert to GeneratedFile array
|
|
62
|
-
const result = [];
|
|
63
|
-
for (const [path, sourceFile] of allFiles) {
|
|
64
|
-
result.push({
|
|
65
|
-
path,
|
|
66
|
-
content: sourceFile.getFullText(),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Generate all files for a single model
|
|
73
|
-
*/
|
|
74
|
-
function generateModelGrouped(project, model, dmmf, config) {
|
|
75
|
-
const files = new Map();
|
|
76
|
-
const modelDir = model.name;
|
|
77
|
-
// Get available input types for this model
|
|
78
|
-
const inputTypeNames = new Set(dmmf.inputTypes.keys());
|
|
79
|
-
const available = {
|
|
80
|
-
hasWhereInput: inputTypeNames.has(`${model.name}WhereInput`),
|
|
81
|
-
hasWhereUniqueInput: inputTypeNames.has(`${model.name}WhereUniqueInput`),
|
|
82
|
-
hasOrderByInput: inputTypeNames.has(`${model.name}OrderByWithRelationInput`),
|
|
83
|
-
hasCreateInput: inputTypeNames.has(`${model.name}CreateInput`),
|
|
84
|
-
hasCreateManyInput: inputTypeNames.has(`${model.name}CreateManyInput`),
|
|
85
|
-
hasUpdateInput: inputTypeNames.has(`${model.name}UpdateInput`),
|
|
86
|
-
hasUpdateManyInput: inputTypeNames.has(`${model.name}UpdateManyMutationInput`),
|
|
87
|
-
hasScalarWhereWithAggregates: inputTypeNames.has(`${model.name}ScalarWhereWithAggregatesInput`),
|
|
88
|
-
};
|
|
89
|
-
// Skip models with no query capability
|
|
90
|
-
if (!available.hasWhereInput && !available.hasWhereUniqueInput) {
|
|
91
|
-
return files;
|
|
92
|
-
}
|
|
93
|
-
// Generate model.ts (ObjectType)
|
|
94
|
-
const modelFile = project.createSourceFile(`${modelDir}/model.ts`, '', { overwrite: true });
|
|
95
|
-
generateModelObjectType(modelFile, model, dmmf, config);
|
|
96
|
-
files.set(`${modelDir}/model.ts`, modelFile);
|
|
97
|
-
// Generate inputs.ts (all inputs for this model)
|
|
98
|
-
const modelInputTypes = getInputTypesForModel(model.name, dmmf);
|
|
99
|
-
if (modelInputTypes.length > 0) {
|
|
100
|
-
const inputsFile = project.createSourceFile(`${modelDir}/inputs.ts`, '', { overwrite: true });
|
|
101
|
-
generateModelInputs(inputsFile, model, modelInputTypes, dmmf, config);
|
|
102
|
-
files.set(`${modelDir}/inputs.ts`, inputsFile);
|
|
103
|
-
}
|
|
104
|
-
// Generate args.ts (all args for this model)
|
|
105
|
-
const argsFile = project.createSourceFile(`${modelDir}/args.ts`, '', { overwrite: true });
|
|
106
|
-
generateModelArgs(argsFile, model, dmmf, config, available);
|
|
107
|
-
files.set(`${modelDir}/args.ts`, argsFile);
|
|
108
|
-
// Generate resolver.ts
|
|
109
|
-
if (config.generateResolvers) {
|
|
110
|
-
const resolverFile = project.createSourceFile(`${modelDir}/resolver.ts`, '', { overwrite: true });
|
|
111
|
-
generateModelResolver(resolverFile, model, dmmf, config, available);
|
|
112
|
-
files.set(`${modelDir}/resolver.ts`, resolverFile);
|
|
113
|
-
}
|
|
114
|
-
// Generate index.ts for the model folder
|
|
115
|
-
const indexFile = project.createSourceFile(`${modelDir}/index.ts`, '', { overwrite: true });
|
|
116
|
-
generateModelIndex(indexFile, model, config, modelInputTypes.length > 0);
|
|
117
|
-
files.set(`${modelDir}/index.ts`, indexFile);
|
|
118
|
-
return files;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Get all input types that belong to a specific model
|
|
122
|
-
*/
|
|
123
|
-
function getInputTypesForModel(modelName, dmmf) {
|
|
124
|
-
const result = [];
|
|
125
|
-
for (const [name, inputType] of dmmf.inputTypes) {
|
|
126
|
-
if (name.startsWith(modelName)) {
|
|
127
|
-
result.push(inputType);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Generate the ObjectType class for a model
|
|
134
|
-
*/
|
|
135
|
-
function generateModelObjectType(sourceFile, model, dmmf, config) {
|
|
136
|
-
const nestjsImports = ['ObjectType', 'Field', 'ID', 'Int', 'Float'];
|
|
137
|
-
const hasJson = model.fields.some(f => f.type === 'Json');
|
|
138
|
-
const hasBigInt = model.fields.some(f => f.type === 'BigInt');
|
|
139
|
-
const relationFields = model.fields.filter(f => (0, transformer_1.isRelationField)(f));
|
|
140
|
-
const relatedModels = [...new Set(relationFields.map(f => f.type))].filter(m => m !== model.name);
|
|
141
|
-
// Add imports
|
|
142
|
-
sourceFile.addImportDeclaration({
|
|
143
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
144
|
-
namedImports: nestjsImports,
|
|
145
|
-
});
|
|
146
|
-
if (hasJson) {
|
|
147
|
-
sourceFile.addImportDeclaration({
|
|
148
|
-
moduleSpecifier: 'graphql-type-json',
|
|
149
|
-
namedImports: ['GraphQLJSON'],
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
if (hasBigInt) {
|
|
153
|
-
sourceFile.addImportDeclaration({
|
|
154
|
-
moduleSpecifier: 'graphql-scalars',
|
|
155
|
-
namedImports: ['GraphQLBigInt'],
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
// Import related models
|
|
159
|
-
if (relatedModels.length > 0) {
|
|
160
|
-
sourceFile.addStatements(`// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { ${relatedModels.join(', ')} } from '../index';`);
|
|
161
|
-
}
|
|
162
|
-
// Import enums
|
|
163
|
-
const enumFields = model.fields.filter(f => (0, transformer_1.isEnumField)(f));
|
|
164
|
-
const enumTypes = [...new Set(enumFields.map(f => f.type))];
|
|
165
|
-
if (enumTypes.length > 0) {
|
|
166
|
-
sourceFile.addImportDeclaration({
|
|
167
|
-
moduleSpecifier: '../enums',
|
|
168
|
-
namedImports: enumTypes,
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
// Create the class
|
|
172
|
-
const classDecl = sourceFile.addClass({
|
|
173
|
-
name: `${config.typePrefix ?? ''}${model.name}${config.typeSuffix ?? ''}`,
|
|
174
|
-
isExported: true,
|
|
175
|
-
decorators: [
|
|
176
|
-
{
|
|
177
|
-
name: 'ObjectType',
|
|
178
|
-
arguments: [
|
|
179
|
-
ts_morph_1.Writers.object({
|
|
180
|
-
description: model.documentation
|
|
181
|
-
? `'${escapeDescription(model.documentation)}'`
|
|
182
|
-
: undefined,
|
|
183
|
-
}),
|
|
184
|
-
],
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
});
|
|
188
|
-
// Add fields
|
|
189
|
-
for (const field of model.fields) {
|
|
190
|
-
addFieldToModelClass(classDecl, field, dmmf);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Add a field to the model class
|
|
195
|
-
*/
|
|
196
|
-
function addFieldToModelClass(classDecl, field, _dmmf) {
|
|
197
|
-
const { graphqlType, tsType } = getFieldTypes(field);
|
|
198
|
-
const isRelation = (0, transformer_1.isRelationField)(field);
|
|
199
|
-
const fieldDecoratorArgs = [];
|
|
200
|
-
if (isRelation) {
|
|
201
|
-
if (field.isList) {
|
|
202
|
-
fieldDecoratorArgs.push(`() => [require('../${field.type}/model').${field.type}]`);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
fieldDecoratorArgs.push(`() => require('../${field.type}/model').${field.type}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
if (field.isList) {
|
|
210
|
-
fieldDecoratorArgs.push(`() => [${graphqlType}]`);
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
fieldDecoratorArgs.push(`() => ${graphqlType}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const options = {};
|
|
217
|
-
if (!field.isRequired && !field.isList) {
|
|
218
|
-
options['nullable'] = 'true';
|
|
219
|
-
}
|
|
220
|
-
if (field.documentation) {
|
|
221
|
-
options['description'] = `'${escapeDescription(field.documentation)}'`;
|
|
222
|
-
}
|
|
223
|
-
if (Object.keys(options).length > 0) {
|
|
224
|
-
const optionsStr = Object.entries(options)
|
|
225
|
-
.map(([k, v]) => `${k}: ${v}`)
|
|
226
|
-
.join(', ');
|
|
227
|
-
fieldDecoratorArgs.push(`{ ${optionsStr} }`);
|
|
228
|
-
}
|
|
229
|
-
let propertyType = tsType;
|
|
230
|
-
if (field.isList) {
|
|
231
|
-
propertyType = `${tsType}[]`;
|
|
232
|
-
}
|
|
233
|
-
if (!field.isRequired) {
|
|
234
|
-
propertyType = `${propertyType} | null`;
|
|
235
|
-
}
|
|
236
|
-
classDecl.addProperty({
|
|
237
|
-
name: field.name,
|
|
238
|
-
type: propertyType,
|
|
239
|
-
hasExclamationToken: field.isRequired || field.isList,
|
|
240
|
-
hasQuestionToken: !field.isRequired && !field.isList,
|
|
241
|
-
decorators: [{ name: 'Field', arguments: fieldDecoratorArgs }],
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Get GraphQL and TypeScript types for a field
|
|
246
|
-
*/
|
|
247
|
-
function getFieldTypes(field) {
|
|
248
|
-
if (field.isId) {
|
|
249
|
-
return { graphqlType: 'ID', tsType: 'string' };
|
|
250
|
-
}
|
|
251
|
-
if ((0, transformer_1.isScalarField)(field)) {
|
|
252
|
-
const graphqlType = types_1.PRISMA_TO_GRAPHQL_SCALAR[field.type] ?? 'String';
|
|
253
|
-
const tsType = types_1.PRISMA_TO_TS_TYPE[field.type] ?? 'string';
|
|
254
|
-
if (field.type === 'Json') {
|
|
255
|
-
return { graphqlType: 'GraphQLJSON', tsType: 'any' };
|
|
256
|
-
}
|
|
257
|
-
return { graphqlType, tsType };
|
|
258
|
-
}
|
|
259
|
-
if ((0, transformer_1.isEnumField)(field)) {
|
|
260
|
-
return { graphqlType: field.type, tsType: field.type };
|
|
261
|
-
}
|
|
262
|
-
if ((0, transformer_1.isRelationField)(field)) {
|
|
263
|
-
return { graphqlType: field.type, tsType: field.type };
|
|
264
|
-
}
|
|
265
|
-
return { graphqlType: 'String', tsType: 'string' };
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Generate all inputs for a model in one file
|
|
269
|
-
*/
|
|
270
|
-
function generateModelInputs(sourceFile, model, inputTypes, dmmf, _config) {
|
|
271
|
-
// Collect all needed imports
|
|
272
|
-
const hasJson = inputTypes.some(it => it.fields.some(f => f.type === 'Json'));
|
|
273
|
-
const hasBigInt = inputTypes.some(it => it.fields.some(f => f.type === 'BigInt'));
|
|
274
|
-
// Add base imports
|
|
275
|
-
sourceFile.addImportDeclaration({
|
|
276
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
277
|
-
namedImports: ['InputType', 'Field', 'Int', 'Float'],
|
|
278
|
-
});
|
|
279
|
-
if (hasJson) {
|
|
280
|
-
sourceFile.addImportDeclaration({
|
|
281
|
-
moduleSpecifier: 'graphql-type-json',
|
|
282
|
-
namedImports: ['GraphQLJSON'],
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
if (hasBigInt) {
|
|
286
|
-
sourceFile.addImportDeclaration({
|
|
287
|
-
moduleSpecifier: 'graphql-scalars',
|
|
288
|
-
namedImports: ['GraphQLBigInt'],
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
// Collect enum imports
|
|
292
|
-
const enumTypes = new Set();
|
|
293
|
-
for (const inputType of inputTypes) {
|
|
294
|
-
for (const field of inputType.fields) {
|
|
295
|
-
if (dmmf.isEnum(field.type)) {
|
|
296
|
-
enumTypes.add(field.type);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
if (enumTypes.size > 0) {
|
|
301
|
-
sourceFile.addImportDeclaration({
|
|
302
|
-
moduleSpecifier: '../enums',
|
|
303
|
-
namedImports: [...enumTypes],
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
// Generate each input class
|
|
307
|
-
for (const inputType of inputTypes) {
|
|
308
|
-
generateInputClass(sourceFile, inputType, dmmf, model.name);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Generate a single input class
|
|
313
|
-
*/
|
|
314
|
-
function generateInputClass(sourceFile, inputType, dmmf, modelName) {
|
|
315
|
-
const classDecl = sourceFile.addClass({
|
|
316
|
-
name: inputType.name,
|
|
317
|
-
isExported: true,
|
|
318
|
-
decorators: [{ name: 'InputType', arguments: [] }],
|
|
319
|
-
});
|
|
320
|
-
for (const field of inputType.fields) {
|
|
321
|
-
addFieldToInputClass(classDecl, field, dmmf, inputType.name, modelName);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Add a field to an input class
|
|
326
|
-
*/
|
|
327
|
-
function addFieldToInputClass(classDecl, field, dmmf, currentTypeName, modelName) {
|
|
328
|
-
const { graphqlType, tsType, isInputObjectType } = getInputFieldTypes(field, dmmf);
|
|
329
|
-
const fieldDecoratorArgs = [];
|
|
330
|
-
// For input object types within the same model, use class reference; others use lazy require
|
|
331
|
-
if (isInputObjectType && graphqlType !== currentTypeName) {
|
|
332
|
-
if (graphqlType.startsWith(modelName)) {
|
|
333
|
-
// Same model's input, just reference the class
|
|
334
|
-
if (field.isList) {
|
|
335
|
-
fieldDecoratorArgs.push(`() => [${graphqlType}]`);
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
fieldDecoratorArgs.push(`() => ${graphqlType}`);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
// Different model's input, use lazy require
|
|
343
|
-
const otherModel = graphqlType.replace(/(?:Where|Create|Update|OrderBy|Scalar).*Input$/, '');
|
|
344
|
-
if (field.isList) {
|
|
345
|
-
fieldDecoratorArgs.push(`() => [require('../${otherModel}/inputs').${graphqlType}]`);
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
fieldDecoratorArgs.push(`() => require('../${otherModel}/inputs').${graphqlType}`);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
if (field.isList) {
|
|
354
|
-
fieldDecoratorArgs.push(`() => [${graphqlType}]`);
|
|
355
|
-
}
|
|
356
|
-
else {
|
|
357
|
-
fieldDecoratorArgs.push(`() => ${graphqlType}`);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
if (!field.isRequired) {
|
|
361
|
-
fieldDecoratorArgs.push('{ nullable: true }');
|
|
362
|
-
}
|
|
363
|
-
let propertyType = tsType;
|
|
364
|
-
if (field.isList) {
|
|
365
|
-
propertyType = `${tsType}[]`;
|
|
366
|
-
}
|
|
367
|
-
if (!field.isRequired) {
|
|
368
|
-
propertyType = `${propertyType} | undefined`;
|
|
369
|
-
}
|
|
370
|
-
classDecl.addProperty({
|
|
371
|
-
name: field.name,
|
|
372
|
-
type: propertyType,
|
|
373
|
-
hasQuestionToken: !field.isRequired,
|
|
374
|
-
decorators: [{ name: 'Field', arguments: fieldDecoratorArgs }],
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Get types for an input field
|
|
379
|
-
*/
|
|
380
|
-
function getInputFieldTypes(field, dmmf) {
|
|
381
|
-
const mainType = field.type;
|
|
382
|
-
if (types_1.PRISMA_TO_GRAPHQL_SCALAR[mainType]) {
|
|
383
|
-
const graphqlType = types_1.PRISMA_TO_GRAPHQL_SCALAR[mainType];
|
|
384
|
-
const tsType = types_1.PRISMA_TO_TS_TYPE[mainType];
|
|
385
|
-
if (mainType === 'Json') {
|
|
386
|
-
return { graphqlType: 'GraphQLJSON', tsType: 'any', isInputObjectType: false };
|
|
387
|
-
}
|
|
388
|
-
return { graphqlType: graphqlType ?? 'String', tsType: tsType ?? 'string', isInputObjectType: false };
|
|
389
|
-
}
|
|
390
|
-
if (dmmf.isEnum(mainType)) {
|
|
391
|
-
return { graphqlType: mainType, tsType: mainType, isInputObjectType: false };
|
|
392
|
-
}
|
|
393
|
-
return { graphqlType: mainType, tsType: 'any', isInputObjectType: true };
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Generate all args for a model in one file
|
|
397
|
-
*/
|
|
398
|
-
function generateModelArgs(sourceFile, model, _dmmf, _config, available) {
|
|
399
|
-
// Add imports
|
|
400
|
-
sourceFile.addImportDeclaration({
|
|
401
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
402
|
-
namedImports: ['ArgsType', 'Field', 'Int'],
|
|
403
|
-
});
|
|
404
|
-
// Import from local inputs.ts
|
|
405
|
-
const inputImports = [];
|
|
406
|
-
if (available.hasWhereInput)
|
|
407
|
-
inputImports.push(`${model.name}WhereInput`);
|
|
408
|
-
if (available.hasWhereUniqueInput)
|
|
409
|
-
inputImports.push(`${model.name}WhereUniqueInput`);
|
|
410
|
-
if (available.hasOrderByInput)
|
|
411
|
-
inputImports.push(`${model.name}OrderByWithRelationInput`);
|
|
412
|
-
if (available.hasCreateInput)
|
|
413
|
-
inputImports.push(`${model.name}CreateInput`);
|
|
414
|
-
if (available.hasCreateManyInput)
|
|
415
|
-
inputImports.push(`${model.name}CreateManyInput`);
|
|
416
|
-
if (available.hasUpdateInput)
|
|
417
|
-
inputImports.push(`${model.name}UpdateInput`);
|
|
418
|
-
if (available.hasUpdateManyInput)
|
|
419
|
-
inputImports.push(`${model.name}UpdateManyMutationInput`);
|
|
420
|
-
if (available.hasScalarWhereWithAggregates)
|
|
421
|
-
inputImports.push(`${model.name}ScalarWhereWithAggregatesInput`);
|
|
422
|
-
if (inputImports.length > 0) {
|
|
423
|
-
sourceFile.addImportDeclaration({
|
|
424
|
-
moduleSpecifier: './inputs',
|
|
425
|
-
namedImports: inputImports,
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
// Import ScalarFieldEnum
|
|
429
|
-
sourceFile.addImportDeclaration({
|
|
430
|
-
moduleSpecifier: '../enums',
|
|
431
|
-
namedImports: [`${model.name}ScalarFieldEnum`],
|
|
432
|
-
});
|
|
433
|
-
// Generate args classes
|
|
434
|
-
if (available.hasWhereInput) {
|
|
435
|
-
generateFindManyArgsClass(sourceFile, model, available);
|
|
436
|
-
generateFindFirstArgsClass(sourceFile, model, available);
|
|
437
|
-
generateDeleteManyArgsClass(sourceFile, model);
|
|
438
|
-
generateAggregateArgsClass(sourceFile, model, available);
|
|
439
|
-
generateGroupByArgsClass(sourceFile, model, available);
|
|
440
|
-
}
|
|
441
|
-
if (available.hasWhereUniqueInput) {
|
|
442
|
-
generateFindUniqueArgsClass(sourceFile, model);
|
|
443
|
-
generateDeleteArgsClass(sourceFile, model);
|
|
444
|
-
}
|
|
445
|
-
if (available.hasCreateInput) {
|
|
446
|
-
generateCreateArgsClass(sourceFile, model);
|
|
447
|
-
}
|
|
448
|
-
if (available.hasCreateManyInput) {
|
|
449
|
-
generateCreateManyArgsClass(sourceFile, model);
|
|
450
|
-
}
|
|
451
|
-
if (available.hasUpdateInput && available.hasWhereUniqueInput) {
|
|
452
|
-
generateUpdateArgsClass(sourceFile, model);
|
|
453
|
-
}
|
|
454
|
-
if (available.hasUpdateManyInput && available.hasWhereInput) {
|
|
455
|
-
generateUpdateManyArgsClass(sourceFile, model);
|
|
456
|
-
}
|
|
457
|
-
if (available.hasCreateInput && available.hasUpdateInput && available.hasWhereUniqueInput) {
|
|
458
|
-
generateUpsertArgsClass(sourceFile, model);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
// Individual args class generators (simplified versions in single file)
|
|
462
|
-
function generateFindManyArgsClass(sourceFile, model, available) {
|
|
463
|
-
const properties = [
|
|
464
|
-
{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] },
|
|
465
|
-
];
|
|
466
|
-
if (available.hasOrderByInput) {
|
|
467
|
-
properties.push({ name: 'orderBy', type: `${model.name}OrderByWithRelationInput[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}OrderByWithRelationInput]`, '{ nullable: true }'] }] });
|
|
468
|
-
}
|
|
469
|
-
if (available.hasWhereUniqueInput) {
|
|
470
|
-
properties.push({ name: 'cursor', type: `${model.name}WhereUniqueInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`, '{ nullable: true }'] }] });
|
|
471
|
-
}
|
|
472
|
-
properties.push({ name: 'take', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'skip', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'distinct', type: `${model.name}ScalarFieldEnum[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}ScalarFieldEnum]`, '{ nullable: true }'] }] });
|
|
473
|
-
sourceFile.addClass({ name: `FindMany${model.name}Args`, isExported: true, decorators: [{ name: 'ArgsType', arguments: [] }], properties });
|
|
474
|
-
}
|
|
475
|
-
function generateFindFirstArgsClass(sourceFile, model, available) {
|
|
476
|
-
const properties = [
|
|
477
|
-
{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] },
|
|
478
|
-
];
|
|
479
|
-
if (available.hasOrderByInput) {
|
|
480
|
-
properties.push({ name: 'orderBy', type: `${model.name}OrderByWithRelationInput[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}OrderByWithRelationInput]`, '{ nullable: true }'] }] });
|
|
481
|
-
}
|
|
482
|
-
if (available.hasWhereUniqueInput) {
|
|
483
|
-
properties.push({ name: 'cursor', type: `${model.name}WhereUniqueInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`, '{ nullable: true }'] }] });
|
|
484
|
-
}
|
|
485
|
-
properties.push({ name: 'take', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'skip', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'distinct', type: `${model.name}ScalarFieldEnum[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}ScalarFieldEnum]`, '{ nullable: true }'] }] });
|
|
486
|
-
sourceFile.addClass({ name: `FindFirst${model.name}Args`, isExported: true, decorators: [{ name: 'ArgsType', arguments: [] }], properties });
|
|
487
|
-
}
|
|
488
|
-
function generateFindUniqueArgsClass(sourceFile, model) {
|
|
489
|
-
sourceFile.addClass({
|
|
490
|
-
name: `FindUnique${model.name}Args`,
|
|
491
|
-
isExported: true,
|
|
492
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
493
|
-
properties: [{ name: 'where', type: `${model.name}WhereUniqueInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`] }] }],
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
function generateCreateArgsClass(sourceFile, model) {
|
|
497
|
-
sourceFile.addClass({
|
|
498
|
-
name: `Create${model.name}Args`,
|
|
499
|
-
isExported: true,
|
|
500
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
501
|
-
properties: [{ name: 'data', type: `${model.name}CreateInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}CreateInput`] }] }],
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
function generateCreateManyArgsClass(sourceFile, model) {
|
|
505
|
-
sourceFile.addClass({
|
|
506
|
-
name: `CreateMany${model.name}Args`,
|
|
507
|
-
isExported: true,
|
|
508
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
509
|
-
properties: [{ name: 'data', type: `${model.name}CreateManyInput[]`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}CreateManyInput]`] }] }],
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
function generateUpdateArgsClass(sourceFile, model) {
|
|
513
|
-
sourceFile.addClass({
|
|
514
|
-
name: `Update${model.name}Args`,
|
|
515
|
-
isExported: true,
|
|
516
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
517
|
-
properties: [
|
|
518
|
-
{ name: 'data', type: `${model.name}UpdateInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}UpdateInput`] }] },
|
|
519
|
-
{ name: 'where', type: `${model.name}WhereUniqueInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`] }] },
|
|
520
|
-
],
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
function generateUpdateManyArgsClass(sourceFile, model) {
|
|
524
|
-
sourceFile.addClass({
|
|
525
|
-
name: `UpdateMany${model.name}Args`,
|
|
526
|
-
isExported: true,
|
|
527
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
528
|
-
properties: [
|
|
529
|
-
{ name: 'data', type: `${model.name}UpdateManyMutationInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}UpdateManyMutationInput`] }] },
|
|
530
|
-
{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] },
|
|
531
|
-
],
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
function generateUpsertArgsClass(sourceFile, model) {
|
|
535
|
-
sourceFile.addClass({
|
|
536
|
-
name: `Upsert${model.name}Args`,
|
|
537
|
-
isExported: true,
|
|
538
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
539
|
-
properties: [
|
|
540
|
-
{ name: 'where', type: `${model.name}WhereUniqueInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`] }] },
|
|
541
|
-
{ name: 'create', type: `${model.name}CreateInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}CreateInput`] }] },
|
|
542
|
-
{ name: 'update', type: `${model.name}UpdateInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}UpdateInput`] }] },
|
|
543
|
-
],
|
|
544
|
-
});
|
|
545
|
-
}
|
|
546
|
-
function generateDeleteArgsClass(sourceFile, model) {
|
|
547
|
-
sourceFile.addClass({
|
|
548
|
-
name: `Delete${model.name}Args`,
|
|
549
|
-
isExported: true,
|
|
550
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
551
|
-
properties: [{ name: 'where', type: `${model.name}WhereUniqueInput`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`] }] }],
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
function generateDeleteManyArgsClass(sourceFile, model) {
|
|
555
|
-
sourceFile.addClass({
|
|
556
|
-
name: `DeleteMany${model.name}Args`,
|
|
557
|
-
isExported: true,
|
|
558
|
-
decorators: [{ name: 'ArgsType', arguments: [] }],
|
|
559
|
-
properties: [{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] }],
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
function generateAggregateArgsClass(sourceFile, model, available) {
|
|
563
|
-
const properties = [
|
|
564
|
-
{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] },
|
|
565
|
-
];
|
|
566
|
-
if (available.hasOrderByInput) {
|
|
567
|
-
properties.push({ name: 'orderBy', type: `${model.name}OrderByWithRelationInput[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}OrderByWithRelationInput]`, '{ nullable: true }'] }] });
|
|
568
|
-
}
|
|
569
|
-
if (available.hasWhereUniqueInput) {
|
|
570
|
-
properties.push({ name: 'cursor', type: `${model.name}WhereUniqueInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereUniqueInput`, '{ nullable: true }'] }] });
|
|
571
|
-
}
|
|
572
|
-
properties.push({ name: 'take', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'skip', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] });
|
|
573
|
-
sourceFile.addClass({ name: `Aggregate${model.name}Args`, isExported: true, decorators: [{ name: 'ArgsType', arguments: [] }], properties });
|
|
574
|
-
}
|
|
575
|
-
function generateGroupByArgsClass(sourceFile, model, available) {
|
|
576
|
-
const properties = [
|
|
577
|
-
{ name: 'where', type: `${model.name}WhereInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}WhereInput`, '{ nullable: true }'] }] },
|
|
578
|
-
];
|
|
579
|
-
if (available.hasOrderByInput) {
|
|
580
|
-
properties.push({ name: 'orderBy', type: `${model.name}OrderByWithRelationInput[]`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}OrderByWithRelationInput]`, '{ nullable: true }'] }] });
|
|
581
|
-
}
|
|
582
|
-
properties.push({ name: 'by', type: `${model.name}ScalarFieldEnum[]`, hasExclamationToken: true, decorators: [{ name: 'Field', arguments: [`() => [${model.name}ScalarFieldEnum]`] }] });
|
|
583
|
-
if (available.hasScalarWhereWithAggregates) {
|
|
584
|
-
properties.push({ name: 'having', type: `${model.name}ScalarWhereWithAggregatesInput`, hasQuestionToken: true, decorators: [{ name: 'Field', arguments: [`() => ${model.name}ScalarWhereWithAggregatesInput`, '{ nullable: true }'] }] });
|
|
585
|
-
}
|
|
586
|
-
properties.push({ name: 'take', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] }, { name: 'skip', type: 'number', hasQuestionToken: true, decorators: [{ name: 'Field', arguments: ['() => Int', '{ nullable: true }'] }] });
|
|
587
|
-
sourceFile.addClass({ name: `GroupBy${model.name}Args`, isExported: true, decorators: [{ name: 'ArgsType', arguments: [] }], properties });
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Generate resolver for a model
|
|
591
|
-
*/
|
|
592
|
-
function generateModelResolver(sourceFile, model, _dmmf, _config, ops) {
|
|
593
|
-
const modelName = model.name;
|
|
594
|
-
const lowerModelName = (0, transformer_1.camelCase)(modelName);
|
|
595
|
-
const pluralName = (0, pluralize_1.default)(lowerModelName);
|
|
596
|
-
const isAlreadyPlural = pluralName === lowerModelName;
|
|
597
|
-
const findManyMethodName = isAlreadyPlural ? `findMany${modelName}` : pluralName;
|
|
598
|
-
const findUniqueMethodName = isAlreadyPlural ? `findUnique${modelName}` : lowerModelName;
|
|
599
|
-
// Build imports
|
|
600
|
-
const nestjsImports = ['Resolver', 'Query', 'Args', 'Info', 'Int'];
|
|
601
|
-
if (ops.hasCreateInput || ops.hasUpdateInput) {
|
|
602
|
-
nestjsImports.push('Mutation');
|
|
603
|
-
}
|
|
604
|
-
sourceFile.addImportDeclaration({
|
|
605
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
606
|
-
namedImports: nestjsImports,
|
|
607
|
-
});
|
|
608
|
-
sourceFile.addImportDeclaration({
|
|
609
|
-
moduleSpecifier: 'graphql',
|
|
610
|
-
namedImports: ['GraphQLResolveInfo'],
|
|
611
|
-
});
|
|
612
|
-
sourceFile.addImportDeclaration({
|
|
613
|
-
moduleSpecifier: './model',
|
|
614
|
-
namedImports: [modelName],
|
|
615
|
-
});
|
|
616
|
-
sourceFile.addImportDeclaration({
|
|
617
|
-
moduleSpecifier: '../common/AffectedRows',
|
|
618
|
-
namedImports: ['AffectedRows'],
|
|
619
|
-
});
|
|
620
|
-
sourceFile.addImportDeclaration({
|
|
621
|
-
moduleSpecifier: '../helpers',
|
|
622
|
-
namedImports: ['transformInfoIntoPrismaArgs', 'getPrismaFromContext'],
|
|
623
|
-
});
|
|
624
|
-
// Import args
|
|
625
|
-
const argsImports = [];
|
|
626
|
-
if (ops.hasWhereInput) {
|
|
627
|
-
argsImports.push(`FindMany${modelName}Args`, `FindFirst${modelName}Args`, `DeleteMany${modelName}Args`);
|
|
628
|
-
}
|
|
629
|
-
if (ops.hasWhereUniqueInput) {
|
|
630
|
-
argsImports.push(`FindUnique${modelName}Args`, `Delete${modelName}Args`);
|
|
631
|
-
}
|
|
632
|
-
if (ops.hasCreateInput)
|
|
633
|
-
argsImports.push(`Create${modelName}Args`);
|
|
634
|
-
if (ops.hasCreateManyInput)
|
|
635
|
-
argsImports.push(`CreateMany${modelName}Args`);
|
|
636
|
-
if (ops.hasUpdateInput && ops.hasWhereUniqueInput)
|
|
637
|
-
argsImports.push(`Update${modelName}Args`);
|
|
638
|
-
if (ops.hasUpdateManyInput && ops.hasWhereInput)
|
|
639
|
-
argsImports.push(`UpdateMany${modelName}Args`);
|
|
640
|
-
if (ops.hasCreateInput && ops.hasUpdateInput && ops.hasWhereUniqueInput)
|
|
641
|
-
argsImports.push(`Upsert${modelName}Args`);
|
|
642
|
-
if (argsImports.length > 0) {
|
|
643
|
-
sourceFile.addImportDeclaration({
|
|
644
|
-
moduleSpecifier: './args',
|
|
645
|
-
namedImports: argsImports,
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
// Create resolver class
|
|
649
|
-
const resolverClass = sourceFile.addClass({
|
|
650
|
-
name: `${modelName}Resolver`,
|
|
651
|
-
isExported: true,
|
|
652
|
-
decorators: [{ name: 'Resolver', arguments: [`() => ${modelName}`] }],
|
|
653
|
-
});
|
|
654
|
-
// Add query methods
|
|
655
|
-
if (ops.hasWhereInput) {
|
|
656
|
-
addResolverMethod(resolverClass, 'Query', findManyMethodName, `FindMany${modelName}Args`, `Promise<${modelName}[]>`, `[${modelName}]`, lowerModelName, 'findMany');
|
|
657
|
-
addResolverMethod(resolverClass, 'Query', `findFirst${modelName}`, `FindFirst${modelName}Args`, `Promise<${modelName} | null>`, modelName, lowerModelName, 'findFirst', true);
|
|
658
|
-
}
|
|
659
|
-
if (ops.hasWhereUniqueInput) {
|
|
660
|
-
addResolverMethod(resolverClass, 'Query', findUniqueMethodName, `FindUnique${modelName}Args`, `Promise<${modelName} | null>`, modelName, lowerModelName, 'findUnique', true);
|
|
661
|
-
}
|
|
662
|
-
// Add mutation methods
|
|
663
|
-
if (ops.hasCreateInput) {
|
|
664
|
-
addResolverMethod(resolverClass, 'Mutation', `createOne${modelName}`, `Create${modelName}Args`, `Promise<${modelName}>`, modelName, lowerModelName, 'create');
|
|
665
|
-
}
|
|
666
|
-
if (ops.hasCreateManyInput) {
|
|
667
|
-
addResolverMethod(resolverClass, 'Mutation', `createMany${modelName}`, `CreateMany${modelName}Args`, 'Promise<AffectedRows>', 'AffectedRows', lowerModelName, 'createMany');
|
|
668
|
-
}
|
|
669
|
-
if (ops.hasUpdateInput && ops.hasWhereUniqueInput) {
|
|
670
|
-
addResolverMethod(resolverClass, 'Mutation', `updateOne${modelName}`, `Update${modelName}Args`, `Promise<${modelName} | null>`, modelName, lowerModelName, 'update', true);
|
|
671
|
-
}
|
|
672
|
-
if (ops.hasUpdateManyInput && ops.hasWhereInput) {
|
|
673
|
-
addResolverMethod(resolverClass, 'Mutation', `updateMany${modelName}`, `UpdateMany${modelName}Args`, 'Promise<AffectedRows>', 'AffectedRows', lowerModelName, 'updateMany');
|
|
674
|
-
}
|
|
675
|
-
if (ops.hasCreateInput && ops.hasUpdateInput && ops.hasWhereUniqueInput) {
|
|
676
|
-
addResolverMethod(resolverClass, 'Mutation', `upsertOne${modelName}`, `Upsert${modelName}Args`, `Promise<${modelName}>`, modelName, lowerModelName, 'upsert');
|
|
677
|
-
}
|
|
678
|
-
if (ops.hasWhereUniqueInput) {
|
|
679
|
-
addResolverMethod(resolverClass, 'Mutation', `deleteOne${modelName}`, `Delete${modelName}Args`, `Promise<${modelName} | null>`, modelName, lowerModelName, 'delete', true);
|
|
680
|
-
}
|
|
681
|
-
if (ops.hasWhereInput) {
|
|
682
|
-
addResolverMethod(resolverClass, 'Mutation', `deleteMany${modelName}`, `DeleteMany${modelName}Args`, 'Promise<AffectedRows>', 'AffectedRows', lowerModelName, 'deleteMany');
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
function addResolverMethod(classDecl, decoratorType, methodName, argsType, returnType, graphqlReturnType, prismaModel, prismaMethod, nullable = false) {
|
|
686
|
-
const returnTypeArg = nullable ? `{ nullable: true }` : '';
|
|
687
|
-
classDecl.addMethod({
|
|
688
|
-
name: methodName,
|
|
689
|
-
isAsync: true,
|
|
690
|
-
decorators: [
|
|
691
|
-
{
|
|
692
|
-
name: decoratorType,
|
|
693
|
-
arguments: returnTypeArg
|
|
694
|
-
? [`() => ${graphqlReturnType}`, returnTypeArg]
|
|
695
|
-
: [`() => ${graphqlReturnType}`],
|
|
696
|
-
},
|
|
697
|
-
],
|
|
698
|
-
parameters: [
|
|
699
|
-
{ name: 'args', type: argsType, decorators: [{ name: 'Args', arguments: [] }] },
|
|
700
|
-
{ name: 'info', type: 'GraphQLResolveInfo', decorators: [{ name: 'Info', arguments: [] }] },
|
|
701
|
-
],
|
|
702
|
-
returnType,
|
|
703
|
-
statements: [
|
|
704
|
-
`const select = transformInfoIntoPrismaArgs(info);`,
|
|
705
|
-
`const prisma = getPrismaFromContext(info);`,
|
|
706
|
-
`return prisma.${prismaModel}.${prismaMethod}({ ...args, ...select });`,
|
|
707
|
-
],
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
/**
|
|
711
|
-
* Generate model folder index
|
|
712
|
-
*/
|
|
713
|
-
function generateModelIndex(sourceFile, _model, config, hasInputs) {
|
|
714
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './model' });
|
|
715
|
-
if (hasInputs) {
|
|
716
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './inputs' });
|
|
717
|
-
}
|
|
718
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './args' });
|
|
719
|
-
if (config.generateResolvers) {
|
|
720
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './resolver' });
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
/**
|
|
724
|
-
* Generate shared enums
|
|
725
|
-
*/
|
|
726
|
-
function generateEnumsGrouped(project, dmmf) {
|
|
727
|
-
const files = new Map();
|
|
728
|
-
for (const enumDef of dmmf.enums) {
|
|
729
|
-
const filePath = `enums/${enumDef.name}.ts`;
|
|
730
|
-
const sourceFile = project.createSourceFile(filePath, '', { overwrite: true });
|
|
731
|
-
sourceFile.addImportDeclaration({
|
|
732
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
733
|
-
namedImports: ['registerEnumType'],
|
|
734
|
-
});
|
|
735
|
-
sourceFile.addEnum({
|
|
736
|
-
name: enumDef.name,
|
|
737
|
-
isExported: true,
|
|
738
|
-
members: enumDef.values.map(v => ({ name: v.name, value: `'${v.name}'` })),
|
|
739
|
-
});
|
|
740
|
-
sourceFile.addStatements(`
|
|
741
|
-
registerEnumType(${enumDef.name}, {
|
|
742
|
-
name: '${enumDef.name}',
|
|
743
|
-
description: ${enumDef.documentation ? `'${escapeDescription(enumDef.documentation)}'` : 'undefined'},
|
|
744
|
-
});
|
|
745
|
-
`);
|
|
746
|
-
files.set(filePath, sourceFile);
|
|
747
|
-
}
|
|
748
|
-
// Generate index
|
|
749
|
-
const indexFile = project.createSourceFile('enums/index.ts', '', { overwrite: true });
|
|
750
|
-
for (const enumDef of dmmf.enums) {
|
|
751
|
-
indexFile.addExportDeclaration({ moduleSpecifier: `./${enumDef.name}` });
|
|
752
|
-
}
|
|
753
|
-
files.set('enums/index.ts', indexFile);
|
|
754
|
-
return files;
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* Generate common types
|
|
758
|
-
*/
|
|
759
|
-
function generateCommonTypesGrouped(project) {
|
|
760
|
-
const files = new Map();
|
|
761
|
-
const affectedRowsFile = project.createSourceFile('common/AffectedRows.ts', '', { overwrite: true });
|
|
762
|
-
affectedRowsFile.addImportDeclaration({
|
|
763
|
-
moduleSpecifier: '@nestjs/graphql',
|
|
764
|
-
namedImports: ['ObjectType', 'Field', 'Int'],
|
|
765
|
-
});
|
|
766
|
-
affectedRowsFile.addClass({
|
|
767
|
-
name: 'AffectedRows',
|
|
768
|
-
isExported: true,
|
|
769
|
-
decorators: [{ name: 'ObjectType', arguments: [] }],
|
|
770
|
-
properties: [
|
|
771
|
-
{
|
|
772
|
-
name: 'count',
|
|
773
|
-
type: 'number',
|
|
774
|
-
hasExclamationToken: true,
|
|
775
|
-
decorators: [{ name: 'Field', arguments: ['() => Int'] }],
|
|
776
|
-
},
|
|
777
|
-
],
|
|
778
|
-
});
|
|
779
|
-
files.set('common/AffectedRows.ts', affectedRowsFile);
|
|
780
|
-
const indexFile = project.createSourceFile('common/index.ts', '', { overwrite: true });
|
|
781
|
-
indexFile.addExportDeclaration({ moduleSpecifier: './AffectedRows' });
|
|
782
|
-
files.set('common/index.ts', indexFile);
|
|
783
|
-
return files;
|
|
784
|
-
}
|
|
785
|
-
/**
|
|
786
|
-
* Generate helpers file
|
|
787
|
-
*/
|
|
788
|
-
function generateHelpersGrouped(project, _config) {
|
|
789
|
-
const sourceFile = project.createSourceFile('helpers.ts', '', { overwrite: true });
|
|
790
|
-
sourceFile.addStatements(`
|
|
791
|
-
import { parseResolveInfo, ResolveTree, FieldsByTypeName } from 'graphql-parse-resolve-info';
|
|
792
|
-
import type { GraphQLResolveInfo } from 'graphql';
|
|
793
|
-
|
|
794
|
-
export function transformInfoIntoPrismaArgs(info: GraphQLResolveInfo): { select?: Record<string, any>; include?: Record<string, any> } {
|
|
795
|
-
const parsedInfo = parseResolveInfo(info) as ResolveTree | null;
|
|
796
|
-
if (!parsedInfo) return {};
|
|
797
|
-
|
|
798
|
-
const select = buildPrismaSelect(parsedInfo.fieldsByTypeName);
|
|
799
|
-
return Object.keys(select).length > 0 ? { select } : {};
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
function buildPrismaSelect(fieldsByTypeName: FieldsByTypeName): Record<string, any> {
|
|
803
|
-
const result: Record<string, any> = {};
|
|
804
|
-
|
|
805
|
-
for (const typeName in fieldsByTypeName) {
|
|
806
|
-
const fields = fieldsByTypeName[typeName];
|
|
807
|
-
for (const fieldName in fields) {
|
|
808
|
-
if (fieldName.startsWith('__') || fieldName.startsWith('_count') || fieldName.startsWith('_avg') || fieldName.startsWith('_sum') || fieldName.startsWith('_min') || fieldName.startsWith('_max')) continue;
|
|
809
|
-
|
|
810
|
-
const field = fields[fieldName];
|
|
811
|
-
const nestedFields = field.fieldsByTypeName;
|
|
812
|
-
|
|
813
|
-
if (Object.keys(nestedFields).length > 0) {
|
|
814
|
-
const nestedSelect = buildPrismaSelect(nestedFields);
|
|
815
|
-
result[fieldName] = Object.keys(nestedSelect).length > 0 ? { select: nestedSelect } : true;
|
|
816
|
-
} else {
|
|
817
|
-
result[fieldName] = true;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
return result;
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
export function getPrismaFromContext(info: GraphQLResolveInfo): any {
|
|
826
|
-
const context = (info.rootValue as any)?.context ?? info.rootValue;
|
|
827
|
-
const prisma = context?.prisma ?? context?.db;
|
|
828
|
-
if (!prisma) throw new Error('Prisma client not found in context. Please provide prisma in your GraphQL context.');
|
|
829
|
-
return prisma;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
export function mergePrismaSelects(...selects: Array<{ select?: Record<string, any>; include?: Record<string, any> }>): { select?: Record<string, any>; include?: Record<string, any> } {
|
|
833
|
-
const result: { select?: Record<string, any>; include?: Record<string, any> } = {};
|
|
834
|
-
for (const s of selects) {
|
|
835
|
-
if (s.select) result.select = { ...(result.select ?? {}), ...s.select };
|
|
836
|
-
if (s.include) result.include = { ...(result.include ?? {}), ...s.include };
|
|
837
|
-
}
|
|
838
|
-
return result;
|
|
839
|
-
}
|
|
840
|
-
`);
|
|
841
|
-
return sourceFile;
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Generate root index
|
|
845
|
-
*/
|
|
846
|
-
function generateRootIndexGrouped(sourceFile, dmmf, _config) {
|
|
847
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './enums' });
|
|
848
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './common' });
|
|
849
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: './helpers' });
|
|
850
|
-
for (const model of dmmf.models) {
|
|
851
|
-
const inputTypeNames = new Set(dmmf.inputTypes.keys());
|
|
852
|
-
const hasWhereInput = inputTypeNames.has(`${model.name}WhereInput`);
|
|
853
|
-
const hasWhereUniqueInput = inputTypeNames.has(`${model.name}WhereUniqueInput`);
|
|
854
|
-
if (hasWhereInput || hasWhereUniqueInput) {
|
|
855
|
-
sourceFile.addExportDeclaration({ moduleSpecifier: `./${model.name}` });
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
function escapeDescription(text) {
|
|
860
|
-
return text.replace(/'/g, "\\'").replace(/\n/g, '\\n');
|
|
861
|
-
}
|
|
862
|
-
//# sourceMappingURL=generate-grouped.js.map
|