Skip to content

Commit 8b5a1c7

Browse files
committed
small refactors
1 parent 6fb41c8 commit 8b5a1c7

16 files changed

+115
-116
lines changed

bun.lockb

1.29 KB
Binary file not shown.

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export default [
1313
},
1414
},
1515
rules: {
16+
"no-console": "error",
1617
"@typescript-eslint/no-non-null-assertion": "error",
1718
"@typescript-eslint/no-unsafe-argument": "error",
1819
"@typescript-eslint/no-unsafe-call": "error",

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"@graphql-codegen/cli": "5.0.2",
2929
"@total-typescript/ts-reset": "0.5.1",
3030
"bun-types": "1.1.4",
31-
"eslint": "9.1.0",
31+
"eslint": "9.1.1",
3232
"husky": "9.0.11",
3333
"prettier": "3.2.5",
3434
"tsup": "8.0.2",
@@ -39,7 +39,7 @@
3939
"build": "tsup src/plugin.ts --clean --dts --external graphql",
4040
"format": "prettier --write .",
4141
"format-check": "prettier --check .",
42-
"integration": "bun run build && graphql-codegen && ./gradlew compileTestKotlin",
42+
"integration": "bun run build && graphql-codegen && ./gradlew build",
4343
"lint": "eslint .",
4444
"prepack": "bun run build",
4545
"prepare": "husky",

src/config.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ export const configSchema = object({
4646
dependentTypesInScope: optional(array(string())),
4747
/**
4848
* Denotes Kotlin classes representing union types to be treated as interfaces rather than annotation classes.
49-
* This should be used for types outside `dependentTypesInScope` that are not generated by the plugin.
49+
* @description This should be used for types outside `dependentTypesInScope` that are not generated by the plugin. This also should only be used when unionGeneration is set to `ANNOTATION_CLASS`.
5050
*/
5151
externalUnionsAsInterfaces: optional(array(string())),
5252
/**
53-
* Additional imports to add to the generated file.
53+
* Additional imports to add to the generated file. GraphQL Kotlin annotations are always imported.
5454
* @example ["com.example.additional.import.*"]
5555
*/
5656
extraImports: optional(array(string())),
@@ -133,6 +133,7 @@ export const configSchema = object({
133133
),
134134
/**
135135
* Denotes the generation strategy for union types. Defaults to `MARKER_INTERFACE`.
136+
*
136137
* https://opensource.expediagroup.com/graphql-kotlin/docs/schema-generator/writing-schemas/unions/
137138
*/
138139
unionGeneration: optional(

src/definitions/input.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export function buildInputObjectDefinition(
4747

4848
const annotations = buildAnnotations({
4949
config,
50-
inputDescription: node.description?.value,
5150
definitionNode: node,
5251
});
5352

src/definitions/object.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,20 @@ export function buildObjectTypeDefinition(
4949

5050
if (isResolverType(node, config)) {
5151
return `${annotations}@GraphQLIgnore\ninterface ${name}${interfaceInheritance} {
52-
${getClassMembers({ node, schema, config })}
52+
${getDataClassMembers({ node, schema, config })}
5353
}
5454
5555
${annotations}@GraphQLIgnore\ninterface ${name}CompletableFuture {
56-
${getClassMembers({ node, schema, config, completableFuture: true })}
56+
${getDataClassMembers({ node, schema, config, completableFuture: true })}
5757
}`;
5858
}
5959

6060
return `${annotations}data class ${name}(
61-
${getClassMembers({ node, schema, config })}
61+
${getDataClassMembers({ node, schema, config })}
6262
)${interfaceInheritance}`;
6363
}
6464

65-
function getClassMembers({
65+
function getDataClassMembers({
6666
node,
6767
schema,
6868
config,

src/definitions/union.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ limitations under the License.
1313

1414
import { UnionTypeDefinitionNode } from "graphql";
1515
import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition";
16-
import { buildDirectiveAnnotations } from "../helpers/build-directive-annotations";
1716
import { CodegenConfigWithDefaults } from "../config";
1817
import {
1918
buildAnnotations,
@@ -32,10 +31,9 @@ export function buildUnionTypeDefinition(
3231
definitionNode: node,
3332
});
3433
if (config.unionGeneration === "ANNOTATION_CLASS") {
35-
const directiveAnnotations = buildDirectiveAnnotations(node, config);
3634
const possibleTypes =
3735
node.types?.map((type) => `${type.name.value}::class`).join(", ") || "";
38-
return `${directiveAnnotations}@GraphQLUnion(
36+
return `${annotations}@GraphQLUnion(
3937
name = "${node.name.value}",
4038
possibleTypes = [${possibleTypes}],
4139
description = "${trimDescription(node.description?.value)}"

src/helpers/add-dependent-types.ts renamed to src/helpers/add-dependent-types-to-only-types.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,24 @@ limitations under the License.
1313

1414
import { CodegenConfigWithDefaults } from "../config";
1515
import { getDependentTypeNames } from "./get-dependent-type-names";
16-
import { dependentTypeIsInScope } from "./dependent-type-is-in-scope";
1716
import { GraphQLSchema } from "graphql";
1817

19-
export function addDependentTypes(
18+
export function addDependentTypesToOnlyTypes(
2019
config: CodegenConfigWithDefaults,
2120
schema: GraphQLSchema,
2221
) {
2322
if (!config.onlyTypes) {
24-
throw new Error(`config.onlyTypes is required to add dependent types`);
23+
throw new Error(`onlyTypes config is required to add dependent types`);
2524
}
2625
const onlyTypesNodes = config.onlyTypes
2726
.map((typeName) => schema.getType(typeName)?.astNode)
2827
.filter(Boolean);
2928
const dependentTypeNames = onlyTypesNodes.flatMap((node) =>
3029
getDependentTypeNames(schema, node, config),
3130
);
32-
const dependentTypesInScope = dependentTypeNames.filter((typeName) =>
33-
dependentTypeIsInScope(typeName, config),
34-
);
31+
const typesInScope = config.dependentTypesInScope;
32+
const dependentTypesInScope = typesInScope
33+
? dependentTypeNames.filter((typeName) => typesInScope.includes(typeName))
34+
: dependentTypeNames;
3535
config.onlyTypes.push(...dependentTypesInScope);
3636
}

src/helpers/build-annotations.ts

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
InputValueDefinitionNode,
1919
TypeDefinitionNode,
2020
} from "graphql";
21+
import { buildDescriptionAnnotation } from "./build-description-annotation";
2122
import { buildDirectiveAnnotations } from "./build-directive-annotations";
2223
import { CodegenConfigWithDefaults } from "../config";
2324
import { TypeMetadata } from "./build-type-metadata";
@@ -30,37 +31,24 @@ export type DefinitionNode =
3031

3132
export function buildAnnotations({
3233
config,
33-
inputDescription,
3434
definitionNode,
3535
resolvedType,
3636
}: {
3737
config: CodegenConfigWithDefaults;
38-
inputDescription?: string;
39-
definitionNode?: DefinitionNode;
38+
definitionNode: DefinitionNode;
4039
resolvedType?: TypeMetadata;
4140
}) {
42-
const description =
43-
inputDescription ?? definitionNode?.description?.value ?? "";
44-
const isDeprecated = isDeprecatedDescription(description, resolvedType);
45-
const descriptionAnnotator = isDeprecated
46-
? "@Deprecated"
47-
: "@GraphQLDescription";
48-
const descriptionValue = isDeprecated
49-
? description.replace("DEPRECATED: ", "")
50-
: description;
51-
const trimmedDescription = trimDescription(descriptionValue);
52-
const descriptionAnnotation = description
53-
? `${descriptionAnnotator}("${trimmedDescription}")\n`
54-
: "";
55-
56-
const directiveAnnotations = definitionNode
57-
? buildDirectiveAnnotations(
58-
definitionNode,
59-
config,
60-
description,
61-
resolvedType,
62-
)
63-
: "";
41+
const description = definitionNode?.description?.value ?? "";
42+
const descriptionAnnotation = buildDescriptionAnnotation(
43+
description,
44+
definitionNode,
45+
config,
46+
resolvedType,
47+
);
48+
const directiveAnnotations = buildDirectiveAnnotations(
49+
definitionNode,
50+
config,
51+
);
6452
const unionAnnotation = resolvedType?.unionAnnotation
6553
? `@${resolvedType.unionAnnotation}\n`
6654
: "";
@@ -84,15 +72,6 @@ export function buildAnnotations({
8472
);
8573
}
8674

87-
export function isDeprecatedDescription(
88-
description?: string,
89-
resolvedType?: TypeMetadata,
90-
) {
91-
return (
92-
description?.startsWith("DEPRECATED: ") && !resolvedType?.unionAnnotation
93-
);
94-
}
95-
9675
export function trimDescription(description?: string) {
9776
return (
9877
description

src/helpers/build-config-with-defaults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export function buildConfigWithDefaults(
1313
...config,
1414
extraImports: [
1515
"com.expediagroup.graphql.generator.annotations.*",
16-
...(config.extraImports ?? ([] satisfies string[])),
16+
...(config.extraImports ?? []),
1717
],
1818
} as const;
1919
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { CodegenConfigWithDefaults } from "../config";
2+
import { TypeMetadata } from "./build-type-metadata";
3+
import { indent } from "@graphql-codegen/visitor-plugin-common";
4+
import { Kind } from "graphql/index";
5+
import { DefinitionNode, trimDescription } from "./build-annotations";
6+
7+
export function buildDescriptionAnnotation(
8+
description: string,
9+
definitionNode: DefinitionNode,
10+
config: CodegenConfigWithDefaults,
11+
resolvedType?: TypeMetadata,
12+
) {
13+
const trimmedDescription = trimDescription(description);
14+
const isDeprecatedDescription = descriptionIsDeprecated(trimmedDescription);
15+
if (isDeprecatedDescription && resolvedType?.unionAnnotation) {
16+
return `@GraphQLDescription("${trimmedDescription}")\n`;
17+
} else if (isDeprecatedDescription) {
18+
const descriptionValue = description.replace("DEPRECATED: ", "");
19+
return `@Deprecated("${trimDescription(descriptionValue)}")\n`;
20+
}
21+
22+
const deprecatedDirective = definitionNode.directives?.find(
23+
(directive) => directive.name.value === "deprecated",
24+
);
25+
const deprecatedReasonNode = deprecatedDirective?.arguments?.find(
26+
(arg) => arg.name.value === "reason",
27+
)?.value;
28+
const deprecatedReason =
29+
deprecatedReasonNode?.kind === "StringValue"
30+
? deprecatedReasonNode.value
31+
: "";
32+
const trimmedDeprecatedReason = trimDescription(deprecatedReason);
33+
34+
if (deprecatedDirective && resolvedType?.unionAnnotation) {
35+
return `@GraphQLDescription("${trimmedDeprecatedReason}")\n`;
36+
} else if (deprecatedDirective) {
37+
const graphqlDescription = trimmedDescription
38+
? `@GraphQLDescription("${trimmedDescription}")\n`
39+
: "";
40+
const deprecatedDescription = `@Deprecated("${trimmedDeprecatedReason}")\n`;
41+
return `${graphqlDescription}${graphqlDescription ? indent(deprecatedDescription, 2) : deprecatedDescription}`;
42+
}
43+
44+
return trimmedDescription &&
45+
(config.unionGeneration === "MARKER_INTERFACE" ||
46+
definitionNode?.kind !== Kind.UNION_TYPE_DEFINITION)
47+
? `@GraphQLDescription("${trimmedDescription}")\n`
48+
: "";
49+
}
50+
51+
function descriptionIsDeprecated(description: string) {
52+
return description.startsWith("DEPRECATED: ");
53+
}

src/helpers/build-directive-annotations.ts

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,55 +12,26 @@ limitations under the License.
1212
*/
1313

1414
import { CodegenConfigWithDefaults } from "../config";
15-
import {
16-
DefinitionNode,
17-
isDeprecatedDescription,
18-
trimDescription,
19-
} from "./build-annotations";
15+
import { DefinitionNode } from "./build-annotations";
2016
import { getFederationDirectiveReplacement } from "./get-federation-directive-replacement";
21-
import { TypeMetadata } from "./build-type-metadata";
2217
import { ConstDirectiveNode } from "graphql/language";
2318

2419
export function buildDirectiveAnnotations(
25-
incomingNode: DefinitionNode,
20+
definitionNode: DefinitionNode,
2621
config: CodegenConfigWithDefaults,
27-
description?: string,
28-
resolvedType?: TypeMetadata,
2922
) {
30-
const kind = incomingNode.kind;
31-
const directives = incomingNode.directives ?? [];
32-
23+
const directives = definitionNode.directives ?? [];
3324
return directives
3425
.map((directive) => {
3526
const directiveName = directive.name.value;
36-
if (
37-
directiveName === "deprecated" &&
38-
!isDeprecatedDescription(description)
39-
) {
40-
const deprecatedReasonNode = directive.arguments?.find(
41-
(arg) => arg.name.value === "reason",
42-
)?.value;
43-
const deprecatedReason =
44-
deprecatedReasonNode?.kind === "StringValue"
45-
? deprecatedReasonNode.value
46-
: "";
47-
if (incomingNode.description?.value && resolvedType?.unionAnnotation) {
48-
return "";
49-
}
50-
const descriptionAnnotator = resolvedType?.unionAnnotation
51-
? "@GraphQLDescription"
52-
: "@Deprecated";
53-
const trimmedDeprecatedReason = trimDescription(deprecatedReason);
54-
return `${descriptionAnnotator}("${trimmedDeprecatedReason}")\n`;
55-
}
5627
const federationReplacement =
5728
getFederationDirectiveReplacement(directive);
5829
if (federationReplacement) return federationReplacement + "\n";
5930

6031
const directiveReplacementFromConfig = config.directiveReplacements?.find(
6132
({ directive, definitionType }) =>
6233
directive === directiveName &&
63-
(!definitionType || definitionType === kind),
34+
(!definitionType || definitionType === definitionNode.kind),
6435
);
6536
if (!directiveReplacementFromConfig) return "";
6637
const kotlinAnnotations = buildKotlinAnnotations(

src/helpers/dependent-type-is-in-scope.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/plugin.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
} from "@graphql-codegen/visitor-plugin-common";
2323
import { Input, safeParse } from "valibot";
2424
import { configSchema } from "./config";
25-
import { addDependentTypes } from "./helpers/add-dependent-types";
25+
import { addDependentTypesToOnlyTypes } from "./helpers/add-dependent-types-to-only-types";
2626
import { visit } from "graphql";
2727
import { buildConfigWithDefaults } from "./helpers/build-config-with-defaults";
2828

@@ -51,12 +51,11 @@ export const plugin: PluginFunction<GraphQLKotlinCodegenConfig> = (
5151
}
5252

5353
const configWithDefaults = buildConfigWithDefaults(config, info.outputFile);
54-
5554
if (
5655
configWithDefaults.onlyTypes &&
5756
configWithDefaults.includeDependentTypes
5857
) {
59-
addDependentTypes(configWithDefaults, schema);
58+
addDependentTypesToOnlyTypes(configWithDefaults, schema);
6059
}
6160
const visitor = new KotlinVisitor(configWithDefaults, schema);
6261
const astNode = getCachedDocumentNodeFromSchema(schema);
@@ -67,7 +66,10 @@ export const plugin: PluginFunction<GraphQLKotlinCodegenConfig> = (
6766
.map((annotation) => `import ${annotation}`)
6867
.join("\n") + "\n";
6968
const typeDefinitions = definitions
70-
.filter((d: unknown) => typeof d === "string" && d.length)
69+
.filter(
70+
(definition: unknown) =>
71+
typeof definition === "string" && definition.length,
72+
)
7173
.join("\n\n");
7274

7375
return [packageName, imports, typeDefinitions].join("\n") + "\n";

0 commit comments

Comments
 (0)