diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c59472..8955bfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,6 @@ jobs: - name: Integration Test run: bun integration + + - name: Build Docs + run: bun docs:build diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0fd16ca..6f878ee 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,16 +31,8 @@ jobs: - name: Install Dependencies run: bun install - - name: Build Plugin - run: bun run build - - - name: Install Docs Dependencies - run: bun install - working-directory: docs - - name: Build Docs run: bun docs:build - working-directory: docs - name: Setup Pages uses: actions/configure-pages@v5 diff --git a/.husky/pre-commit b/.husky/pre-commit index 4d126ce..d0f726a 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -bun lint && bun format && git add . +bun lint:fix && bun format && git add . diff --git a/bun.lockb b/bun.lockb index 8bc3e44..5d315ce 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/docs/bun.lockb b/docs/bun.lockb deleted file mode 100755 index 236f48b..0000000 Binary files a/docs/bun.lockb and /dev/null differ diff --git a/docs/package.json b/docs/package.json index 5f695a5..84913fd 100644 --- a/docs/package.json +++ b/docs/package.json @@ -2,9 +2,9 @@ "name": "docs", "private": true, "scripts": { - "docs:start": "docusaurus start", - "docs:build": "tsc && bun generate && docusaurus build", - "generate": "jsdoc2md --files ../dist/plugin.cjs --partial partials/main.hbs --partial partials/scope.hbs -c jsdoc.conf > docs/configuration.md" + "build": "tsc && bun generate && docusaurus build", + "generate": "jsdoc2md --files ../dist/plugin.cjs --partial partials/main.hbs --partial partials/scope.hbs -c jsdoc.conf > docs/configuration.md", + "start": "docusaurus start" }, "devDependencies": { "@docusaurus/core": "3.3.2", @@ -13,6 +13,7 @@ "@docusaurus/tsconfig": "3.3.2", "@docusaurus/types": "3.3.2", "@mdx-js/react": "3.0.1", + "ajv": "8.14.0", "clsx": "2.1.1", "jsdoc-to-markdown": "8.0.1", "prism-react-renderer": "2.3.1", diff --git a/eslint.config.js b/eslint.config.js index 09c7cc4..8af2284 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -20,6 +20,6 @@ export default [ }, }, { - ignores: ["build", "dist", "docs"], + ignores: ["build", "dist", "docs", "scripts"], }, ]; diff --git a/package.json b/package.json index 0f665ab..a6eae7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@expediagroup/graphql-kotlin-codegen", - "packageManager": "bun@1.1.6", + "packageManager": "bun@1.1.10", "main": "dist/plugin.cjs", "types": "dist/plugin.d.cts", "files": [ @@ -22,6 +22,7 @@ "@graphql-codegen/java-common": "3.0.0", "@graphql-codegen/plugin-helpers": "5.0.4", "@graphql-codegen/visitor-plugin-common": "5.2.0", + "ts-deepmerge": "7.0.0", "valibot": "0.30.0" }, "devDependencies": { @@ -37,13 +38,19 @@ }, "scripts": { "build": "tsup src/plugin.ts --clean --dts --external graphql", + "docs:build": "bun run build && bun --filter docs build", + "docs:start": "bun --filter docs start", "format": "prettier --write .", "format-check": "prettier --check .", "integration": "bun run build && graphql-codegen && ./gradlew graphqlGenerateSDL && bun test ./test/integration.test.ts", - "lint": "eslint .", + "lint": "bun ./scripts/check-headers.ts && eslint .", + "lint:fix": "bun ./scripts/fix-headers.ts && eslint --fix .", "prepack": "bun run build", "prepare": "husky", "unit": "bun test ./test/plugin.test.ts" }, - "type": "module" + "type": "module", + "workspaces": [ + "docs" + ] } diff --git a/scripts/check-headers.ts b/scripts/check-headers.ts new file mode 100644 index 0000000..500817c --- /dev/null +++ b/scripts/check-headers.ts @@ -0,0 +1,18 @@ +import { Glob } from "bun"; + +const filePaths = new Glob("src/**/*.ts").scan(); + +let filesWithoutCopyrightHeader: string[] = []; +for await (const filePath of filePaths) { + const fileContents = await Bun.file(filePath).text(); + if (!fileContents.startsWith("/*\nCopyright")) { + filesWithoutCopyrightHeader.push(filePath); + } +} + +if (filesWithoutCopyrightHeader.length) { + console.error( + `\nThe following files are missing a valid copyright header:${filesWithoutCopyrightHeader.map((file) => `\n • ${file}`).join()}`, + ); + process.exit(1); +} diff --git a/scripts/fix-headers.ts b/scripts/fix-headers.ts new file mode 100644 index 0000000..79c25ae --- /dev/null +++ b/scripts/fix-headers.ts @@ -0,0 +1,24 @@ +import { Glob } from "bun"; + +const copyrightHeader = `/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +`; + +const filePaths = new Glob("src/**/*.ts").scan(); +for await (const filePath of filePaths) { + const fileContents = await Bun.file(filePath).text(); + if (!fileContents.startsWith("/*\nCopyright")) { + await Bun.write(filePath, `${copyrightHeader}${fileContents}`); + } +} diff --git a/src/helpers/build-annotations.ts b/src/annotations/build-annotations.ts similarity index 94% rename from src/helpers/build-annotations.ts rename to src/annotations/build-annotations.ts index d81c498..ff27031 100644 --- a/src/helpers/build-annotations.ts +++ b/src/annotations/build-annotations.ts @@ -21,8 +21,8 @@ import { } from "graphql"; import { buildDescriptionAnnotation } from "./build-description-annotation"; import { buildDirectiveAnnotations } from "./build-directive-annotations"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; -import { TypeMetadata } from "./build-type-metadata"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { TypeMetadata } from "../utils/build-type-metadata"; export type DefinitionNode = | TypeDefinitionNode diff --git a/src/helpers/build-description-annotation.ts b/src/annotations/build-description-annotation.ts similarity index 74% rename from src/helpers/build-description-annotation.ts rename to src/annotations/build-description-annotation.ts index 04c3c0a..e7b93a0 100644 --- a/src/helpers/build-description-annotation.ts +++ b/src/annotations/build-description-annotation.ts @@ -1,5 +1,18 @@ -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; -import { TypeMetadata } from "./build-type-metadata"; +/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { TypeMetadata } from "../utils/build-type-metadata"; import { indent } from "@graphql-codegen/visitor-plugin-common"; import { Kind } from "graphql/index"; import { DefinitionNode, trimDescription } from "./build-annotations"; diff --git a/src/helpers/build-directive-annotations.ts b/src/annotations/build-directive-annotations.ts similarity index 78% rename from src/helpers/build-directive-annotations.ts rename to src/annotations/build-directive-annotations.ts index 11f7434..a96498d 100644 --- a/src/helpers/build-directive-annotations.ts +++ b/src/annotations/build-directive-annotations.ts @@ -11,9 +11,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; import { DefinitionNode } from "./build-annotations"; -import { getFederationDirectiveReplacement } from "./get-federation-directive-replacement"; import { ConstDirectiveNode } from "graphql/language"; import { Kind } from "graphql"; @@ -75,3 +74,23 @@ function buildKotlinAnnotations( return `@${kotlinAnnotation.annotationName}(${directiveArguments})`; }); } + +function getFederationDirectiveReplacement(directive: ConstDirectiveNode) { + const federationDirectivePrefix = + "com.expediagroup.graphql.generator.federation.directives."; + switch (directive.name.value) { + case "key": + if ( + directive.arguments?.[0] && + directive.arguments[0].value.kind === Kind.STRING + ) { + const fieldArg = directive.arguments[0]?.value.value; + return `@${federationDirectivePrefix}KeyDirective(${federationDirectivePrefix}FieldSet("${fieldArg}"))`; + } + return undefined; + case "extends": + return `@${federationDirectivePrefix}ExtendsDirective`; + case "external": + return `@${federationDirectivePrefix}ExternalDirective`; + } +} diff --git a/src/helpers/add-dependent-types-to-only-types.ts b/src/config/add-dependent-types-to-only-types.ts similarity index 65% rename from src/helpers/add-dependent-types-to-only-types.ts rename to src/config/add-dependent-types-to-only-types.ts index ab97959..58dd59c 100644 --- a/src/helpers/add-dependent-types-to-only-types.ts +++ b/src/config/add-dependent-types-to-only-types.ts @@ -12,8 +12,13 @@ limitations under the License. */ import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; -import { getDependentTypeNames } from "./get-dependent-type-names"; import { GraphQLSchema } from "graphql"; +import { TypeDefinitionNode } from "graphql/index"; +import { + getDependentFieldTypeNames, + getDependentInterfaceNames, + getDependentUnionNames, +} from "../utils/dependent-type-utils"; export function addDependentTypesToOnlyTypes( config: CodegenConfigWithDefaults, @@ -34,3 +39,18 @@ export function addDependentTypesToOnlyTypes( : dependentTypeNames; config.onlyTypes.push(...dependentTypesInScope); } + +function getDependentTypeNames( + schema: GraphQLSchema, + node: TypeDefinitionNode, + config: CodegenConfigWithDefaults, +): string[] { + const namedTypes = getDependentFieldTypeNames(node, config) + .concat(getDependentUnionNames(node)) + .concat(getDependentInterfaceNames(node)); + const recursivelyFoundTypes = namedTypes + .map((typeName) => schema.getType(typeName)?.astNode) + .filter(Boolean) + .flatMap((node) => getDependentTypeNames(schema, node, config)); + return namedTypes.concat(recursivelyFoundTypes); +} diff --git a/src/config/build-config-with-defaults.ts b/src/config/build-config-with-defaults.ts new file mode 100644 index 0000000..a293b9d --- /dev/null +++ b/src/config/build-config-with-defaults.ts @@ -0,0 +1,36 @@ +/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { GraphQLKotlinCodegenConfig } from "../plugin"; +import { buildPackageNameFromPath } from "@graphql-codegen/java-common"; +import { dirname, normalize } from "path"; +import { merge } from "ts-deepmerge"; + +export function buildConfigWithDefaults( + config: GraphQLKotlinCodegenConfig, + outputFile: string, +) { + const defaultConfig = { + packageName: buildPackageNameFromPath(dirname(normalize(outputFile))), + includeDependentTypes: true, + unionGeneration: "MARKER_INTERFACE", + extraImports: ["com.expediagroup.graphql.generator.annotations.*"], + } as const satisfies GraphQLKotlinCodegenConfig; + + return merge(defaultConfig, config) as GraphQLKotlinCodegenConfig & + typeof defaultConfig; +} + +export type CodegenConfigWithDefaults = ReturnType< + typeof buildConfigWithDefaults +>; diff --git a/src/config/find-type-in-resolver-interfaces-config.ts b/src/config/find-type-in-resolver-interfaces-config.ts new file mode 100644 index 0000000..e5dd2bb --- /dev/null +++ b/src/config/find-type-in-resolver-interfaces-config.ts @@ -0,0 +1,24 @@ +/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode } from "graphql"; +import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; + +export function findTypeInResolverInterfacesConfig( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + config: CodegenConfigWithDefaults, +) { + return config.resolverInterfaces?.findLast( + (resolverInterface) => resolverInterface.typeName === node.name.value, + ); +} diff --git a/src/config.ts b/src/config/schema.ts similarity index 100% rename from src/config.ts rename to src/config/schema.ts diff --git a/src/helpers/should-include-type-definition.ts b/src/config/should-exclude-type-definition.ts similarity index 87% rename from src/helpers/should-include-type-definition.ts rename to src/config/should-exclude-type-definition.ts index 2187d1b..3b375e5 100644 --- a/src/helpers/should-include-type-definition.ts +++ b/src/config/should-exclude-type-definition.ts @@ -14,9 +14,9 @@ limitations under the License. import { TypeDefinitionNode } from "graphql"; import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; -export function shouldIncludeTypeDefinition( +export function shouldExcludeTypeDefinition( node: TypeDefinitionNode, config: CodegenConfigWithDefaults, ) { - return !config.onlyTypes || config.onlyTypes.includes(node.name.value); + return config.onlyTypes && !config.onlyTypes.includes(node.name.value); } diff --git a/src/definitions/enum.ts b/src/definitions/enum.ts index a06e352..0cfd696 100644 --- a/src/definitions/enum.ts +++ b/src/definitions/enum.ts @@ -13,15 +13,15 @@ limitations under the License. import { EnumTypeDefinitionNode, EnumValueDefinitionNode } from "graphql"; import { indentMultiline } from "@graphql-codegen/visitor-plugin-common"; -import { buildAnnotations } from "../helpers/build-annotations"; -import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition"; -import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults"; +import { buildAnnotations } from "../annotations/build-annotations"; +import { shouldExcludeTypeDefinition } from "../config/should-exclude-type-definition"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; export function buildEnumTypeDefinition( node: EnumTypeDefinitionNode, config: CodegenConfigWithDefaults, ) { - if (!shouldIncludeTypeDefinition(node, config)) { + if (shouldExcludeTypeDefinition(node, config)) { return ""; } diff --git a/src/definitions/field.ts b/src/definitions/field.ts new file mode 100644 index 0000000..7ed3c28 --- /dev/null +++ b/src/definitions/field.ts @@ -0,0 +1,338 @@ +/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { buildTypeMetadata, TypeMetadata } from "../utils/build-type-metadata"; +import { + FieldDefinitionNode, + GraphQLSchema, + InterfaceTypeDefinitionNode, + Kind, + ObjectTypeDefinitionNode, + isInterfaceType, +} from "graphql"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { indent } from "@graphql-codegen/visitor-plugin-common"; +import { buildAnnotations } from "../annotations/build-annotations"; +import { findTypeInResolverInterfacesConfig } from "../config/find-type-in-resolver-interfaces-config"; +import { shouldGenerateFunctionsInClass } from "./object"; + +export function buildObjectFieldDefinition({ + node, + fieldNode, + schema, + config, +}: { + node: ObjectTypeDefinitionNode; + fieldNode: FieldDefinitionNode; + schema: GraphQLSchema; + config: CodegenConfigWithDefaults; +}) { + const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig( + node, + config, + ); + const functionDefinition = buildFunctionDefinition( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + config, + ); + const typeMetadata = buildTypeMetadata(fieldNode.type, schema, config); + const defaultImplementation = getDefaultImplementation( + node, + fieldNode, + typeInResolverInterfacesConfig, + ); + const defaultFunctionValue = `${typeMetadata.isNullable ? "?" : ""} = ${defaultImplementation}`; + const shouldGenerateFunctions = shouldGenerateFunctionsInClass( + node, + typeInResolverInterfacesConfig, + ); + const defaultValue = shouldGenerateFunctions + ? defaultFunctionValue + : typeMetadata.defaultValue; + const field = buildField( + node, + fieldNode, + functionDefinition, + defaultValue, + typeInResolverInterfacesConfig, + typeMetadata, + ); + const annotations = buildAnnotations({ + config, + definitionNode: fieldNode, + typeMetadata, + }); + return `${annotations}${field}${shouldGenerateFunctions || isLastFieldInType(node, fieldNode) ? "" : ","}`; +} + +export function buildConstructorFieldDefinition({ + node, + fieldNode, + schema, + config, +}: { + node: ObjectTypeDefinitionNode; + fieldNode: FieldDefinitionNode; + schema: GraphQLSchema; + config: CodegenConfigWithDefaults; +}) { + const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig( + node, + config, + ); + const functionDefinition = buildConstructorFunctionDefinition( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + ); + const typeMetadata = buildTypeMetadata(fieldNode.type, schema, config); + const defaultDefinitionValue = typeMetadata.defaultValue; + + const field = buildField( + node, + fieldNode, + functionDefinition, + defaultDefinitionValue, + typeInResolverInterfacesConfig, + typeMetadata, + ); + const annotations = buildAnnotations({ + config, + definitionNode: fieldNode, + typeMetadata, + }); + const shouldGenerateFunctions = shouldGenerateFunctionsInClass( + node, + typeInResolverInterfacesConfig, + ); + return `${annotations}${field}${shouldGenerateFunctions || isLastFieldInType(node, fieldNode) ? "" : ","}`; +} + +export function buildInterfaceFieldDefinition({ + node, + fieldNode, + schema, + config, +}: { + node: InterfaceTypeDefinitionNode; + fieldNode: FieldDefinitionNode; + schema: GraphQLSchema; + config: CodegenConfigWithDefaults; +}) { + const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig( + node, + config, + ); + const functionDefinition = buildFunctionDefinition( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + config, + ); + const typeMetadata = buildTypeMetadata(fieldNode.type, schema, config); + const defaultDefinitionValue = typeMetadata.isNullable ? "?" : ""; + const field = buildField( + node, + fieldNode, + functionDefinition, + defaultDefinitionValue, + typeInResolverInterfacesConfig, + typeMetadata, + ); + const annotations = buildAnnotations({ + config, + definitionNode: fieldNode, + typeMetadata, + }); + return `${annotations}${field}`; +} + +function buildField( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + functionDefinition: string, + defaultDefinitionValue: string, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, + typeMetadata: TypeMetadata, +) { + const defaultImplementation = getDefaultImplementation( + node, + fieldNode, + typeInResolverInterfacesConfig, + ); + const isCompletableFuture = + typeInResolverInterfacesConfig?.classMethods === "COMPLETABLE_FUTURE"; + const completableFutureDefinition = `java.util.concurrent.CompletableFuture<${typeMetadata.typeName}${typeMetadata.isNullable ? "?" : ""}> = ${defaultImplementation}`; + const defaultDefinition = `${typeMetadata.typeName}${defaultDefinitionValue}`; + return indent( + `${functionDefinition}: ${isCompletableFuture ? completableFutureDefinition : defaultDefinition}`, + 2, + ); +} + +function buildFunctionDefinition( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + schema: GraphQLSchema, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, + config: CodegenConfigWithDefaults, +) { + const modifier = buildFieldModifier( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + ); + const fieldArguments = buildFieldArguments( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + config, + ); + return `${modifier} ${fieldNode.name.value}${fieldArguments}`; +} + +function buildConstructorFunctionDefinition( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + schema: GraphQLSchema, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, +) { + const modifier = fieldNode.arguments?.length + ? "private val" + : buildFieldModifier( + node, + fieldNode, + schema, + typeInResolverInterfacesConfig, + ); + const fieldArguments = ""; + return `${modifier} ${fieldNode.name.value}${fieldArguments}`; +} + +function buildFieldModifier( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + schema: GraphQLSchema, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, +) { + const shouldOverrideField = shouldModifyFieldWithOverride( + node, + fieldNode, + schema, + ); + + if (!typeInResolverInterfacesConfig && !fieldNode.arguments?.length) { + return shouldOverrideField ? "override val" : "val"; + } + const functionModifier = + typeInResolverInterfacesConfig?.classMethods === "SUSPEND" + ? "suspend " + : ""; + if (node.kind === Kind.INTERFACE_TYPE_DEFINITION) { + return `${functionModifier}fun`; + } + const isCompletableFuture = + typeInResolverInterfacesConfig?.classMethods === "COMPLETABLE_FUTURE"; + if (shouldOverrideField && !isCompletableFuture) { + return "override fun"; + } + return `open ${functionModifier}fun`; +} + +function buildFieldArguments( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + schema: GraphQLSchema, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, + config: CodegenConfigWithDefaults, +) { + if (!typeInResolverInterfacesConfig && !fieldNode.arguments?.length) { + return ""; + } + const isOverrideFunction = shouldModifyFieldWithOverride( + node, + fieldNode, + schema, + ); + const nullableSuffix = isOverrideFunction ? "?" : "? = null"; + const existingFieldArguments = fieldNode.arguments?.map((arg) => { + const argMetadata = buildTypeMetadata(arg.type, schema, config); + return `${arg.name.value}: ${argMetadata.typeName}${arg.type.kind === Kind.NON_NULL_TYPE ? "" : nullableSuffix}`; + }); + const dataFetchingEnvironmentArgument = + "dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment"; + const extraFieldArguments = [dataFetchingEnvironmentArgument]; + const allFieldArguments = existingFieldArguments?.concat(extraFieldArguments); + return allFieldArguments?.length + ? `(${allFieldArguments?.join(", ")})` + : "()"; +} + +function shouldModifyFieldWithOverride( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + schema: GraphQLSchema, +) { + return node.interfaces?.some((interfaceNode) => { + const typeNode = schema.getType(interfaceNode.name.value); + return ( + isInterfaceType(typeNode) && + typeNode.astNode?.fields?.some( + (field) => field.name.value === fieldNode.name.value, + ) + ); + }); +} + +function getDefaultImplementation( + node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, + fieldNode: FieldDefinitionNode, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, +) { + const notImplementedError = `throw NotImplementedError("${node.name.value}.${fieldNode.name.value} must be implemented.")`; + const atLeastOneFieldHasNoArguments = node.fields?.some( + (fieldNode) => !fieldNode.arguments?.length, + ); + return !typeInResolverInterfacesConfig && atLeastOneFieldHasNoArguments + ? fieldNode.name.value + : notImplementedError; +} + +function isLastFieldInType( + node: ObjectTypeDefinitionNode, + fieldNode: FieldDefinitionNode, +) { + const fieldIndex = node.fields?.findIndex( + (field) => field.name.value === fieldNode.name.value, + ); + return node.fields && fieldIndex === node.fields.length - 1; +} diff --git a/src/definitions/input.ts b/src/definitions/input.ts index 0fd416c..0205448 100644 --- a/src/definitions/input.ts +++ b/src/definitions/input.ts @@ -12,19 +12,19 @@ limitations under the License. */ import { GraphQLSchema, InputObjectTypeDefinitionNode } from "graphql"; -import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition"; -import { buildTypeMetadata } from "../helpers/build-type-metadata"; -import { buildAnnotations } from "../helpers/build-annotations"; +import { shouldExcludeTypeDefinition } from "../config/should-exclude-type-definition"; +import { buildTypeMetadata } from "../utils/build-type-metadata"; +import { buildAnnotations } from "../annotations/build-annotations"; import { indent } from "@graphql-codegen/visitor-plugin-common"; -import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults"; -import { inputTypeHasMatchingOutputType } from "../helpers/input-type-has-matching-output-type"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { inputTypeHasMatchingOutputType } from "../utils/input-type-has-matching-output-type"; export function buildInputObjectDefinition( node: InputObjectTypeDefinitionNode, schema: GraphQLSchema, config: CodegenConfigWithDefaults, ) { - if (!shouldIncludeTypeDefinition(node, config)) { + if (shouldExcludeTypeDefinition(node, config)) { return ""; } diff --git a/src/definitions/interface.ts b/src/definitions/interface.ts index 00525ac..c95ecd6 100644 --- a/src/definitions/interface.ts +++ b/src/definitions/interface.ts @@ -12,33 +12,29 @@ limitations under the License. */ import { GraphQLSchema, InterfaceTypeDefinitionNode } from "graphql"; -import { buildAnnotations } from "../helpers/build-annotations"; -import { buildTypeMetadata } from "../helpers/build-type-metadata"; -import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition"; -import { buildFieldDefinition } from "../helpers/build-field-definition"; -import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults"; -import { getDependentInterfaceNames } from "../helpers/dependent-type-utils"; +import { buildAnnotations } from "../annotations/build-annotations"; +import { shouldExcludeTypeDefinition } from "../config/should-exclude-type-definition"; +import { buildInterfaceFieldDefinition } from "./field"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { getDependentInterfaceNames } from "../utils/dependent-type-utils"; export function buildInterfaceDefinition( node: InterfaceTypeDefinitionNode, schema: GraphQLSchema, config: CodegenConfigWithDefaults, ) { - if (!shouldIncludeTypeDefinition(node, config)) { + if (shouldExcludeTypeDefinition(node, config)) { return ""; } const classMembers = node.fields ?.map((fieldNode) => { - const typeMetadata = buildTypeMetadata(fieldNode.type, schema, config); - return buildFieldDefinition( + return buildInterfaceFieldDefinition({ node, fieldNode, schema, config, - typeMetadata, - Boolean(fieldNode.arguments?.length), - ); + }); }) .join("\n"); diff --git a/src/definitions/object.ts b/src/definitions/object.ts index 763e3ef..54279bb 100644 --- a/src/definitions/object.ts +++ b/src/definitions/object.ts @@ -17,24 +17,26 @@ import { isInputObjectType, ObjectTypeDefinitionNode, } from "graphql"; -import { buildAnnotations } from "../helpers/build-annotations"; -import { buildTypeMetadata } from "../helpers/build-type-metadata"; -import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition"; +import { buildAnnotations } from "../annotations/build-annotations"; +import { shouldExcludeTypeDefinition } from "../config/should-exclude-type-definition"; import { getDependentInterfaceNames, getDependentUnionsForType, -} from "../helpers/dependent-type-utils"; -import { buildFieldDefinition } from "../helpers/build-field-definition"; -import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults"; -import { inputTypeHasMatchingOutputType } from "../helpers/input-type-has-matching-output-type"; -import { findTypeInResolverInterfacesConfig } from "../helpers/findTypeInResolverInterfacesConfig"; +} from "../utils/dependent-type-utils"; +import { + buildConstructorFieldDefinition, + buildObjectFieldDefinition, +} from "./field"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; +import { inputTypeHasMatchingOutputType } from "../utils/input-type-has-matching-output-type"; +import { findTypeInResolverInterfacesConfig } from "../config/find-type-in-resolver-interfaces-config"; export function buildObjectTypeDefinition( node: ObjectTypeDefinitionNode, schema: GraphQLSchema, config: CodegenConfigWithDefaults, ) { - if (!shouldIncludeTypeDefinition(node, config)) { + if (shouldExcludeTypeDefinition(node, config)) { return ""; } @@ -64,9 +66,16 @@ export function buildObjectTypeDefinition( node, config, ); - const shouldGenerateFunctions = Boolean( - typeInResolverInterfacesConfig || - node.fields?.some((fieldNode) => fieldNode.arguments?.length), + const fieldsWithArguments = node.fields?.filter( + (fieldNode) => fieldNode.arguments?.length, + ); + const fieldNodes = typeInResolverInterfacesConfig + ? node.fields + : fieldsWithArguments; + + const shouldGenerateFunctions = shouldGenerateFunctionsInClass( + node, + typeInResolverInterfacesConfig, ); if (shouldGenerateFunctions) { const atLeastOneFieldHasNoArguments = node.fields?.some( @@ -76,64 +85,57 @@ export function buildObjectTypeDefinition( !typeInResolverInterfacesConfig && atLeastOneFieldHasNoArguments ? `(\n${node.fields ?.map((fieldNode) => { - const typeMetadata = buildTypeMetadata( - fieldNode.type, - schema, - config, - ); - return buildFieldDefinition( + return buildConstructorFieldDefinition({ node, fieldNode, schema, config, - typeMetadata, - shouldGenerateFunctions, - true, - ); + }); }) .join(",\n")}\n)` : ""; - const fieldsWithArguments = node.fields?.filter( - (fieldNode) => fieldNode.arguments?.length, - ); - const fieldNodes = typeInResolverInterfacesConfig - ? node.fields - : fieldsWithArguments; return `${annotations}${outputRestrictionAnnotation}open class ${name}${constructor}${interfaceInheritance} { -${getDataClassMembers({ node, fieldNodes, schema, config, shouldGenerateFunctions })} +${getClassMembers({ node, fieldNodes, schema, config })} }`; } return `${annotations}${outputRestrictionAnnotation}data class ${name}( -${getDataClassMembers({ node, schema, config })} +${getClassMembers({ node, schema, config })} )${interfaceInheritance}`; } -function getDataClassMembers({ +function getClassMembers({ node, fieldNodes, schema, config, - shouldGenerateFunctions, }: { node: ObjectTypeDefinitionNode; fieldNodes?: readonly FieldDefinitionNode[]; schema: GraphQLSchema; config: CodegenConfigWithDefaults; - shouldGenerateFunctions?: boolean; }) { return (fieldNodes ?? node.fields) ?.map((fieldNode) => { - const typeMetadata = buildTypeMetadata(fieldNode.type, schema, config); - return buildFieldDefinition( + return buildObjectFieldDefinition({ node, fieldNode, schema, config, - typeMetadata, - shouldGenerateFunctions, - ); + }); }) - .join(`${shouldGenerateFunctions ? "" : ","}\n`); + .join("\n"); +} + +export function shouldGenerateFunctionsInClass( + node: ObjectTypeDefinitionNode, + typeInResolverInterfacesConfig: ReturnType< + typeof findTypeInResolverInterfacesConfig + >, +) { + return Boolean( + typeInResolverInterfacesConfig || + node.fields?.some((fieldNode) => fieldNode.arguments?.length), + ); } diff --git a/src/definitions/union.ts b/src/definitions/union.ts index d7c55f2..1ee8a0e 100644 --- a/src/definitions/union.ts +++ b/src/definitions/union.ts @@ -12,18 +12,18 @@ limitations under the License. */ import { UnionTypeDefinitionNode } from "graphql"; -import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition"; -import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults"; +import { shouldExcludeTypeDefinition } from "../config/should-exclude-type-definition"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; import { buildAnnotations, trimDescription, -} from "../helpers/build-annotations"; +} from "../annotations/build-annotations"; export function buildUnionTypeDefinition( node: UnionTypeDefinitionNode, config: CodegenConfigWithDefaults, ) { - if (!shouldIncludeTypeDefinition(node, config)) { + if (shouldExcludeTypeDefinition(node, config)) { return ""; } const annotations = buildAnnotations({ diff --git a/src/helpers/build-config-with-defaults.ts b/src/helpers/build-config-with-defaults.ts deleted file mode 100644 index 7f08012..0000000 --- a/src/helpers/build-config-with-defaults.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { GraphQLKotlinCodegenConfig } from "../plugin"; -import { buildPackageNameFromPath } from "@graphql-codegen/java-common"; -import { dirname, normalize } from "path"; - -export function buildConfigWithDefaults( - config: GraphQLKotlinCodegenConfig, - outputFile: string, -) { - return { - packageName: buildPackageNameFromPath(dirname(normalize(outputFile))), - includeDependentTypes: true, - unionGeneration: "MARKER_INTERFACE", - ...config, - extraImports: [ - "com.expediagroup.graphql.generator.annotations.*", - ...(config.extraImports ?? []), - ], - } as const satisfies GraphQLKotlinCodegenConfig; -} - -export type CodegenConfigWithDefaults = ReturnType< - typeof buildConfigWithDefaults ->; diff --git a/src/helpers/build-field-definition.ts b/src/helpers/build-field-definition.ts deleted file mode 100644 index 610eda8..0000000 --- a/src/helpers/build-field-definition.ts +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2024 Expedia, Inc. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { buildTypeMetadata, TypeMetadata } from "./build-type-metadata"; -import { - FieldDefinitionNode, - GraphQLSchema, - InterfaceTypeDefinitionNode, - Kind, - ObjectTypeDefinitionNode, - isInterfaceType, -} from "graphql"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; -import { indent } from "@graphql-codegen/visitor-plugin-common"; -import { buildAnnotations } from "./build-annotations"; -import { findTypeInResolverInterfacesConfig } from "./findTypeInResolverInterfacesConfig"; - -export function buildFieldDefinition( - node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - fieldNode: FieldDefinitionNode, - schema: GraphQLSchema, - config: CodegenConfigWithDefaults, - typeMetadata: TypeMetadata, - shouldGenerateFunctions?: boolean, - isConstructorField?: boolean, -) { - const modifier = buildFieldModifier( - node, - fieldNode, - schema, - config, - isConstructorField, - ); - const fieldArguments = isConstructorField - ? "" - : buildFieldArguments(node, fieldNode, schema, config); - const fieldDefinition = `${modifier} ${fieldNode.name.value}${fieldArguments}`; - const annotations = buildAnnotations({ - config, - definitionNode: fieldNode, - typeMetadata, - }); - if (node.kind === Kind.INTERFACE_TYPE_DEFINITION) { - return buildInterfaceFieldDefinition( - fieldDefinition, - typeMetadata, - annotations, - ); - } - - const notImplementedError = `throw NotImplementedError("${node.name.value}.${fieldNode.name.value} must be implemented.")`; - const atLeastOneFieldHasNoArguments = node.fields?.some( - (fieldNode) => !fieldNode.arguments?.length, - ); - const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig( - node, - config, - ); - const defaultImplementation = - !typeInResolverInterfacesConfig && atLeastOneFieldHasNoArguments - ? fieldNode.name.value - : notImplementedError; - const defaultFunctionValue = `${typeMetadata.isNullable ? "?" : ""} = ${defaultImplementation}`; - const defaultValue = - shouldGenerateFunctions && !isConstructorField - ? defaultFunctionValue - : typeMetadata.defaultValue; - const defaultDefinition = `${typeMetadata.typeName}${defaultValue}`; - - const isCompletableFuture = - typeInResolverInterfacesConfig?.classMethods === "COMPLETABLE_FUTURE"; - const completableFutureDefinition = `java.util.concurrent.CompletableFuture<${typeMetadata.typeName}${typeMetadata.isNullable ? "?" : ""}> = ${defaultImplementation}`; - const field = indent( - `${fieldDefinition}: ${isCompletableFuture ? completableFutureDefinition : defaultDefinition}`, - 2, - ); - return `${annotations}${field}`; -} - -function buildFieldModifier( - node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - fieldNode: FieldDefinitionNode, - schema: GraphQLSchema, - config: CodegenConfigWithDefaults, - isConstructorField?: boolean, -) { - const typeInResolverInterfacesConfig = findTypeInResolverInterfacesConfig( - node, - config, - ); - const shouldOverrideField = shouldModifyFieldWithOverride( - node, - fieldNode, - schema, - ); - - if (isConstructorField && fieldNode.arguments?.length) { - return "private val"; - } - if (!typeInResolverInterfacesConfig && !fieldNode.arguments?.length) { - return shouldOverrideField ? "override val" : "val"; - } - const functionModifier = - typeInResolverInterfacesConfig?.classMethods === "SUSPEND" - ? "suspend " - : ""; - if (node.kind === Kind.INTERFACE_TYPE_DEFINITION) { - return `${functionModifier}fun`; - } - const isCompletableFuture = - typeInResolverInterfacesConfig?.classMethods === "COMPLETABLE_FUTURE"; - if (shouldOverrideField && !isCompletableFuture) { - return "override fun"; - } - return `open ${functionModifier}fun`; -} - -function buildFieldArguments( - node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - fieldNode: FieldDefinitionNode, - schema: GraphQLSchema, - config: CodegenConfigWithDefaults, -) { - const typeIsInResolverInterfaces = findTypeInResolverInterfacesConfig( - node, - config, - ); - if (!typeIsInResolverInterfaces && !fieldNode.arguments?.length) { - return ""; - } - const isOverrideFunction = shouldModifyFieldWithOverride( - node, - fieldNode, - schema, - ); - const nullableSuffix = isOverrideFunction ? "?" : "? = null"; - const existingFieldArguments = fieldNode.arguments?.map((arg) => { - const argMetadata = buildTypeMetadata(arg.type, schema, config); - return `${arg.name.value}: ${argMetadata.typeName}${arg.type.kind === Kind.NON_NULL_TYPE ? "" : nullableSuffix}`; - }); - const dataFetchingEnvironmentArgument = - "dataFetchingEnvironment: graphql.schema.DataFetchingEnvironment"; - const extraFieldArguments = [dataFetchingEnvironmentArgument]; - const allFieldArguments = existingFieldArguments?.concat(extraFieldArguments); - return allFieldArguments?.length - ? `(${allFieldArguments?.join(", ")})` - : "()"; -} - -function shouldModifyFieldWithOverride( - node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - fieldNode: FieldDefinitionNode, - schema: GraphQLSchema, -) { - return node.interfaces?.some((interfaceNode) => { - const typeNode = schema.getType(interfaceNode.name.value); - return ( - isInterfaceType(typeNode) && - typeNode.astNode?.fields?.some( - (field) => field.name.value === fieldNode.name.value, - ) - ); - }); -} - -function buildInterfaceFieldDefinition( - fieldDefinition: string, - typeMetadata: TypeMetadata, - annotations: string, -) { - const fieldText = indent( - `${fieldDefinition}: ${typeMetadata.typeName}${ - typeMetadata.isNullable ? "?" : "" - }`, - 2, - ); - return `${annotations}${fieldText}`; -} diff --git a/src/helpers/findTypeInResolverInterfacesConfig.ts b/src/helpers/findTypeInResolverInterfacesConfig.ts deleted file mode 100644 index 35d9ae3..0000000 --- a/src/helpers/findTypeInResolverInterfacesConfig.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { InterfaceTypeDefinitionNode, ObjectTypeDefinitionNode } from "graphql"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; - -export function findTypeInResolverInterfacesConfig( - node: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, - config: CodegenConfigWithDefaults, -) { - return config.resolverInterfaces?.find( - (resolverInterface) => resolverInterface.typeName === node.name.value, - ); -} diff --git a/src/helpers/get-dependent-type-names.ts b/src/helpers/get-dependent-type-names.ts deleted file mode 100644 index 60d3e49..0000000 --- a/src/helpers/get-dependent-type-names.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright 2024 Expedia, Inc. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { TypeDefinitionNode } from "graphql/index"; -import { GraphQLSchema } from "graphql"; -import { - getDependentFieldTypeNames, - getDependentInterfaceNames, - getDependentUnionNames, -} from "./dependent-type-utils"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; - -export function getDependentTypeNames( - schema: GraphQLSchema, - node: TypeDefinitionNode, - config: CodegenConfigWithDefaults, -): string[] { - const namedTypes = getDependentFieldTypeNames(node, config) - .concat(getDependentUnionNames(node)) - .concat(getDependentInterfaceNames(node)); - const recursivelyFoundTypes = namedTypes - .map((typeName) => schema.getType(typeName)?.astNode) - .filter(Boolean) - .flatMap((node) => getDependentTypeNames(schema, node, config)); - return namedTypes.concat(recursivelyFoundTypes); -} diff --git a/src/helpers/get-federation-directive-replacement.ts b/src/helpers/get-federation-directive-replacement.ts deleted file mode 100644 index 4472d77..0000000 --- a/src/helpers/get-federation-directive-replacement.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2024 Expedia, Inc. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import { ConstDirectiveNode } from "graphql/language"; -import { Kind } from "graphql/index"; - -const federationDirectivePrefix = - "com.expediagroup.graphql.generator.federation.directives."; - -export function getFederationDirectiveReplacement( - directive: ConstDirectiveNode, -) { - switch (directive.name.value) { - case "key": - if ( - directive.arguments?.[0] && - directive.arguments[0].value.kind === Kind.STRING - ) { - const fieldArg = directive.arguments[0]?.value.value; - return `@${federationDirectivePrefix}KeyDirective(${federationDirectivePrefix}FieldSet("${fieldArg}"))`; - } - return undefined; - case "extends": - return `@${federationDirectivePrefix}ExtendsDirective`; - case "external": - return `@${federationDirectivePrefix}ExternalDirective`; - } -} diff --git a/src/plugin.ts b/src/plugin.ts index 09d5ceb..310006a 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -21,10 +21,10 @@ import { RawConfig, } from "@graphql-codegen/visitor-plugin-common"; import { Input, safeParse } from "valibot"; -import { configSchema } from "./config"; -import { addDependentTypesToOnlyTypes } from "./helpers/add-dependent-types-to-only-types"; +import { configSchema } from "./config/schema"; +import { buildConfigWithDefaults } from "./config/build-config-with-defaults"; +import { addDependentTypesToOnlyTypes } from "./config/add-dependent-types-to-only-types"; import { visit } from "graphql"; -import { buildConfigWithDefaults } from "./helpers/build-config-with-defaults"; export type GraphQLKotlinCodegenConfig = Partial & Input; diff --git a/src/helpers/build-type-metadata.ts b/src/utils/build-type-metadata.ts similarity index 98% rename from src/helpers/build-type-metadata.ts rename to src/utils/build-type-metadata.ts index 86d0bf9..de8df89 100644 --- a/src/helpers/build-type-metadata.ts +++ b/src/utils/build-type-metadata.ts @@ -22,7 +22,7 @@ import { } from "graphql"; import { getBaseTypeNode } from "@graphql-codegen/visitor-plugin-common"; import { wrapTypeWithModifiers } from "@graphql-codegen/java-common"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; import { getTypeNameWithoutInput, inputTypeHasMatchingOutputType, diff --git a/src/helpers/dependent-type-utils.ts b/src/utils/dependent-type-utils.ts similarity index 96% rename from src/helpers/dependent-type-utils.ts rename to src/utils/dependent-type-utils.ts index 17e7e18..0826e60 100644 --- a/src/helpers/dependent-type-utils.ts +++ b/src/utils/dependent-type-utils.ts @@ -19,7 +19,7 @@ import { TypeDefinitionNode, TypeNode, } from "graphql"; -import { CodegenConfigWithDefaults } from "./build-config-with-defaults"; +import { CodegenConfigWithDefaults } from "../config/build-config-with-defaults"; import { getBaseTypeNode } from "@graphql-codegen/visitor-plugin-common"; export function getDependentFieldTypeNames( diff --git a/src/helpers/input-type-has-matching-output-type.ts b/src/utils/input-type-has-matching-output-type.ts similarity index 78% rename from src/helpers/input-type-has-matching-output-type.ts rename to src/utils/input-type-has-matching-output-type.ts index 87bbe7d..775bc24 100644 --- a/src/helpers/input-type-has-matching-output-type.ts +++ b/src/utils/input-type-has-matching-output-type.ts @@ -1,3 +1,16 @@ +/* +Copyright 2024 Expedia, Inc. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + https://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + import { GraphQLSchema, InputObjectTypeDefinitionNode, diff --git a/src/visitor.ts b/src/visitor.ts index 52e9082..f58dc1b 100644 --- a/src/visitor.ts +++ b/src/visitor.ts @@ -20,7 +20,7 @@ import { ObjectTypeDefinitionNode, UnionTypeDefinitionNode, } from "graphql"; -import { CodegenConfigWithDefaults } from "./helpers/build-config-with-defaults"; +import { CodegenConfigWithDefaults } from "./config/build-config-with-defaults"; import { buildEnumTypeDefinition } from "./definitions/enum"; import { buildInterfaceDefinition } from "./definitions/interface"; import { buildInputObjectDefinition } from "./definitions/input";