From e79606567fc1729fee760522182fd4da95e83389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 20 Apr 2023 11:12:00 +0200 Subject: [PATCH] Prefer using a local version of Prettier when writing typegen files --- .changeset/smooth-ducks-relax.md | 5 ++ .changeset/tough-foxes-deliver.md | 5 ++ apps/cli/package.json | 1 + apps/cli/src/bin.ts | 59 +++++++++++++++++++++-- packages/shared/package.json | 1 - packages/shared/src/index.ts | 2 - packages/shared/src/removeFile.ts | 12 ----- packages/shared/src/writeToTypegenFile.ts | 27 ----------- 8 files changed, 65 insertions(+), 47 deletions(-) create mode 100644 .changeset/smooth-ducks-relax.md create mode 100644 .changeset/tough-foxes-deliver.md delete mode 100644 packages/shared/src/removeFile.ts delete mode 100644 packages/shared/src/writeToTypegenFile.ts diff --git a/.changeset/smooth-ducks-relax.md b/.changeset/smooth-ducks-relax.md new file mode 100644 index 00000000..1d7e1596 --- /dev/null +++ b/.changeset/smooth-ducks-relax.md @@ -0,0 +1,5 @@ +--- +'@xstate/cli': minor +--- + +A local version of Prettier (if available) should now be used when writing typegen files. diff --git a/.changeset/tough-foxes-deliver.md b/.changeset/tough-foxes-deliver.md new file mode 100644 index 00000000..a897bd72 --- /dev/null +++ b/.changeset/tough-foxes-deliver.md @@ -0,0 +1,5 @@ +--- +'@xstate/tools-shared': major +--- + +Removed some FS-related utils from the package. diff --git a/apps/cli/package.json b/apps/cli/package.json index 509dd179..1ac8ea16 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -22,6 +22,7 @@ "@xstate/tools-shared": "^2.0.2", "chokidar": "^3.5.3", "commander": "^8.0.0", + "prettier": "^2.8.7", "xstate": "^4.33.4" }, "author": "Stately Team", diff --git a/apps/cli/src/bin.ts b/apps/cli/src/bin.ts index bb931c87..b45264d5 100644 --- a/apps/cli/src/bin.ts +++ b/apps/cli/src/bin.ts @@ -2,10 +2,11 @@ import { extractMachinesFromFile } from '@xstate/machine-extractor'; import { + TypegenData, getTsTypesEdits, getTypegenData, + getTypegenOutput, processFileEdits, - writeToTypegenFile, } from '@xstate/tools-shared'; import { watch } from 'chokidar'; import { Command } from 'commander'; @@ -13,6 +14,50 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import { version } from '../package.json'; +async function removeFile(filePath: string) { + try { + await fs.unlink(filePath); + } catch (e: any) { + if (e?.code === 'ENOENT') { + return; + } + throw e; + } +} + +let prettier: typeof import('prettier') | undefined; + +function getPrettierInstance(cwd: string): typeof import('prettier') { + if (prettier) { + return prettier; + } + try { + return require(require.resolve('prettier', { paths: [cwd] })); + } catch (err) { + if (!err || (err as any).code !== 'MODULE_NOT_FOUND') { + throw err; + } + // we load our own prettier instance lazily on purpose to speed up the init time + return (prettier = require('prettier')); + } +} + +const writeToTypegenFile = async ( + typegenUri: string, + types: TypegenData[], + { cwd }: { cwd: string }, +) => { + const prettierInstance = getPrettierInstance(cwd); + await fs.writeFile( + typegenUri, + // // Prettier v3 returns a promise + await prettierInstance.format(getTypegenOutput(types), { + ...(await prettierInstance.resolveConfig(typegenUri)), + parser: 'typescript', + }), + ); +}; + // TODO: just use the native one when support for node 12 gets dropped const allSettled: typeof Promise.allSettled = (promises: Promise[]) => Promise.all( @@ -28,7 +73,7 @@ const program = new Command(); program.version(version); -const writeToFiles = async (uriArray: string[]) => { +const writeToFiles = async (uriArray: string[], { cwd }: { cwd: string }) => { /** * TODO - implement pretty readout */ @@ -43,6 +88,9 @@ const writeToFiles = async (uriArray: string[]) => { return; } + const typegenUri = + uri.slice(0, -path.extname(uri).length) + '.typegen.ts'; + const types = extracted.machines .filter( ( @@ -54,7 +102,7 @@ const writeToFiles = async (uriArray: string[]) => { getTypegenData(path.basename(uri), index, machineResult), ); - await writeToTypegenFile(uri, types); + await writeToTypegenFile(typegenUri, types, { cwd }); const edits = getTsTypesEdits(types); if (edits.length > 0) { @@ -80,13 +128,14 @@ program .argument('', 'The files to target, expressed as a glob pattern') .option('-w, --watch', 'Run the typegen in watch mode') .action(async (filesPattern: string, opts: { watch?: boolean }) => { + const cwd = process.cwd(); if (opts.watch) { // TODO: implement per path queuing to avoid tasks related to the same file from overlapping their execution const processFile = (path: string) => { if (path.endsWith('.typegen.ts')) { return; } - writeToFiles([path]).catch(() => {}); + writeToFiles([path], { cwd }).catch(() => {}); }; // TODO: handle removals watch(filesPattern, { awaitWriteFinish: true }) @@ -100,7 +149,7 @@ program if (path.endsWith('.typegen.ts')) { return; } - tasks.push(writeToFiles([path])); + tasks.push(writeToFiles([path], { cwd })); }) .on('ready', async () => { const settled = await allSettled(tasks); diff --git a/packages/shared/package.json b/packages/shared/package.json index 8290e06d..b0e25c54 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -11,7 +11,6 @@ "test": "jest" }, "peerDependencies": { - "prettier": "^2.3.1", "xstate": "^4" }, "devDependencies": { diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 2d4e95df..6e012d82 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -12,7 +12,5 @@ export * from './getTypegenOutput'; export * from './introspectMachine'; export * from './isCursorInPosition'; export * from './processFileEdits'; -export * from './removeFile'; export * from './resolveUriToFilePrefix'; export * from './types'; -export * from './writeToTypegenFile'; diff --git a/packages/shared/src/removeFile.ts b/packages/shared/src/removeFile.ts deleted file mode 100644 index 29aaf041..00000000 --- a/packages/shared/src/removeFile.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as fs from 'fs/promises'; - -export async function removeFile(filePath: string) { - try { - await fs.unlink(filePath); - } catch (e: any) { - if (e?.code === 'ENOENT') { - return; - } - throw e; - } -} diff --git a/packages/shared/src/writeToTypegenFile.ts b/packages/shared/src/writeToTypegenFile.ts deleted file mode 100644 index 2e005a0c..00000000 --- a/packages/shared/src/writeToTypegenFile.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as fs from 'fs/promises'; -import * as path from 'path'; -import * as prettier from 'prettier'; -import { TypegenData } from './getTypegenData'; -import { getTypegenOutput } from './getTypegenOutput'; -import { removeFile } from './removeFile'; - -export const writeToTypegenFile = async ( - filePath: string, - types: TypegenData[], -) => { - const pathToSave = - filePath.slice(0, -path.extname(filePath).length) + '.typegen.ts'; - - if (!types.length) { - await removeFile(pathToSave); - return; - } - - await fs.writeFile( - pathToSave, - prettier.format(getTypegenOutput(types), { - ...(await prettier.resolveConfig(filePath)), - parser: 'typescript', - }), - ); -};