Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-codegen/typescript-operations": patch
---
dependencies updates:
- Removed dependency [`@graphql-codegen/typescript@^5.0.7` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.7) (from `dependencies`)
9 changes: 9 additions & 0 deletions .changeset/khaki-spies-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@graphql-codegen/typescript-operations': major
---

BREAKING CHANGE: Decouple `typescript-operations` plugin from `typescript` plugin

Previously, `TypeScriptOperationVariablesToObject` from `typescript-operations` was extending from `typescript` plugin. This made it (1) very hard to read, as we need to jump from base class <-> typescript class <-> typescript-operations class to understand the flow and (2) very hard to evolve the two independently (which is the point of this work).

Since there's not much shared logic anyways, it's simpler to extend the `typescript-operations` class from the base class directly.
1 change: 0 additions & 1 deletion packages/plugins/typescript/operations/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"dependencies": {
"@graphql-codegen/plugin-helpers": "^6.1.0",
"@graphql-codegen/schema-ast": "^5.0.0",
"@graphql-codegen/typescript": "^5.0.7",
Copy link
Collaborator Author

@eddeee888 eddeee888 Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bye! 🫡

@graphql-codegen/typescript served us well for the last 10+ years. But with goal of creating the independence of typescript for typescript-operations plugin for this work, we can now remove this dep.

"@graphql-codegen/visitor-plugin-common": "6.2.2",
"auto-bind": "~4.0.0",
"tslib": "~2.6.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { TypeScriptOperationVariablesToObject as TSOperationVariablesToObject } from '@graphql-codegen/typescript';
import {
OperationVariablesToObject,
ConvertNameFn,
NormalizedAvoidOptionalsConfig,
NormalizedScalarsMap,
ParsedEnumValuesMap,
} from '@graphql-codegen/visitor-plugin-common';
import { Kind, TypeNode } from 'graphql';

export const SCALARS = {
ID: 'string | number',
Expand All @@ -10,7 +17,36 @@ export const SCALARS = {

const MAYBE_SUFFIX = ' | null';

export class TypeScriptOperationVariablesToObject extends TSOperationVariablesToObject {
export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject {
constructor(
_scalars: NormalizedScalarsMap,
_convertName: ConvertNameFn,
private _avoidOptionals: NormalizedAvoidOptionalsConfig,
private _immutableTypes: boolean,
_namespacedImportName: string | null,
_enumNames: string[],
_enumPrefix: boolean,
_enumSuffix: boolean,
_enumValues: ParsedEnumValuesMap,
_applyCoercion: boolean
Comment on lines +22 to +31
Copy link
Collaborator Author

@eddeee888 eddeee888 Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are lots of default values here from the typescript version of this class.

Since we are really dedicating this implementation for typescript-operations, it's a lot easier to force them to be non-optional since we only have one use case to cater for.

We event removed the last param _maybeType since we don't use it in typescript-operations any more!

) {
super(
_scalars,
_convertName,
_namespacedImportName,
_enumNames,
_enumPrefix,
_enumSuffix,
_enumValues,
_applyCoercion,
{}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is _directiveArgumentAndInputFieldMappings.

We were receiving undefined all the time from the only callsite, so it's ok to just pass through the default value.

);
}

protected formatFieldString(fieldName: string, isNonNullType: boolean, hasDefaultValue: boolean): string {
return `${fieldName}${this.getAvoidOption(isNonNullType, hasDefaultValue) ? '?' : ''}`;
}

protected formatTypeString(fieldType: string, _isNonNullType: boolean, _hasDefaultValue: boolean): string {
return fieldType;
}
Expand All @@ -23,11 +59,37 @@ export class TypeScriptOperationVariablesToObject extends TSOperationVariablesTo
return str;
}

protected getAvoidOption(isNonNullType: boolean, hasDefaultValue: boolean) {
const options = this._avoidOptionals;
return ((options.object || !options.defaultValue) && hasDefaultValue) || (!options.object && !isNonNullType);
}

public wrapAstTypeWithModifiers(baseType: string, typeNode: TypeNode, applyCoercion = false): string {
if (typeNode.kind === Kind.NON_NULL_TYPE) {
const type = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion);

return this.clearOptional(type);
}
if (typeNode.kind === Kind.LIST_TYPE) {
const innerType = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion);
const listInputCoercionExtension = applyCoercion ? ` | ${innerType}` : '';

return this.wrapMaybe(
`${this._immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>${listInputCoercionExtension}`
);
}
return this.wrapMaybe(baseType);
}

protected wrapMaybe(type: string): string {
return type?.endsWith(MAYBE_SUFFIX) ? type : `${type}${MAYBE_SUFFIX}`;
}

protected getScalar(name: string): string {
return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'unknown';
}

protected getPunctuation(): string {
return ';';
}
}
4 changes: 1 addition & 3 deletions packages/plugins/typescript/operations/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor<
this.config.enumPrefix,
this.config.enumSuffix,
this.config.enumValues,
this.config.arrayInputCoercion,
undefined,
undefined
Comment on lines -173 to -174
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are always passing undefined through, we can just use the default.

this.config.arrayInputCoercion
)
);
this._declarationBlockConfig = {
Expand Down