Repository navigation
[visitor-plugin-common] fix: satisfy strict mode in selection-set-to-object, client-side-base-visitor and base-documents-visitor (#4683) #11031
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| --- | ||
| '@graphql-codegen/visitor-plugin-common': patch | ||
| --- | ||
|
|
||
| Fix type errors in `visitor-plugin-common` (`selection-set-to-object`, `client-side-base-visitor` and `base-documents-visitor`) under `strict: true`: | ||
|
|
||
| - `BaseDocumentsVisitor._selectionSetToObject` is optional, since it is only set by `setSelectionSetHandler`. `FragmentDefinition` and `OperationDefinition` throw a descriptive error when it is not set, and `FragmentDefinition` throws one when the fragment's type condition is not in the schema. | ||
| - `BaseDocumentsVisitor.FragmentDefinition` may return `null`, which it already returns when `generateOperationTypes` is `false`. | ||
| - `ClientSideBaseVisitor.buildOperation` may return `null`, which its base implementation already returns. | ||
| - `SelectionSetToObject.transformSelectionSet` declares its return type, and throws a descriptive error when the instance has no selection set. | ||
| - `LinkField`'s `alias` is optional, matching the link fields built for fields without an alias. | ||
| - `BaseSelectionSetProcessor.typeCache` is keyed by `Location | undefined`, since selection sets parsed with `noLocation` have no `loc`. | ||
| - `getPossibleTypes` accepts any `GraphQLType` or `undefined`, which it already handles by unwrapping lists and non-nulls and returning no types, and returns a copy of the schema's possible types instead of the schema's own readonly array. | ||
| - `OperationVariablesToObject.transform` accepts `undefined`, which it already handles by returning `null`. | ||
|
|
||
| Generated output is unchanged. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -256,7 +256,7 @@ export class ClientSideBaseVisitor< | |
| fragments: LoadedFragment[], | ||
| rawConfig: TRawConfig, | ||
| additionalConfig: Partial<TPluginConfig>, | ||
| documents?: Types.DocumentFile[], | ||
| documents: Types.DocumentFile[] = [], | ||
| ) { | ||
| super(rawConfig, { | ||
| scalars: buildScalarsFromConfig(_schema, rawConfig), | ||
|
|
@@ -464,10 +464,10 @@ export class ClientSideBaseVisitor< | |
| ): Record<string, any> | void | undefined { | ||
| let meta: Record<string, any> | void | undefined; | ||
|
|
||
| if (node.kind === Kind.OPERATION_DEFINITION) { | ||
| if (node.kind === Kind.OPERATION_DEFINITION && this._onExecutableDocumentNode) { | ||
| meta = this._onExecutableDocumentNode({ | ||
| kind: Kind.DOCUMENT, | ||
| definitions, | ||
| definitions: definitions || [], | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -487,8 +487,8 @@ export class ClientSideBaseVisitor< | |
| } { | ||
| const deferredFields: { [fargmentName: string]: string[] } = {}; | ||
| const queue: SelectionNode[] = [...node.selectionSet.selections]; | ||
| while (queue.length) { | ||
| const selection = queue.shift(); | ||
| // `for...of` also visits the selections pushed to `queue` while iterating | ||
| for (const selection of queue) { | ||
| if ( | ||
| selection.kind === Kind.FRAGMENT_SPREAD && | ||
| selection.directives?.some((d: DirectiveNode) => d.name.value === 'defer') | ||
|
|
@@ -675,7 +675,7 @@ export class ClientSideBaseVisitor< | |
| this.config.importDocumentNodeExternallyFrom === 'near-operation-file' && | ||
| this._documents.length === 1 | ||
| ) { | ||
| let documentPath = `./${this.clearExtension(basename(this._documents[0].location))}`; | ||
| let documentPath = `./${this.clearExtension(basename(this._documents[0].location || ''))}`; | ||
| documentPath += normalizeImportExtension({ | ||
| emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports, | ||
| importExtension: this.config.importExtension, | ||
|
|
@@ -692,7 +692,7 @@ export class ClientSideBaseVisitor< | |
|
|
||
| this._imports.add( | ||
| `import * as Operations from '${this.clearExtension( | ||
| this.config.importDocumentNodeExternallyFrom, | ||
| this.config.importDocumentNodeExternallyFrom || '', | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: This branch is reached right after the warning above when Generated by Claude Code Generated by Claude Code |
||
| )}';`, | ||
| ); | ||
| } | ||
|
|
@@ -722,7 +722,7 @@ export class ClientSideBaseVisitor< | |
| importSource: { | ||
| ...fragmentImports[0].importSource, | ||
| identifiers: unique( | ||
| flatten(fragmentImports.map(fi => fi.importSource.identifiers)), | ||
| flatten(fragmentImports.map(fi => fi.importSource.identifiers || [])), | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Generated by Claude Code Generated by Claude Code |
||
| identifier => identifier.name, | ||
| ), | ||
| }, | ||
|
|
@@ -747,7 +747,7 @@ export class ClientSideBaseVisitor< | |
| _operationResultType: string, | ||
| _operationVariablesTypes: string, | ||
| _hasRequiredVariables: boolean, | ||
| ): string { | ||
| ): string | null { | ||
| return null; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,7 @@ export type PrimitiveAliasedFields = { | |
| fieldName: string; | ||
| }; | ||
| export type LinkField = { | ||
| alias: string; | ||
| alias?: string; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this optional now?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Link fields have always been built with Generated by Claude Code Generated by Claude Code |
||
| name: string; | ||
| type: string; | ||
| selectionSet: string; | ||
|
|
@@ -34,7 +34,8 @@ export type SelectionSetProcessorConfig = { | |
| }; | ||
|
|
||
| export class BaseSelectionSetProcessor<Config extends SelectionSetProcessorConfig> { | ||
| typeCache = new Map<Location, Map<string, [string, string]>>(); | ||
| // Keyed by the selection set's `loc`, which is `undefined` for documents parsed with `noLocation` | ||
| typeCache = new Map<Location | undefined, Map<string, [string, string]>>(); | ||
|
|
||
| constructor(public config: Config) {} | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note:
definitionsis an optional param of this protected method, so a subclass that doesn't pass it gets an empty document here instead of one withdefinitions: undefined.Generated by Claude Code
Generated by Claude Code