Skip to content

Commit fddd3df

Browse files
committed
small refactors
1 parent 6fb41c8 commit fddd3df

30 files changed

+171
-166
lines changed

bun.lockb

1.29 KB
Binary file not shown.

docs/docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ sidebar_position: 3
55
# Configuration
66

77
```ts reference title="Config Schema"
8-
https://github.com/ExpediaGroup/graphql-kotlin-codegen/blob/main/src/config.ts#L17-L100000
8+
https://github.com/ExpediaGroup/graphql-kotlin-codegen/blob/main/src/config.ts#L1-L100000
99
```

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: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
union,
2323
} from "valibot";
2424
import { Kind } from "graphql";
25-
import { buildConfigWithDefaults } from "./helpers/build-config-with-defaults";
2625

2726
export const configSchema = object({
2827
/**
@@ -46,11 +45,11 @@ export const configSchema = object({
4645
dependentTypesInScope: optional(array(string())),
4746
/**
4847
* 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.
48+
* @description This should be used for types outside `dependentTypesInScope` that are not generated by the plugin. Only use when unionGeneration is set to `ANNOTATION_CLASS`.
5049
*/
5150
externalUnionsAsInterfaces: optional(array(string())),
5251
/**
53-
* Additional imports to add to the generated file.
52+
* Additional imports to add to the generated file. GraphQL Kotlin annotations are always imported.
5453
* @example ["com.example.additional.import.*"]
5554
*/
5655
extraImports: optional(array(string())),
@@ -133,13 +132,12 @@ export const configSchema = object({
133132
),
134133
/**
135134
* Denotes the generation strategy for union types. Defaults to `MARKER_INTERFACE`.
135+
*
136136
* https://opensource.expediagroup.com/graphql-kotlin/docs/schema-generator/writing-schemas/unions/
137+
*
138+
* @description The `MARKER_INTERFACE` option is highly recommended, since it is slightly more type-safe than using annotation classes.
137139
*/
138140
unionGeneration: optional(
139141
union([literal("ANNOTATION_CLASS"), literal("MARKER_INTERFACE")]),
140142
),
141143
});
142-
143-
export type CodegenConfigWithDefaults = ReturnType<
144-
typeof buildConfigWithDefaults
145-
>;

src/definitions/enum.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { EnumTypeDefinitionNode, EnumValueDefinitionNode } from "graphql";
1515
import { indentMultiline } from "@graphql-codegen/visitor-plugin-common";
1616
import { buildAnnotations } from "../helpers/build-annotations";
1717
import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition";
18-
import { CodegenConfigWithDefaults } from "../config";
18+
import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults";
1919

2020
export function buildEnumTypeDefinition(
2121
node: EnumTypeDefinitionNode,

src/definitions/input.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-defi
1616
import { buildTypeMetadata } from "../helpers/build-type-metadata";
1717
import { buildAnnotations } from "../helpers/build-annotations";
1818
import { indent } from "@graphql-codegen/visitor-plugin-common";
19-
import { CodegenConfigWithDefaults } from "../config";
19+
import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults";
2020

2121
export function buildInputObjectDefinition(
2222
node: InputObjectTypeDefinitionNode,
@@ -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/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { indent } from "@graphql-codegen/visitor-plugin-common";
1717
import { buildTypeMetadata } from "../helpers/build-type-metadata";
1818
import { shouldIncludeTypeDefinition } from "../helpers/should-include-type-definition";
1919
import { buildFieldDefinition } from "../helpers/build-field-definition";
20-
import { CodegenConfigWithDefaults } from "../config";
20+
import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults";
2121

2222
export function buildInterfaceDefinition(
2323
node: InterfaceTypeDefinitionNode,

src/definitions/object.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
import { isResolverType } from "../helpers/is-resolver-type";
2424
import { buildFieldDefinition } from "../helpers/build-field-definition";
2525
import { isExternalField } from "../helpers/is-external-field";
26-
import { CodegenConfigWithDefaults } from "../config";
26+
import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults";
2727

2828
export function buildObjectTypeDefinition(
2929
node: ObjectTypeDefinitionNode,
@@ -42,27 +42,27 @@ export function buildObjectTypeDefinition(
4242
const dependentInterfaces = getDependentInterfaceNames(node);
4343
const dependentUnions = getDependentUnionsForType(schema, node);
4444
const interfacesToInherit =
45-
config.unionGeneration === "ANNOTATION_CLASS"
46-
? dependentInterfaces
47-
: dependentInterfaces.concat(dependentUnions);
45+
config.unionGeneration === "MARKER_INTERFACE"
46+
? dependentInterfaces.concat(dependentUnions)
47+
: dependentInterfaces;
4848
const interfaceInheritance = `${interfacesToInherit.length ? ` : ${interfacesToInherit.join(", ")}` : ""}`;
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: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ 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";
17-
import { CodegenConfigWithDefaults } from "../config";
16+
import { CodegenConfigWithDefaults } from "../helpers/build-config-with-defaults";
1817
import {
1918
buildAnnotations,
2019
trimDescription,
@@ -31,17 +30,16 @@ export function buildUnionTypeDefinition(
3130
config,
3231
definitionNode: node,
3332
});
34-
if (config.unionGeneration === "ANNOTATION_CLASS") {
35-
const directiveAnnotations = buildDirectiveAnnotations(node, config);
36-
const possibleTypes =
37-
node.types?.map((type) => `${type.name.value}::class`).join(", ") || "";
38-
return `${directiveAnnotations}@GraphQLUnion(
33+
if (config.unionGeneration === "MARKER_INTERFACE") {
34+
return `${annotations}interface ${node.name.value}`;
35+
}
36+
37+
const possibleTypes =
38+
node.types?.map((type) => `${type.name.value}::class`).join(", ") || "";
39+
return `${annotations}@GraphQLUnion(
3940
name = "${node.name.value}",
4041
possibleTypes = [${possibleTypes}],
4142
description = "${trimDescription(node.description?.value)}"
4243
)
4344
annotation class ${node.name.value}`;
44-
}
45-
46-
return `${annotations}interface ${node.name.value}`;
4745
}

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,26 @@ See the License for the specific language governing permissions and
1111
limitations under the License.
1212
*/
1313

14-
import { CodegenConfigWithDefaults } from "../config";
14+
import { CodegenConfigWithDefaults } from "./build-config-with-defaults";
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: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ import {
1818
InputValueDefinitionNode,
1919
TypeDefinitionNode,
2020
} from "graphql";
21+
import { buildDescriptionAnnotation } from "./build-description-annotation";
2122
import { buildDirectiveAnnotations } from "./build-directive-annotations";
22-
import { CodegenConfigWithDefaults } from "../config";
23+
import { CodegenConfigWithDefaults } from "./build-config-with-defaults";
2324
import { TypeMetadata } from "./build-type-metadata";
2425

2526
export type DefinitionNode =
@@ -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: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ 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
}
20+
21+
export type CodegenConfigWithDefaults = ReturnType<
22+
typeof buildConfigWithDefaults
23+
>;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { CodegenConfigWithDefaults } from "./build-config-with-defaults";
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 = trimmedDescription.startsWith(
15+
deprecatedDescriptionPrefix,
16+
);
17+
if (isDeprecatedDescription && resolvedType?.unionAnnotation) {
18+
return `@GraphQLDescription("${trimmedDescription}")\n`;
19+
} else if (isDeprecatedDescription) {
20+
const descriptionValue = description.replace(
21+
deprecatedDescriptionPrefix,
22+
"",
23+
);
24+
return `@Deprecated("${trimDescription(descriptionValue)}")\n`;
25+
}
26+
27+
const deprecatedDirective = definitionNode.directives?.find(
28+
(directive) => directive.name.value === "deprecated",
29+
);
30+
const deprecatedReasonNode = deprecatedDirective?.arguments?.find(
31+
(arg) => arg.name.value === "reason",
32+
)?.value;
33+
const deprecatedReason =
34+
deprecatedReasonNode?.kind === "StringValue"
35+
? deprecatedReasonNode.value
36+
: "";
37+
const trimmedDeprecatedReason = trimDescription(deprecatedReason);
38+
39+
if (deprecatedDirective && resolvedType?.unionAnnotation) {
40+
return `@GraphQLDescription("${trimmedDeprecatedReason}")\n`;
41+
} else if (deprecatedDirective) {
42+
const graphqlDescription = trimmedDescription
43+
? `@GraphQLDescription("${trimmedDescription}")\n`
44+
: "";
45+
const deprecatedDescription = `@Deprecated("${trimmedDeprecatedReason}")\n`;
46+
return `${graphqlDescription}${graphqlDescription ? indent(deprecatedDescription, 2) : deprecatedDescription}`;
47+
}
48+
49+
if (
50+
trimmedDescription &&
51+
(config.unionGeneration === "MARKER_INTERFACE" ||
52+
definitionNode?.kind !== Kind.UNION_TYPE_DEFINITION)
53+
) {
54+
return `@GraphQLDescription("${trimmedDescription}")\n`;
55+
}
56+
57+
return "";
58+
}
59+
60+
const deprecatedDescriptionPrefix = "DEPRECATED: ";

0 commit comments

Comments
 (0)