Skip to content

Commit

Permalink
fix: update resolver generator to add types to @Args
Browse files Browse the repository at this point in the history
  • Loading branch information
rintoj committed Jun 9, 2024
1 parent b6235df commit 6d9d992
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 42 deletions.
72 changes: 53 additions & 19 deletions src/gql/gql-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,25 +245,57 @@ export function createParentDecorator(context: Context) {
export function createArgsDecorator(node: ts.ParameterDeclaration, context: Context) {
context.imports.push(createImport('@nestjs/graphql', 'Args'))
const name = getName(node)
const type = getType(node) ?? getTypeFromDecorator(node, 'Args')
const argumentsArray: ts.Expression[] = []
if (type && !['string', 'boolean'].includes(type)) {
argumentsArray.push(
factory.createObjectLiteralExpression(
toNonNullArray([
factory.createPropertyAssignment(
factory.createIdentifier('name'),
factory.createStringLiteral(name),
),
factory.createPropertyAssignment(
factory.createIdentifier('type'),
factory.createArrowFunction(
undefined,
undefined,
[],
undefined,
factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
factory.createIdentifier(type),
),
),
isNullable(node)
? factory.createPropertyAssignment(
factory.createIdentifier('nullable'),
factory.createTrue(),
)
: (undefined as any),
]),
),
)
} else {
argumentsArray.push(factory.createStringLiteral(name))
if (isNullable(node)) {
argumentsArray.push(
factory.createObjectLiteralExpression(
[
factory.createPropertyAssignment(
factory.createIdentifier('nullable'),
factory.createTrue(),
),
],
false,
),
)
}
}
if (type && ['ID', 'INT'].includes(type)) {
context.imports.push(createImport('@nestjs/graphql', type))
}
return factory.createDecorator(
factory.createCallExpression(
factory.createIdentifier('Args'),
undefined,
toNonNullArray([
factory.createStringLiteral(name),
isNullable(node)
? factory.createObjectLiteralExpression(
[
factory.createPropertyAssignment(
factory.createIdentifier('nullable'),
factory.createTrue(),
),
],
false,
)
: (undefined as any),
]),
),
factory.createCallExpression(factory.createIdentifier('Args'), undefined, argumentsArray),
)
}

Expand Down Expand Up @@ -419,7 +451,9 @@ export function createPromiseType(...types: string[]) {
return factory.createTypeReferenceNode(factory.createIdentifier('Promise'), [innerType])
}

export function getType(node: ts.PropertyDeclaration | ts.MethodDeclaration) {
export function getType(
node: ts.PropertyDeclaration | ts.ParameterDeclaration | ts.MethodDeclaration,
) {
const typeFromDecorator = getTypeFromDecorator(node, 'Field')
if (typeFromDecorator) return typeFromDecorator
if (getName(node) === 'id') return 'ID'
Expand Down
74 changes: 52 additions & 22 deletions src/gql/resolver/resolver-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,36 @@ describe('generateResolver', () => {
)
})

test('should generate paginated model', async () => {
const output = await generate(
'user.resolver.ts',
`
@Resolver(() => UserModel)
class UserResolver {
@ResolveField()
findAll(context, page?: Page): Users { }
}
`,
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, ResolveField, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver {
@ResolveField(() => Users)
findAll(
@Context()
context: GQLContext,
@Args({ name: 'page', type: () => Page, nullable: true })
page?: Page,
): Users {}
}
`),
)
})

test('should use the correct model name', async () => {
const output = await generate(
'user.resolver.ts',
Expand Down Expand Up @@ -181,7 +211,7 @@ describe('generateResolver', () => {
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, Query, Resolver } from '@nestjs/graphql'
import { Args, Context, ID, Query, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
Expand All @@ -190,7 +220,7 @@ describe('generateResolver', () => {
@Context()
context: GQLContext,
@Args('id')
@Args({ name: 'id', type: () => ID })
id: string,
): User | null {}
}
Expand All @@ -212,13 +242,13 @@ describe('generateResolver', () => {
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, Parent, Query, Resolver } from '@nestjs/graphql'
import { Args, Context, ID, Parent, Query, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Query(() => User)
user(
@Args('id')
@Args({ name: 'id', type: () => ID })
id: string,
@Parent()
Expand Down Expand Up @@ -246,7 +276,7 @@ describe('generateResolver', () => {
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, Query, Resolver } from '@nestjs/graphql'
import { Args, Context, ID, Query, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
Expand All @@ -255,7 +285,7 @@ describe('generateResolver', () => {
@Context()
context: GQLContext,
@Args('id', { nullable: true })
@Args({ name: 'id', type: () => ID, nullable: true })
id?: string,
): User | null {}
}
Expand All @@ -277,7 +307,7 @@ describe('generateResolver', () => {
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, ResolveField, Resolver } from '@nestjs/graphql'
import { Args, Context, ID, ResolveField, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
Expand All @@ -286,7 +316,7 @@ describe('generateResolver', () => {
@Context()
context: GQLContext,
@Args('id', { nullable: true })
@Args({ name: 'id', type: () => ID, nullable: true })
id?: string,
) {}
}
Expand All @@ -308,7 +338,7 @@ describe('generateResolver', () => {
)
expect(toParsedOutput(output)).toBe(
toParsedOutput(`
import { Args, Context, ResolveField, Resolver } from '@nestjs/graphql'
import { Args, Context, ID, ResolveField, Resolver } from '@nestjs/graphql'
@Resolver(() => UserModel)
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
Expand All @@ -317,7 +347,7 @@ describe('generateResolver', () => {
@Context()
context: GQLContext,
@Args('id', { nullable: true })
@Args({ name: 'id', type: () => ID, nullable: true })
id?: string,
): User | null {}
}
Expand All @@ -331,7 +361,7 @@ describe('generateResolver', () => {
`
class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Mutation(() => User)
user(context, id, parent): User {
user(context, userId, parent): User {
}
}
Expand All @@ -348,8 +378,8 @@ describe('generateResolver', () => {
@Context()
context: GQLContext,
@Args('id')
id: string,
@Args('userId')
userId: string,
@Parent()
parent: UserAPIType,
Expand All @@ -365,7 +395,7 @@ describe('generateResolver', () => {
`
class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Mutation()
createUser(id?: string): User | null {
createUser(userId?: string): User | null {
}
}
Expand All @@ -379,8 +409,8 @@ describe('generateResolver', () => {
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Mutation(() => User, { nullable: true })
createUser(
@Args('id', { nullable: true })
id?: string,
@Args('userId', { nullable: true })
userId?: string,
): User | null {}
}
`),
Expand All @@ -393,7 +423,7 @@ describe('generateResolver', () => {
`
class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Query()
user(id?: string): Promise<User | null> {
user(userId?: string): Promise<User | null> {
}
}
Expand All @@ -407,8 +437,8 @@ describe('generateResolver', () => {
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Query(() => User, { nullable: true })
user(
@Args('id', { nullable: true })
id?: string,
@Args('userId', { nullable: true })
userId?: string,
): User | null {}
}
`),
Expand All @@ -421,7 +451,7 @@ describe('generateResolver', () => {
`
class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Query()
async user(id?: string): Promise<User | null> {
async user(userId?: string): Promise<User | null> {
}
}
Expand All @@ -435,8 +465,8 @@ describe('generateResolver', () => {
export class UserResolver implements FieldResolver<UserModel, UserAPIType> {
@Query(() => User, { nullable: true })
async user(
@Args('id', { nullable: true })
id?: string,
@Args('userId', { nullable: true })
userId?: string,
): Promise<User | null> {}
}
`),
Expand Down
2 changes: 1 addition & 1 deletion src/gql/resolver/resolver-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,13 @@ function processClassDeclaration(classDeclaration: ts.ClassDeclaration, context:
),
),
node => {
const fieldDecoratorType = getFieldDecoratorType(node)
if (
ts.isMethodDeclaration(node) ||
(ts.isPropertyDeclaration(node) && node.type && ts.isFunctionTypeNode(node.type))
) {
const method = convertToMethod(node as any, ts.isPropertyDeclaration(node))
if (method) {
const fieldDecoratorType = getFieldDecoratorType(method)
return addDecorator(
processParameters(
processReturnType(removeNullability(transformName(method, toCamelCase)), context),
Expand Down

0 comments on commit 6d9d992

Please sign in to comment.