From f26a0bf438275fbe2d93ca10a8afe9c2711d1430 Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 9 Apr 2024 22:19:56 +0200 Subject: [PATCH] fix(cli): Improve type generation for interfaces & gql types --- .../add/api-extension/add-api-extension.ts | 55 ++++++++++++++++++- packages/cli/src/shared/entity-ref.ts | 10 +--- packages/cli/src/utilities/ast-utils.ts | 8 ++- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/commands/add/api-extension/add-api-extension.ts b/packages/cli/src/commands/add/api-extension/add-api-extension.ts index 456852dd58..c3127d52ef 100644 --- a/packages/cli/src/commands/add/api-extension/add-api-extension.ts +++ b/packages/cli/src/commands/add/api-extension/add-api-extension.ts @@ -422,6 +422,23 @@ function createCrudApiExtension(project: Project, plugin: VendurePluginRef, serv const entityRef = serviceRef.crudEntityRef; if (entityRef) { writer.indent(() => { + if (entityRef.isTranslatable()) { + const translationClass = entityRef.getTranslationClass(); + if (translationClass) { + writer.writeLine(` type ${translationClass.getName() ?? ''} {`); + writer.writeLine(` id: ID!`); + writer.writeLine(` createdAt: DateTime!`); + writer.writeLine(` updatedAt: DateTime!`); + writer.writeLine(` languageCode: LanguageCode!`); + for (const { name, type, nullable } of entityRef.getProps()) { + if (type.getText().includes('LocaleString')) { + writer.writeLine(` ${name}: String${nullable ? '' : '!'}`); + } + } + writer.writeLine(` }`); + writer.newLine(); + } + } writer.writeLine(` type ${entityRef.name} implements Node {`); writer.writeLine(` id: ID!`); writer.writeLine(` createdAt: DateTime!`); @@ -432,6 +449,11 @@ function createCrudApiExtension(project: Project, plugin: VendurePluginRef, serv writer.writeLine(` ${name}: ${graphQlType}${nullable ? '' : '!'}`); } } + if (entityRef.isTranslatable()) { + writer.writeLine( + ` translations: [${entityRef.getTranslationClass()?.getName() ?? ''}!]!`, + ); + } writer.writeLine(` }`); writer.newLine(); @@ -460,6 +482,24 @@ function createCrudApiExtension(project: Project, plugin: VendurePluginRef, serv writer.writeLine(` }`); writer.newLine(); + if ( + entityRef.isTranslatable() && + (serviceRef.features.create || serviceRef.features.update) + ) { + writer.writeLine( + ` input ${entityRef.getTranslationClass()?.getName() ?? ''}Input {`, + ); + writer.writeLine(` id: ID`); + writer.writeLine(` languageCode: LanguageCode!`); + for (const { name, type, nullable } of entityRef.getProps()) { + if (type.getText().includes('LocaleString')) { + writer.writeLine(` ${name}: String`); + } + } + writer.writeLine(` }`); + writer.newLine(); + } + if (serviceRef.features.create) { writer.writeLine(` input Create${entityRef.name}Input {`); for (const { name, type, nullable } of entityRef.getProps()) { @@ -468,6 +508,11 @@ function createCrudApiExtension(project: Project, plugin: VendurePluginRef, serv writer.writeLine(` ${name}: ${graphQlType}${nullable ? '' : '!'}`); } } + if (entityRef.isTranslatable()) { + writer.writeLine( + ` translations: [${entityRef.getTranslationClass()?.getName() ?? ''}Input!]!`, + ); + } writer.writeLine(` }`); writer.newLine(); } @@ -481,6 +526,11 @@ function createCrudApiExtension(project: Project, plugin: VendurePluginRef, serv writer.writeLine(` ${name}: ${graphQlType}`); } } + if (entityRef.isTranslatable()) { + writer.writeLine( + ` translations: [${entityRef.getTranslationClass()?.getName() ?? ''}Input!]`, + ); + } writer.writeLine(` }`); writer.newLine(); } @@ -567,9 +617,12 @@ function getGraphQLType(type: Type): string | undefined { if (type.isNumber()) { return 'Int'; } - if (type.isClass() && type.getText() === 'Date') { + if (type.isObject() && type.getText() === 'Date') { return 'DateTime'; } + if (type.getText().includes('LocaleString')) { + return 'String'; + } return; } diff --git a/packages/cli/src/shared/entity-ref.ts b/packages/cli/src/shared/entity-ref.ts index 5ed50e3b0d..4453de5b55 100644 --- a/packages/cli/src/shared/entity-ref.ts +++ b/packages/cli/src/shared/entity-ref.ts @@ -27,15 +27,7 @@ export class EntityRef { return this.classDeclaration.getProperties().map(prop => { const propType = prop.getType(); const name = prop.getName(); - if (propType.isUnion()) { - // get the non-null part of the union - const nonNullType = propType.getUnionTypes().find(t => !t.isNull() && !t.isUndefined()); - if (!nonNullType) { - throw new Error('Could not find non-null type in union'); - } - return { name, type: nonNullType, nullable: true }; - } - return { name, type: propType, nullable: false }; + return { name, type: propType.getNonNullableType(), nullable: propType.isNullable() }; }); } diff --git a/packages/cli/src/utilities/ast-utils.ts b/packages/cli/src/utilities/ast-utils.ts index 5d926d7412..1e7328a7b3 100644 --- a/packages/cli/src/utilities/ast-utils.ts +++ b/packages/cli/src/utilities/ast-utils.ts @@ -130,23 +130,25 @@ export function customizeCreateUpdateInputInterfaces(sourceFile: SourceFile, ent .getInterface('UpdateEntityInput') ?.rename(`Update${entityRef.name}Input`); + let index = 0; for (const { name, type, nullable } of entityRef.getProps()) { if ( type.isBoolean() || type.isString() || type.isNumber() || - (type.isClass() && type.getText() === 'Date') + (type.isObject() && type.getText() === 'Date') ) { - createInputInterface?.addProperty({ + createInputInterface?.insertProperty(index, { name, type: writer => writer.write(type.getText()), hasQuestionToken: nullable, }); - updateInputInterface?.addProperty({ + updateInputInterface?.insertProperty(index + 1, { name, type: writer => writer.write(type.getText()), hasQuestionToken: true, }); + index++; } }