Skip to content

Commit

Permalink
add generate input version in gql
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesxsh committed Sep 2, 2021
1 parent 21f597a commit 152fd3c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 21 deletions.
15 changes: 7 additions & 8 deletions examples/generated/controllers.ts
Expand Up @@ -42,13 +42,15 @@ export class BaseRequestDto {
@ApiPropertyOptional()
user: JwtUserDto;
}
export class UserChangeDto {
@ApiPropertyOptional()
name: string;
}
export class CreateUserRequestDto {
@ApiPropertyOptional()
id: number;
@ApiPropertyOptional()
name: string;
@ApiPropertyOptional()
age: number;
user: UserChangeDto;
}
export class CreateUserResponseDto {
@ApiPropertyOptional()
Expand All @@ -58,9 +60,7 @@ export class CreateUserRequestBodyDto {
@ApiPropertyOptional()
id: number;
@ApiPropertyOptional()
name: string;
@ApiPropertyOptional()
age: number;
user: UserChangeDto;
}
export class GetUserRequestDto {
@ApiPropertyOptional()
Expand Down Expand Up @@ -105,8 +105,7 @@ export class UserUsercaseController {
user) {
const ucReq = {
id: body.id,
name: body.name,
age: body.age,
user: body.user,
user
} as CreateUserRequest;
return this.userUsercase.createUser(ucReq);
Expand Down
8 changes: 6 additions & 2 deletions examples/generated/schema.graphql
Expand Up @@ -31,6 +31,9 @@ type UserProfile {
type BaseRequest {
user: JwtUser
}
type UserChange {
name: String
}
type GetUserResponse {
user: User
}
Expand All @@ -45,10 +48,11 @@ type CreateUserResponse {
}
input CreateUserRequest {
id: Int
user: UserChangeInput
}
input UserChangeInput {
name: String
age: Int
}

type Query {
getUser(request: GetUserRequest): GetUserResponse
me: MeResponse
Expand Down
6 changes: 4 additions & 2 deletions examples/generated/types.ts
Expand Up @@ -17,8 +17,7 @@ export interface JwtUser {
}
export interface CreateUserRequest extends BaseRequest {
id?: number;
name?: string;
age?: number;
user?: UserChange;
}
export interface CreateUserResponse {
user?: User;
Expand Down Expand Up @@ -68,3 +67,6 @@ export interface UserProfile {
export interface BaseRequest {
user?: JwtUser;
}
export interface UserChange {
name?: string;
}
12 changes: 7 additions & 5 deletions examples/user-usecase/defs/type.yaml
Expand Up @@ -23,7 +23,11 @@ types:
BaseRequest:
properties:
user:
type: JwtUser
type: JwtUser
UserChange:
properties:
name:
type: string

schemas:
UserResponse:
Expand Down Expand Up @@ -71,10 +75,8 @@ usecases:
properties:
id:
type: integer
name:
type: string
age:
type: integer
user:
type: UserChange
res:
$ref: '#/schemas/UserResponse'
gen:
Expand Down
47 changes: 43 additions & 4 deletions src/gen/graphql-schema.ts
Expand Up @@ -6,6 +6,8 @@ import { Register } from '../decorators';
interface GraphQLSchemaGeneratorExtension {
queries: string[];
mutations: string[];
// types mentioned in input, which need to generate input version
typeToInput: string[];
}

@Register('gql')
Expand All @@ -14,11 +16,24 @@ export class GraphQLSchemaGenerator extends Generator {
ctx.genExt['gql'] = {
queries: [],
mutations: [],
typeToInput: [],
} as GraphQLSchemaGeneratorExtension;
}
public after(ctx: GContext) {
const ext = ctx.genExt['gql'] as GraphQLSchemaGeneratorExtension;

if (ext.typeToInput) {
ext.typeToInput.forEach((ty) => {
const schema = ctx.getTypeSchemaByName(ty);
const str = this.genGqlType(
ctx,
schema,
this.getGqlInputTypeName(schema.name),
'input',
);
ctx.addStrToTextFile(this.output, str);
});
}
if (ext.queries) {
const queryStr = this.genGqlTypeRaw('Query', ext.queries);
ctx.addStrToTextFile(this.output, queryStr);
Expand All @@ -37,6 +52,11 @@ export class GraphQLSchemaGenerator extends Generator {
}
`;
}

private getGqlInputTypeName(tName: string): string {
return `${tName}Input`;
}

protected genTscaDef(ctx: GContext, def: TscaDef) {
def.types.forEach((ty) => this.genTscaSchema(ctx, ty, null));
const methods = def.usecases
Expand Down Expand Up @@ -70,20 +90,28 @@ export class GraphQLSchemaGenerator extends Generator {
if (schema.enum) {
str = this.genGqlEnum(schema);
} else {
str = this.genGqlType(schema, overrideName, type);
str = this.genGqlType(ctx, schema, overrideName, type);
}
str += '\n';
ctx.addStrToTextFile(this.output, str);
}

private genGqlType(
ctx: GContext,
schema: TscaSchema,
overrideName: string,
type = 'type',
): string {
let schemaStr = `${type} ${overrideName || schema.name} {\n`;
schema.properties?.forEach((prop) => {
const gqlTy = this.getGqlType(prop);
// to see if we need to generate input version of this type
if (type == 'input' && !this.isPrimitiveGqlTyoe(prop)) {
const ext = ctx.genExt['gql'] as GraphQLSchemaGeneratorExtension;
if (!ext.typeToInput.includes(prop.type)) {
ext.typeToInput.push(prop.type);
}
}
const gqlTy = this.getGqlType(prop, type == 'input');
const child = ` ${prop.name}: ${gqlTy}\n`;
schemaStr += child;
});
Expand All @@ -110,7 +138,15 @@ export class GraphQLSchemaGenerator extends Generator {
return `${method.name}(request: ${reqName}): ${resName}`;
}

private getGqlType(schema: TscaSchema): string {
private isPrimitiveGqlTyoe(schema: TscaSchema): boolean {
if (schema.type == 'array') {
return this.isPrimitiveGqlTyoe(schema.items);
}
const types = ['string', 'number', 'integer', 'boolean'];
return types.includes(schema.type);
}

private getGqlType(schema: TscaSchema, input: boolean): string {
if (schema.gen?.gql && schema.gen?.gql.type) {
return schema.gen?.gql.type;
}
Expand All @@ -125,9 +161,12 @@ export class GraphQLSchemaGenerator extends Generator {
case 'object':
throw new Error('anonymous object decleration is not allowed');
case 'array':
const itemType = this.getGqlType(schema.items);
const itemType = this.getGqlType(schema.items, input);
return `[${itemType}]`;
default:
if (input) {
return this.getGqlInputTypeName(schema.type);
}
return schema.type;
}
}
Expand Down

0 comments on commit 152fd3c

Please sign in to comment.