Skip to content

Commit

Permalink
fix: Conflict with models ending with Output
Browse files Browse the repository at this point in the history
closes: #10
  • Loading branch information
unlight committed Mar 4, 2021
1 parent f22632a commit a08d4c4
Show file tree
Hide file tree
Showing 15 changed files with 273 additions and 117 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Possible tokens:

Combine nested/nullable scalar filters to single
Type: `boolean`
Default: `true`
Default: `false`

#### `noAtomicOperations`

Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-create-many.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class DummyCreateManyInput {
})
bigInt?: BigInt;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-create.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class DummyCreateInput {
})
bigInt?: BigInt;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-unchecked-create.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class DummyUncheckedCreateInput {
})
bigInt?: BigInt;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-unchecked-update.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class DummyUncheckedUpdateInput {
})
bigInt?: NullableBigIntFieldUpdateOperationsInput;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-update-many-mutation.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class DummyUpdateManyMutationInput {
})
bigInt?: NullableBigIntFieldUpdateOperationsInput;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
2 changes: 1 addition & 1 deletion src/@generated/dummy/dummy-update.input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class DummyUpdateInput {
})
bigInt?: NullableBigIntFieldUpdateOperationsInput;

@Field(() => String, {
@Field(() => GraphQLJSON, {
nullable: true,
})
json?: any;
Expand Down
46 changes: 44 additions & 2 deletions src/generate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ describe('model with one id int', () => {
});
});

describe('user count aggregate', () => {
describe('user count aggregate (UserCountAggregate)', () => {
before(() => {
sourceFile = project.getSourceFile(s =>
s.getFilePath().endsWith('user-count-aggregate.output.ts'),
Expand All @@ -168,8 +168,9 @@ describe('model with one id int', () => {
?.getStructure()!;
});

it('should be number', () => {
it('id property should be Int/number', () => {
expect(propertyStructure.type).toEqual('number');
expect(d('id')?.arguments?.[0]).toEqual('() => Int');
});

it('should be not null', () => {
Expand Down Expand Up @@ -1258,4 +1259,45 @@ describe('hide field', () => {
});
});

it('model with prisma keyword output', async () => {
await testGenerate({
schema: `
model Output {
id Int @id
}
model Aggregate {
id Int @id
output Output
x XOutput
}
model XOutput {
id Int @id
}
`,
options: [`outputFilePattern = "{name}.{type}.ts"`],
});
});

// const a = sourceFiles.map(s => s.getFilePath());
// sourceFile = sourceFiles.find(s =>
// s.getFilePath().endsWith('aggregate.output.ts'),
// )!;
// console.log('sourceFile.getText()', sourceFile.getText());
// // console.log('a', a);
// it.only('only', async () => {
// await testGenerate({
// schema: `
// model BuildOutput {
// id String @id
// BuildAction BuildAction[]
// }
// model BuildAction {
// id String @id
// output BuildOutput
// }
// `,
// options: [],
// });
// });

// it('^', () => console.log(sourceFile.getText()));
17 changes: 14 additions & 3 deletions src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { createAggregateInput } from './handlers/create-aggregate-input';
import { generateFiles } from './handlers/generate-files';
import { inputType } from './handlers/input-type';
import { modelData } from './handlers/model-data';
import { modelOutputType } from './handlers/model-output-type';
import { noAtomicOperations } from './handlers/no-atomic-operations';
import { outputType } from './handlers/output-type';
import { reExportAll } from './handlers/re-export-all';
Expand All @@ -32,8 +33,13 @@ export async function generate(
x => x.provider === 'prisma-client-js',
)?.output;
assert(prismaClientOutput, 'prismaClientOutput');
const prismaClientDmmf =
args.prismaClientDmmf ?? (require(prismaClientOutput).dmmf as DMMF.Document);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const prismaClientDmmf = JSON.parse(
JSON.stringify(
args.prismaClientDmmf ??
(require(prismaClientOutput).dmmf as DMMF.Document),
),
);
const project = new Project({
useInMemoryFileSystem: true,
manipulationSettings: {
Expand All @@ -46,6 +52,7 @@ export async function generate(
eventEmitter.on('Model', modelData);
eventEmitter.on('EnumType', registerEnum);
eventEmitter.on('OutputType', outputType);
eventEmitter.on('ModelOutputType', modelOutputType);
eventEmitter.on('AggregateOutput', createAggregateInput);
eventEmitter.on('InputType', inputType);
eventEmitter.on('InputType', typeNames);
Expand Down Expand Up @@ -101,7 +108,11 @@ export async function generate(
await eventEmitter.emit('EnumType', enumType, eventArguments);
}

for (const outputType of outputObjectTypes.prisma.concat(outputObjectTypes.model)) {
for (const outputType of outputObjectTypes.model) {
await eventEmitter.emit('ModelOutputType', outputType, eventArguments);
}

for (const outputType of outputObjectTypes.prisma) {
await eventEmitter.emit('OutputType', outputType, eventArguments);
}

Expand Down
2 changes: 1 addition & 1 deletion src/handlers/create-aggregate-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EventArguments, InputType, OutputType } from '../types';
/**
* Create aggregate inputs from aggregate outputs.
* See client/src/generation/TSClient.ts @ getAggregationTypes
* Subcribes on: AggregateOutput
* Subcribes on: 'AggregateOutput'
*/
export function createAggregateInput(
args: EventArguments & { outputType: OutputType },
Expand Down
155 changes: 155 additions & 0 deletions src/handlers/model-output-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import assert from 'assert';
import { CommentStatement } from 'ts-morph';

import { generateClass } from '../helpers/generate-class';
import { generateDecorator } from '../helpers/generate-decorator';
import { generateImport } from '../helpers/generate-import';
import { generateProperty } from '../helpers/generate-property';
import { getGraphqlImport } from '../helpers/get-graphql-import';
import { getGraphqlType } from '../helpers/get-graphql-type';
import { getPropertyType } from '../helpers/get-property-type';
import { EventArguments, OutputType } from '../types';

export function modelOutputType(outputType: OutputType, args: EventArguments) {
const { getSourceFile, models, config, modelFields } = args;

const model = models.get(outputType.name);
assert(model);
const fileType = 'model';
const sourceFile = getSourceFile({
name: outputType.name,
type: fileType,
});

const classDeclaration = generateClass({
decorator: {
name: 'ObjectType',
properties: [
{
name: 'description',
value: model.documentation,
},
],
},
sourceFile,
name: outputType.name,
});

generateImport({
sourceFile,
name: 'Field',
moduleSpecifier: '@nestjs/graphql',
});

for (const field of outputType.fields) {
// Do not generate already defined properties for model
if (classDeclaration.getProperty(field.name)) {
continue;
}

const { location, isList, type } = field.outputType;
const outputTypeName = String(type);
const modelField = modelFields.get(model.name)?.get(field.name);
const fieldMeta = modelField?.meta;
const customType = config.types[outputTypeName];

// console.log({
// 'field.outputType': field.outputType,
// 'outputType.name': outputType.name,
// 'model?.name': model?.name,
// outputTypeName,
// 'field.name': field.name,
// fieldMeta,
// });

const propertyType = customType?.fieldType
? [customType.fieldType]
: getPropertyType({
location,
type: outputTypeName,
});

const propertyDeclaration = generateProperty({
classDeclaration,
name: field.name,
isNullable: field.isNullable,
propertyType,
isList,
});

if (fieldMeta?.hideOutput) {
generateImport({
sourceFile,
name: 'HideField',
moduleSpecifier: '@nestjs/graphql',
});
propertyDeclaration.addDecorator({ name: 'HideField()' });
continue;
}

const graphqlType =
customType?.graphqlType ??
getGraphqlType({
location,
type: outputTypeName,
isId: modelField?.isId,
});

const graphqlImport = getGraphqlImport({
sourceFile,
fileType,
location,
isId: modelField?.isId,
name: graphqlType,
customType,
getSourceFile,
});

if (graphqlImport.name !== outputType.name && graphqlImport.specifier) {
generateImport({
sourceFile,
name: graphqlImport.name,
moduleSpecifier: graphqlImport.specifier,
});
}

// Create import for typescript field/property type
if (customType && customType.fieldModule && customType.fieldType) {
generateImport({
sourceFile,
name: customType.fieldType,
moduleSpecifier: customType.fieldModule,
});
}

generateDecorator({
propertyDeclaration,
graphqlType,
isList,
isNullable: field.isNullable,
defaultValue: modelField?.default,
description: modelField?.documentation,
});
}

// Check re-export, comment generated class if found
const exportDeclaration = sourceFile.getExportDeclaration(d => {
return d.getNamedExports().some(x => x.getNameNode().getText() === model.name);
});
if (exportDeclaration) {
let commentStatement: CommentStatement | undefined;
while (
(commentStatement = sourceFile.getStatementByKind(
2 /* SingleLineCommentTrivia */,
))
) {
commentStatement.remove();
}
const commentedText = classDeclaration
.getText()
.split('\n')
.map(x => `// ${x}`);
classDeclaration.remove();
sourceFile.addStatements(['\n', ...commentedText]);
}
}
Loading

0 comments on commit a08d4c4

Please sign in to comment.