Skip to content

Commit

Permalink
feat: support fine-grained directive replacements (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
danadajian authored Apr 9, 2024
1 parent c6f4184 commit efe99f9
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 5 deletions.
27 changes: 25 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { array, boolean, enum_, object, optional, string } from "valibot";
import {
array,
boolean,
enum_,
object,
optional,
string,
union,
} from "valibot";
import { Kind } from "graphql";

export const configSchema = object({
Expand Down Expand Up @@ -70,7 +78,22 @@ export const configSchema = object({
/**
* A list of Kotlin annotations to replace the directive with.
*/
kotlinAnnotations: array(string()),
kotlinAnnotations: array(
union([
string(),
object({
/**
* The name of the annotation to replace the directive with.
*/
annotationName: string(),
/**
* The arguments to forward from the directive directly to the Kotlin annotation. Can be INT, FLOAT, STRING, BOOLEAN, or ENUM.
* @example @YourGraphQLDirective(arg1: "value1") -> @YourKotlinAnnotation(arg1 = "value1")
*/
argumentsToRetain: array(string()),
}),
]),
),
/**
* The type definition to apply the directive replacement to. If omitted, the replacement will apply to all definition types.
*/
Expand Down
41 changes: 39 additions & 2 deletions src/helpers/build-directive-annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { CodegenConfig } from "../plugin";
import { CodegenConfig, GraphQLKotlinCodegenConfig } from "../plugin";
import { DefinitionNode, isDeprecatedDescription } from "./build-annotations";
import { getFederationDirectiveReplacement } from "./get-federation-directive-replacement";
import { TypeMetadata } from "./build-type-metadata";
import { ConstDirectiveNode } from "graphql/language";

export function buildDirectiveAnnotations(
incomingNode: DefinitionNode,
Expand Down Expand Up @@ -57,7 +58,43 @@ export function buildDirectiveAnnotations(
(!definitionType || definitionType === kind),
);
if (!directiveReplacementFromConfig) return "";
return directiveReplacementFromConfig.kotlinAnnotations.join("\n") + "\n";
const kotlinAnnotations = buildKotlinAnnotations(
directive,
directiveReplacementFromConfig.kotlinAnnotations,
);
return kotlinAnnotations.join("\n") + "\n";
})
.join("");
}

function buildKotlinAnnotations(
directive: ConstDirectiveNode,
kotlinAnnotations: NonNullable<
GraphQLKotlinCodegenConfig["directiveReplacements"]
>[number]["kotlinAnnotations"],
) {
return kotlinAnnotations.map((kotlinAnnotation) => {
if (typeof kotlinAnnotation === "string") return kotlinAnnotation;
const directiveArguments = kotlinAnnotation.argumentsToRetain
?.map((argumentToRetain) => {
const argumentValueNode = directive.arguments?.find(
(argument) => argument.name.value === argumentToRetain,
)?.value;
if (!argumentValueNode)
throw new Error(
`Argument ${argumentToRetain} was provided in argumentsToRetain config but was not found in directive ${directive.name.value}`,
);
if (!("value" in argumentValueNode))
throw new Error(
`Directive argument ${argumentToRetain} in directive ${directive.name.value} has an unsupported type. Only INT, FLOAT, STRING, BOOLEAN, and ENUM are supported.`,
);
const argumentValue =
argumentValueNode.kind === "StringValue"
? `"${argumentValueNode.value}"`
: argumentValueNode.value;
return `${argumentToRetain} = ${argumentValue}`;
})
.join(", ");
return `@${kotlinAnnotation.annotationName}(${directiveArguments})`;
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,14 @@ export default {
directive: "directive1",
kotlinAnnotations: ["@SomeAnnotation1", "@SomeAnnotation2"],
},
{
directive: "directiveWithArgs",
kotlinAnnotations: [
{
annotationName: "SomeAnnotation3",
argumentsToRetain: ["arg1", "arg2"],
},
],
},
],
} satisfies GraphQLKotlinCodegenConfig;
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.expediagroup.graphql.generator.annotations.*
@GraphQLDescription("A description for MyDirectiveType")
@SomeAnnotation1
@SomeAnnotation2
@SomeAnnotation3(arg1 = "arg1", arg2 = 0)
data class MyDirectiveType(
val field: String? = null
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
directive @directive1 on OBJECT | UNION
directive @directiveWithArgs(arg1: String, arg2: Int) on OBJECT | UNION

"A description for MyDirectiveType"
type MyDirectiveType @directive1 {
type MyDirectiveType @directive1 @directiveWithArgs(arg1: "arg1", arg2: 0) {
field: String
}

Expand Down

0 comments on commit efe99f9

Please sign in to comment.