-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
711 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
--- | ||
"@graphql-codegen/cli": minor | ||
"@graphql-codegen/core": minor | ||
"@graphql-codegen/plugin-helpers": minor | ||
"@graphql-codegen/client-preset": minor | ||
"@graphql-codegen/gql-tag-operations-preset": minor | ||
"@graphql-codegen/graphql-modules-preset": minor | ||
--- | ||
|
||
Introduce a new feature called DocumentTransform. | ||
|
||
DocumentTransform is a functionality that allows you to modify `documents` before they are processed by plugins. You can use functions passed to the `documentTransforms` option to make changes to GraphQL documents. | ||
|
||
To use this feature, you can write `documentTransforms` as follows: | ||
|
||
```ts | ||
import type { CodegenConfig } from '@graphql-codegen/cli'; | ||
|
||
const config: CodegenConfig = { | ||
schema: 'https://localhost:4000/graphql', | ||
documents: ['src/**/*.tsx'], | ||
generates: { | ||
'./src/gql/': { | ||
preset: 'client', | ||
documentTransforms: [ | ||
{ | ||
transform: ({ documents }) => { | ||
// Make some changes to the documents | ||
return documents; | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
export default config; | ||
``` | ||
|
||
For instance, to remove a `@localOnlyDirective` directive from `documents`, you can write the following code: | ||
|
||
```js | ||
import type { CodegenConfig } from '@graphql-codegen/cli'; | ||
import { visit } from 'graphql'; | ||
|
||
const config: CodegenConfig = { | ||
schema: 'https://localhost:4000/graphql', | ||
documents: ['src/**/*.tsx'], | ||
generates: { | ||
'./src/gql/': { | ||
preset: 'client', | ||
documentTransforms: [ | ||
{ | ||
transform: ({ documents }) => { | ||
return documents.map(documentFile => { | ||
documentFile.document = visit(documentFile.document, { | ||
Directive: { | ||
leave(node) { | ||
if (node.name.value === 'localOnlyDirective') return null; | ||
}, | ||
}, | ||
}); | ||
return documentFile; | ||
}); | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
export default config; | ||
``` | ||
|
||
DocumentTransform can also be specified by file name. You can create a custom file for a specific transformation and pass it to `documentTransforms`. | ||
|
||
Let's create the document transform as a file: | ||
|
||
```js | ||
module.exports = { | ||
transform: ({ documents }) => { | ||
// Make some changes to the documents | ||
return documents; | ||
}, | ||
}; | ||
``` | ||
|
||
Then, you can specify the file name as follows: | ||
|
||
```ts | ||
import type { CodegenConfig } from '@graphql-codegen/cli'; | ||
|
||
const config: CodegenConfig = { | ||
schema: 'https://localhost:4000/graphql', | ||
documents: ['src/**/*.tsx'], | ||
generates: { | ||
'./src/gql/': { | ||
preset: 'client', | ||
documentTransforms: ['./my-document-transform.js'], | ||
}, | ||
}, | ||
}; | ||
export default config; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { resolve } from 'path'; | ||
import { Types } from '@graphql-codegen/plugin-helpers'; | ||
|
||
export async function getDocumentTransform( | ||
documentTransform: Types.OutputDocumentTransform, | ||
loader: Types.PackageLoaderFn<Types.DocumentTransformObject>, | ||
defaultName: string | ||
): Promise<Types.ConfiguredDocumentTransform> { | ||
if (typeof documentTransform === 'string') { | ||
const transformObject = await getDocumentTransformByName(documentTransform, loader); | ||
return { name: documentTransform, transformObject }; | ||
} | ||
if (isTransformObject(documentTransform)) { | ||
return { name: defaultName, transformObject: documentTransform }; | ||
} | ||
if (isTransformFileConfig(documentTransform)) { | ||
const name = Object.keys(documentTransform)[0]; | ||
const transformObject = await getDocumentTransformByName(name, loader); | ||
return { name, transformObject, config: Object.values(documentTransform)[0] }; | ||
} | ||
throw new Error( | ||
` | ||
An unknown format document transform: '${defaultName}'. | ||
` | ||
); | ||
} | ||
|
||
function isTransformObject(config: Types.OutputDocumentTransform): config is Types.DocumentTransformObject { | ||
return typeof config === 'object' && config.transform && typeof config.transform === 'function'; | ||
} | ||
|
||
function isTransformFileConfig(config: Types.OutputDocumentTransform): config is Types.DocumentTransformFileConfig { | ||
const keys = Object.keys(config); | ||
return keys.length === 1 && typeof keys[0] === 'string'; | ||
} | ||
|
||
export async function getDocumentTransformByName( | ||
name: string, | ||
loader: Types.PackageLoaderFn<Types.DocumentTransformObject> | ||
): Promise<Types.DocumentTransformObject> { | ||
const possibleNames = [ | ||
`@graphql-codegen/${name}`, | ||
`@graphql-codegen/${name}-document-transform`, | ||
name, | ||
resolve(process.cwd(), name), | ||
]; | ||
|
||
const possibleModules = possibleNames.concat(resolve(process.cwd(), name)); | ||
|
||
for (const moduleName of possibleModules) { | ||
try { | ||
return await loader(moduleName); | ||
} catch (err) { | ||
if (err.code !== 'MODULE_NOT_FOUND' && err.code !== 'ERR_MODULE_NOT_FOUND') { | ||
throw new Error( | ||
` | ||
Unable to load document transform matching '${name}'. | ||
Reason: | ||
${err.message} | ||
` | ||
); | ||
} | ||
} | ||
} | ||
|
||
const possibleNamesMsg = possibleNames | ||
.map(name => | ||
` | ||
- ${name} | ||
`.trimEnd() | ||
) | ||
.join(''); | ||
|
||
throw new Error( | ||
` | ||
Unable to find document transform matching '${name}' | ||
Install one of the following packages: | ||
${possibleNamesMsg} | ||
` | ||
); | ||
} |
Oops, something went wrong.