diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index ec0fda1f737..437203517c3 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -61,6 +61,7 @@ "debounce": "^1.2.0", "dependency-graph": "^0.11.0", "detect-indent": "^6.0.0", + "fs-extra": "^9.1.0", "glob": "^7.1.6", "graphql-config": "^3.2.0", "indent-string": "^4.0.0", @@ -72,7 +73,6 @@ "listr-update-renderer": "^0.5.0", "log-symbols": "^4.0.0", "minimatch": "^3.0.4", - "mkdirp": "^1.0.4", "string-env-interpolation": "^1.0.1", "ts-log": "^2.2.3", "tslib": "~2.1.0", @@ -92,7 +92,6 @@ "@types/listr": "0.14.2", "@types/log-symbols": "3.0.0", "@types/minimatch": "3.0.3", - "@types/mkdirp": "1.0.1", "@types/valid-url": "1.0.3", "bdd-stdin": "0.2.0", "dotenv": "8.2.0", diff --git a/packages/graphql-codegen-cli/src/generate-and-save.ts b/packages/graphql-codegen-cli/src/generate-and-save.ts index dd06a051eda..80dd022b08e 100644 --- a/packages/graphql-codegen-cli/src/generate-and-save.ts +++ b/packages/graphql-codegen-cli/src/generate-and-save.ts @@ -2,8 +2,8 @@ import { lifecycleHooks } from './hooks'; import { Types } from '@graphql-codegen/plugin-helpers'; import { executeCodegen } from './codegen'; import { createWatcher } from './utils/watcher'; -import { fileExists, readSync, writeSync, unlinkFile } from './utils/file-system'; -import { sync as mkdirpSync } from 'mkdirp'; +import { fileExists, readFile, writeFile, unlinkFile } from './utils/file-system'; +import { mkdirp } from 'fs-extra'; import { dirname, join, isAbsolute } from 'path'; import { debugLog } from './utils/debugging'; import { CodegenContext, ensureContext } from './config'; @@ -26,7 +26,7 @@ export async function generate( const staleFilenames = previouslyGeneratedFilenames.filter(f => !filenames.includes(f)); staleFilenames.forEach(filename => { if (shouldOverwrite(config, filename)) { - unlinkFile(filename, err => { + return unlinkFile(filename, err => { const prettyFilename = filename.replace(`${input.cwd || process.cwd()}/`, ''); if (err) { debugLog(`Cannot remove stale file: ${prettyFilename}\n${err}`); @@ -53,7 +53,7 @@ export async function generate( await Promise.all( generationResult.map(async (result: Types.FileOutput) => { - const exists = fileExists(result.filename); + const exists = await fileExists(result.filename); if (!shouldOverwrite(config, result.filename) && exists) { return; @@ -64,7 +64,7 @@ export async function generate( let previousHash = recentOutputHash.get(result.filename); if (!previousHash && exists) { - previousHash = hash(readSync(result.filename)); + previousHash = hash(await readFile(result.filename)); } if (previousHash && currentHash === previousHash) { @@ -81,11 +81,11 @@ export async function generate( const basedir = dirname(result.filename); await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename); await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename); - mkdirpSync(basedir); + await mkdirp(basedir); const absolutePath = isAbsolute(result.filename) ? result.filename : join(input.cwd || process.cwd(), result.filename); - writeSync(absolutePath, result.content); + await writeFile(absolutePath, result.content); await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename); await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename); }) diff --git a/packages/graphql-codegen-cli/src/utils/file-system.ts b/packages/graphql-codegen-cli/src/utils/file-system.ts index 6c9384e3228..b1fdc54a5c5 100644 --- a/packages/graphql-codegen-cli/src/utils/file-system.ts +++ b/packages/graphql-codegen-cli/src/utils/file-system.ts @@ -1,21 +1,21 @@ -import { writeFileSync, statSync, readFileSync, unlink } from 'fs'; +import { writeFile as fsWriteFile, stat as fsStat, readFile as fsReadFile, unlink as fsUnlink } from 'fs-extra'; -export function writeSync(filepath: string, content: string) { - return writeFileSync(filepath, content); +export function writeFile(filepath: string, content: string) { + return fsWriteFile(filepath, content); } -export function readSync(filepath: string) { - return readFileSync(filepath, 'utf-8'); +export function readFile(filepath: string) { + return fsReadFile(filepath, 'utf-8'); } -export function fileExists(filePath: string): boolean { +export async function fileExists(filePath: string): Promise { try { - return statSync(filePath).isFile(); + return (await fsStat(filePath)).isFile(); } catch (err) { return false; } } export function unlinkFile(filePath: string, cb?: (err?: Error) => any): void { - unlink(filePath, cb); + fsUnlink(filePath, cb); } diff --git a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts index 632b86b45da..1533ed40edb 100644 --- a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts +++ b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts @@ -21,7 +21,7 @@ describe('generate-and-save', () => { test('allow to specify overwrite for specific output (should write file)', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); const output = await generate( { @@ -47,10 +47,10 @@ describe('generate-and-save', () => { test('allow to specify overwrite for specific output (should not write file)', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); // forces file to exist const fileExistsSpy = jest.spyOn(fs, 'fileExists'); - fileExistsSpy.mockImplementation(file => file === filename); + fileExistsSpy.mockImplementation(async file => file === filename); const output = await generate( { @@ -78,7 +78,7 @@ describe('generate-and-save', () => { test('should use global overwrite option and write a file', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); const output = await generate( { @@ -103,10 +103,10 @@ describe('generate-and-save', () => { test('should use global overwrite option and not write a file', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); // forces file to exist const fileExistsSpy = jest.spyOn(fs, 'fileExists'); - fileExistsSpy.mockImplementation(file => file === filename); + fileExistsSpy.mockImplementation(async file => file === filename); const output = await generate( { @@ -133,12 +133,12 @@ describe('generate-and-save', () => { test('should overwrite a file by default', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); - const readSpy = jest.spyOn(fs, 'readSync').mockImplementation(); - readSpy.mockImplementation(_f => ''); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); + const readSpy = jest.spyOn(fs, 'readFile').mockImplementation(); + readSpy.mockImplementation(async _f => ''); // forces file to exist const fileExistsSpy = jest.spyOn(fs, 'fileExists'); - fileExistsSpy.mockImplementation(file => file === filename); + fileExistsSpy.mockImplementation(async file => file === filename); const output = await generate( { @@ -195,7 +195,7 @@ describe('generate-and-save', () => { }); test('should extract a document from the gql tag (imported from apollo-server)', async () => { const filename = 'overwrite.ts'; - const writeSpy = jest.spyOn(fs, 'writeSync').mockImplementation(); + const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation(); const output = await generate( { diff --git a/yarn.lock b/yarn.lock index b0e612d25d1..d792f9deaa9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9797,7 +9797,7 @@ fs-extra@9.0.1, fs-extra@^9.0.1: jsonfile "^6.0.1" universalify "^1.0.0" -fs-extra@9.1.0: +fs-extra@9.1.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==