Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/configurable-variable-naming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@swc-contrib/plugin-graphql-codegen-client-preset": minor
---

Add configurable document/fragment variable prefix, suffix, dedupeOperationSuffix, and omitOperationSuffix options matching @graphql-codegen/client-preset
13 changes: 13 additions & 0 deletions contrib/graphql-codegen-client-preset/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ You will need to provide the `artifactDirectory` path that should be the same as

The plugin also supports a `namingConvention` option to match the naming convention configured in your `codegen.ts`. The default is `"change-case-all#pascalCase"` which matches the default for `@graphql-codegen/client-preset`. If you have set `namingConvention: "change-case-all#upperCaseFirst"` in your `codegen.ts`, you must also set it in the plugin options.

#### Variable prefix/suffix options

By default the plugin appends `"Document"` to operation names and `"FragmentDoc"` to fragment names when generating import identifiers — matching the `@graphql-codegen/client-preset` defaults. If you've changed these in your codegen config, set the same values here so the plugin generates matching imports.

| Option | Default | Description |
|--------|---------|-------------|
| `documentVariablePrefix` | `""` | Prefix for operation variable names |
| `documentVariableSuffix` | `"Document"` | Suffix for operation variable names |
| `fragmentVariablePrefix` | `""` | Prefix for fragment variable names |
| `fragmentVariableSuffix` | `"FragmentDoc"` | Suffix for fragment variable names |
| `dedupeOperationSuffix` | `false` | When `true`, deduplicates overlapping suffix on fragments (e.g. `MyFragment` + `FragmentDoc` → `MyFragmentDoc` instead of `MyFragmentFragmentDoc`) |
| `omitOperationSuffix` | `false` | When `true`, omits the fragment variable suffix entirely |

#### Vite

```ts
Expand Down
97 changes: 77 additions & 20 deletions contrib/graphql-codegen-client-preset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ pub struct GraphQLCodegenOptions {
pub artifact_directory: String,
pub gql_tag_name: String,
pub naming_convention: String,
pub document_variable_prefix: String,
pub document_variable_suffix: String,
pub fragment_variable_prefix: String,
pub fragment_variable_suffix: String,
pub dedupe_operation_suffix: bool,
pub omit_operation_suffix: bool,
}

pub struct GraphQLVisitor {
Expand All @@ -137,6 +143,23 @@ impl GraphQLVisitor {
}
}

fn resolve_fragment_suffix(&self, fragment_name: &str) -> &str {
if self.options.omit_operation_suffix {
""
} else if self.options.dedupe_operation_suffix
&& fragment_name.to_lowercase().ends_with("fragment")
&& self
.options
.fragment_variable_suffix
.to_lowercase()
.starts_with("fragment")
{
&self.options.fragment_variable_suffix["fragment".len()..]
} else {
&self.options.fragment_variable_suffix
}
}

fn handle_error(&self, details: &str, span: Span) {
let message = format!("@graphql-codegen/client-preset-swc-plugin details: {details}");
HANDLER.with(|handler| handler.struct_span_err(span, &message).emit());
Expand Down Expand Up @@ -246,29 +269,31 @@ impl VisitMut for GraphQLVisitor {

let operation_name = match first_definition {
graphql_parser::query::Definition::Fragment(fragment) => {
fragment.name.to_string() + "FragmentDoc"
let suffix = self.resolve_fragment_suffix(fragment.name);
format!(
"{}{}{}",
self.options.fragment_variable_prefix, fragment.name, suffix
)
Comment thread
m-sanders marked this conversation as resolved.
}
graphql_parser::query::Definition::Operation(op) => match op {
graphql_parser::query::OperationDefinition::Query(query) => {
match query.name {
Some(name) => name.to_string() + "Document",
None => return,
graphql_parser::query::Definition::Operation(op) => {
let name = match op {
graphql_parser::query::OperationDefinition::Query(q) => q.name,
graphql_parser::query::OperationDefinition::Mutation(m) => m.name,
graphql_parser::query::OperationDefinition::Subscription(s) => {
s.name
}
}
graphql_parser::query::OperationDefinition::Mutation(mutation) => {
match mutation.name {
Some(name) => name.to_string() + "Document",
None => return,
}
}
graphql_parser::query::OperationDefinition::Subscription(
subscription,
) => match subscription.name {
Some(name) => name.to_string() + "Document",
_ => return,
};
match name {
Some(name) => format!(
"{}{}{}",
self.options.document_variable_prefix,
name,
self.options.document_variable_suffix
),
Comment thread
m-sanders marked this conversation as resolved.
None => return,
},
_ => return,
},
}
}
};

let import_name =
Expand Down Expand Up @@ -349,6 +374,14 @@ fn naming_convention_default() -> String {
"change-case-all#pascalCase".to_string()
}

fn document_variable_suffix_default() -> String {
"Document".to_string()
}

fn fragment_variable_suffix_default() -> String {
"FragmentDoc".to_string()
}

#[derive(Deserialize)]
#[serde(untagged)]
enum NamingConventionOption {
Expand Down Expand Up @@ -383,6 +416,24 @@ struct PluginOptions {

#[serde(default = "naming_convention_option_default")]
namingConvention: NamingConventionOption,

#[serde(default)]
documentVariablePrefix: String,

#[serde(default = "document_variable_suffix_default")]
documentVariableSuffix: String,

#[serde(default)]
fragmentVariablePrefix: String,

#[serde(default = "fragment_variable_suffix_default")]
fragmentVariableSuffix: String,

#[serde(default)]
dedupeOperationSuffix: bool,

#[serde(default)]
omitOperationSuffix: bool,
}

#[plugin_transform]
Expand Down Expand Up @@ -414,6 +465,12 @@ pub fn process_transform(program: Program, metadata: TransformPluginProgramMetad
artifact_directory,
gql_tag_name: plugin_config.gqlTagName,
naming_convention: plugin_config.namingConvention.as_type_name_convention(),
document_variable_prefix: plugin_config.documentVariablePrefix,
document_variable_suffix: plugin_config.documentVariableSuffix,
fragment_variable_prefix: plugin_config.fragmentVariablePrefix,
fragment_variable_suffix: plugin_config.fragmentVariableSuffix,
dedupe_operation_suffix: plugin_config.dedupeOperationSuffix,
omit_operation_suffix: plugin_config.omitOperationSuffix,
});

program.apply(&mut visit_mut_pass(visitor))
Expand Down
Loading
Loading