@nmarks/graphql-codegen-per-operation-file-preset
v1.0.10
Published
GraphQL Code Generator preset for generating one file per operation/fragment
Downloads
2,746
Readme
@graphql-codegen/per-operation-file-preset
Generate one file per GraphQL operation or fragment, named after the operation/fragment itself.
Installation
npm install @graphql-codegen/per-operation-file-presetUsage
// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'schema.graphql',
documents: 'src/**/*.ts',
generates: {
'src/': {
preset: 'per-operation-file',
presetConfig: {
baseTypesPath: 'types.ts',
},
plugins: ['typescript-operations'],
},
},
};
export default config;How It Works
Unlike the near-operation-file preset which generates one file per source file, this preset generates one file per operation/fragment.
Example
Input:
// src/queries/user.ts
export const GetUserQuery = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`;
export const GetUsersQuery = gql`
query GetUsers {
users {
id
name
}
}
`;Output:
src/queries/__generated__/GetUser.ts # Generated types for GetUser query
src/queries/__generated__/GetUsers.ts # Generated types for GetUsers queryFragments
Input:
// src/fragments/user.ts
export const UserFieldsFragment = gql`
fragment UserFields on User {
id
name
email
}
`;Output:
src/fragments/__generated__/UserFields.tsConfiguration
baseTypesPath (required)
Path to your base schema types file (generated by the typescript plugin).
presetConfig: {
baseTypesPath: 'types.ts'
}You can also use npm packages:
presetConfig: {
baseTypesPath: '~@myapp/graphql-types'
}folder (optional)
Folder name for generated files, relative to the source file location.
Default: __generated__
presetConfig: {
baseTypesPath: 'types.ts',
folder: 'generated' // Use 'generated' instead of '__generated__'
}extension (optional)
File extension for generated files.
Default: .ts
presetConfig: {
baseTypesPath: 'types.ts',
extension: '.generated.ts'
}importTypesNamespace (optional)
Namespace for importing base schema types.
Default: Types
presetConfig: {
baseTypesPath: 'types.ts',
importTypesNamespace: 'SchemaTypes'
}cwd (optional)
Override the current working directory.
Default: process.cwd()
presetConfig: {
baseTypesPath: 'types.ts',
cwd: '/custom/path'
}Fragment Imports
The preset automatically handles fragment imports. If an operation uses a fragment from another file, it will generate the correct import statement.
Example:
// src/fragments/user.ts
fragment UserFields on User { id name }
// src/queries/user.ts
query GetUser($id: ID!) {
user(id: $id) {
...UserFields
}
}Generated:
// src/queries/__generated__/GetUser.ts
import { UserFieldsFragment, UserFieldsFragmentDoc } from '../../fragments/__generated__/UserFields';
// ... rest of generated codeComparison with near-operation-file
| Feature | near-operation-file | per-operation-file | |---------|-------------------|-------------------| | File Strategy | One file per source file | One file per operation/fragment | | Output Naming | Based on source filename | Based on operation/fragment name | | Multiple Operations | Combined in one file | Split into separate files | | Fragment Imports | ✅ Supported | ✅ Supported | | Use Case | Co-location with source | Migration from other tools, explicit operation files |
When to Use This Preset
Use per-operation-file when:
- ✅ Migrating from tools that generate one file per operation
- ✅ You want explicit, discoverable operation files
- ✅ You have multiple operations per source file
- ✅ You want operation names to match generated file names
Use near-operation-file when:
- ✅ You want generated files to mirror your source structure
- ✅ You prefer one-to-one mapping between source and generated files
- ✅ You typically have one operation per source file
License
MIT
