@pegasusheavy/nestjs-prisma-graphql 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2608 @@
1
+ import { generatorHandler } from '@prisma/generator-helper';
2
+ import { ok } from 'assert';
3
+ import { memoize, mapKeys, merge, trim, castArray, uniqWith, isEqual, countBy, startCase, camelCase, keyBy, remove, partition, kebabCase, isObject, omit, cloneDeep } from 'lodash-es';
4
+ import { Project, QuoteKind, StructureKind } from 'ts-morph';
5
+ import JSON52 from 'json5';
6
+ import pupa from 'pupa';
7
+ import getRelativePath from 'get-relative-path';
8
+ import outmatch2 from 'outmatch';
9
+ import { existsSync, rmdirSync } from 'fs';
10
+ import filenamify from 'filenamify';
11
+ import { unflatten } from 'flat';
12
+ import pluralize from 'pluralize';
13
+
14
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
15
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
16
+ }) : x)(function(x) {
17
+ if (typeof require !== "undefined") return require.apply(this, arguments);
18
+ throw Error('Dynamic require of "' + x + '" is not supported');
19
+ });
20
+
21
+ // src/helpers/is-many-and-return.ts
22
+ function isManyAndReturnOutputType(name) {
23
+ const lowerName = name.toLowerCase();
24
+ if ((lowerName.startsWith("createmany") || lowerName.startsWith("updatemany")) && (lowerName.endsWith("andreturnoutputtype") || lowerName.endsWith("andreturn"))) {
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ function pascalCase(string) {
30
+ return startCase(camelCase(string)).replaceAll(" ", "");
31
+ }
32
+
33
+ // src/handlers/args-type.ts
34
+ function argsType(field, args) {
35
+ if (["queryRaw", "executeRaw"].includes(field.name)) {
36
+ return;
37
+ }
38
+ if (isManyAndReturnOutputType(field.name)) return;
39
+ const { eventEmitter, typeNames, getModelName: getModelName2 } = args;
40
+ let className = pascalCase(`${field.name}Args`);
41
+ const modelName = getModelName2(className) ?? "";
42
+ switch (className) {
43
+ case `Aggregate${modelName}Args`: {
44
+ className = `${modelName}AggregateArgs`;
45
+ break;
46
+ }
47
+ case `GroupBy${modelName}Args`: {
48
+ className = `${modelName}GroupByArgs`;
49
+ break;
50
+ }
51
+ }
52
+ const inputType2 = {
53
+ constraints: { maxNumFields: null, minNumFields: null },
54
+ name: className,
55
+ fields: [...field.args]
56
+ };
57
+ if (!field.args.some((x) => x.name === "_count") && [`${modelName}AggregateArgs`, `${modelName}GroupByArgs`].includes(className)) {
58
+ const names = ["Count", "Avg", "Sum", "Min", "Max"];
59
+ if (`${modelName}GroupByArgs` === inputType2.name) {
60
+ const byField = inputType2.fields.find((f) => f.name === "by");
61
+ if (byField?.inputTypes) {
62
+ byField.inputTypes = byField.inputTypes.filter((it) => it.isList);
63
+ }
64
+ }
65
+ for (const name of names) {
66
+ if (!typeNames.has(`${modelName}${name}AggregateInput`)) {
67
+ continue;
68
+ }
69
+ inputType2.fields.push({
70
+ name: `_${name.toLowerCase()}`,
71
+ isRequired: false,
72
+ isNullable: true,
73
+ inputTypes: [
74
+ {
75
+ location: "inputObjectTypes",
76
+ type: `${modelName}${name}AggregateInput`,
77
+ isList: false
78
+ }
79
+ ]
80
+ });
81
+ }
82
+ }
83
+ eventEmitter.emitSync("InputType", {
84
+ ...args,
85
+ inputType: inputType2,
86
+ fileType: "args",
87
+ classDecoratorName: "ArgsType"
88
+ });
89
+ }
90
+
91
+ // src/event-names.ts
92
+ var BeforeGenerateField = "BeforeGenerateField";
93
+
94
+ // src/handlers/combine-scalar-filters.ts
95
+ function combineScalarFilters(eventEmitter) {
96
+ eventEmitter.on("BeforeInputType", beforeInputType);
97
+ eventEmitter.on(BeforeGenerateField, beforeGenerateField);
98
+ eventEmitter.on("PostBegin", postBegin);
99
+ }
100
+ function beforeInputType(args) {
101
+ const { inputType: inputType2, removeTypes } = args;
102
+ if (isContainBogus(inputType2.name) && isScalarFilter(inputType2)) {
103
+ removeTypes.add(inputType2.name);
104
+ inputType2.name = replaceBogus(inputType2.name);
105
+ }
106
+ }
107
+ function beforeGenerateField(field) {
108
+ for (const fieldInput of field.inputTypes) {
109
+ if (fieldInput.location !== "inputObjectTypes") {
110
+ continue;
111
+ }
112
+ const fieldInputType = String(fieldInput.type);
113
+ if (isContainBogus(fieldInputType)) {
114
+ fieldInput.type = replaceBogus(fieldInputType);
115
+ }
116
+ }
117
+ }
118
+ function replaceBogus(name) {
119
+ return name.replaceAll(/Nullable|Nested/g, "");
120
+ }
121
+ function isContainBogus(name) {
122
+ return name.startsWith("Nested") || name.includes("Nullable") && name.endsWith("Filter") || name.endsWith("NullableFilter");
123
+ }
124
+ function isScalarFilter(inputType2) {
125
+ if (!inputType2.name.endsWith("Filter")) {
126
+ return false;
127
+ }
128
+ let result = false;
129
+ const equals = inputType2.fields.find((f) => f.name === "equals");
130
+ if (equals) {
131
+ result = equals.inputTypes.every((x) => {
132
+ return ["enumTypes", "scalar"].includes(x.location);
133
+ });
134
+ }
135
+ return result;
136
+ }
137
+ function postBegin(args) {
138
+ const { modelNames, schema } = args;
139
+ const inputTypes = schema.inputObjectTypes.prisma ?? [];
140
+ const enumTypes = schema.enumTypes.model ?? [];
141
+ const types = [
142
+ "Bool",
143
+ "Int",
144
+ "String",
145
+ "DateTime",
146
+ "Decimal",
147
+ "Float",
148
+ "Json",
149
+ "Bytes",
150
+ "BigInt"
151
+ ];
152
+ for (const enumType of enumTypes) {
153
+ const { name } = enumType;
154
+ types.push(`Enum${name}`);
155
+ }
156
+ const inputTypeByName = keyBy(inputTypes, (it) => it.name);
157
+ const replaceBogusFilters = (filterName, filterNameCandidates) => {
158
+ for (const filterNameCandidate of filterNameCandidates) {
159
+ const candidate = inputTypeByName[filterNameCandidate];
160
+ if (candidate) {
161
+ const it = cloneDeep({ ...candidate, name: filterName });
162
+ inputTypes.push(it);
163
+ inputTypeByName[filterName] = it;
164
+ break;
165
+ }
166
+ }
167
+ };
168
+ for (const type of types) {
169
+ replaceBogusFilters(`${type}Filter`, [
170
+ `${type}NullableFilter`,
171
+ `Nested${type}NullableFilter`
172
+ ]);
173
+ replaceBogusFilters(`${type}WithAggregatesFilter`, [
174
+ `${type}NullableWithAggregatesFilter`,
175
+ `Nested${type}NullableWithAggregatesFilter`
176
+ ]);
177
+ replaceBogusFilters(`${type}ListFilter`, [
178
+ `${type}NullableListFilter`,
179
+ `Nested${type}NullableListFilter`
180
+ ]);
181
+ }
182
+ for (const modelName of modelNames) {
183
+ replaceBogusFilters(`${modelName}RelationFilter`, [
184
+ `${modelName}NullableRelationFilter`
185
+ ]);
186
+ }
187
+ for (const modelName of modelNames) {
188
+ replaceBogusFilters(`${modelName}ScalarRelationFilter`, [
189
+ `${modelName}NullableScalarRelationFilter`
190
+ ]);
191
+ }
192
+ remove(inputTypes, (it) => {
193
+ return isContainBogus(it.name);
194
+ });
195
+ }
196
+
197
+ // src/handlers/create-aggregate-input.ts
198
+ function createAggregateInput(args) {
199
+ const { eventEmitter, outputType: outputType2 } = args;
200
+ const className = `${outputType2.name}Input`;
201
+ const inputType2 = {
202
+ constraints: { maxNumFields: null, minNumFields: null },
203
+ name: className,
204
+ fields: outputType2.fields.map((x) => ({
205
+ name: x.name,
206
+ isNullable: x.isNullable ?? true,
207
+ isRequired: false,
208
+ inputTypes: [
209
+ {
210
+ isList: false,
211
+ type: "true",
212
+ location: "scalar"
213
+ }
214
+ ]
215
+ }))
216
+ };
217
+ eventEmitter.emitSync("InputType", {
218
+ ...args,
219
+ inputType: inputType2,
220
+ fileType: "input",
221
+ classDecoratorName: "InputType"
222
+ });
223
+ }
224
+ function emitSingle(emitter) {
225
+ emitter.on("ClassProperty", classProperty);
226
+ }
227
+ function classProperty(property, eventArguments) {
228
+ const { location, isList, propertyType } = eventArguments;
229
+ if (["inputObjectTypes", "outputObjectTypes"].includes(location) && !isList) {
230
+ const [safeTypes, instanceofTypes] = partition(
231
+ propertyType,
232
+ (t) => t === "null" || t.startsWith("Prisma.")
233
+ );
234
+ const mappedInstanceofTypes = instanceofTypes.map((t) => `InstanceType<typeof ${t}>`);
235
+ property.type = [...mappedInstanceofTypes, ...safeTypes].join(" | ");
236
+ }
237
+ }
238
+ var ImportDeclarationMap = class extends Map {
239
+ add(name, value, isTypeOnly) {
240
+ if (!this.has(name)) {
241
+ const structure = typeof value === "string" ? { moduleSpecifier: value, namedImports: [{ name }], isTypeOnly } : value;
242
+ this.set(name, structure);
243
+ }
244
+ }
245
+ /**
246
+ * Add a type-only import for ESM circular dependency resolution
247
+ */
248
+ addType(name, moduleSpecifier) {
249
+ const typeOnlyKey = `type:${name}`;
250
+ if (!this.has(typeOnlyKey) && !this.has(name)) {
251
+ this.set(typeOnlyKey, {
252
+ moduleSpecifier,
253
+ namedImports: [{ name }],
254
+ isTypeOnly: true
255
+ });
256
+ }
257
+ }
258
+ create(args) {
259
+ const { from, defaultImport, namespaceImport, namedImport, isTypeOnly } = args;
260
+ let name = args.name;
261
+ const value = {
262
+ moduleSpecifier: from,
263
+ namedImports: [],
264
+ defaultImport: void 0,
265
+ namespaceImport: void 0,
266
+ isTypeOnly
267
+ };
268
+ if (namedImport === true && namespaceImport) {
269
+ value.namedImports = [{ name: namespaceImport }];
270
+ name = namespaceImport;
271
+ } else if (defaultImport) {
272
+ value.defaultImport = defaultImport === true ? name : defaultImport;
273
+ name = value.defaultImport;
274
+ } else if (namespaceImport) {
275
+ value.namespaceImport = namespaceImport;
276
+ name = namespaceImport;
277
+ } else {
278
+ value.namedImports = [{ name }];
279
+ }
280
+ const key = isTypeOnly ? `type:${name}` : name;
281
+ if (!this.has(key)) {
282
+ this.set(key, value);
283
+ }
284
+ }
285
+ *toStatements() {
286
+ const iterator = this.values();
287
+ let result = iterator.next();
288
+ while (result.value) {
289
+ yield {
290
+ ...result.value,
291
+ kind: StructureKind.ImportDeclaration
292
+ };
293
+ result = iterator.next();
294
+ }
295
+ }
296
+ };
297
+
298
+ // src/handlers/generate-files.ts
299
+ async function generateFiles(args) {
300
+ const { config, eventEmitter, output, project } = args;
301
+ if (config.emitSingle) {
302
+ const rootDirectory = project.getDirectory(output) ?? project.createDirectory(output);
303
+ const sourceFile = rootDirectory.getSourceFile("index.ts") ?? rootDirectory.createSourceFile("index.ts", void 0, { overwrite: true });
304
+ const statements = project.getSourceFiles().flatMap((s) => {
305
+ if (s === sourceFile) {
306
+ return [];
307
+ }
308
+ const classDeclaration = s.getClass(() => true);
309
+ const stmts = s.getStructure().statements;
310
+ if (Array.isArray(stmts)) {
311
+ for (const statement of stmts) {
312
+ if (!(typeof statement === "object" && statement.kind === StructureKind.Class)) {
313
+ continue;
314
+ }
315
+ for (const property of statement.properties ?? []) {
316
+ for (const decorator of property.decorators ?? []) {
317
+ const fullName = classDeclaration?.getProperty(property.name)?.getDecorator(decorator.name)?.getFullName();
318
+ ok(
319
+ fullName,
320
+ `Cannot get full name of decorator of class ${statement.name}`
321
+ );
322
+ decorator.name = fullName;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ project.removeSourceFile(s);
328
+ return stmts;
329
+ });
330
+ const imports = new ImportDeclarationMap();
331
+ const enums = [];
332
+ const classes = [];
333
+ for (const statement of statements) {
334
+ if (typeof statement === "string") {
335
+ if (statement.startsWith("registerEnumType")) {
336
+ enums.push(statement);
337
+ }
338
+ continue;
339
+ }
340
+ switch (statement.kind) {
341
+ case StructureKind.ImportDeclaration: {
342
+ if (statement.moduleSpecifier.startsWith("./") || statement.moduleSpecifier.startsWith("..")) {
343
+ continue;
344
+ }
345
+ for (const namedImport of statement.namedImports) {
346
+ const name = namedImport.alias ?? namedImport.name;
347
+ imports.add(name, statement.moduleSpecifier);
348
+ }
349
+ if (statement.defaultImport) {
350
+ imports.create({
351
+ defaultImport: statement.defaultImport,
352
+ from: statement.moduleSpecifier,
353
+ name: statement.defaultImport
354
+ });
355
+ }
356
+ if (statement.namespaceImport) {
357
+ imports.create({
358
+ from: statement.moduleSpecifier,
359
+ name: statement.namespaceImport,
360
+ namespaceImport: statement.namespaceImport
361
+ });
362
+ }
363
+ break;
364
+ }
365
+ case StructureKind.Enum: {
366
+ enums.unshift(statement);
367
+ break;
368
+ }
369
+ case StructureKind.Class: {
370
+ classes.push(statement);
371
+ break;
372
+ }
373
+ }
374
+ }
375
+ for (const customImport of config.customImport) {
376
+ imports.create(customImport);
377
+ }
378
+ sourceFile.set({
379
+ kind: StructureKind.SourceFile,
380
+ statements: [...imports.toStatements(), ...enums, ...classes]
381
+ });
382
+ }
383
+ if (config.emitCompiled) {
384
+ project.compilerOptions.set({
385
+ declaration: true,
386
+ declarationDir: output,
387
+ emitDecoratorMetadata: false,
388
+ outDir: output,
389
+ rootDir: output,
390
+ skipLibCheck: true
391
+ });
392
+ const emitResult = await project.emit();
393
+ const errors = emitResult.getDiagnostics().map((d) => String(d.getMessageText()));
394
+ if (errors.length > 0) {
395
+ eventEmitter.emitSync("Warning", errors);
396
+ }
397
+ } else {
398
+ await project.save();
399
+ }
400
+ }
401
+
402
+ // src/helpers/file-type-by-location.ts
403
+ function fileTypeByLocation(fieldLocation) {
404
+ switch (fieldLocation) {
405
+ case "inputObjectTypes": {
406
+ return "input";
407
+ }
408
+ case "outputObjectTypes": {
409
+ return "output";
410
+ }
411
+ case "enumTypes": {
412
+ return "enum";
413
+ }
414
+ }
415
+ return "object";
416
+ }
417
+ function relativePath(from, to) {
418
+ if (!from.startsWith("/")) {
419
+ from = `/${from}`;
420
+ }
421
+ if (!to.startsWith("/")) {
422
+ to = `/${to}`;
423
+ }
424
+ let result = getRelativePath(from, to);
425
+ if (!result.startsWith(".")) {
426
+ result = `./${result}`;
427
+ }
428
+ if (result.endsWith(".ts")) {
429
+ result = result.slice(0, -3);
430
+ }
431
+ return result;
432
+ }
433
+
434
+ // src/helpers/get-graphql-import.ts
435
+ function getGraphqlImport(args) {
436
+ const {
437
+ config,
438
+ fileType,
439
+ getSourceFile,
440
+ isId,
441
+ location,
442
+ noTypeId,
443
+ sourceFile,
444
+ typeName
445
+ } = args;
446
+ if (location === "scalar") {
447
+ if (isId && !noTypeId) {
448
+ return { name: "ID", specifier: "@nestjs/graphql" };
449
+ }
450
+ const graphqlType = config.graphqlScalars[typeName];
451
+ if (graphqlType) {
452
+ return { name: graphqlType.name, specifier: graphqlType.specifier };
453
+ }
454
+ switch (typeName) {
455
+ case "Float":
456
+ case "Int": {
457
+ return { name: typeName, specifier: "@nestjs/graphql" };
458
+ }
459
+ case "DateTime": {
460
+ return { name: "Date", specifier: void 0 };
461
+ }
462
+ case "true":
463
+ case "Boolean": {
464
+ return { name: "Boolean", specifier: void 0 };
465
+ }
466
+ case "Decimal": {
467
+ return {
468
+ name: "GraphQLDecimal",
469
+ specifier: "prisma-graphql-type-decimal"
470
+ };
471
+ }
472
+ case "Json": {
473
+ return { name: "GraphQLJSON", specifier: "graphql-type-json" };
474
+ }
475
+ }
476
+ return { name: "String", specifier: void 0 };
477
+ }
478
+ let sourceFileType = fileTypeByLocation(location);
479
+ if (sourceFileType === "output" && fileType === "model") {
480
+ sourceFileType = "model";
481
+ }
482
+ const specifier = relativePath(
483
+ sourceFile.getFilePath(),
484
+ getSourceFile({
485
+ name: typeName,
486
+ type: sourceFileType
487
+ }).getFilePath()
488
+ );
489
+ return { name: typeName, specifier };
490
+ }
491
+ function getGraphqlInputType(inputTypes, pattern) {
492
+ let result;
493
+ inputTypes = inputTypes.filter((t) => !["null", "Null"].includes(String(t.type)));
494
+ inputTypes = uniqWith(inputTypes, isEqual);
495
+ if (inputTypes.length === 1) {
496
+ return inputTypes[0];
497
+ }
498
+ const countTypes = countBy(inputTypes, (x) => x.location);
499
+ const isOneType = Object.keys(countTypes).length === 1;
500
+ if (isOneType) {
501
+ result = inputTypes.find((x) => x.isList);
502
+ if (result) {
503
+ return result;
504
+ }
505
+ }
506
+ if (pattern) {
507
+ if (pattern.startsWith("matcher:") || pattern.startsWith("match:")) {
508
+ const { 1: patternValue } = pattern.split(":", 2);
509
+ const isMatch = outmatch2(patternValue, { separator: false });
510
+ result = inputTypes.find((x) => isMatch(String(x.type)));
511
+ if (result) {
512
+ return result;
513
+ }
514
+ }
515
+ result = inputTypes.find((x) => String(x.type).includes(pattern));
516
+ if (result) {
517
+ return result;
518
+ }
519
+ }
520
+ result = inputTypes.find((x) => x.location === "inputObjectTypes");
521
+ if (result) {
522
+ return result;
523
+ }
524
+ if (countTypes.enumTypes && countTypes.scalar && inputTypes.some((x) => x.type === "Json" && x.location === "scalar")) {
525
+ result = inputTypes.find((x) => x.type === "Json" && x.location === "scalar");
526
+ if (result) {
527
+ return result;
528
+ }
529
+ }
530
+ if ((countTypes.scalar >= 1 || countTypes.enumTypes >= 1) && countTypes.fieldRefTypes === 1) {
531
+ result = inputTypes.find(
532
+ (x) => (x.location === "scalar" || x.location === "enumTypes") && x.isList
533
+ );
534
+ if (result) {
535
+ return result;
536
+ }
537
+ result = inputTypes.find(
538
+ (x) => x.location === "scalar" || x.location === "enumTypes"
539
+ );
540
+ if (result) {
541
+ return result;
542
+ }
543
+ }
544
+ throw new TypeError(
545
+ `Cannot get matching input type from ${inputTypes.map((x) => x.type).join(", ") || "zero length inputTypes"}`
546
+ );
547
+ }
548
+
549
+ // src/helpers/get-property-type.ts
550
+ function getPropertyType(args) {
551
+ const { location, type } = args;
552
+ switch (type) {
553
+ case "Float":
554
+ case "Int": {
555
+ return ["number"];
556
+ }
557
+ case "String": {
558
+ return ["string"];
559
+ }
560
+ case "Boolean": {
561
+ return ["boolean"];
562
+ }
563
+ case "DateTime": {
564
+ return ["Date", "string"];
565
+ }
566
+ case "Decimal": {
567
+ return ["Decimal"];
568
+ }
569
+ case "Json": {
570
+ return ["any"];
571
+ }
572
+ case "Null": {
573
+ return ["null"];
574
+ }
575
+ case "Bytes": {
576
+ return ["Uint8Array"];
577
+ }
578
+ case "BigInt": {
579
+ return ["bigint", "number"];
580
+ }
581
+ }
582
+ if (["inputObjectTypes", "outputObjectTypes"].includes(location)) {
583
+ return [type];
584
+ }
585
+ if (location === "enumTypes") {
586
+ const enumType = "`${" + type + "}`";
587
+ return [enumType];
588
+ }
589
+ if (location === "scalar") {
590
+ return [type];
591
+ }
592
+ return ["unknown"];
593
+ }
594
+
595
+ // src/helpers/get-where-unique-at-least-keys.ts
596
+ function getWhereUniqueAtLeastKeys(model) {
597
+ const names = model.fields.filter((field) => field.isUnique || field.isId).map((field) => field.name);
598
+ if (model.primaryKey) {
599
+ names.push(createFieldName(model.primaryKey));
600
+ }
601
+ for (const uniqueIndex of model.uniqueIndexes) {
602
+ names.push(createFieldName(uniqueIndex));
603
+ }
604
+ return names;
605
+ }
606
+ function createFieldName(args) {
607
+ const { name, fields } = args;
608
+ return name || fields.join("_");
609
+ }
610
+
611
+ // src/helpers/is-where-unique-input-type.ts
612
+ function isWhereUniqueInputType(name) {
613
+ return name.endsWith("WhereUniqueInput");
614
+ }
615
+ function propertyStructure(args) {
616
+ const {
617
+ isNullable,
618
+ propertyType,
619
+ name,
620
+ isList,
621
+ hasQuestionToken,
622
+ hasExclamationToken
623
+ } = args;
624
+ const type = propertyType.map((type2) => isList ? `Array<${type2}>` : type2).join(" | ");
625
+ return {
626
+ kind: StructureKind.Property,
627
+ name,
628
+ type,
629
+ hasQuestionToken: hasQuestionToken ?? isNullable,
630
+ hasExclamationToken: hasExclamationToken ?? !isNullable,
631
+ decorators: [],
632
+ leadingTrivia: "\n"
633
+ };
634
+ }
635
+
636
+ // src/handlers/input-type.ts
637
+ function inputType(args) {
638
+ const {
639
+ circularDependencies,
640
+ classDecoratorName,
641
+ classTransformerTypeModels,
642
+ config,
643
+ eventEmitter,
644
+ fieldSettings,
645
+ fileType,
646
+ getModelName: getModelName2,
647
+ getSourceFile,
648
+ inputType: inputType2,
649
+ models,
650
+ output,
651
+ removeTypes,
652
+ typeNames
653
+ } = args;
654
+ typeNames.add(inputType2.name);
655
+ const importDeclarations = new ImportDeclarationMap();
656
+ const sourceFile = getSourceFile({
657
+ name: inputType2.name,
658
+ type: fileType
659
+ });
660
+ const classStructure = {
661
+ kind: StructureKind.Class,
662
+ isExported: true,
663
+ name: inputType2.name,
664
+ decorators: [
665
+ {
666
+ name: classDecoratorName,
667
+ arguments: []
668
+ }
669
+ ],
670
+ properties: []
671
+ };
672
+ const modelName = getModelName2(inputType2.name) ?? "";
673
+ const model = models.get(modelName);
674
+ const modelFieldSettings = model && fieldSettings.get(model.name);
675
+ const moduleSpecifier = "@nestjs/graphql";
676
+ const lazyTypes = /* @__PURE__ */ new Set();
677
+ importDeclarations.set("Field", {
678
+ namedImports: [{ name: "Field" }],
679
+ moduleSpecifier
680
+ }).set(classDecoratorName, {
681
+ namedImports: [{ name: classDecoratorName }],
682
+ moduleSpecifier
683
+ });
684
+ if (config.esmCompatible) {
685
+ const typeRegistryPath = relativePath(
686
+ sourceFile.getFilePath(),
687
+ `${output}/type-registry.ts`
688
+ );
689
+ importDeclarations.add("registerType", typeRegistryPath);
690
+ importDeclarations.add("getType", typeRegistryPath);
691
+ }
692
+ const useInputType = config.useInputType.find(
693
+ (x) => inputType2.name.includes(x.typeName)
694
+ );
695
+ const isWhereUnique = isWhereUniqueInputType(inputType2.name);
696
+ for (const field of inputType2.fields) {
697
+ field.inputTypes = field.inputTypes.filter((t) => !removeTypes.has(String(t.type)));
698
+ eventEmitter.emitSync(BeforeGenerateField, field, args);
699
+ const { inputTypes, isRequired, name } = field;
700
+ if (inputTypes.length === 0) {
701
+ continue;
702
+ }
703
+ const usePattern = useInputType?.ALL ?? useInputType?.[name];
704
+ const graphqlInputType = getGraphqlInputType(inputTypes, usePattern);
705
+ const { isList, location, type } = graphqlInputType;
706
+ const typeName = String(type);
707
+ const settings = modelFieldSettings?.get(name);
708
+ const propertySettings = settings?.getPropertyType({
709
+ name: inputType2.name,
710
+ input: true
711
+ });
712
+ const modelField = model?.fields.find((f) => f.name === name);
713
+ const isCustomsApplicable = typeName === modelField?.type;
714
+ const atLeastKeys = model && getWhereUniqueAtLeastKeys(model);
715
+ const whereUniqueInputTypeValue = isWhereUniqueInputType(typeName) && atLeastKeys && `Prisma.AtLeast<${typeName}, ${atLeastKeys.map((n) => `'${n}'`).join(" | ")}>`;
716
+ const propertyType = castArray(
717
+ propertySettings?.name ?? (whereUniqueInputTypeValue || getPropertyType({
718
+ location,
719
+ type: typeName
720
+ }))
721
+ );
722
+ const hasExclamationToken = Boolean(
723
+ isWhereUnique && config.unsafeCompatibleWhereUniqueInput && atLeastKeys?.includes(name)
724
+ );
725
+ const property = propertyStructure({
726
+ name,
727
+ isNullable: !isRequired,
728
+ hasExclamationToken: hasExclamationToken || void 0,
729
+ hasQuestionToken: hasExclamationToken ? false : void 0,
730
+ propertyType,
731
+ isList
732
+ });
733
+ classStructure.properties.push(property);
734
+ if (propertySettings) {
735
+ importDeclarations.create({ ...propertySettings });
736
+ } else if (propertyType.includes("Decimal")) {
737
+ importDeclarations.add("Decimal", `${config.prismaClientImport}/../internal/prismaNamespace`);
738
+ } else if (propertyType.some((p) => p.startsWith("Prisma."))) {
739
+ importDeclarations.add("Prisma", config.prismaClientImport);
740
+ }
741
+ let graphqlType;
742
+ let useGetType = false;
743
+ const shouldHideField = settings?.shouldHideField({
744
+ name: inputType2.name,
745
+ input: true
746
+ }) || config.decorate.some(
747
+ (d) => d.name === "HideField" && d.from === moduleSpecifier && d.isMatchField(name) && d.isMatchType(inputType2.name)
748
+ );
749
+ const fieldType = settings?.getFieldType({
750
+ name: inputType2.name,
751
+ input: true
752
+ });
753
+ if (fieldType && isCustomsApplicable && !shouldHideField) {
754
+ graphqlType = fieldType.name;
755
+ importDeclarations.create({ ...fieldType });
756
+ } else {
757
+ const graphqlImport = getGraphqlImport({
758
+ config,
759
+ sourceFile,
760
+ location,
761
+ typeName,
762
+ getSourceFile
763
+ });
764
+ graphqlType = graphqlImport.name;
765
+ let referenceName = propertyType[0];
766
+ if (location === "enumTypes") {
767
+ const parts = referenceName.split(" ");
768
+ referenceName = parts.at(-1) ?? parts[0];
769
+ }
770
+ const shouldUseLazyType = config.esmCompatible && location === "inputObjectTypes";
771
+ if (graphqlImport.name === inputType2.name && shouldUseLazyType) {
772
+ lazyTypes.add(graphqlImport.name);
773
+ useGetType = true;
774
+ } else if (graphqlImport.specifier && !importDeclarations.has(graphqlImport.name) && graphqlImport.name !== inputType2.name) {
775
+ if (shouldUseLazyType) {
776
+ importDeclarations.addType(graphqlImport.name, graphqlImport.specifier);
777
+ lazyTypes.add(graphqlImport.name);
778
+ } else {
779
+ importDeclarations.set(graphqlImport.name, {
780
+ namedImports: [{ name: graphqlImport.name }],
781
+ moduleSpecifier: graphqlImport.specifier
782
+ });
783
+ }
784
+ }
785
+ if (lazyTypes.has(graphqlImport.name)) {
786
+ useGetType = true;
787
+ }
788
+ }
789
+ ok(property.decorators, "property.decorators is undefined");
790
+ if (shouldHideField) {
791
+ importDeclarations.add("HideField", moduleSpecifier);
792
+ property.decorators.push({ name: "HideField", arguments: [] });
793
+ } else {
794
+ let typeExpression;
795
+ if (useGetType) {
796
+ typeExpression = isList ? `() => [getType('${graphqlType}')]` : `() => getType('${graphqlType}')`;
797
+ } else {
798
+ typeExpression = isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`;
799
+ }
800
+ property.decorators.push({
801
+ name: "Field",
802
+ arguments: [
803
+ typeExpression,
804
+ JSON52.stringify({
805
+ ...settings?.fieldArguments(),
806
+ nullable: !isRequired
807
+ })
808
+ ]
809
+ });
810
+ if (graphqlType === "GraphQLDecimal") {
811
+ importDeclarations.add("transformToDecimal", "prisma-graphql-type-decimal");
812
+ importDeclarations.add("Transform", "class-transformer");
813
+ importDeclarations.add("Type", "class-transformer");
814
+ property.decorators.push(
815
+ {
816
+ name: "Type",
817
+ arguments: ["() => Object"]
818
+ },
819
+ {
820
+ name: "Transform",
821
+ arguments: ["transformToDecimal"]
822
+ }
823
+ );
824
+ } else if (location === "inputObjectTypes" && (modelField?.type === "Decimal" || [
825
+ "connect",
826
+ "connectOrCreate",
827
+ "create",
828
+ "createMany",
829
+ "data",
830
+ "delete",
831
+ "deleteMany",
832
+ "disconnect",
833
+ "set",
834
+ "update",
835
+ "updateMany",
836
+ "upsert",
837
+ "where"
838
+ ].includes(name) || classTransformerTypeModels.has(getModelName2(graphqlType) ?? "") || modelField?.kind === "object" && models.get(modelField.type) && models.get(modelField.type)?.fields.some(
839
+ (f) => f.kind === "object" && classTransformerTypeModels.has(f.type)
840
+ ))) {
841
+ importDeclarations.add("Type", "class-transformer");
842
+ if (useGetType) {
843
+ property.decorators.push({
844
+ name: "Type",
845
+ arguments: [`getType('${graphqlType}')`]
846
+ });
847
+ } else {
848
+ property.decorators.push({ name: "Type", arguments: [`() => ${graphqlType}`] });
849
+ }
850
+ }
851
+ if (isCustomsApplicable) {
852
+ for (const options of settings ?? []) {
853
+ if ((options.kind === "Decorator" && options.input && options.match?.(name)) ?? true) {
854
+ property.decorators.push({
855
+ name: options.name,
856
+ arguments: options.arguments
857
+ });
858
+ ok(options.from, "Missed 'from' part in configuration or field setting");
859
+ importDeclarations.create(options);
860
+ }
861
+ }
862
+ }
863
+ for (const decorate of config.decorate) {
864
+ if (decorate.isMatchField(name) && decorate.isMatchType(inputType2.name)) {
865
+ property.decorators.push({
866
+ name: decorate.name,
867
+ arguments: decorate.arguments?.map((x) => pupa(x, { propertyType }))
868
+ });
869
+ importDeclarations.create(decorate);
870
+ }
871
+ }
872
+ }
873
+ eventEmitter.emitSync("ClassProperty", property, {
874
+ location,
875
+ isList,
876
+ propertyType
877
+ });
878
+ }
879
+ const statements = [
880
+ ...importDeclarations.toStatements(),
881
+ classStructure
882
+ ];
883
+ if (config.esmCompatible) {
884
+ statements.push(`
885
+ registerType('${inputType2.name}', ${inputType2.name});`);
886
+ }
887
+ sourceFile.set({
888
+ statements
889
+ });
890
+ }
891
+ var ObjectSettings = class extends Array {
892
+ shouldHideField({
893
+ name,
894
+ input = false,
895
+ output = false
896
+ }) {
897
+ const hideField = this.find((s) => s.name === "HideField");
898
+ return Boolean(
899
+ hideField?.input && input || hideField?.output && output || hideField?.match?.(name)
900
+ );
901
+ }
902
+ getFieldType({
903
+ name,
904
+ input,
905
+ output
906
+ }) {
907
+ const fieldType = this.find((s) => s.kind === "FieldType");
908
+ if (!fieldType) {
909
+ return void 0;
910
+ }
911
+ if (fieldType.match) {
912
+ return fieldType.match(name) ? fieldType : void 0;
913
+ }
914
+ if (input && !fieldType.input) {
915
+ return void 0;
916
+ }
917
+ if (output && !fieldType.output) {
918
+ return void 0;
919
+ }
920
+ return fieldType;
921
+ }
922
+ getPropertyType({
923
+ name,
924
+ input,
925
+ output
926
+ }) {
927
+ const propertyType = this.find((s) => s.kind === "PropertyType");
928
+ if (!propertyType) {
929
+ return void 0;
930
+ }
931
+ if (propertyType.match) {
932
+ return propertyType.match(name) ? propertyType : void 0;
933
+ }
934
+ if (input && !propertyType.input) {
935
+ return void 0;
936
+ }
937
+ if (output && !propertyType.output) {
938
+ return void 0;
939
+ }
940
+ return propertyType;
941
+ }
942
+ getObjectTypeArguments(options) {
943
+ const objectTypeOptions = merge({}, options);
944
+ const resultArguments = [objectTypeOptions];
945
+ const objectType = this.find((s) => s.kind === "ObjectType");
946
+ if (objectType && isObject(objectType.arguments)) {
947
+ const name = objectType.arguments.name;
948
+ merge(objectTypeOptions, omit(objectType.arguments, "name"));
949
+ if (name) {
950
+ resultArguments.unshift(name);
951
+ }
952
+ }
953
+ return resultArguments.map((x) => JSON52.stringify(x));
954
+ }
955
+ fieldArguments() {
956
+ const item = this.find((item2) => item2.kind === "Field");
957
+ if (item) {
958
+ return item.arguments;
959
+ }
960
+ }
961
+ };
962
+ function createObjectSettings(args) {
963
+ const { config, text } = args;
964
+ const result = new ObjectSettings();
965
+ const textLines = text.split("\n");
966
+ const documentationLines = [];
967
+ let fieldElement = result.find((item) => item.kind === "Field");
968
+ if (!fieldElement) {
969
+ fieldElement = {
970
+ name: "",
971
+ kind: "Field",
972
+ arguments: {}
973
+ };
974
+ }
975
+ for (const line of textLines) {
976
+ const match = /^@(?<name>\w+(\.(\w+))?)\((?<args>.*)\)/.exec(line);
977
+ const { element, documentLine } = createSettingElement({
978
+ line,
979
+ config,
980
+ fieldElement,
981
+ match
982
+ });
983
+ if (element) {
984
+ result.push(element);
985
+ }
986
+ if (documentLine) {
987
+ documentationLines.push(line);
988
+ }
989
+ }
990
+ return {
991
+ settings: result,
992
+ documentation: documentationLines.filter(Boolean).join("\n") || void 0
993
+ };
994
+ }
995
+ function createSettingElement({
996
+ line,
997
+ config,
998
+ fieldElement,
999
+ match
1000
+ }) {
1001
+ const result = {
1002
+ documentLine: "",
1003
+ element: void 0
1004
+ };
1005
+ if (line.startsWith("@deprecated")) {
1006
+ fieldElement.arguments["deprecationReason"] = trim(line.slice(11));
1007
+ result.element = fieldElement;
1008
+ return result;
1009
+ }
1010
+ if (line.startsWith("@complexity")) {
1011
+ let n = Number.parseInt(trim(line.slice(11)));
1012
+ if (n !== n || n < 1) n = 1;
1013
+ fieldElement.arguments["complexity"] = n;
1014
+ result.element = fieldElement;
1015
+ return result;
1016
+ }
1017
+ const name = match?.groups?.name;
1018
+ if (!(match && name)) {
1019
+ result.documentLine = line;
1020
+ return result;
1021
+ }
1022
+ const element = {
1023
+ kind: "Decorator",
1024
+ name: "",
1025
+ arguments: [],
1026
+ input: false,
1027
+ output: false,
1028
+ model: false,
1029
+ from: ""
1030
+ };
1031
+ result.element = element;
1032
+ if (name === "TypeGraphQL.omit" || name === "HideField") {
1033
+ Object.assign(element, hideFieldDecorator(match));
1034
+ return result;
1035
+ }
1036
+ if (["FieldType", "PropertyType"].includes(name) && match.groups?.args) {
1037
+ const options2 = customType(match.groups.args);
1038
+ merge(element, options2.namespace && config.fields[options2.namespace], options2, {
1039
+ kind: name
1040
+ });
1041
+ return result;
1042
+ }
1043
+ if (name === "ObjectType" && match.groups?.args) {
1044
+ element.kind = "ObjectType";
1045
+ const options2 = customType(match.groups.args);
1046
+ if (typeof options2[0] === "string" && options2[0]) {
1047
+ options2.name = options2[0];
1048
+ }
1049
+ if (isObject(options2[1])) {
1050
+ merge(options2, options2[1]);
1051
+ }
1052
+ element.arguments = {
1053
+ name: options2.name,
1054
+ isAbstract: options2.isAbstract
1055
+ };
1056
+ return result;
1057
+ }
1058
+ if (name === "Directive" && match.groups?.args) {
1059
+ const options2 = customType(match.groups.args);
1060
+ merge(element, { model: true, from: "@nestjs/graphql" }, options2, {
1061
+ name,
1062
+ namespace: false,
1063
+ kind: "Decorator",
1064
+ arguments: Array.isArray(options2.arguments) ? options2.arguments.map((s) => JSON52.stringify(s)) : options2.arguments
1065
+ });
1066
+ return result;
1067
+ }
1068
+ const namespace = getNamespace(name);
1069
+ element.namespaceImport = namespace;
1070
+ const options = {
1071
+ name,
1072
+ arguments: (match.groups?.args || "").split(",").map((s) => trim(s)).filter(Boolean)
1073
+ };
1074
+ merge(element, namespace && config.fields[namespace], options);
1075
+ return result;
1076
+ }
1077
+ function customType(args) {
1078
+ const result = {};
1079
+ let options = parseArgs(args);
1080
+ if (typeof options === "string") {
1081
+ options = { name: options };
1082
+ }
1083
+ Object.assign(result, options);
1084
+ const namespace = getNamespace(options.name);
1085
+ result.namespace = namespace;
1086
+ if (options.name?.includes(".")) {
1087
+ result.namespaceImport = namespace;
1088
+ }
1089
+ if (typeof options.match === "string" || Array.isArray(options.match)) {
1090
+ result.match = outmatch2(options.match, { separator: false });
1091
+ }
1092
+ return result;
1093
+ }
1094
+ function hideFieldDecorator(match) {
1095
+ const result = {
1096
+ name: "HideField",
1097
+ arguments: [],
1098
+ from: "@nestjs/graphql",
1099
+ defaultImport: void 0,
1100
+ namespaceImport: void 0,
1101
+ match: void 0
1102
+ };
1103
+ if (!match.groups?.args) {
1104
+ result.output = true;
1105
+ return result;
1106
+ }
1107
+ if (match.groups.args.includes("{") && match.groups.args.includes("}")) {
1108
+ const options = parseArgs(match.groups.args);
1109
+ result.output = Boolean(options.output);
1110
+ result.input = Boolean(options.input);
1111
+ if (typeof options.match === "string" || Array.isArray(options.match)) {
1112
+ result.match = outmatch2(options.match, { separator: false });
1113
+ }
1114
+ } else {
1115
+ if (/output:\s*true/.test(match.groups.args)) {
1116
+ result.output = true;
1117
+ }
1118
+ if (/input:\s*true/.test(match.groups.args)) {
1119
+ result.input = true;
1120
+ }
1121
+ }
1122
+ return result;
1123
+ }
1124
+ function parseArgs(string) {
1125
+ try {
1126
+ return JSON52.parse(string);
1127
+ } catch {
1128
+ try {
1129
+ return JSON52.parse(`[${string}]`);
1130
+ } catch {
1131
+ throw new Error(`Failed to parse: ${string}`);
1132
+ }
1133
+ }
1134
+ }
1135
+ function getNamespace(name) {
1136
+ if (name === void 0) {
1137
+ return void 0;
1138
+ }
1139
+ let result = String(name);
1140
+ if (result.includes(".")) {
1141
+ [result] = result.split(".");
1142
+ }
1143
+ return result;
1144
+ }
1145
+
1146
+ // src/handlers/model-data.ts
1147
+ function modelData(model, args) {
1148
+ const {
1149
+ config,
1150
+ modelNames,
1151
+ models,
1152
+ modelFields,
1153
+ fieldSettings,
1154
+ classTransformerTypeModels
1155
+ } = args;
1156
+ modelNames.push(model.name);
1157
+ models.set(model.name, model);
1158
+ const modelFieldsValue = /* @__PURE__ */ new Map();
1159
+ modelFields.set(model.name, modelFieldsValue);
1160
+ const fieldSettingsValue = /* @__PURE__ */ new Map();
1161
+ fieldSettings.set(model.name, fieldSettingsValue);
1162
+ for (const field of model.fields) {
1163
+ if (field.documentation) {
1164
+ const { documentation, settings } = createObjectSettings({
1165
+ text: field.documentation,
1166
+ config
1167
+ });
1168
+ field.documentation = documentation;
1169
+ fieldSettingsValue.set(field.name, settings);
1170
+ }
1171
+ modelFieldsValue.set(field.name, field);
1172
+ }
1173
+ if (model.fields.some((field) => field.type === "Decimal")) {
1174
+ classTransformerTypeModels.add(model.name);
1175
+ }
1176
+ }
1177
+
1178
+ // src/helpers/create-comment.ts
1179
+ function createComment(documentation, settings) {
1180
+ const documentationLines = documentation.split("\n");
1181
+ const commentLines = ["/**"];
1182
+ for (const line of documentationLines) {
1183
+ commentLines.push(` * ${line}`);
1184
+ }
1185
+ const deprecationReason = settings?.fieldArguments()?.deprecationReason;
1186
+ if (deprecationReason) {
1187
+ commentLines.push(` * @deprecated ${deprecationReason}`);
1188
+ }
1189
+ commentLines.push(" */\n");
1190
+ return commentLines.join("\n");
1191
+ }
1192
+
1193
+ // src/helpers/detect-circular-deps.ts
1194
+ function buildDependencyGraph(models) {
1195
+ const graph = /* @__PURE__ */ new Map();
1196
+ for (const model of models) {
1197
+ graph.set(model.name, /* @__PURE__ */ new Set());
1198
+ }
1199
+ for (const model of models) {
1200
+ const dependencies = graph.get(model.name);
1201
+ for (const field of model.fields) {
1202
+ if (field.kind === "object" && field.type !== model.name) {
1203
+ if (graph.has(field.type)) {
1204
+ dependencies.add(field.type);
1205
+ }
1206
+ }
1207
+ }
1208
+ }
1209
+ return graph;
1210
+ }
1211
+ function detectCircularDependencies(graph) {
1212
+ const circularPairs = /* @__PURE__ */ new Set();
1213
+ const visited = /* @__PURE__ */ new Set();
1214
+ const recursionStack = /* @__PURE__ */ new Set();
1215
+ const path = [];
1216
+ function dfs(node) {
1217
+ visited.add(node);
1218
+ recursionStack.add(node);
1219
+ path.push(node);
1220
+ const dependencies = graph.get(node) || /* @__PURE__ */ new Set();
1221
+ for (const dep of dependencies) {
1222
+ if (!visited.has(dep)) {
1223
+ dfs(dep);
1224
+ } else if (recursionStack.has(dep)) {
1225
+ const cycleStartIndex = path.indexOf(dep);
1226
+ if (cycleStartIndex !== -1) {
1227
+ const cyclePath = path.slice(cycleStartIndex);
1228
+ for (let i = 0; i < cyclePath.length; i++) {
1229
+ const a = cyclePath[i];
1230
+ const b = cyclePath[(i + 1) % cyclePath.length];
1231
+ const pair = a < b ? `${a}:${b}` : `${b}:${a}`;
1232
+ circularPairs.add(pair);
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+ path.pop();
1238
+ recursionStack.delete(node);
1239
+ }
1240
+ for (const node of graph.keys()) {
1241
+ if (!visited.has(node)) {
1242
+ dfs(node);
1243
+ }
1244
+ }
1245
+ return circularPairs;
1246
+ }
1247
+ function hasCircularDependency(circularDeps, modelA, modelB) {
1248
+ const pair = modelA < modelB ? `${modelA}:${modelB}` : `${modelB}:${modelA}`;
1249
+ return circularDeps.has(pair);
1250
+ }
1251
+
1252
+ // src/helpers/get-output-type-name.ts
1253
+ function getOutputTypeName(name) {
1254
+ return name.replace(/(?:OutputType|Output)$/, "");
1255
+ }
1256
+
1257
+ // src/handlers/model-output-type.ts
1258
+ var nestjsGraphql = "@nestjs/graphql";
1259
+ function modelOutputType(outputType2, args) {
1260
+ const {
1261
+ circularDependencies,
1262
+ config,
1263
+ eventEmitter,
1264
+ fieldSettings,
1265
+ getSourceFile,
1266
+ modelFields,
1267
+ models,
1268
+ output
1269
+ } = args;
1270
+ if (isManyAndReturnOutputType(outputType2.name)) return;
1271
+ const model = models.get(outputType2.name);
1272
+ ok(model, `Cannot find model by name ${outputType2.name}`);
1273
+ const sourceFile = getSourceFile({
1274
+ name: outputType2.name,
1275
+ type: "model"
1276
+ });
1277
+ const sourceFileStructure = sourceFile.getStructure();
1278
+ const exportDeclaration = getExportDeclaration(
1279
+ model.name,
1280
+ sourceFileStructure.statements
1281
+ );
1282
+ const importDeclarations = new ImportDeclarationMap();
1283
+ const classStructure = {
1284
+ decorators: [
1285
+ {
1286
+ arguments: [],
1287
+ name: "ObjectType"
1288
+ }
1289
+ ],
1290
+ isExported: true,
1291
+ kind: StructureKind.Class,
1292
+ name: outputType2.name,
1293
+ properties: []
1294
+ };
1295
+ sourceFileStructure.statements.push(classStructure);
1296
+ ok(classStructure.decorators, "classStructure.decorators is undefined");
1297
+ const decorator = classStructure.decorators.find((d) => d.name === "ObjectType");
1298
+ ok(decorator, "ObjectType decorator not found");
1299
+ let modelSettings;
1300
+ if (model.documentation) {
1301
+ const objectTypeOptions = {};
1302
+ const { documentation, settings } = createObjectSettings({
1303
+ config,
1304
+ text: model.documentation
1305
+ });
1306
+ if (documentation) {
1307
+ if (!classStructure.leadingTrivia) {
1308
+ classStructure.leadingTrivia = createComment(documentation);
1309
+ }
1310
+ objectTypeOptions.description = documentation;
1311
+ }
1312
+ decorator.arguments = settings.getObjectTypeArguments(objectTypeOptions);
1313
+ modelSettings = settings;
1314
+ }
1315
+ importDeclarations.add("Field", nestjsGraphql);
1316
+ importDeclarations.add("ObjectType", nestjsGraphql);
1317
+ const lazyTypes = /* @__PURE__ */ new Set();
1318
+ if (config.esmCompatible) {
1319
+ const typeRegistryPath = relativePath(
1320
+ sourceFile.getFilePath(),
1321
+ `${output}/type-registry.ts`
1322
+ );
1323
+ importDeclarations.add("registerType", typeRegistryPath);
1324
+ importDeclarations.add("getType", typeRegistryPath);
1325
+ }
1326
+ for (const field of outputType2.fields) {
1327
+ if (config.omitModelsCount && field.name === "_count") continue;
1328
+ let fileType = "model";
1329
+ const { isList, location, namespace, type } = field.outputType;
1330
+ let outputTypeName = String(type);
1331
+ if (namespace !== "model") {
1332
+ fileType = "output";
1333
+ outputTypeName = getOutputTypeName(outputTypeName);
1334
+ }
1335
+ const modelField = modelFields.get(model.name)?.get(field.name);
1336
+ const settings = fieldSettings.get(model.name)?.get(field.name);
1337
+ const fieldType = settings?.getFieldType({
1338
+ name: outputType2.name,
1339
+ output: true
1340
+ });
1341
+ const propertySettings = settings?.getPropertyType({
1342
+ name: outputType2.name,
1343
+ output: true
1344
+ });
1345
+ const propertyType = castArray(
1346
+ propertySettings?.name ?? getPropertyType({
1347
+ location,
1348
+ type: outputTypeName
1349
+ })
1350
+ );
1351
+ propertyType.splice(1, propertyType.length);
1352
+ if (field.isNullable && !isList) {
1353
+ propertyType.push("null");
1354
+ }
1355
+ let graphqlType;
1356
+ let useGetType = false;
1357
+ if (fieldType) {
1358
+ graphqlType = fieldType.name;
1359
+ importDeclarations.create({ ...fieldType });
1360
+ } else {
1361
+ const graphqlImport = getGraphqlImport({
1362
+ config,
1363
+ fileType,
1364
+ getSourceFile,
1365
+ isId: modelField?.isId,
1366
+ location,
1367
+ noTypeId: config.noTypeId,
1368
+ sourceFile,
1369
+ typeName: outputTypeName
1370
+ });
1371
+ graphqlType = graphqlImport.name;
1372
+ if (graphqlImport.name !== outputType2.name && graphqlImport.specifier) {
1373
+ const isCircular = config.esmCompatible && location === "outputObjectTypes" && namespace === "model" && hasCircularDependency(circularDependencies, outputType2.name, outputTypeName);
1374
+ if (isCircular) {
1375
+ importDeclarations.addType(graphqlImport.name, graphqlImport.specifier);
1376
+ lazyTypes.add(graphqlImport.name);
1377
+ useGetType = true;
1378
+ } else {
1379
+ importDeclarations.add(graphqlImport.name, graphqlImport.specifier);
1380
+ }
1381
+ }
1382
+ }
1383
+ const property = propertyStructure({
1384
+ hasExclamationToken: true,
1385
+ hasQuestionToken: location === "outputObjectTypes",
1386
+ isList,
1387
+ isNullable: field.isNullable,
1388
+ name: field.name,
1389
+ propertyType
1390
+ });
1391
+ if (typeof property.leadingTrivia === "string" && modelField?.documentation) {
1392
+ property.leadingTrivia += createComment(modelField.documentation, settings);
1393
+ }
1394
+ classStructure.properties?.push(property);
1395
+ if (propertySettings) {
1396
+ importDeclarations.create({ ...propertySettings });
1397
+ } else if (propertyType.includes("Decimal")) {
1398
+ importDeclarations.add("Decimal", `${config.prismaClientImport}/../internal/prismaNamespace`);
1399
+ }
1400
+ ok(property.decorators, "property.decorators is undefined");
1401
+ const shouldHideField = settings?.shouldHideField({ name: outputType2.name, output: true }) || config.decorate.some(
1402
+ (d) => d.name === "HideField" && d.from === "@nestjs/graphql" && d.isMatchField(field.name) && d.isMatchType(outputTypeName)
1403
+ );
1404
+ if (shouldHideField) {
1405
+ importDeclarations.add("HideField", nestjsGraphql);
1406
+ property.decorators.push({ arguments: [], name: "HideField" });
1407
+ } else {
1408
+ let typeExpression;
1409
+ if (useGetType) {
1410
+ typeExpression = isList ? `() => [getType('${graphqlType}')]` : `() => getType('${graphqlType}')`;
1411
+ } else {
1412
+ typeExpression = isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`;
1413
+ }
1414
+ property.decorators.push({
1415
+ arguments: [
1416
+ typeExpression,
1417
+ JSON52.stringify({
1418
+ ...settings?.fieldArguments(),
1419
+ defaultValue: ["number", "string", "boolean"].includes(
1420
+ typeof modelField?.default
1421
+ ) ? modelField?.default : void 0,
1422
+ description: modelField?.documentation,
1423
+ nullable: Boolean(field.isNullable)
1424
+ })
1425
+ ],
1426
+ name: "Field"
1427
+ });
1428
+ for (const setting of settings ?? []) {
1429
+ if (shouldBeDecorated(setting) && (setting.match?.(field.name) ?? true)) {
1430
+ property.decorators.push({
1431
+ arguments: setting.arguments,
1432
+ name: setting.name
1433
+ });
1434
+ ok(setting.from, "Missed 'from' part in configuration or field setting");
1435
+ importDeclarations.create(setting);
1436
+ }
1437
+ }
1438
+ for (const decorate of config.decorate) {
1439
+ if (decorate.isMatchField(field.name) && decorate.isMatchType(outputTypeName)) {
1440
+ property.decorators.push({
1441
+ arguments: decorate.arguments?.map((x) => pupa(x, { propertyType })),
1442
+ name: decorate.name
1443
+ });
1444
+ importDeclarations.create(decorate);
1445
+ }
1446
+ }
1447
+ }
1448
+ eventEmitter.emitSync("ClassProperty", property, {
1449
+ isList,
1450
+ location,
1451
+ propertyType
1452
+ });
1453
+ }
1454
+ for (const setting of modelSettings ?? []) {
1455
+ if (shouldBeDecorated(setting)) {
1456
+ classStructure.decorators.push({
1457
+ arguments: setting.arguments,
1458
+ name: setting.name
1459
+ });
1460
+ importDeclarations.create(setting);
1461
+ }
1462
+ }
1463
+ const statements = [
1464
+ ...importDeclarations.toStatements(),
1465
+ classStructure
1466
+ ];
1467
+ if (config.esmCompatible) {
1468
+ statements.push(`
1469
+ registerType('${outputType2.name}', ${outputType2.name});`);
1470
+ }
1471
+ if (exportDeclaration) {
1472
+ sourceFile.set({
1473
+ statements: [exportDeclaration, "\n", classStructure]
1474
+ });
1475
+ const classDeclaration = sourceFile.getClassOrThrow(model.name);
1476
+ const commentedText = classDeclaration.getText().split("\n").map((x) => `// ${x}`);
1477
+ classDeclaration.remove();
1478
+ sourceFile.addStatements(["\n", ...commentedText]);
1479
+ } else {
1480
+ sourceFile.set({
1481
+ statements
1482
+ });
1483
+ }
1484
+ }
1485
+ function shouldBeDecorated(setting) {
1486
+ return setting.kind === "Decorator" && (setting.output || setting.model) && !(setting.output && setting.model);
1487
+ }
1488
+ function getExportDeclaration(name, statements) {
1489
+ return statements.find((structure) => {
1490
+ return structure.kind === StructureKind.ExportDeclaration && structure.namedExports.some(
1491
+ (o) => (o.alias ?? o.name) === name
1492
+ );
1493
+ });
1494
+ }
1495
+
1496
+ // src/handlers/no-atomic-operations.ts
1497
+ function noAtomicOperations(eventEmitter) {
1498
+ eventEmitter.on("BeforeInputType", beforeInputType2);
1499
+ eventEmitter.on("BeforeGenerateFiles", beforeGenerateFiles);
1500
+ }
1501
+ function beforeInputType2(args) {
1502
+ const { inputType: inputType2, getModelName: getModelName2 } = args;
1503
+ for (const field of inputType2.fields) {
1504
+ const fieldName = field.name;
1505
+ field.inputTypes = field.inputTypes.filter((it) => {
1506
+ const inputTypeName = String(it.type);
1507
+ const modelName = getModelName2(inputTypeName);
1508
+ if (isAtomicOperation(inputTypeName) || modelName && isListInput(inputTypeName, modelName, fieldName)) {
1509
+ return false;
1510
+ }
1511
+ return true;
1512
+ });
1513
+ }
1514
+ }
1515
+ function beforeGenerateFiles(args) {
1516
+ const { project } = args;
1517
+ for (const sourceFile of project.getSourceFiles()) {
1518
+ const className = sourceFile.getClass(() => true)?.getName();
1519
+ if (className && isAtomicOperation(className)) {
1520
+ project.removeSourceFile(sourceFile);
1521
+ }
1522
+ }
1523
+ }
1524
+ function isAtomicOperation(typeName) {
1525
+ if (typeName.endsWith("FieldUpdateOperationsInput")) {
1526
+ return true;
1527
+ }
1528
+ return false;
1529
+ }
1530
+ function isListInput(typeName, model, field) {
1531
+ return typeName === `${model}Create${field}Input` || typeName === `${model}Update${field}Input`;
1532
+ }
1533
+
1534
+ // src/helpers/get-enum-name.ts
1535
+ function getEnumName(referenceName) {
1536
+ return referenceName.slice(3, -2);
1537
+ }
1538
+
1539
+ // src/handlers/output-type.ts
1540
+ var nestjsGraphql2 = "@nestjs/graphql";
1541
+ function outputType(outputTypeArg, args) {
1542
+ const { config, eventEmitter, fieldSettings, getModelName: getModelName2, getSourceFile, models } = args;
1543
+ const importDeclarations = new ImportDeclarationMap();
1544
+ const fileType = "output";
1545
+ const modelName = getModelName2(outputTypeArg.name) ?? "";
1546
+ const model = models.get(modelName);
1547
+ const isAggregateOutput = model && /(?:Count|Avg|Sum|Min|Max)AggregateOutputType$/.test(outputTypeArg.name) && String(outputTypeArg.name).startsWith(model.name);
1548
+ const isCountOutput = model?.name && outputTypeArg.name === `${model.name}CountOutputType`;
1549
+ if (!config.emitBlocks.outputs && !isCountOutput) return;
1550
+ outputTypeArg.name = getOutputTypeName(outputTypeArg.name);
1551
+ if (isAggregateOutput) {
1552
+ eventEmitter.emitSync("AggregateOutput", { ...args, outputType: outputTypeArg });
1553
+ }
1554
+ const sourceFile = getSourceFile({
1555
+ name: outputTypeArg.name,
1556
+ type: fileType
1557
+ });
1558
+ const classStructure = {
1559
+ decorators: [
1560
+ {
1561
+ arguments: [],
1562
+ name: "ObjectType"
1563
+ }
1564
+ ],
1565
+ isExported: true,
1566
+ kind: StructureKind.Class,
1567
+ name: outputTypeArg.name,
1568
+ properties: []
1569
+ };
1570
+ importDeclarations.add("Field", nestjsGraphql2);
1571
+ importDeclarations.add("ObjectType", nestjsGraphql2);
1572
+ for (const field of outputTypeArg.fields) {
1573
+ const { isList, location, type } = field.outputType;
1574
+ const outputTypeName = getOutputTypeName(String(type));
1575
+ const settings = isCountOutput ? void 0 : model && fieldSettings.get(model.name)?.get(field.name);
1576
+ const propertySettings = settings?.getPropertyType({
1577
+ name: outputTypeArg.name,
1578
+ output: true
1579
+ });
1580
+ const isCustomsApplicable = outputTypeName === model?.fields.find((f) => f.name === field.name)?.type;
1581
+ field.outputType.type = outputTypeName;
1582
+ const propertyType = castArray(
1583
+ propertySettings?.name ?? getPropertyType({
1584
+ location,
1585
+ type: outputTypeName
1586
+ })
1587
+ );
1588
+ const property = propertyStructure({
1589
+ hasQuestionToken: isCountOutput ? true : void 0,
1590
+ isList,
1591
+ isNullable: field.isNullable,
1592
+ name: field.name,
1593
+ propertyType
1594
+ });
1595
+ classStructure.properties?.push(property);
1596
+ if (propertySettings) {
1597
+ importDeclarations.create({ ...propertySettings });
1598
+ } else if (propertyType.includes("Decimal")) {
1599
+ importDeclarations.add("Decimal", `${config.prismaClientImport}/../internal/prismaNamespace`);
1600
+ }
1601
+ let graphqlType;
1602
+ const shouldHideField = settings?.shouldHideField({
1603
+ name: outputTypeArg.name,
1604
+ output: true
1605
+ }) || config.decorate.some(
1606
+ (d) => d.name === "HideField" && d.from === "@nestjs/graphql" && d.isMatchField(field.name) && d.isMatchType(outputTypeName)
1607
+ );
1608
+ const fieldType = settings?.getFieldType({
1609
+ name: outputTypeArg.name,
1610
+ output: true
1611
+ });
1612
+ if (fieldType && isCustomsApplicable && !shouldHideField) {
1613
+ graphqlType = fieldType.name;
1614
+ importDeclarations.create({ ...fieldType });
1615
+ } else {
1616
+ const graphqlImport = getGraphqlImport({
1617
+ config,
1618
+ fileType,
1619
+ getSourceFile,
1620
+ isId: false,
1621
+ location,
1622
+ sourceFile,
1623
+ typeName: outputTypeName
1624
+ });
1625
+ const referenceName = location === "enumTypes" ? getEnumName(propertyType[0]) : propertyType[0];
1626
+ graphqlType = graphqlImport.name;
1627
+ if (graphqlImport.specifier && !importDeclarations.has(graphqlImport.name) && (graphqlImport.name !== outputTypeArg.name && !shouldHideField || shouldHideField && referenceName === graphqlImport.name)) {
1628
+ importDeclarations.set(graphqlImport.name, {
1629
+ moduleSpecifier: graphqlImport.specifier,
1630
+ namedImports: [{ name: graphqlImport.name }]
1631
+ });
1632
+ }
1633
+ }
1634
+ ok(property.decorators, "property.decorators is undefined");
1635
+ if (shouldHideField) {
1636
+ importDeclarations.add("HideField", nestjsGraphql2);
1637
+ property.decorators.push({ arguments: [], name: "HideField" });
1638
+ } else {
1639
+ property.decorators.push({
1640
+ arguments: [
1641
+ isList ? `() => [${graphqlType}]` : `() => ${graphqlType}`,
1642
+ JSON52.stringify({
1643
+ ...settings?.fieldArguments(),
1644
+ nullable: Boolean(field.isNullable)
1645
+ })
1646
+ ],
1647
+ name: "Field"
1648
+ });
1649
+ if (isCustomsApplicable) {
1650
+ for (const options of settings ?? []) {
1651
+ if ((options.kind === "Decorator" && options.output && options.match?.(field.name)) ?? true) {
1652
+ property.decorators.push({
1653
+ arguments: options.arguments,
1654
+ name: options.name
1655
+ });
1656
+ ok(options.from, "Missed 'from' part in configuration or field setting");
1657
+ importDeclarations.create(options);
1658
+ }
1659
+ }
1660
+ }
1661
+ }
1662
+ eventEmitter.emitSync("ClassProperty", property, {
1663
+ isList,
1664
+ location,
1665
+ propertyType
1666
+ });
1667
+ }
1668
+ sourceFile.set({
1669
+ statements: [...importDeclarations.toStatements(), classStructure]
1670
+ });
1671
+ }
1672
+ function purgeOutput(emitter) {
1673
+ emitter.on("Begin", begin);
1674
+ emitter.on("End", end);
1675
+ }
1676
+ function begin({ project, output }) {
1677
+ const sourceFiles = project.getDirectory(output)?.getDescendantSourceFiles();
1678
+ if (sourceFiles) {
1679
+ for (const sourceFile of sourceFiles) {
1680
+ sourceFile.delete();
1681
+ }
1682
+ }
1683
+ }
1684
+ function end({ project, output }) {
1685
+ const directories = project.getDirectory(output)?.getDescendantDirectories().filter((directory) => directory.getSourceFiles().length === 0).map((directory) => directory.getPath());
1686
+ for (const directory of directories ?? []) {
1687
+ try {
1688
+ rmdirSync(directory);
1689
+ } catch {
1690
+ }
1691
+ }
1692
+ }
1693
+ var ReExport = /* @__PURE__ */ ((ReExport2) => {
1694
+ ReExport2["None"] = "None";
1695
+ ReExport2["Directories"] = "Directories";
1696
+ ReExport2["Single"] = "Single";
1697
+ ReExport2["All"] = "All";
1698
+ return ReExport2;
1699
+ })(ReExport || {});
1700
+ function reExport(emitter) {
1701
+ emitter.on("BeforeGenerateFiles", beforeGenerateFiles2);
1702
+ }
1703
+ function beforeGenerateFiles2(args) {
1704
+ const { project, output, config } = args;
1705
+ const rootDirectory = project.getDirectoryOrThrow(output);
1706
+ if (["Directories" /* Directories */, "All" /* All */].includes(config.reExport)) {
1707
+ for (const directory of rootDirectory.getDescendantDirectories()) {
1708
+ let indexSourceFile;
1709
+ const exportDeclarations = directory.getSourceFiles().filter((sourceFile) => {
1710
+ return sourceFile.getBaseName() !== "index.ts";
1711
+ }).map((sourcesFile) => getExportDeclaration2(directory, sourcesFile));
1712
+ if (exportDeclarations.length > 0) {
1713
+ indexSourceFile = directory.createSourceFile(
1714
+ "index.ts",
1715
+ {
1716
+ statements: exportDeclarations
1717
+ },
1718
+ {
1719
+ overwrite: true
1720
+ }
1721
+ );
1722
+ }
1723
+ if (indexSourceFile) {
1724
+ continue;
1725
+ }
1726
+ const namespaceExportDeclarations = directory.getDirectories().map(
1727
+ (sourceDirectory) => getNamespaceExportDeclaration(directory, sourceDirectory)
1728
+ );
1729
+ project.createSourceFile(
1730
+ `${directory.getPath()}/index.ts`,
1731
+ {
1732
+ statements: namespaceExportDeclarations
1733
+ },
1734
+ {
1735
+ overwrite: true
1736
+ }
1737
+ );
1738
+ }
1739
+ }
1740
+ if (config.reExport === "Single" /* Single */) {
1741
+ const exportDeclarations = project.getSourceFiles().filter((sourceFile) => {
1742
+ return sourceFile.getBaseName() !== "index.ts";
1743
+ }).map((sourceFile) => getExportDeclaration2(rootDirectory, sourceFile));
1744
+ rootDirectory.createSourceFile(
1745
+ "index.ts",
1746
+ {
1747
+ statements: exportDeclarations
1748
+ },
1749
+ {
1750
+ overwrite: true
1751
+ }
1752
+ );
1753
+ }
1754
+ if (config.reExport === "All" /* All */) {
1755
+ const exportDeclarations = [];
1756
+ for (const directory of rootDirectory.getDirectories()) {
1757
+ if (directory.getBaseName() === "node_modules") continue;
1758
+ const sourceFile = directory.getSourceFileOrThrow("index.ts");
1759
+ exportDeclarations.push(getExportDeclaration2(rootDirectory, sourceFile));
1760
+ }
1761
+ rootDirectory.createSourceFile(
1762
+ "index.ts",
1763
+ {
1764
+ statements: exportDeclarations
1765
+ },
1766
+ {
1767
+ overwrite: true
1768
+ }
1769
+ );
1770
+ }
1771
+ }
1772
+ function getExportDeclaration2(directory, sourceFile) {
1773
+ let moduleSpecifier = directory.getRelativePathAsModuleSpecifierTo(sourceFile);
1774
+ if (!moduleSpecifier.endsWith(".js") && !moduleSpecifier.endsWith(".ts")) {
1775
+ moduleSpecifier = moduleSpecifier + ".js";
1776
+ } else if (moduleSpecifier.endsWith(".ts")) {
1777
+ moduleSpecifier = moduleSpecifier.slice(0, -3) + ".js";
1778
+ }
1779
+ return {
1780
+ kind: StructureKind.ExportDeclaration,
1781
+ namedExports: sourceFile.getExportSymbols().map((s) => ({ name: s.getName() })),
1782
+ moduleSpecifier
1783
+ };
1784
+ }
1785
+ function getNamespaceExportDeclaration(directory, sourceDirectory) {
1786
+ let moduleSpecifier = directory.getRelativePathAsModuleSpecifierTo(sourceDirectory);
1787
+ if (!moduleSpecifier.endsWith("/index.js")) {
1788
+ moduleSpecifier = moduleSpecifier + "/index.js";
1789
+ }
1790
+ return {
1791
+ kind: StructureKind.ExportDeclaration,
1792
+ moduleSpecifier
1793
+ };
1794
+ }
1795
+
1796
+ // src/handlers/prisma-enum-doc.ts
1797
+ function extractEnumValueDocs(values) {
1798
+ return Object.fromEntries(
1799
+ values.map((value) => {
1800
+ const { name } = value;
1801
+ const documentation = value.documentation;
1802
+ if (typeof documentation !== "string") return null;
1803
+ if (documentation.startsWith("@deprecated")) {
1804
+ return [name, { deprecationReason: documentation.slice(11).trim() }];
1805
+ }
1806
+ return [name, { description: documentation }];
1807
+ }).filter((entry) => entry !== null)
1808
+ );
1809
+ }
1810
+
1811
+ // src/handlers/register-enum.ts
1812
+ function registerEnum(enumType, args) {
1813
+ const { config, enums, getSourceFile } = args;
1814
+ if (!config.emitBlocks.prismaEnums && !enums[enumType.name]) return;
1815
+ const dataModelEnum = enums[enumType.name];
1816
+ const enumTypesData = dataModelEnum?.values ?? [];
1817
+ const sourceFile = getSourceFile({
1818
+ name: enumType.name,
1819
+ type: "enum"
1820
+ });
1821
+ const importDeclarations = new ImportDeclarationMap();
1822
+ importDeclarations.set("registerEnumType", {
1823
+ moduleSpecifier: "@nestjs/graphql",
1824
+ namedImports: [{ name: "registerEnumType" }]
1825
+ });
1826
+ const valuesMap = extractEnumValueDocs(enumTypesData);
1827
+ const filteredValuesMap = Object.fromEntries(
1828
+ Object.entries(valuesMap).filter(([, v]) => Object.keys(v).length > 0)
1829
+ );
1830
+ const hasValuesMap = Object.keys(filteredValuesMap).length > 0;
1831
+ const formattedValuesMap = hasValuesMap ? JSON.stringify(filteredValuesMap, null, 2).replace(/"([^"]+)":/g, "$1:") : "";
1832
+ const valuesMapEntry = hasValuesMap ? `, valuesMap: ${formattedValuesMap}` : "";
1833
+ const enumStructure = {
1834
+ kind: StructureKind.Enum,
1835
+ isExported: true,
1836
+ name: enumType.name,
1837
+ members: enumType.values.map((v) => ({
1838
+ name: v,
1839
+ initializer: JSON.stringify(v)
1840
+ }))
1841
+ };
1842
+ sourceFile.set({
1843
+ statements: [
1844
+ ...importDeclarations.toStatements(),
1845
+ enumStructure,
1846
+ "\n",
1847
+ `registerEnumType(${enumType.name}, { name: '${enumType.name}', description: ${JSON.stringify(
1848
+ dataModelEnum?.documentation
1849
+ )}${valuesMapEntry} })`
1850
+ ]
1851
+ });
1852
+ }
1853
+ function generateRegisterAllTypes(args) {
1854
+ const { config, output, project } = args;
1855
+ if (!config.esmCompatible) {
1856
+ return;
1857
+ }
1858
+ const rootDirectory = project.getDirectory(output) || project.createDirectory(output);
1859
+ const sourceFile = rootDirectory.createSourceFile(
1860
+ "register-all-types.ts",
1861
+ void 0,
1862
+ { overwrite: true }
1863
+ );
1864
+ const importPaths = [];
1865
+ const typeNames = [];
1866
+ const allSourceFiles = project.getSourceFiles(`${output}/**/*.ts`);
1867
+ for (const file of allSourceFiles) {
1868
+ const filePath = file.getFilePath();
1869
+ if (filePath.endsWith("type-registry.ts") || filePath.endsWith("register-all-types.ts") || filePath.endsWith("index.ts")) {
1870
+ continue;
1871
+ }
1872
+ const fileText = file.getText();
1873
+ const registerMatch = fileText.match(/registerType\(['"]([^'"]+)['"]/);
1874
+ if (registerMatch) {
1875
+ const relPath = relativePath(sourceFile.getFilePath(), filePath);
1876
+ importPaths.push(relPath);
1877
+ typeNames.push(registerMatch[1]);
1878
+ }
1879
+ }
1880
+ importPaths.sort();
1881
+ typeNames.sort();
1882
+ const fileContent = `/**
1883
+ * ESM Type Registration Module
1884
+ *
1885
+ * This file registers all generated types with the type registry to solve
1886
+ * ESM circular dependency issues. In ESM, unlike CommonJS, circular imports
1887
+ * can result in undefined values because modules are evaluated in a different order.
1888
+ *
1889
+ * IMPORTANT: Import this file at the very top of your application entry point,
1890
+ * BEFORE any other code that uses the generated types.
1891
+ *
1892
+ * Example usage in main.ts:
1893
+ *
1894
+ * // This MUST be the first import
1895
+ * import './@generated/register-all-types.js';
1896
+ *
1897
+ * // Now you can safely import and use generated types
1898
+ * import { NestFactory } from '@nestjs/core';
1899
+ * import { AppModule } from './app.module.js';
1900
+ *
1901
+ * Why this is needed:
1902
+ * - ESM uses "live bindings" where imports reference the actual export
1903
+ * - With circular deps (User -> Post -> User), one module isn't ready when imported
1904
+ * - CJS would give a partial object that fills in later; ESM gives undefined
1905
+ * - This registry pattern defers type resolution until runtime when all modules are loaded
1906
+ */
1907
+
1908
+ import { markRegistrationComplete } from './type-registry.js';
1909
+
1910
+ // Import all generated type files to trigger their registerType() calls
1911
+ // These are side-effect imports that populate the type registry
1912
+ ${importPaths.map((p) => `import '${p}';`).join("\n")}
1913
+
1914
+ // Mark registration as complete to enable warning messages
1915
+ markRegistrationComplete();
1916
+
1917
+ // Export type names for validation (optional)
1918
+ export const registeredTypes = [
1919
+ ${typeNames.map((n) => ` '${n}',`).join("\n")}
1920
+ ] as const;
1921
+
1922
+ export type RegisteredTypeName = typeof registeredTypes[number];
1923
+ `;
1924
+ sourceFile.addStatements(fileContent);
1925
+ }
1926
+
1927
+ // src/handlers/require-single-fields-in-whereunique-input.ts
1928
+ function requireSingleFieldsInWhereUniqueInput(eventEmitter) {
1929
+ eventEmitter.on("BeforeInputType", beforeInputType3);
1930
+ }
1931
+ function beforeInputType3(args) {
1932
+ const { inputType: inputType2 } = args;
1933
+ if (!isWhereUniqueInputType(inputType2.name) || inputType2.fields.length !== 1) {
1934
+ return;
1935
+ }
1936
+ for (const field of inputType2.fields) {
1937
+ field.isRequired = true;
1938
+ field.isNullable = false;
1939
+ }
1940
+ }
1941
+ function generateTypeRegistry(args) {
1942
+ const { config, output, project } = args;
1943
+ if (!config.esmCompatible) {
1944
+ return;
1945
+ }
1946
+ const rootDirectory = project.getDirectory(output) || project.createDirectory(output);
1947
+ const sourceFile = rootDirectory.createSourceFile(
1948
+ "type-registry.ts",
1949
+ void 0,
1950
+ { overwrite: true }
1951
+ );
1952
+ const registryCode = `/**
1953
+ * Type Registry for ESM Circular Dependency Resolution
1954
+ *
1955
+ * In ESM, circular dependencies behave differently than CommonJS:
1956
+ * - CJS: Modules get a partial/incomplete export object that gets filled in
1957
+ * - ESM: Imports are "live bindings" but can be undefined if not yet initialized
1958
+ *
1959
+ * This registry solves this by:
1960
+ * 1. Deferring type resolution until runtime (after all modules are loaded)
1961
+ * 2. Providing a forwardRef pattern for GraphQL field type declarations
1962
+ * 3. Validating all types are registered before they're needed
1963
+ */
1964
+
1965
+ const registry = new Map<string, unknown>();
1966
+ const pendingResolutions = new Map<string, Array<(type: unknown) => void>>();
1967
+ let registrationComplete = false;
1968
+
1969
+ /**
1970
+ * Register a type with the registry.
1971
+ * This should be called at module load time after the class is defined.
1972
+ */
1973
+ export function registerType(name: string, type: unknown): void {
1974
+ if (type === undefined) {
1975
+ console.warn(\`[nestjs-prisma-graphql] Warning: Registering undefined type for "\${name}". This may indicate a circular dependency issue.\`);
1976
+ }
1977
+ registry.set(name, type);
1978
+
1979
+ // Resolve any pending forwardRef callbacks
1980
+ const pending = pendingResolutions.get(name);
1981
+ if (pending) {
1982
+ for (const callback of pending) {
1983
+ callback(type);
1984
+ }
1985
+ pendingResolutions.delete(name);
1986
+ }
1987
+ }
1988
+
1989
+ /**
1990
+ * Get a type from the registry.
1991
+ * Returns the type if registered, undefined otherwise.
1992
+ *
1993
+ * For use in \\@Field(() => getType('TypeName')) decorators.
1994
+ */
1995
+ export function getType<T = unknown>(name: string): T {
1996
+ const type = registry.get(name);
1997
+ if (type === undefined && registrationComplete) {
1998
+ console.warn(\`[nestjs-prisma-graphql] Warning: Type "\${name}" not found in registry. Ensure register-all-types is imported before using generated types.\`);
1999
+ }
2000
+ return type as T;
2001
+ }
2002
+
2003
+ /**
2004
+ * Create a forward reference to a type that may not be registered yet.
2005
+ * This is useful for handling circular dependencies where type A references type B
2006
+ * and type B references type A.
2007
+ *
2008
+ * Usage: \\@Field(() => forwardRef('Post'))
2009
+ */
2010
+ export function forwardRef<T = unknown>(name: string): () => T {
2011
+ return () => {
2012
+ const type = registry.get(name);
2013
+ if (type === undefined) {
2014
+ throw new Error(
2015
+ \`[nestjs-prisma-graphql] Type "\${name}" not registered. \\n\` +
2016
+ \`This usually means:\\n\` +
2017
+ \` 1. The register-all-types.ts file was not imported early enough\\n\` +
2018
+ \` 2. There's a circular dependency that couldn't be resolved\\n\` +
2019
+ \` 3. The type file failed to load\\n\\n\` +
2020
+ \`Make sure to import 'register-all-types' at the top of your main.ts or app.module.ts\`
2021
+ );
2022
+ }
2023
+ return type as T;
2024
+ };
2025
+ }
2026
+
2027
+ /**
2028
+ * Lazily resolve a type, returning a thunk that can be called later.
2029
+ * This is the safest pattern for circular references in ESM.
2030
+ *
2031
+ * Usage: \\@Field(lazyType('Post'))
2032
+ */
2033
+ export function lazyType<T = unknown>(name: string): () => T {
2034
+ return () => getType<T>(name);
2035
+ }
2036
+
2037
+ /**
2038
+ * Mark registration as complete. Called after all types are imported.
2039
+ * This enables warning messages for missing types.
2040
+ */
2041
+ export function markRegistrationComplete(): void {
2042
+ registrationComplete = true;
2043
+
2044
+ // Warn about any unresolved forward refs
2045
+ if (pendingResolutions.size > 0) {
2046
+ const missing = Array.from(pendingResolutions.keys()).join(', ');
2047
+ console.warn(\`[nestjs-prisma-graphql] Warning: Unresolved forward references: \${missing}\`);
2048
+ }
2049
+ }
2050
+
2051
+ /**
2052
+ * Get all registered type names (useful for debugging)
2053
+ */
2054
+ export function getRegisteredTypes(): string[] {
2055
+ return Array.from(registry.keys());
2056
+ }
2057
+
2058
+ /**
2059
+ * Check if a type is registered
2060
+ */
2061
+ export function isTypeRegistered(name: string): boolean {
2062
+ return registry.has(name);
2063
+ }
2064
+
2065
+ /**
2066
+ * Validate that all expected types are registered.
2067
+ * Throws an error if any types are missing.
2068
+ */
2069
+ export function validateRegistry(expectedTypes: string[]): void {
2070
+ const missing = expectedTypes.filter(name => !registry.has(name));
2071
+ if (missing.length > 0) {
2072
+ throw new Error(
2073
+ \`[nestjs-prisma-graphql] Missing type registrations: \${missing.join(', ')}\\n\` +
2074
+ \`Ensure register-all-types.ts is imported before using these types.\`
2075
+ );
2076
+ }
2077
+ }
2078
+ `;
2079
+ sourceFile.addStatements(registryCode);
2080
+ }
2081
+
2082
+ // src/handlers/warning.ts
2083
+ function warning(message) {
2084
+ if (Array.isArray(message)) {
2085
+ console.log("nestjs-prisma-graphql:");
2086
+ console.log(message.join("\n"));
2087
+ } else {
2088
+ console.log("nestjs-prisma-graphql:", message);
2089
+ }
2090
+ }
2091
+
2092
+ // src/helpers/create-emit-blocks.ts
2093
+ var allEmmittedBlocks = [
2094
+ "prismaEnums",
2095
+ "schemaEnums",
2096
+ "models",
2097
+ "inputs",
2098
+ "args",
2099
+ "outputs"
2100
+ ];
2101
+ var blocksDependencyMap = {
2102
+ enums: ["schemaEnums", "prismaEnums"],
2103
+ models: ["models", "schemaEnums"],
2104
+ inputs: ["inputs", "prismaEnums"],
2105
+ outputs: ["outputs"],
2106
+ args: ["args", "inputs", "prismaEnums"]
2107
+ };
2108
+ function createEmitBlocks(data) {
2109
+ if (!data) {
2110
+ return Object.fromEntries(allEmmittedBlocks.map((block) => [block, true]));
2111
+ }
2112
+ let blocksToEmit = {};
2113
+ for (const block of data) {
2114
+ if (!Object.keys(blocksDependencyMap).includes(block)) continue;
2115
+ blocksToEmit = {
2116
+ ...blocksToEmit,
2117
+ ...Object.fromEntries(
2118
+ blocksDependencyMap[block].map((block2) => [block2, true])
2119
+ )
2120
+ };
2121
+ }
2122
+ return blocksToEmit;
2123
+ }
2124
+
2125
+ // src/helpers/create-config.ts
2126
+ function createConfig(data) {
2127
+ const config = merge({}, unflatten(data, { delimiter: "_" }));
2128
+ const $warnings = [];
2129
+ const configOutputFilePattern = String(
2130
+ config.outputFilePattern || `{model}/{name}.{type}.ts`
2131
+ );
2132
+ let outputFilePattern = filenamify(configOutputFilePattern, {
2133
+ replacement: "/"
2134
+ }).replaceAll("..", "/").replaceAll(/\/+/g, "/");
2135
+ outputFilePattern = trim(outputFilePattern, "/");
2136
+ if (outputFilePattern !== configOutputFilePattern) {
2137
+ $warnings.push(
2138
+ `Due to invalid filepath 'outputFilePattern' changed to '${outputFilePattern}'`
2139
+ );
2140
+ }
2141
+ if (config.reExportAll) {
2142
+ $warnings.push(`Option 'reExportAll' is deprecated, use 'reExport' instead`);
2143
+ if (toBoolean(config.reExportAll)) {
2144
+ config.reExport = "All";
2145
+ }
2146
+ }
2147
+ const fields = Object.fromEntries(
2148
+ Object.entries(
2149
+ config.fields ?? {}
2150
+ ).filter(({ 1: value }) => typeof value === "object").map(([name, value]) => {
2151
+ const fieldSetting = {
2152
+ arguments: [],
2153
+ output: toBoolean(value.output),
2154
+ input: toBoolean(value.input),
2155
+ model: toBoolean(value.model),
2156
+ from: value.from,
2157
+ defaultImport: toBoolean(value.defaultImport) ? true : value.defaultImport,
2158
+ namespaceImport: value.namespaceImport
2159
+ };
2160
+ return [name, fieldSetting];
2161
+ })
2162
+ );
2163
+ const decorate = [];
2164
+ const configDecorate = Object.values(
2165
+ config.decorate || {}
2166
+ );
2167
+ for (const element of configDecorate) {
2168
+ if (!element) continue;
2169
+ ok(
2170
+ element.from && element.name,
2171
+ `Missed 'from' or 'name' part in configuration for decorate`
2172
+ );
2173
+ decorate.push({
2174
+ isMatchField: outmatch2(element.field, { separator: false }),
2175
+ isMatchType: outmatch2(element.type, { separator: false }),
2176
+ from: element.from,
2177
+ name: element.name,
2178
+ namedImport: toBoolean(element.namedImport),
2179
+ defaultImport: toBoolean(element.defaultImport) ? true : element.defaultImport,
2180
+ namespaceImport: element.namespaceImport,
2181
+ arguments: element.arguments ? JSON52.parse(element.arguments) : void 0
2182
+ });
2183
+ }
2184
+ const customImport = [];
2185
+ const configCustomImport = Object.values(
2186
+ config.customImport || {}
2187
+ );
2188
+ for (const element of configCustomImport) {
2189
+ if (!element) continue;
2190
+ ok(
2191
+ element.from && element.name,
2192
+ `Missed 'from' or 'name' part in configuration for customImport`
2193
+ );
2194
+ customImport.push({
2195
+ from: element.from,
2196
+ name: element.name,
2197
+ namedImport: toBoolean(element.namedImport),
2198
+ defaultImport: toBoolean(element.defaultImport) ? true : element.defaultImport,
2199
+ namespaceImport: element.namespaceImport
2200
+ });
2201
+ }
2202
+ return {
2203
+ outputFilePattern,
2204
+ tsConfigFilePath: createTsConfigFilePathValue(config.tsConfigFilePath),
2205
+ prismaClientImport: createPrismaImport(config.prismaClientImport),
2206
+ combineScalarFilters: toBoolean(config.combineScalarFilters),
2207
+ noAtomicOperations: toBoolean(config.noAtomicOperations),
2208
+ reExport: ReExport[String(config.reExport)] || "None" /* None */,
2209
+ emitSingle: toBoolean(config.emitSingle),
2210
+ emitCompiled: toBoolean(config.emitCompiled),
2211
+ emitBlocks: createEmitBlocks(config.emitBlocks),
2212
+ omitModelsCount: toBoolean(config.omitModelsCount),
2213
+ $warnings,
2214
+ fields,
2215
+ purgeOutput: toBoolean(config.purgeOutput),
2216
+ useInputType: createUseInputType(config.useInputType),
2217
+ noTypeId: toBoolean(config.noTypeId),
2218
+ requireSingleFieldsInWhereUniqueInput: toBoolean(
2219
+ config.requireSingleFieldsInWhereUniqueInput
2220
+ ),
2221
+ unsafeCompatibleWhereUniqueInput: toBoolean(
2222
+ config.unsafeCompatibleWhereUniqueInput
2223
+ ),
2224
+ graphqlScalars: config.graphqlScalars || {},
2225
+ decorate,
2226
+ customImport,
2227
+ esmCompatible: toBoolean(config.esmCompatible)
2228
+ };
2229
+ }
2230
+ var tsConfigFileExists = memoize((filePath) => {
2231
+ return existsSync(filePath);
2232
+ });
2233
+ function createTsConfigFilePathValue(value) {
2234
+ if (typeof value === "string") return value;
2235
+ if (tsConfigFileExists("tsconfig.json")) return "tsconfig.json";
2236
+ }
2237
+ function createPrismaImport(value) {
2238
+ if (typeof value === "string") return value;
2239
+ return "@prisma/client";
2240
+ }
2241
+ function createUseInputType(data) {
2242
+ if (!data) {
2243
+ return [];
2244
+ }
2245
+ const result = [];
2246
+ for (const [typeName, useInputs] of Object.entries(data)) {
2247
+ const entry = {
2248
+ typeName,
2249
+ ALL: void 0
2250
+ };
2251
+ if (useInputs.ALL) {
2252
+ entry.ALL = useInputs.ALL;
2253
+ delete useInputs.ALL;
2254
+ }
2255
+ for (const [propertyName, pattern] of Object.entries(useInputs)) {
2256
+ entry[propertyName] = pattern;
2257
+ }
2258
+ result.push(entry);
2259
+ }
2260
+ return result;
2261
+ }
2262
+ function toBoolean(value) {
2263
+ return ["true", "1", "on"].includes(String(value));
2264
+ }
2265
+ function generateFileName(args) {
2266
+ const { getModelName: getModelName2, name, template, type } = args;
2267
+ return pupa(template, {
2268
+ get model() {
2269
+ const result = getModelName2(name) || "prisma";
2270
+ return kebabCase(result);
2271
+ },
2272
+ get name() {
2273
+ let result = kebabCase(name);
2274
+ for (const suffix of ["input", "args", "enum"]) {
2275
+ const ending = `-${suffix}`;
2276
+ if (type === suffix && result.endsWith(ending)) {
2277
+ result = result.slice(0, -ending.length);
2278
+ }
2279
+ }
2280
+ return result;
2281
+ },
2282
+ plural: {
2283
+ get type() {
2284
+ return pluralize(type);
2285
+ }
2286
+ },
2287
+ type
2288
+ });
2289
+ }
2290
+
2291
+ // src/helpers/factory-get-source-file.ts
2292
+ function factoryGetSourceFile(args) {
2293
+ const { outputFilePattern, output, getModelName: getModelName2, project } = args;
2294
+ return function getSourceFile(args2) {
2295
+ const { name, type } = args2;
2296
+ let filePath = generateFileName({
2297
+ getModelName: getModelName2,
2298
+ name,
2299
+ type,
2300
+ template: outputFilePattern
2301
+ });
2302
+ filePath = `${output}/${filePath}`;
2303
+ return project.getSourceFile(filePath) || project.createSourceFile(filePath, void 0, { overwrite: true });
2304
+ };
2305
+ }
2306
+ function createGetModelName(modelNames) {
2307
+ return memoize(tryGetName);
2308
+ function tryGetName(name) {
2309
+ return getModelName({ modelNames, name });
2310
+ }
2311
+ }
2312
+ function getModelName(args) {
2313
+ const { modelNames, name } = args;
2314
+ for (const keyword of splitKeywords) {
2315
+ const [test] = name.split(keyword, 1);
2316
+ if (modelNames.includes(test)) {
2317
+ return test;
2318
+ }
2319
+ }
2320
+ for (const keyword of endsWithKeywords) {
2321
+ const [test] = name.split(keyword).slice(-1);
2322
+ if (modelNames.includes(test)) {
2323
+ return test;
2324
+ }
2325
+ }
2326
+ for (const [start, end2] of middleKeywords) {
2327
+ let test = name.slice(start.length).slice(0, -end2.length);
2328
+ if (modelNames.includes(test) && name.startsWith(start) && name.endsWith(end2)) {
2329
+ return test;
2330
+ }
2331
+ test = name.slice(0, -(start + end2).length);
2332
+ if (modelNames.includes(test) && name.endsWith(start + end2)) {
2333
+ return test;
2334
+ }
2335
+ }
2336
+ if (name.slice(-19) === "CompoundUniqueInput") {
2337
+ const test = name.slice(0, -19);
2338
+ const models = modelNames.filter((x) => test.startsWith(x)).sort((a, b) => b.length - a.length);
2339
+ return models[0];
2340
+ }
2341
+ if (name.slice(-5) === "Count") {
2342
+ const test = name.slice(0, -5);
2343
+ if (modelNames.includes(test)) {
2344
+ return test;
2345
+ }
2346
+ }
2347
+ }
2348
+ var splitKeywords = [
2349
+ "CreateInput",
2350
+ "CreateMany",
2351
+ "CreateNested",
2352
+ "CreateOneWithout",
2353
+ "CreateOrConnect",
2354
+ "CreateWithout",
2355
+ "DistinctField",
2356
+ "Filter",
2357
+ "ManyWithout",
2358
+ "OrderByInput",
2359
+ "RelationFilter",
2360
+ "NullableRelationFilter",
2361
+ "ListRelationFilter",
2362
+ "ScalarWhereInput",
2363
+ "UpdateInput",
2364
+ "UpdateMany",
2365
+ "UpdateOneRequiredWithout",
2366
+ "UpdateOneWithout",
2367
+ "UpdateWith",
2368
+ "UpsertWith",
2369
+ "UpsertWithout",
2370
+ "WhereInput",
2371
+ "WhereUniqueInput",
2372
+ "AvgAggregate",
2373
+ "SumAggregate",
2374
+ "MinAggregate",
2375
+ "MaxAggregate",
2376
+ "CountAggregate",
2377
+ "ScalarField",
2378
+ "GroupBy",
2379
+ "OrderBy",
2380
+ "UncheckedUpdate",
2381
+ "UncheckedCreate",
2382
+ "ScalarWhere",
2383
+ "CountOutputType",
2384
+ "CountOrderBy",
2385
+ "SumOrderBy",
2386
+ "MinOrderBy",
2387
+ "MaxOrderBy",
2388
+ "AvgOrderBy",
2389
+ "Create",
2390
+ "Update",
2391
+ "ScalarRelationFilter",
2392
+ "NullableScalarRelationFilter"
2393
+ ].sort((a, b) => b.length - a.length);
2394
+ var endsWithKeywords = [
2395
+ "Aggregate",
2396
+ "GroupBy",
2397
+ "CreateOne",
2398
+ "CreateMany",
2399
+ "DeleteMany",
2400
+ "DeleteOne",
2401
+ "FindMany",
2402
+ "FindOne",
2403
+ "FindUnique",
2404
+ "UpdateMany",
2405
+ "UpdateOne",
2406
+ "UpsertOne"
2407
+ ];
2408
+ var middleKeywords = [
2409
+ ["FindFirst", "OrThrowArgs"],
2410
+ ["FindUnique", "OrThrowArgs"],
2411
+ ["Aggregate", "Args"],
2412
+ ["CreateOne", "Args"],
2413
+ ["CreateMany", "Args"],
2414
+ ["DeleteMany", "Args"],
2415
+ ["DeleteOne", "Args"],
2416
+ ["FindMany", "Args"],
2417
+ ["FindFirst", "Args"],
2418
+ ["FindOne", "Args"],
2419
+ ["FindUnique", "Args"],
2420
+ ["UpdateMany", "Args"],
2421
+ ["UpdateMany", "AndReturnOutputType"],
2422
+ ["UpdateOne", "Args"],
2423
+ ["UpsertOne", "Args"],
2424
+ ["GroupBy", "Args"],
2425
+ ["OrderBy", "Args"]
2426
+ ];
2427
+
2428
+ // src/generate.ts
2429
+ var AwaitEventEmitter = __require("await-event-emitter").default;
2430
+ async function generate(args) {
2431
+ const { connectCallback, dmmf, generator, skipAddOutputSourceFiles } = args;
2432
+ const generatorOutputValue = generator.output?.value;
2433
+ ok(generatorOutputValue, "Missing generator configuration: output");
2434
+ const config = createConfig(generator.config);
2435
+ const eventEmitter = new AwaitEventEmitter();
2436
+ eventEmitter.on("Warning", warning);
2437
+ config.emitBlocks.models && eventEmitter.on("Model", modelData);
2438
+ if (config.emitBlocks.prismaEnums || config.emitBlocks.schemaEnums) {
2439
+ eventEmitter.on("EnumType", registerEnum);
2440
+ }
2441
+ if (config.emitBlocks.outputs || config.emitBlocks.models && !config.omitModelsCount) {
2442
+ eventEmitter.on("OutputType", outputType);
2443
+ }
2444
+ config.emitBlocks.models && eventEmitter.on("ModelOutputType", modelOutputType);
2445
+ config.emitBlocks.outputs && eventEmitter.on("AggregateOutput", createAggregateInput);
2446
+ config.emitBlocks.inputs && eventEmitter.on("InputType", inputType);
2447
+ config.emitBlocks.args && eventEmitter.on("ArgsType", argsType);
2448
+ eventEmitter.on("GenerateFiles", generateFiles);
2449
+ for (const message of config.$warnings) {
2450
+ eventEmitter.emitSync("Warning", message);
2451
+ }
2452
+ const project = new Project({
2453
+ manipulationSettings: {
2454
+ quoteKind: QuoteKind.Single
2455
+ },
2456
+ skipAddingFilesFromTsConfig: true,
2457
+ skipLoadingLibFiles: !config.emitCompiled,
2458
+ tsConfigFilePath: config.tsConfigFilePath
2459
+ });
2460
+ if (!skipAddOutputSourceFiles) {
2461
+ project.addSourceFilesAtPaths([
2462
+ `${generatorOutputValue}/**/*.ts`,
2463
+ `!${generatorOutputValue}/**/*.d.ts`
2464
+ ]);
2465
+ }
2466
+ config.combineScalarFilters && combineScalarFilters(eventEmitter);
2467
+ config.noAtomicOperations && noAtomicOperations(eventEmitter);
2468
+ config.reExport !== "None" /* None */ && reExport(eventEmitter);
2469
+ config.emitSingle && emitSingle(eventEmitter);
2470
+ config.purgeOutput && purgeOutput(eventEmitter);
2471
+ config.requireSingleFieldsInWhereUniqueInput && requireSingleFieldsInWhereUniqueInput(eventEmitter);
2472
+ const models = /* @__PURE__ */ new Map();
2473
+ const modelNames = [];
2474
+ const modelFields = /* @__PURE__ */ new Map();
2475
+ const fieldSettings = /* @__PURE__ */ new Map();
2476
+ const getModelName2 = createGetModelName(modelNames);
2477
+ const getSourceFile = factoryGetSourceFile({
2478
+ getModelName: getModelName2,
2479
+ output: generatorOutputValue,
2480
+ outputFilePattern: config.outputFilePattern,
2481
+ project
2482
+ });
2483
+ const { datamodel, schema } = JSON.parse(JSON.stringify(dmmf));
2484
+ const removeTypes = /* @__PURE__ */ new Set();
2485
+ const allModels = [...datamodel.models, ...datamodel.types ?? []];
2486
+ const dependencyGraph = buildDependencyGraph(allModels);
2487
+ const circularDependencies = detectCircularDependencies(dependencyGraph);
2488
+ const eventArguments = {
2489
+ circularDependencies,
2490
+ classTransformerTypeModels: /* @__PURE__ */ new Set(),
2491
+ config,
2492
+ enums: mapKeys(datamodel.enums, (x) => x.name),
2493
+ eventEmitter,
2494
+ fieldSettings,
2495
+ getModelName: getModelName2,
2496
+ getSourceFile,
2497
+ modelFields,
2498
+ modelNames,
2499
+ models,
2500
+ output: generatorOutputValue,
2501
+ project,
2502
+ removeTypes,
2503
+ schema,
2504
+ typeNames: /* @__PURE__ */ new Set()
2505
+ };
2506
+ if (connectCallback) {
2507
+ await connectCallback(eventEmitter, eventArguments);
2508
+ }
2509
+ await eventEmitter.emit("Begin", eventArguments);
2510
+ if (config.esmCompatible) {
2511
+ generateTypeRegistry(eventArguments);
2512
+ }
2513
+ for (const model of datamodel.models) {
2514
+ await eventEmitter.emit("Model", model, eventArguments);
2515
+ }
2516
+ for (const model of datamodel.types ?? []) {
2517
+ await eventEmitter.emit("Model", model, eventArguments);
2518
+ }
2519
+ const { enumTypes, inputObjectTypes, outputObjectTypes } = schema;
2520
+ await eventEmitter.emit("PostBegin", eventArguments);
2521
+ for (const enumType of enumTypes.prisma.concat(enumTypes.model ?? [])) {
2522
+ await eventEmitter.emit("EnumType", enumType, eventArguments);
2523
+ }
2524
+ for (const outputTypeItem of outputObjectTypes.model) {
2525
+ await eventEmitter.emit("ModelOutputType", outputTypeItem, eventArguments);
2526
+ }
2527
+ const queryOutputTypes = [];
2528
+ for (const outputTypeItem of outputObjectTypes.prisma) {
2529
+ if (["Query", "Mutation"].includes(outputTypeItem.name)) {
2530
+ queryOutputTypes.push(outputTypeItem);
2531
+ continue;
2532
+ }
2533
+ await eventEmitter.emit("OutputType", outputTypeItem, eventArguments);
2534
+ }
2535
+ const inputTypes = (inputObjectTypes.prisma ?? []).concat(inputObjectTypes.model ?? []);
2536
+ for (const inputTypeItem of inputTypes) {
2537
+ const event = {
2538
+ ...eventArguments,
2539
+ classDecoratorName: "InputType",
2540
+ fileType: "input",
2541
+ inputType: inputTypeItem
2542
+ };
2543
+ if (inputTypeItem.fields.length === 0) {
2544
+ removeTypes.add(inputTypeItem.name);
2545
+ continue;
2546
+ }
2547
+ await eventEmitter.emit("BeforeInputType", event);
2548
+ await eventEmitter.emit("InputType", event);
2549
+ }
2550
+ for (const outputTypeItem of queryOutputTypes) {
2551
+ for (const field of outputTypeItem.fields) {
2552
+ await eventEmitter.emit("ArgsType", field, eventArguments);
2553
+ }
2554
+ }
2555
+ if (config.esmCompatible) {
2556
+ generateRegisterAllTypes(eventArguments);
2557
+ }
2558
+ await eventEmitter.emit("BeforeGenerateFiles", eventArguments);
2559
+ await eventEmitter.emit("GenerateFiles", eventArguments);
2560
+ await eventEmitter.emit("End", eventArguments);
2561
+ for (const name of Object.keys(eventEmitter._events)) {
2562
+ eventEmitter.off(name);
2563
+ }
2564
+ }
2565
+
2566
+ // src/index.ts
2567
+ function isGeneratorDisabled(options, env = process.env) {
2568
+ const envVarsToCheck = [
2569
+ "DISABLE_NESTJS_PRISMA_GRAPHQL",
2570
+ // Most specific
2571
+ "CI_SKIP_PRISMA_GRAPHQL",
2572
+ // CI-specific
2573
+ "PRISMA_GENERATOR_SKIP",
2574
+ // Common convention
2575
+ "SKIP_PRISMA_GENERATE"
2576
+ // Alternative
2577
+ ];
2578
+ for (const envVar of envVarsToCheck) {
2579
+ const value = env[envVar];
2580
+ if (value === "true" || value === "1") {
2581
+ return true;
2582
+ }
2583
+ }
2584
+ const configDisabled = options.generator.config["disabled"];
2585
+ if (configDisabled === "true" || configDisabled === "1" || configDisabled === "yes") {
2586
+ return true;
2587
+ }
2588
+ return false;
2589
+ }
2590
+ generatorHandler({
2591
+ async onGenerate(options) {
2592
+ if (isGeneratorDisabled(options)) {
2593
+ console.log("\u23ED\uFE0F nestjs-prisma-graphql: Generation skipped (disabled via environment variable or config)");
2594
+ return;
2595
+ }
2596
+ await generate(options);
2597
+ },
2598
+ onManifest() {
2599
+ return {
2600
+ defaultOutput: ".",
2601
+ prettyName: "NestJS Prisma GraphQL (ESM)"
2602
+ };
2603
+ }
2604
+ });
2605
+
2606
+ export { isGeneratorDisabled };
2607
+ //# sourceMappingURL=index.js.map
2608
+ //# sourceMappingURL=index.js.map