Describe the bug
I am trying to have the generated types be globally available. In order for types to be globally available, two conditions must be met:
.d.ts.export or import keywords.However, there is a caveat with point two. If the file requires the import or export keyword, such as needing to import a type from another package, then the types in that file can still be made globally available by adding them inside of a global statement:
declare global {
type GloballyAvailableType = "isAvailableWithoutNeedingToImport"
}
After looking through the [3] issues related to globally available types, it seems a noExport configuration option was added and when set to true, will remove the export keyword from the generated types. I have not been able to produce this functionality. Is my codegen.yaml configured incorrectly?
More generally, assuming I am able to eventually get the export keyword removed from the types, will the keyword only be removed, or will the export-less types also be placed inside of a declare global { ... } scope? In the generated file, I see the following lines are added:
import { Context } from "@context.ts"
import {
GraphQLResolveInfo,
GraphQLScalarType,
GraphQLScalarTypeConfig,
} from "graphql"
With those lines included in the file, simply removing the export keyword will not be enough to make the types globally available. They will need to be placed inside of a declare global { ... } scope.
To Reproduce
Steps to reproduce the behavior:
codegen.yml file. I've included the comments so you can see what options I have tried. Of particular note, there is of course noExport: true, enumsAsTypes: true (as recommended by @dotansimha in this issue, globalNamespace: true, namePrefix: gql, and the require: option at the bottom, which I think at one point prevented the GraphQL type imports. overwrite: true
schema: ./schema.ts
# to help with the 'cannot use modules outside..' issue.
noRequire: true
documents: null
generates:
# server location for schema type definitions
./types/gen-types.d.ts:
hooks:
# applies prettier immediately after file update
afterOneFileWrite:
- prettier --write
plugins:
- typescript
- typescript-operations
- typescript-resolvers
config:
noExport: true
enumsAsTypes: true
contextType: "@context.ts#Context"
# defaultMapper: any
# globalNamespace: true
# namePrefix: gql
# noNamespaces: true
# client location for schema type definitions
../client/types/gen-types.d.tsx:
hooks:
# applies prettier immediately after file update
afterOneFileWrite:
- prettier --write
plugins:
- typescript:
noExport: true
- typescript-operations
- typescript-react-apollo
# require:
# - ts-node/register/transpile-only
# - tsconfig-paths/register
tsconfig.json file. Not sure how helpful this will be, but I have included it anyway.{
"compilerOptions": {
"module": "commonjs",
// this is necessary so that typescript compiles puppeteer to code that can
// use features like ..., const [v] = arr, and many other features
"target": "es2020",
"sourceMap": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// allows array destructuring of regex matches
"downlevelIteration": true,
// no implicit any, no nulls, and a few others
"strict": true,
// show full typescript definition on hover
"noErrorTruncation": true,
// supposedly adds color to typescript out
"pretty": true,
// do not emit outputs
// "noEmit": true,
// do not emit comments
"removeComments": true,
// enables typescript to parse react syntax
"jsx": "react",
// enables functions such as Object.entries
"lib": ["es2018", "es6", "dom", "dom.iterable", "esnext"],
// the process the compiler uses to figure out what an import refers to.
// the node resolution strategy attempts to mimic the node.js module resolution mechanism at runtime.
"moduleResolution": "node",
// transpile each file as a separate module (?)
"isolatedModules": true,
// make the TypeScript compiler to emit declaration files for all types
"declaration": true,
"traceResolution": true,
// needed to recognize import keyword
"esModuleInterop": true,
// allow imports without *
"allowSyntheticDefaultImports": true,
// have TypeScript analyze imported .json files and provide correct information regarding their shape, obviating the need for a wildcard module declaration and validating the presence of the file.
"resolveJsonModule": true,
/* ! 1. you need the tsconfig-paths-webpack-plugin
npm install --save-dev tsconfig-paths-webpack-plugin
*/
/* ! 2. update webpack configuration
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
resolve: {
plugins: [new TsconfigPathsPlugin({...options})]
}
}
*/
// needed for "paths" option to work
// got it working as ".", immediately after changing from "/"
"baseUrl": ".",
"paths": {
"*": ["types/*"],
// "@helpers/*": ["./helpers/*"],
"@utilities/*": ["./utilities/*"],
"@dynamodb": ["./databases/dynamodb"],
"@schema": ["./schema"],
"@resolvers": ["./resolvers"],
"@scalars": ["./scalars"],
"@context": ["./context"],
"@logger": ["./utilities/logger"],
"@highlighter": ["./utilities/highlighter"],
"@errors": ["./utilities/errors"]
}
},
"exclude": ["node_modules"],
"include": ["./**/*.ts"]
}
With this codegen.yml file, my generated types look like this:
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
parent: TParent,
context: TContext,
info: GraphQLResolveInfo,
) => Maybe<TTypes>
export type NextResolverFn<T> = () => Promise<T>
export type DirectiveResolverFn<
TResult = {},
TParent = {},
TContext = {},
TArgs = {}
> = (
next: NextResolverFn<TResult>,
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo,
) => TResult | Promise<TResult>
Expected behavior
I expect adding noExport: true to config: will remove the export keyword from the generated types and add them to a declare global { ... } scoping if other types need to be imported e.g. Context.
Environment:
@graphql-codegen/...:
"@graphql-codegen/cli": "^1.9.1",
"@graphql-codegen/introspection": "1.0.0",
"@graphql-codegen/typescript": "1.0.0",
"@graphql-codegen/typescript-operations": "1.0.0",
"@graphql-codegen/typescript-react-apollo": "1.0.0",
"@graphql-codegen/typescript-resolvers": "1.0.0",
NodeJS: v13.4.0
Hi @the-unbearable-lightness-of-being !
I'm not sure typescript-resolvers supports noExport, but we can check that.
Can you please try without typescript-resolvers and see if it works for you as global declaration?
Hello @dotansimha, unfortunately that did not produce the global types. The export keyword still appears before each generated type.
@the-unbearable-lightness-of-being I see. Can you please create a reproduction? I tried to check and it seems like noExport works for the base plugin
I was facing this as well, in my own case, it was because a single-file had multiple plugins (that's the default configuration if you follow the wizard and choose more than one plugin). While the tool is going to respect the noExport for the typescript plugin it won't for the others鈥攕o my solution was to split the generation into multiple files. i.e:
overwrite: true
schema: 'http://localhost:3000/graphql'
generates:
src/typings/graphql/global.d.ts:
plugins:
- 'typescript'
config:
noExport: true
src/typings/graphql/resolvers.d.ts:
plugins:
- 'typescript-resolvers'
@the-unbearable-lightness-of-being
Closing. Feel free to provide a reproduction and we'll check that again.
Most helpful comment
I was facing this as well, in my own case, it was because a single-file had multiple plugins (that's the default configuration if you follow the wizard and choose more than one plugin). While the tool is going to respect the
noExportfor thetypescriptplugin it won't for the others鈥攕o my solution was to split the generation into multiple files. i.e: