diff --git a/src/gen.ts b/src/gen.ts index a024d74e..9f2c14b4 100644 --- a/src/gen.ts +++ b/src/gen.ts @@ -1,4 +1,5 @@ import globby from 'globby'; +import createExecContext from './lib/exec-context'; import fullGenerate, { CodegenContext, SkippedContext, @@ -13,8 +14,8 @@ import { rimraf } from './lib/file'; async function removeOldTsxCaches( cwd: string, config: ConfigTypes, - codegenContext: CodegenContext, - skippedContext: SkippedContext, + codegenContext: CodegenContext[], + skippedContext: SkippedContext[], ) { const cacheDir = getCacheFullDir(cwd, config.cacheDir); const validTsxCaches = [ @@ -28,13 +29,16 @@ async function removeOldTsxCaches( for (const tsx of oldTsxPaths) await rimraf(tsx); } -export default async function gen(commandOpts: CommandOpts): Promise { +export default async function gen({ + cwd, + configFilePath, +}: CommandOpts): Promise { logUpdate(PRINT_PREFIX + 'Running graphql-codegen...'); - const { cwd, configFilePath } = commandOpts; const [config, configHash] = await loadConfig(cwd, configFilePath); + const execContext = createExecContext(cwd, config, configHash); - const [generated, skipped] = await fullGenerate(cwd, config, configHash); + const [generated, skipped] = await fullGenerate(execContext); await removeOldTsxCaches(cwd, config, generated, skipped); diff --git a/src/jestTransformer.ts b/src/jestTransformer.ts index a2c4bb6f..47a23267 100644 --- a/src/jestTransformer.ts +++ b/src/jestTransformer.ts @@ -4,6 +4,7 @@ import { createTransformer, getCacheKey as getBabelCacheKey } from 'babel-jest'; import graphQLTransformer from 'jest-transform-graphql'; import { join as pathJoin, relative as pathRelative } from 'path'; import { readFileSync } from 'fs'; +import createExecContext from './lib/exec-context'; import { loadConfigSync } from './lib/load-config'; import { createPaths } from './lib/paths'; @@ -23,7 +24,8 @@ const jestTransformer: Transformer = { }, process(input, filePath, jestConfig, transformOptions) { const { rootDir } = jestConfig; - const [config] = loadConfigSync(rootDir); + const [config, configHash] = loadConfigSync(rootDir); + const execContext = createExecContext(rootDir, config, configHash); const fileSchema = config.schema as string; const schemaFullPath = pathJoin(rootDir, fileSchema); @@ -37,9 +39,8 @@ const jestTransformer: Transformer = { } const { tsxFullPath } = createPaths( - rootDir, + execContext, pathRelative(rootDir, filePath), - config.cacheDir, ); const tsxContent = readFileSync(tsxFullPath, 'utf-8'); diff --git a/src/lib/create-codegen-opts.ts b/src/lib/create-codegen-opts.ts index eed9658b..c274c23b 100644 --- a/src/lib/create-codegen-opts.ts +++ b/src/lib/create-codegen-opts.ts @@ -3,9 +3,9 @@ import { ConfigTypes } from './types'; export type PartialCodegenOpts = Pick; -export default async function createCodegenOpts( +export default function createCodegenOpts( config: ConfigTypes, -): Promise { +): PartialCodegenOpts { return { config: { withHOC: false, // True by default diff --git a/src/lib/dts.ts b/src/lib/dts.ts index 2246f419..69b79000 100644 --- a/src/lib/dts.ts +++ b/src/lib/dts.ts @@ -1,5 +1,6 @@ import makeDir from 'make-dir'; import path from 'path'; +import slash from 'slash'; import { createCompilerHost, createProgram, @@ -10,7 +11,9 @@ import { findConfigFile, readConfigFile, } from 'typescript'; +import { ExecContext } from './exec-context'; import { withHash, writeFile } from './file'; +import { CodegenContext } from './full-generate'; import { ConfigTypes } from './types'; const essentialCompilerOptions: CompilerOptions = { @@ -20,9 +23,9 @@ const essentialCompilerOptions: CompilerOptions = { noEmit: false, }; -function resolveCompilerOptions(configObj: ConfigTypes) { - const fileName = configObj.TSConfigFile || 'tsconfig.json'; - const configPath = findConfigFile(process.cwd(), sys.fileExists, fileName); +function resolveCompilerOptions(cwd: string, { TSConfigFile }: ConfigTypes) { + const fileName = TSConfigFile || 'tsconfig.json'; + const configPath = findConfigFile(cwd, sys.fileExists, fileName); let compilerOptions = essentialCompilerOptions; if (configPath != null) { @@ -32,7 +35,7 @@ function resolveCompilerOptions(configObj: ConfigTypes) { if (config != null) { const settings = convertCompilerOptionsFromJson( { ...config['compilerOptions'], ...essentialCompilerOptions }, - process.cwd(), + cwd, ); if (settings.errors.length > 0) { console.log(settings.errors); @@ -51,16 +54,29 @@ function resolveCompilerOptions(configObj: ConfigTypes) { } export function genDts( - tsxFullPaths: string[], - configObj: ConfigTypes, + { cwd, config }: ExecContext, + codegenContext: CodegenContext[], ): string[] { - const compilerOptions = resolveCompilerOptions(configObj); + const compilerOptions = resolveCompilerOptions(cwd, config); + const tsxFullPaths = codegenContext.map(({ tsxFullPath }) => + slash(tsxFullPath), + ); + const tsxFullPathSet = new Set(tsxFullPaths); const compilerHost = createCompilerHost(compilerOptions); const dtsContents: string[] = []; - compilerHost.writeFile = (name, dtsContent) => { - // XXX: How to improve memory usage? + compilerHost.writeFile = ( + name, + dtsContent, + writeByteOrderMark, + onError, + sourceFiles, + ) => { + // TypeScript can write `d.ts`s of submodules imported from `.tsx`s. + // We only pick up `.d.ts`s for `.tsx` entry points. + const [{ fileName }] = sourceFiles!; + if (!tsxFullPathSet.has(fileName)) return; dtsContents.push(dtsContent); }; @@ -94,19 +110,23 @@ export function genDts( throw new Error('Failed to generate .d.ts.'); } + if (codegenContext.length !== dtsContents.length) { + throw new Error( + `Never supposed to be here. Please make an issue on GitHub.`, + ); + } + return dtsContents; } export async function processGenDts( - dtsFullPath: string, - tsxFullPath: string, - gqlRelPath: string, - sourceHash: string, - config: ConfigTypes, + execContext: ExecContext, + codegenContext: CodegenContext, ) { + const { dtsFullPath, gqlHash } = codegenContext; await makeDir(path.dirname(dtsFullPath)); - const [dtsContent] = await genDts([tsxFullPath], config); + const [dtsContent] = await genDts(execContext, [codegenContext]); if (!dtsContent) throw new Error(`Generate ${dtsFullPath} fails.`); - await writeFile(dtsFullPath, withHash(sourceHash, dtsContent)); + await writeFile(dtsFullPath, withHash(gqlHash, dtsContent)); return dtsContent; } diff --git a/src/lib/exec-context.ts b/src/lib/exec-context.ts new file mode 100644 index 00000000..27d7fab9 --- /dev/null +++ b/src/lib/exec-context.ts @@ -0,0 +1,27 @@ +import createCodegenOpts, { PartialCodegenOpts } from './create-codegen-opts'; +import { getCacheFullDir } from './paths'; +import { ConfigTypes } from './types'; + +export type ExecContext = { + cwd: string; + config: ConfigTypes; + configHash: string; + codegenOpts: PartialCodegenOpts; + cacheFullDir: string; +}; + +export default function createExecContext( + cwd: string, + config: ConfigTypes, + configHash: string, +) { + const codegenOpts = createCodegenOpts(config); + const cacheFullDir = getCacheFullDir(cwd, config.cacheDir); + return { + cwd, + config, + codegenOpts, + configHash, + cacheFullDir, + }; +} diff --git a/src/lib/full-generate.ts b/src/lib/full-generate.ts index f442b308..9c95baf3 100644 --- a/src/lib/full-generate.ts +++ b/src/lib/full-generate.ts @@ -2,40 +2,34 @@ import glob from 'globby'; import logUpdate from 'log-update'; import makeDir from 'make-dir'; import { join as pathJoin, dirname } from 'path'; -import createCodegenOpts, { PartialCodegenOpts } from './create-codegen-opts'; import { genDts } from './dts'; +import { ExecContext } from './exec-context'; import { createHash } from './hash'; -import { createPaths } from './paths'; +import { CreatedPaths, createPaths } from './paths'; import { PRINT_PREFIX } from './print'; import { processGenerateResolverTypes, shouldGenResolverTypes, } from './resolver-types'; -import { ConfigTypes } from './types'; import { processGraphQLCodegen } from './graphql-codegen'; import { readFile, writeFile, withHash, readHash } from './file'; -export type CodegenContext = { - tsxFullPath: string; - dtsFullPath: string; - gqlRelPath: string; +export type CodegenContext = CreatedPaths & { gqlHash: string; dtsContentDecorator: (content: string) => string; -}[]; +}; export type SkippedContext = { tsxFullPath: string; dtsFullPath: string; -}[]; +}; export async function processResolverTypesIfNeeded( - cwd: string, - config: ConfigTypes, - configHash: string, - codegenOpts: PartialCodegenOpts, - codegenContext: CodegenContext, - skippedContext: SkippedContext, + execContext: ExecContext, + codegenContext: CodegenContext[], + skippedContext: SkippedContext[], ) { + const { cwd, config, configHash, codegenOpts } = execContext; // To pass config change on subsequent generation, // configHash should be primary hash seed. let schemaHash = configHash; @@ -45,7 +39,7 @@ export async function processResolverTypesIfNeeded( const schemaFullPath = pathJoin(cwd, fileSchema); const content = await readFile(schemaFullPath); schemaHash = createHash(schemaHash + content); - const createdPaths = createPaths(cwd, fileSchema, config.cacheDir); + const createdPaths = createPaths(execContext, fileSchema); const shouldUpdate = schemaHash !== (await readHash(createdPaths.tsxFullPath)) || @@ -60,11 +54,7 @@ export async function processResolverTypesIfNeeded( `Local schema files are detected. Generating resolver types...`, ); - const { - tsxFullPath, - dtsFullPath, - gqlRelPath, - } = await processGenerateResolverTypes( + await processGenerateResolverTypes( schemaHash, config, codegenOpts, @@ -73,9 +63,7 @@ export async function processResolverTypesIfNeeded( ); codegenContext.push({ - tsxFullPath, - dtsFullPath, - gqlRelPath, + ...createdPaths, gqlHash: schemaHash, dtsContentDecorator: (s) => { return `${s} @@ -99,22 +87,18 @@ export default typeof DocumentNode } export async function processDocuments( + execContext: ExecContext, gqlRelPaths: string[], - cwd: string, - config: ConfigTypes, schemaHash: string, - codegenOpts: PartialCodegenOpts, - codegenContext: CodegenContext, - skippedContext: SkippedContext, + codegenContext: CodegenContext[], + skippedContext: SkippedContext[], ) { + const { cwd, config, codegenOpts } = execContext; for (const gqlRelPath of gqlRelPaths) { const gqlContent = await readFile(pathJoin(cwd, gqlRelPath), 'utf-8'); - const { tsxFullPath, dtsFullPath } = createPaths( - cwd, - gqlRelPath, - config.cacheDir, - ); + const createdPaths = createPaths(execContext, gqlRelPath); + const { tsxFullPath, dtsFullPath } = createdPaths; // Here I add "schemaHash" as a hash seed. Types of GraphQL documents // basically depends on schema, which change should effect to document results. @@ -137,9 +121,7 @@ export async function processDocuments( documents: gqlRelPath, }); codegenContext.push({ - tsxFullPath, - dtsFullPath, - gqlRelPath, + ...createdPaths, gqlHash, dtsContentDecorator: (s) => s, }); @@ -149,8 +131,7 @@ export async function processDocuments( } } -export async function prepareFullGenerate(cwd: string, config: ConfigTypes) { - const codegenOpts = await createCodegenOpts(config); +export async function prepareFullGenerate({ cwd, config }: ExecContext) { const gqlRelPaths = await glob(config.documents, { cwd, gitignore: config.respectGitIgnore, @@ -162,18 +143,15 @@ export async function prepareFullGenerate(cwd: string, config: ConfigTypes) { )}. Check "documents" in .graphql-let.yml.`, ); } - return { codegenOpts, gqlRelPaths }; + return gqlRelPaths; } export async function processDtsForCodegenContext( - codegenContext: CodegenContext, - config: ConfigTypes, + execContext: ExecContext, + codegenContext: CodegenContext[], ) { logUpdate(PRINT_PREFIX + 'Generating .d.ts...'); - const dtsContents = genDts( - codegenContext.map((s) => s.tsxFullPath), - config, - ); + const dtsContents = genDts(execContext, codegenContext); await makeDir(dirname(codegenContext[0].dtsFullPath)); for (const [i, dtsContent] of dtsContents.entries()) { @@ -184,36 +162,29 @@ export async function processDtsForCodegenContext( } async function fullGenerate( - cwd: string, - config: ConfigTypes, - configHash: string, -): Promise<[CodegenContext, SkippedContext]> { - const codegenContext: CodegenContext = []; - const skippedContext: SkippedContext = []; + execContext: ExecContext, +): Promise<[CodegenContext[], SkippedContext[]]> { + const codegenContext: CodegenContext[] = []; + const skippedContext: SkippedContext[] = []; - const { codegenOpts, gqlRelPaths } = await prepareFullGenerate(cwd, config); + const gqlRelPaths = await prepareFullGenerate(execContext); const { schemaHash } = await processResolverTypesIfNeeded( - cwd, - config, - configHash, - codegenOpts, + execContext, codegenContext, skippedContext, ); await processDocuments( + execContext, gqlRelPaths, - cwd, - config, schemaHash, - codegenOpts, codegenContext, skippedContext, ); if (codegenContext.length) - await processDtsForCodegenContext(codegenContext, config); + await processDtsForCodegenContext(execContext, codegenContext); return [codegenContext, skippedContext]; } diff --git a/src/lib/graphql-codegen.ts b/src/lib/graphql-codegen.ts index edcddb91..bd271ac6 100644 --- a/src/lib/graphql-codegen.ts +++ b/src/lib/graphql-codegen.ts @@ -2,7 +2,7 @@ import { Types } from '@graphql-codegen/plugin-helpers'; import { generate } from '@graphql-codegen/cli'; import makeDir from 'make-dir'; import path from 'path'; -import createCodegenOpts from './create-codegen-opts'; +import { ExecContext } from './exec-context'; import { ConfigTypes } from './types'; import { withHash, writeFile } from './file'; @@ -63,18 +63,15 @@ export async function processGraphQLCodegen( /** * Process graphql-codegen including calling "loadSchema", which is also a possibly expensive function */ -export async function processGraphQLCodegenFromConfig( - config: ConfigTypes, - userDir: string, +export function processGraphQLCodegenFromConfig( + { cwd, config, codegenOpts }: ExecContext, tsxFullPath: string, gqlRelPath: string, gqlContent: string, gqlHash: string, ) { - const codegenOpts = await createCodegenOpts(config); - - return await processGraphQLCodegen({ - cwd: userDir, + return processGraphQLCodegen({ + cwd, schema: config.schema, filename: tsxFullPath, documents: gqlContent, diff --git a/src/lib/paths.ts b/src/lib/paths.ts index 414685a2..06f755ba 100644 --- a/src/lib/paths.ts +++ b/src/lib/paths.ts @@ -1,4 +1,5 @@ import path from 'path'; +import { ExecContext } from './exec-context'; export type CreatedPaths = { gqlRelPath: string; @@ -22,12 +23,9 @@ export const getCacheFullDir = (cwd: string, cacheDir?: string) => { }; export function createPaths( - cwd: string, + { cwd, cacheFullDir }: ExecContext, gqlRelPath: string, - customCacheDir?: string, ): CreatedPaths { - const cacheFullDir = getCacheFullDir(cwd, customCacheDir); - const tsxRelPath = `${gqlRelPath}.tsx`; const tsxFullPath = path.join(cacheFullDir, tsxRelPath); const dtsRelPath = `${gqlRelPath}.d.ts`; diff --git a/src/lib/resolver-types.ts b/src/lib/resolver-types.ts index c35c7f20..07e2e38e 100644 --- a/src/lib/resolver-types.ts +++ b/src/lib/resolver-types.ts @@ -37,9 +37,10 @@ export async function processGenerateResolverTypes( schemaHash: string, config: ConfigTypes, codegenOpts: PartialCodegenOpts, - { dtsFullPath, dtsRelPath, gqlFullPath, tsxFullPath }: CreatedPaths, + createdPath: CreatedPaths, cwd: string, -) { +): Promise { + const { gqlFullPath, tsxFullPath } = createdPath; await processGraphQLCodegen({ cwd, schema: gqlFullPath, @@ -50,14 +51,5 @@ export async function processGenerateResolverTypes( gqlHash: schemaHash, }); - const schemaPathWithExtension = getSchemaPointerWithExtension(config.schema); - if (!schemaPathWithExtension) throw new Error('never'); - - return { - schemaHash, - tsxFullPath, - dtsFullPath, - dtsRelPath, - gqlRelPath: schemaPathWithExtension, - }; + if (!getSchemaPointerWithExtension(config.schema)) throw new Error('never'); } diff --git a/src/loader.ts b/src/loader.ts index 04016a12..51f7067c 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -2,6 +2,7 @@ import logUpdate from 'log-update'; import { loader } from 'webpack'; import { join as pathJoin, relative as pathRelative } from 'path'; import { processGenDts } from './lib/dts'; +import createExecContext from './lib/exec-context'; import { readHash } from './lib/file'; import { processGraphQLCodegenFromConfig } from './lib/graphql-codegen'; import { createHash } from './lib/hash'; @@ -20,26 +21,29 @@ const processGraphQLCodegenLoader = memoize( cwd: string, ): Promise => { const [config, configHash] = await loadConfig(cwd); + const execContext = createExecContext(cwd, config, configHash); // To pass config change on subsequent generation, // configHash should be primary hash seed. - let schemaHash = configHash; + let schemaHash; if (shouldGenResolverTypes(config)) { const fileSchema = config.schema as string; const schemaFullPath = pathJoin(cwd, fileSchema); const content = await readFile(schemaFullPath); - schemaHash = createHash(schemaHash + content); + schemaHash = createHash(configHash + content); // If using resolver types, all documents should depend on all schema files. addDependency(schemaFullPath); + } else { + schemaHash = configHash; } - const { tsxFullPath, dtsFullPath, dtsRelPath, gqlRelPath } = createPaths( - cwd, + const createdPaths = createPaths( + execContext, pathRelative(cwd, gqlFullPath), - config.cacheDir, ); + const { tsxFullPath, dtsFullPath, dtsRelPath, gqlRelPath } = createdPaths; const gqlHash = createHash(schemaHash + gqlContent); const shouldUpdate = @@ -54,21 +58,18 @@ const processGraphQLCodegenLoader = memoize( // 2. Windows throws EPERM error for the deleting and creating file process. tsxContent = await processGraphQLCodegenFromConfig( - config, - cwd, + execContext, tsxFullPath, gqlRelPath, String(gqlContent), gqlHash, ); - await processGenDts( - dtsFullPath, - tsxFullPath, - gqlRelPath, + await processGenDts(execContext, { + ...createdPaths, gqlHash, - config, - ); + dtsContentDecorator: (_) => _, + }); logUpdate(PRINT_PREFIX + `${dtsRelPath} was generated.`); // Hack to prevent duplicated logs for simultaneous build, in SSR app for an example. await new Promise((resolve) => setTimeout(resolve, 0)); diff --git a/src/schemaLoader.ts b/src/schemaLoader.ts index 633bb558..a29cfc77 100644 --- a/src/schemaLoader.ts +++ b/src/schemaLoader.ts @@ -1,5 +1,6 @@ import logUpdate from 'log-update'; import { loader } from 'webpack'; +import createExecContext from './lib/exec-context'; import { processDtsForCodegenContext, prepareFullGenerate, @@ -15,17 +16,15 @@ import { PRINT_PREFIX } from './lib/print'; const processGraphQLCodegenSchemaLoader = memoize( async (cwd: string) => { const [config, configHash] = await loadConfig(cwd); + const execContext = createExecContext(cwd, config, configHash); - const codegenContext: CodegenContext = []; - const skippedContext: SkippedContext = []; + const codegenContext: CodegenContext[] = []; + const skippedContext: SkippedContext[] = []; - const { codegenOpts, gqlRelPaths } = await prepareFullGenerate(cwd, config); + const gqlRelPaths = await prepareFullGenerate(execContext); const { schemaHash } = await processResolverTypesIfNeeded( - cwd, - config, - configHash, - codegenOpts, + execContext, codegenContext, skippedContext, ); @@ -33,16 +32,14 @@ const processGraphQLCodegenSchemaLoader = memoize( // Only if schema was changed, documents are also handled for quick startup of webpack dev. if (codegenContext.length) { await processDocuments( + execContext, gqlRelPaths, - cwd, - config, schemaHash, - codegenOpts, codegenContext, skippedContext, ); - await processDtsForCodegenContext(codegenContext, config); + await processDtsForCodegenContext(execContext, codegenContext); } }, () => 'schemaLoader', diff --git a/test/__fixtures/gen/.graphql-let.yml b/test/__fixtures/gen/.graphql-let.yml index 669db069..0e657fb6 100644 --- a/test/__fixtures/gen/.graphql-let.yml +++ b/test/__fixtures/gen/.graphql-let.yml @@ -9,4 +9,4 @@ plugins: respectGitIgnore: true config: useIndexSignature: true -cacheDir: "test/__fixtures/gen/__generated__" +cacheDir: __generated__ diff --git a/test/__fixtures/hmr/.graphql-let.yml b/test/__fixtures/hmr/.graphql-let.yml index 6c41b2d1..b45142bc 100644 --- a/test/__fixtures/hmr/.graphql-let.yml +++ b/test/__fixtures/hmr/.graphql-let.yml @@ -5,3 +5,4 @@ plugins: - typescript-operations - typescript-react-apollo respectGitIgnore: true +cacheDir: __generated__ diff --git a/test/__fixtures/issue-118/.graphql-let.yml b/test/__fixtures/issue-118/.graphql-let.yml new file mode 100644 index 00000000..d6e48b4e --- /dev/null +++ b/test/__fixtures/issue-118/.graphql-let.yml @@ -0,0 +1,9 @@ +schema: lib/type-defs.graphqls +documents: "**/*.graphql" +plugins: + - typescript +respectGitIgnore: true +config: + mappers: + User: lib/user#User +cacheDir: __generated__ diff --git a/test/__fixtures/issue-118/lib/type-defs.graphqls b/test/__fixtures/issue-118/lib/type-defs.graphqls new file mode 100644 index 00000000..6a2ef0f9 --- /dev/null +++ b/test/__fixtures/issue-118/lib/type-defs.graphqls @@ -0,0 +1,13 @@ +type User { + id: ID! + name: String! + status: String! +} + +type Query { + viewer: User +} + +type Subscription { + sub: String +} diff --git a/test/__fixtures/issue-118/lib/user.ts b/test/__fixtures/issue-118/lib/user.ts new file mode 100644 index 00000000..dd96825a --- /dev/null +++ b/test/__fixtures/issue-118/lib/user.ts @@ -0,0 +1,11 @@ +export class User { + id: string; + name: string; + status: string; + + constructor(id: string, name: string, status: string) { + this.id = id; + this.name = name; + this.status = status; + } +} diff --git a/test/__fixtures/issue-118/lib/viewer.graphql b/test/__fixtures/issue-118/lib/viewer.graphql new file mode 100644 index 00000000..7f2a5b4f --- /dev/null +++ b/test/__fixtures/issue-118/lib/viewer.graphql @@ -0,0 +1,7 @@ +query Viewer { + viewer { + id + name + status + } +} diff --git a/test/__fixtures/issue-118/tsconfig.json b/test/__fixtures/issue-118/tsconfig.json new file mode 100644 index 00000000..1a3bd015 --- /dev/null +++ b/test/__fixtures/issue-118/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "allowJs": true, + "alwaysStrict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "jsx": "preserve", + "lib": ["dom", "es2017"], + "module": "esnext", + "moduleResolution": "node", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "esnext", + "baseUrl": "." + }, + "exclude": ["node_modules"], + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/test/__fixtures/loader/.graphql-let.yml b/test/__fixtures/loader/.graphql-let.yml index c29bfcee..4070e16d 100644 --- a/test/__fixtures/loader/.graphql-let.yml +++ b/test/__fixtures/loader/.graphql-let.yml @@ -5,3 +5,4 @@ plugins: - typescript-operations - typescript-react-apollo respectGitIgnore: true +cacheDir: __generated__ diff --git a/test/__fixtures/tsconfig/graphql-let.yml b/test/__fixtures/tsconfig/graphql-let.yml index 2f26602b..a8ff43d0 100644 --- a/test/__fixtures/tsconfig/graphql-let.yml +++ b/test/__fixtures/tsconfig/graphql-let.yml @@ -1,4 +1,4 @@ -schema: "schema/type-defs.graphqls" +schema: schema/type-defs.graphqls documents: - "**/*.graphql" plugins: @@ -7,5 +7,5 @@ plugins: - typescript-react-apollo config: useIndexSignature: true -TSConfigFile: "test/__fixtures/tsconfig/es3config.json" -cacheDir: "test/__fixtures/tsconfig/__generated__" +TSConfigFile: es3config.json +cacheDir: __generated__ diff --git a/test/__fixtures/tsconfig/graphql-let2.yml b/test/__fixtures/tsconfig/graphql-let2.yml index 46f9ecaa..0cc9af5d 100644 --- a/test/__fixtures/tsconfig/graphql-let2.yml +++ b/test/__fixtures/tsconfig/graphql-let2.yml @@ -1,4 +1,4 @@ -schema: "schema/type-defs.graphqls" +schema: schema/type-defs.graphqls documents: - "**/*.graphql" plugins: @@ -8,5 +8,5 @@ plugins: config: withHOC: false withHocks: true -TSConfigFile: "test/__fixtures/tsconfig/esnextconfig.json" -cacheDir: "test/__fixtures/tsconfig/__generated__" +TSConfigFile: esnextconfig.json +cacheDir: __generated__ diff --git a/test/__fixtures/tsconfig/graphql-let3.yml b/test/__fixtures/tsconfig/graphql-let3.yml index 612e4312..c97ca4a3 100644 --- a/test/__fixtures/tsconfig/graphql-let3.yml +++ b/test/__fixtures/tsconfig/graphql-let3.yml @@ -1,4 +1,4 @@ -schema: "schema/type-defs.graphqls" +schema: schema/type-defs.graphqls documents: - "**/*.graphql" plugins: @@ -7,4 +7,4 @@ plugins: - typescript-react-apollo config: useIndexSignature: true -cacheDir: "test/__fixtures/tsconfig/__generated__" +cacheDir: __generated__ diff --git a/test/__fixtures/tsconfig/graphql-let4.yml b/test/__fixtures/tsconfig/graphql-let4.yml index cd88d0eb..47a4c5cb 100644 --- a/test/__fixtures/tsconfig/graphql-let4.yml +++ b/test/__fixtures/tsconfig/graphql-let4.yml @@ -10,4 +10,4 @@ plugins: - typescript-react-apollo config: useIndexSignature: true -cacheDir: "test/__fixtures/tsconfig/__generated__" +cacheDir: __generated__ diff --git a/test/__fixtures/tsconfig/tsconfig.json b/test/__fixtures/tsconfig/tsconfig.json index 24ba961c..752eefa4 100644 --- a/test/__fixtures/tsconfig/tsconfig.json +++ b/test/__fixtures/tsconfig/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es3", + "target": "esnext", "module": "commonjs", "jsx": "preserve", "outDir": "./dist", diff --git a/test/__snapshots__/gen.test.ts.snap b/test/__snapshots__/gen.test.ts.snap index 445d3d6a..55d01287 100644 --- a/test/__snapshots__/gen.test.ts.snap +++ b/test/__snapshots__/gen.test.ts.snap @@ -3,52 +3,67 @@ exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected * ignoring "!" paths in "schema" and "documents" of graphql-let.yml * ignoring files specified in .gitignore -: pages/viewer.graphql.d.ts 1`] = ` -"/* f60a3f57259624d6235cbc35e4220b930c0e3538 +: __generated__/pages/viewer.graphql.tsx 1`] = ` +"/* c4ffa0d4a98b9173e641f88cb713cbbaa35a8692 * This file is automatically generated by graphql-let. */ -/// +import gql from 'graphql-tag'; +import * as React from 'react'; import * as ApolloReactCommon from '@apollo/react-common'; import * as ApolloReactComponents from '@apollo/react-components'; import * as ApolloReactHooks from '@apollo/react-hooks'; -export declare type Maybe = T | null; -export declare type Exact = { - [K in keyof T]: T[K]; -}; -export declare type Omit = Pick>; +export type Maybe = T | null; +export type Exact = { [K in keyof T]: T[K] }; +export type Omit = Pick>; /** All built-in and custom scalars, mapped to their actual values */ -export declare type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; -export declare type Query = { - __typename?: 'Query'; - viewer?: Maybe; + +export type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; -export declare type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; + +export type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; -export declare type ViewerQueryVariables = Exact<{ - [key: string]: never; -}>; -export declare type ViewerQuery = ({ - __typename?: 'Query'; -} & { - viewer?: Maybe<({ - __typename?: 'User'; - } & Pick)>; -}); -export declare const ViewerDocument: import(\\"graphql\\").DocumentNode; -export declare type ViewerComponentProps = Omit, 'query'>; -export declare const ViewerComponent: (props: ViewerComponentProps) => JSX.Element; + +export type ViewerQueryVariables = Exact<{ [key: string]: never; }>; + + +export type ViewerQuery = ( + { __typename?: 'Query' } + & { viewer?: Maybe<( + { __typename?: 'User' } + & Pick + )> } +); + + +export const ViewerDocument = gql\` + query Viewer { + viewer { + id + name + status + } +} + \`; +export type ViewerComponentProps = Omit, 'query'>; + + export const ViewerComponent = (props: ViewerComponentProps) => ( + query={ViewerDocument} {...props} /> + ); + + /** * __useViewerQuery__ * @@ -64,67 +79,81 @@ export declare const ViewerComponent: (props: ViewerComponentProps) => JSX.Eleme * }, * }); */ -export declare function useViewerQuery(baseOptions?: ApolloReactHooks.QueryHookOptions): ApolloReactCommon.QueryResult>; -export declare function useViewerLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions): ApolloReactHooks.QueryTuple>; -export declare type ViewerQueryHookResult = ReturnType; -export declare type ViewerLazyQueryHookResult = ReturnType; -export declare type ViewerQueryResult = ApolloReactCommon.QueryResult; -" +export function useViewerQuery(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(ViewerDocument, baseOptions); + } +export function useViewerLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(ViewerDocument, baseOptions); + } +export type ViewerQueryHookResult = ReturnType; +export type ViewerLazyQueryHookResult = ReturnType; +export type ViewerQueryResult = ApolloReactCommon.QueryResult;" `; exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected * ignoring "!" paths in "schema" and "documents" of graphql-let.yml * ignoring files specified in .gitignore -: pages/viewer2.graphql.d.ts 1`] = ` -"/* ad0917d5881bbadbe3a38bcfa56a3880e5791393 +: __generated__/pages/viewer2.graphql.tsx 1`] = ` +"/* b2463a5b834ec0328b95dd554ca377c66498827e * This file is automatically generated by graphql-let. */ -/// +import gql from 'graphql-tag'; +import * as React from 'react'; import * as ApolloReactCommon from '@apollo/react-common'; import * as ApolloReactComponents from '@apollo/react-components'; import * as ApolloReactHooks from '@apollo/react-hooks'; -export declare type Maybe = T | null; -export declare type Exact = { - [K in keyof T]: T[K]; -}; -export declare type Omit = Pick>; +export type Maybe = T | null; +export type Exact = { [K in keyof T]: T[K] }; +export type Omit = Pick>; /** All built-in and custom scalars, mapped to their actual values */ -export declare type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; -export declare type Query = { - __typename?: 'Query'; - viewer?: Maybe; + +export type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; -export declare type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; + +export type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; -export declare type Viewer2QueryVariables = Exact<{ - [key: string]: never; -}>; -export declare type Viewer2Query = ({ - __typename?: 'Query'; -} & { - viewer?: Maybe<({ - __typename?: 'User'; - } & Pick)>; -}); -export declare const Viewer2Document: import(\\"graphql\\").DocumentNode; -export declare type Viewer2ComponentProps = Omit, 'query'>; -export declare const Viewer2Component: (props: Viewer2ComponentProps) => JSX.Element; + +export type Viewer2QueryVariables = Exact<{ [key: string]: never; }>; + + +export type Viewer2Query = ( + { __typename?: 'Query' } + & { viewer?: Maybe<( + { __typename?: 'User' } + & Pick + )> } +); + + +export const Viewer2Document = gql\` + query Viewer2 { + viewer { + id + name + status + } +} + \`; +export type Viewer2ComponentProps = Omit, 'query'>; + + export const Viewer2Component = (props: Viewer2ComponentProps) => ( + query={Viewer2Document} {...props} /> + ); + + /** * __useViewer2Query__ * @@ -140,192 +169,217 @@ export declare const Viewer2Component: (props: Viewer2ComponentProps) => JSX.Ele * }, * }); */ -export declare function useViewer2Query(baseOptions?: ApolloReactHooks.QueryHookOptions): ApolloReactCommon.QueryResult>; -export declare function useViewer2LazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions): ApolloReactHooks.QueryTuple>; -export declare type Viewer2QueryHookResult = ReturnType; -export declare type Viewer2LazyQueryHookResult = ReturnType; -export declare type Viewer2QueryResult = ApolloReactCommon.QueryResult; -" +export function useViewer2Query(baseOptions?: ApolloReactHooks.QueryHookOptions) { + return ApolloReactHooks.useQuery(Viewer2Document, baseOptions); + } +export function useViewer2LazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { + return ApolloReactHooks.useLazyQuery(Viewer2Document, baseOptions); + } +export type Viewer2QueryHookResult = ReturnType; +export type Viewer2LazyQueryHookResult = ReturnType; +export type Viewer2QueryResult = ApolloReactCommon.QueryResult;" `; exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected * ignoring "!" paths in "schema" and "documents" of graphql-let.yml * ignoring files specified in .gitignore -: schema/type-defs.graphqls.d.ts 1`] = ` -"/* 04c878b1083226163fc16f7c2aee84d2ede9d378 +: __generated__/schema/type-defs.graphqls.tsx 1`] = ` +"/* 14d70566f4d02e53323ea8c820b4a3edeecc4672 * This file is automatically generated by graphql-let. */ import { GraphQLResolveInfo } from 'graphql'; -export declare type Maybe = T | null; -export declare type Exact = { - [K in keyof T]: T[K]; -}; +export type Maybe = T | null; +export type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ -export declare type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; -}; -export declare type Query = { - __typename?: 'Query'; - viewer?: Maybe; +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; -export declare type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; + +export type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; -export declare type WithIndex = TObject & Record; -export declare type ResolversObject = WithIndex; -export declare type ResolverTypeWrapper = Promise | T; -export declare type LegacyStitchingResolver = { - fragment: string; - resolve: ResolverFn; + +export type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; -export declare type NewStitchingResolver = { - selectionSet: string; - resolve: ResolverFn; + +export type WithIndex = TObject & Record; +export type ResolversObject = WithIndex; + +export type ResolverTypeWrapper = Promise | T; + + +export type LegacyStitchingResolver = { + fragment: string; + resolve: ResolverFn; }; -export declare type StitchingResolver = LegacyStitchingResolver | NewStitchingResolver; -export declare type Resolver = ResolverFn | StitchingResolver; -export declare type ResolverFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => Promise | TResult; -export declare type SubscriptionSubscribeFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => AsyncIterator | Promise>; -export declare type SubscriptionResolveFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => TResult | Promise; + +export type NewStitchingResolver = { + selectionSet: string; + resolve: ResolverFn; +}; +export type StitchingResolver = LegacyStitchingResolver | NewStitchingResolver; +export type Resolver = + | ResolverFn + | StitchingResolver; + +export type ResolverFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => Promise | TResult; + +export type SubscriptionSubscribeFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => AsyncIterator | Promise>; + +export type SubscriptionResolveFn = ( + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => TResult | Promise; + export interface SubscriptionSubscriberObject { - subscribe: SubscriptionSubscribeFn<{ - [key in TKey]: TResult; - }, TParent, TContext, TArgs>; - resolve?: SubscriptionResolveFn; + subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>; + resolve?: SubscriptionResolveFn; } + export interface SubscriptionResolverObject { - subscribe: SubscriptionSubscribeFn; - resolve: SubscriptionResolveFn; + subscribe: SubscriptionSubscribeFn; + resolve: SubscriptionResolveFn; } -export declare type SubscriptionObject = SubscriptionSubscriberObject | SubscriptionResolverObject; -export declare type SubscriptionResolver = ((...args: any[]) => SubscriptionObject) | SubscriptionObject; -export declare type TypeResolveFn = (parent: TParent, context: TContext, info: GraphQLResolveInfo) => Maybe | Promise>; -export declare type IsTypeOfResolverFn = (obj: T, info: GraphQLResolveInfo) => boolean | Promise; -export declare type NextResolverFn = () => Promise; -export declare type DirectiveResolverFn = (next: NextResolverFn, parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => TResult | Promise; + +export type SubscriptionObject = + | SubscriptionSubscriberObject + | SubscriptionResolverObject; + +export type SubscriptionResolver = + | ((...args: any[]) => SubscriptionObject) + | SubscriptionObject; + +export type TypeResolveFn = ( + parent: TParent, + context: TContext, + info: GraphQLResolveInfo +) => Maybe | Promise>; + +export type IsTypeOfResolverFn = (obj: T, info: GraphQLResolveInfo) => boolean | Promise; + +export type NextResolverFn = () => Promise; + +export type DirectiveResolverFn = ( + next: NextResolverFn, + parent: TParent, + args: TArgs, + context: TContext, + info: GraphQLResolveInfo +) => TResult | Promise; + /** Mapping between all available schema types and the resolvers types */ -export declare type ResolversTypes = ResolversObject<{ - Query: ResolverTypeWrapper<{}>; - User: ResolverTypeWrapper; - ID: ResolverTypeWrapper; - String: ResolverTypeWrapper; - Boolean: ResolverTypeWrapper; +export type ResolversTypes = ResolversObject<{ + Query: ResolverTypeWrapper<{}>; + User: ResolverTypeWrapper; + ID: ResolverTypeWrapper; + String: ResolverTypeWrapper; + Boolean: ResolverTypeWrapper; }>; + /** Mapping between all available schema types and the resolvers parents */ -export declare type ResolversParentTypes = ResolversObject<{ - Query: {}; - User: User; - ID: Scalars['ID']; - String: Scalars['String']; - Boolean: Scalars['Boolean']; +export type ResolversParentTypes = ResolversObject<{ + Query: {}; + User: User; + ID: Scalars['ID']; + String: Scalars['String']; + Boolean: Scalars['Boolean']; }>; -export declare type QueryResolvers = ResolversObject<{ - viewer?: Resolver, ParentType, ContextType>; + +export type QueryResolvers = ResolversObject<{ + viewer?: Resolver, ParentType, ContextType>; }>; -export declare type UserResolvers = ResolversObject<{ - id?: Resolver; - name?: Resolver; - status?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; + +export type UserResolvers = ResolversObject<{ + id?: Resolver; + name?: Resolver; + status?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; }>; -export declare type Resolvers = ResolversObject<{ - Query?: QueryResolvers; - User?: UserResolvers; + +export type Resolvers = ResolversObject<{ + Query?: QueryResolvers; + User?: UserResolvers; }>; + + /** * @deprecated * Use \\"Resolvers\\" root object instead. If you wish to get \\"IResolvers\\", add \\"typesPrefix: I\\" to your config. */ -export declare type IResolvers = Resolvers; - - -// This is an extra code in addition to what graphql-codegen makes. -// Users are likely to use 'graphql-tag/loader' with 'graphql-tag/schema/loader' -// in webpack. This code enables the result to be typed. -import { DocumentNode } from 'graphql' -export default typeof DocumentNode +export type IResolvers = Resolvers; " `; exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected * ignoring "!" paths in "schema" and "documents" of graphql-let.yml * ignoring files specified in .gitignore -: test/__fixtures/gen/__generated__/pages/viewer.graphql.tsx 1`] = ` -"/* f60a3f57259624d6235cbc35e4220b930c0e3538 +: pages/viewer.graphql.d.ts 1`] = ` +"/* c4ffa0d4a98b9173e641f88cb713cbbaa35a8692 * This file is automatically generated by graphql-let. */ -import gql from 'graphql-tag'; -import * as React from 'react'; +/// import * as ApolloReactCommon from '@apollo/react-common'; import * as ApolloReactComponents from '@apollo/react-components'; import * as ApolloReactHooks from '@apollo/react-hooks'; -export type Maybe = T | null; -export type Exact = { [K in keyof T]: T[K] }; -export type Omit = Pick>; +export declare type Maybe = T | null; +export declare type Exact = { + [K in keyof T]: T[K]; +}; +export declare type Omit = Pick>; /** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; +export declare type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; - -export type Query = { - __typename?: 'Query'; - viewer?: Maybe; +export declare type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; - -export type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; +export declare type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; - -export type ViewerQueryVariables = Exact<{ [key: string]: never; }>; - - -export type ViewerQuery = ( - { __typename?: 'Query' } - & { viewer?: Maybe<( - { __typename?: 'User' } - & Pick - )> } -); - - -export const ViewerDocument = gql\` - query Viewer { - viewer { - id - name - status - } -} - \`; -export type ViewerComponentProps = Omit, 'query'>; - - export const ViewerComponent = (props: ViewerComponentProps) => ( - query={ViewerDocument} {...props} /> - ); - - +export declare type ViewerQueryVariables = Exact<{ + [key: string]: never; +}>; +export declare type ViewerQuery = ({ + __typename?: 'Query'; +} & { + viewer?: Maybe<({ + __typename?: 'User'; + } & Pick)>; +}); +export declare const ViewerDocument: import(\\"graphql\\").DocumentNode; +export declare type ViewerComponentProps = Omit, 'query'>; +export declare const ViewerComponent: (props: ViewerComponentProps) => JSX.Element; /** * __useViewerQuery__ * @@ -341,81 +395,67 @@ export type ViewerComponentProps = Omit) { - return ApolloReactHooks.useQuery(ViewerDocument, baseOptions); - } -export function useViewerLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { - return ApolloReactHooks.useLazyQuery(ViewerDocument, baseOptions); - } -export type ViewerQueryHookResult = ReturnType; -export type ViewerLazyQueryHookResult = ReturnType; -export type ViewerQueryResult = ApolloReactCommon.QueryResult;" -`; - -exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected -* ignoring "!" paths in "schema" and "documents" of graphql-let.yml -* ignoring files specified in .gitignore -: test/__fixtures/gen/__generated__/pages/viewer2.graphql.tsx 1`] = ` -"/* ad0917d5881bbadbe3a38bcfa56a3880e5791393 - * This file is automatically generated by graphql-let. */ - -import gql from 'graphql-tag'; -import * as React from 'react'; +export declare function useViewerQuery(baseOptions?: ApolloReactHooks.QueryHookOptions): ApolloReactCommon.QueryResult>; +export declare function useViewerLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions): ApolloReactHooks.QueryTuple>; +export declare type ViewerQueryHookResult = ReturnType; +export declare type ViewerLazyQueryHookResult = ReturnType; +export declare type ViewerQueryResult = ApolloReactCommon.QueryResult; +" +`; + +exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected +* ignoring "!" paths in "schema" and "documents" of graphql-let.yml +* ignoring files specified in .gitignore +: pages/viewer2.graphql.d.ts 1`] = ` +"/* b2463a5b834ec0328b95dd554ca377c66498827e + * This file is automatically generated by graphql-let. */ + +/// import * as ApolloReactCommon from '@apollo/react-common'; import * as ApolloReactComponents from '@apollo/react-components'; import * as ApolloReactHooks from '@apollo/react-hooks'; -export type Maybe = T | null; -export type Exact = { [K in keyof T]: T[K] }; -export type Omit = Pick>; +export declare type Maybe = T | null; +export declare type Exact = { + [K in keyof T]: T[K]; +}; +export declare type Omit = Pick>; /** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; +export declare type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; - -export type Query = { - __typename?: 'Query'; - viewer?: Maybe; +export declare type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; - -export type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; +export declare type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; - -export type Viewer2QueryVariables = Exact<{ [key: string]: never; }>; - - -export type Viewer2Query = ( - { __typename?: 'Query' } - & { viewer?: Maybe<( - { __typename?: 'User' } - & Pick - )> } -); - - -export const Viewer2Document = gql\` - query Viewer2 { - viewer { - id - name - status - } -} - \`; -export type Viewer2ComponentProps = Omit, 'query'>; - - export const Viewer2Component = (props: Viewer2ComponentProps) => ( - query={Viewer2Document} {...props} /> - ); - - +export declare type Viewer2QueryVariables = Exact<{ + [key: string]: never; +}>; +export declare type Viewer2Query = ({ + __typename?: 'Query'; +} & { + viewer?: Maybe<({ + __typename?: 'User'; + } & Pick)>; +}); +export declare const Viewer2Document: import(\\"graphql\\").DocumentNode; +export declare type Viewer2ComponentProps = Omit, 'query'>; +export declare const Viewer2Component: (props: Viewer2ComponentProps) => JSX.Element; /** * __useViewer2Query__ * @@ -431,172 +471,132 @@ export type Viewer2ComponentProps = Omit) { - return ApolloReactHooks.useQuery(Viewer2Document, baseOptions); - } -export function useViewer2LazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions) { - return ApolloReactHooks.useLazyQuery(Viewer2Document, baseOptions); - } -export type Viewer2QueryHookResult = ReturnType; -export type Viewer2LazyQueryHookResult = ReturnType; -export type Viewer2QueryResult = ApolloReactCommon.QueryResult;" +export declare function useViewer2Query(baseOptions?: ApolloReactHooks.QueryHookOptions): ApolloReactCommon.QueryResult>; +export declare function useViewer2LazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions): ApolloReactHooks.QueryTuple>; +export declare type Viewer2QueryHookResult = ReturnType; +export declare type Viewer2LazyQueryHookResult = ReturnType; +export declare type Viewer2QueryResult = ApolloReactCommon.QueryResult; +" `; exports[`"graphql-let" command generates number of .d.ts ignoring specified files as expected * ignoring "!" paths in "schema" and "documents" of graphql-let.yml * ignoring files specified in .gitignore -: test/__fixtures/gen/__generated__/schema/type-defs.graphqls.tsx 1`] = ` -"/* 04c878b1083226163fc16f7c2aee84d2ede9d378 +: schema/type-defs.graphqls.d.ts 1`] = ` +"/* 14d70566f4d02e53323ea8c820b4a3edeecc4672 * This file is automatically generated by graphql-let. */ import { GraphQLResolveInfo } from 'graphql'; -export type Maybe = T | null; -export type Exact = { [K in keyof T]: T[K] }; +export declare type Maybe = T | null; +export declare type Exact = { + [K in keyof T]: T[K]; +}; /** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; +export declare type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; }; - -export type Query = { - __typename?: 'Query'; - viewer?: Maybe; +export declare type Query = { + __typename?: 'Query'; + viewer?: Maybe; }; - -export type User = { - __typename?: 'User'; - id: Scalars['ID']; - name: Scalars['String']; - status: Scalars['String']; +export declare type User = { + __typename?: 'User'; + id: Scalars['ID']; + name: Scalars['String']; + status: Scalars['String']; }; - -export type WithIndex = TObject & Record; -export type ResolversObject = WithIndex; - -export type ResolverTypeWrapper = Promise | T; - - -export type LegacyStitchingResolver = { - fragment: string; - resolve: ResolverFn; +export declare type WithIndex = TObject & Record; +export declare type ResolversObject = WithIndex; +export declare type ResolverTypeWrapper = Promise | T; +export declare type LegacyStitchingResolver = { + fragment: string; + resolve: ResolverFn; }; - -export type NewStitchingResolver = { - selectionSet: string; - resolve: ResolverFn; +export declare type NewStitchingResolver = { + selectionSet: string; + resolve: ResolverFn; }; -export type StitchingResolver = LegacyStitchingResolver | NewStitchingResolver; -export type Resolver = - | ResolverFn - | StitchingResolver; - -export type ResolverFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => Promise | TResult; - -export type SubscriptionSubscribeFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => AsyncIterator | Promise>; - -export type SubscriptionResolveFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => TResult | Promise; - +export declare type StitchingResolver = LegacyStitchingResolver | NewStitchingResolver; +export declare type Resolver = ResolverFn | StitchingResolver; +export declare type ResolverFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => Promise | TResult; +export declare type SubscriptionSubscribeFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => AsyncIterator | Promise>; +export declare type SubscriptionResolveFn = (parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => TResult | Promise; export interface SubscriptionSubscriberObject { - subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>; - resolve?: SubscriptionResolveFn; + subscribe: SubscriptionSubscribeFn<{ + [key in TKey]: TResult; + }, TParent, TContext, TArgs>; + resolve?: SubscriptionResolveFn; } - export interface SubscriptionResolverObject { - subscribe: SubscriptionSubscribeFn; - resolve: SubscriptionResolveFn; + subscribe: SubscriptionSubscribeFn; + resolve: SubscriptionResolveFn; } - -export type SubscriptionObject = - | SubscriptionSubscriberObject - | SubscriptionResolverObject; - -export type SubscriptionResolver = - | ((...args: any[]) => SubscriptionObject) - | SubscriptionObject; - -export type TypeResolveFn = ( - parent: TParent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe | Promise>; - -export type IsTypeOfResolverFn = (obj: T, info: GraphQLResolveInfo) => boolean | Promise; - -export type NextResolverFn = () => Promise; - -export type DirectiveResolverFn = ( - next: NextResolverFn, - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => TResult | Promise; - +export declare type SubscriptionObject = SubscriptionSubscriberObject | SubscriptionResolverObject; +export declare type SubscriptionResolver = ((...args: any[]) => SubscriptionObject) | SubscriptionObject; +export declare type TypeResolveFn = (parent: TParent, context: TContext, info: GraphQLResolveInfo) => Maybe | Promise>; +export declare type IsTypeOfResolverFn = (obj: T, info: GraphQLResolveInfo) => boolean | Promise; +export declare type NextResolverFn = () => Promise; +export declare type DirectiveResolverFn = (next: NextResolverFn, parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => TResult | Promise; /** Mapping between all available schema types and the resolvers types */ -export type ResolversTypes = ResolversObject<{ - Query: ResolverTypeWrapper<{}>; - User: ResolverTypeWrapper; - ID: ResolverTypeWrapper; - String: ResolverTypeWrapper; - Boolean: ResolverTypeWrapper; +export declare type ResolversTypes = ResolversObject<{ + Query: ResolverTypeWrapper<{}>; + User: ResolverTypeWrapper; + ID: ResolverTypeWrapper; + String: ResolverTypeWrapper; + Boolean: ResolverTypeWrapper; }>; - /** Mapping between all available schema types and the resolvers parents */ -export type ResolversParentTypes = ResolversObject<{ - Query: {}; - User: User; - ID: Scalars['ID']; - String: Scalars['String']; - Boolean: Scalars['Boolean']; +export declare type ResolversParentTypes = ResolversObject<{ + Query: {}; + User: User; + ID: Scalars['ID']; + String: Scalars['String']; + Boolean: Scalars['Boolean']; }>; - -export type QueryResolvers = ResolversObject<{ - viewer?: Resolver, ParentType, ContextType>; +export declare type QueryResolvers = ResolversObject<{ + viewer?: Resolver, ParentType, ContextType>; }>; - -export type UserResolvers = ResolversObject<{ - id?: Resolver; - name?: Resolver; - status?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; +export declare type UserResolvers = ResolversObject<{ + id?: Resolver; + name?: Resolver; + status?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; }>; - -export type Resolvers = ResolversObject<{ - Query?: QueryResolvers; - User?: UserResolvers; +export declare type Resolvers = ResolversObject<{ + Query?: QueryResolvers; + User?: UserResolvers; }>; - - /** * @deprecated * Use \\"Resolvers\\" root object instead. If you wish to get \\"IResolvers\\", add \\"typesPrefix: I\\" to your config. */ -export type IResolvers = Resolvers; +export declare type IResolvers = Resolvers; + + +// This is an extra code in addition to what graphql-codegen makes. +// Users are likely to use 'graphql-tag/loader' with 'graphql-tag/schema/loader' +// in webpack. This code enables the result to be typed. +import { DocumentNode } from 'graphql' +export default typeof DocumentNode " `; exports[`"graphql-let" command passes config to graphql-codegen as expected * "useIndexSignature: true" in config effect to result having "WithIndex" type 1`] = ` -"/* 04c878b1083226163fc16f7c2aee84d2ede9d378 +"/* 14d70566f4d02e53323ea8c820b4a3edeecc4672 * This file is automatically generated by graphql-let. */ import { GraphQLResolveInfo } from 'graphql'; diff --git a/test/__snapshots__/loader.test.ts.snap b/test/__snapshots__/loader.test.ts.snap index fc5f0dfa..8648a739 100644 --- a/test/__snapshots__/loader.test.ts.snap +++ b/test/__snapshots__/loader.test.ts.snap @@ -3,7 +3,7 @@ exports[`graphql-let/loader generates .tsx and .d.ts 1`] = ` "function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } -/* d6a6401ede1dfbc1e581d726ba922b01fb999024 +/* 74e3b5f14d67e5468e98f3cc80008b3caf777cf9 * This file is automatically generated by graphql-let. */ import gql from 'graphql-tag'; import * as React from 'react'; diff --git a/test/gen.test.ts b/test/gen.test.ts index 73099bbc..6e87df8e 100644 --- a/test/gen.test.ts +++ b/test/gen.test.ts @@ -12,7 +12,7 @@ const rel = (relPath: string) => pathJoin(cwd, relPath); describe('"graphql-let" command', () => { beforeAll(async () => { await rename(rel('_gitignore'), rel('.gitignore')); - await rimraf(pathJoin(__dirname, '../__generated__')); + await rimraf(rel('__generated__')); await rimraf(rel('**/*.graphql.d.ts')); await rimraf(rel('**/*.graphqls.d.ts')); }, 60 * 1000); @@ -55,12 +55,9 @@ describe('"graphql-let" command', () => { expect(content).toMatchSnapshot(filename); }); - const tsxResults = await glob( - 'test/__fixtures/gen/__generated__/**/*.tsx', - { - cwd, - }, - ); + const tsxResults = await glob('__generated__/**/*.tsx', { + cwd, + }); strictEqual(tsxResults.length, 3); strictEqual( tsxResults.find((r) => r.includes('shouldBeIgnored1')), @@ -82,13 +79,13 @@ describe('"graphql-let" command', () => { test(`runs twice and keeps valid caches`, async () => { await gen({ cwd }); await gen({ cwd }); - const actual = await glob('test/__fixtures/gen/__generated__/**/*.tsx', { + const actual = await glob('__generated__/**/*.tsx', { cwd, }); - deepStrictEqual(actual, [ - 'test/__fixtures/gen/__generated__/pages/viewer.graphql.tsx', - 'test/__fixtures/gen/__generated__/pages/viewer2.graphql.tsx', - 'test/__fixtures/gen/__generated__/schema/type-defs.graphqls.tsx', + deepStrictEqual(actual.sort(), [ + '__generated__/pages/viewer.graphql.tsx', + '__generated__/pages/viewer2.graphql.tsx', + '__generated__/schema/type-defs.graphqls.tsx', ]); }); diff --git a/test/issue-118.test.ts b/test/issue-118.test.ts new file mode 100644 index 00000000..d62c5c10 --- /dev/null +++ b/test/issue-118.test.ts @@ -0,0 +1,22 @@ +import { join as pathJoin } from 'path'; +import { rimraf } from './__tools/file'; + +const cwd = pathJoin(__dirname, '__fixtures/issue-118'); +const rel = (relPath: string) => pathJoin(cwd, relPath); +import gen from '../src/gen'; + +describe('"baseUrl" and "mappers" combo', () => { + beforeAll(async () => { + await rimraf(rel('__generated__')); + await rimraf(rel('**/*.graphql.d.ts')); + await rimraf(rel('**/*.graphqls.d.ts')); + }, 60 * 1000); + + it( + 'should run graphql-let command properly', + async () => { + await gen({ cwd }); + }, + 1000 * 1000, + ); +}); diff --git a/test/tsconfig.test.ts b/test/tsconfig.test.ts index 23b4e9ed..92f57e49 100644 --- a/test/tsconfig.test.ts +++ b/test/tsconfig.test.ts @@ -143,7 +143,7 @@ describe('"graphql-let" command', () => { console.log(e); error = e; } - ok(error === null); + ok(error === null, error); expect(fetch).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith( 'http://localhost:3000/graphql',