diff --git a/packages/nx/src/command-line/migrate/migrate.ts b/packages/nx/src/command-line/migrate/migrate.ts index 8e15984acea77..83cd3708d65ae 100644 --- a/packages/nx/src/command-line/migrate/migrate.ts +++ b/packages/nx/src/command-line/migrate/migrate.ts @@ -28,6 +28,7 @@ import { extractFileFromTarball, fileExists, JsonReadOptions, + JsonWriteOptions, readJsonFile, writeJsonFile, } from '../../utils/fileutils'; @@ -54,7 +55,7 @@ import { onlyDefaultRunnerIsUsed, } from '../connect/connect-to-nx-cloud'; import { output } from '../../utils/output'; -import { existsSync, readFileSync } from 'fs'; +import { existsSync, readFileSync, writeFileSync } from 'fs'; import { workspaceRoot } from '../../utils/workspace-root'; import { isCI } from '../../utils/is-ci'; import { getNxRequirePaths } from '../../utils/installation-directory'; @@ -66,6 +67,7 @@ import { createProjectGraphAsync, readProjectsConfigurationFromProjectGraph, } from '../../project-graph/project-graph'; +import { formatFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available'; export interface ResolvedMigrationConfiguration extends MigrationsJson { packageGroup?: ArrayPackageGroup; @@ -1105,17 +1107,17 @@ function readPackageMigrationConfig( } } -function createMigrationsFile( +async function createMigrationsFile( root: string, migrations: { package: string; name: string; }[] ) { - writeJsonFile(join(root, 'migrations.json'), { migrations }); + await writeFormattedJsonFile(join(root, 'migrations.json'), { migrations }); } -function updatePackageJson( +async function updatePackageJson( root: string, updatedPackages: Record ) { @@ -1145,7 +1147,7 @@ function updatePackageJson( } }); - writeJsonFile(packageJsonPath, json, { + await writeFormattedJsonFile(packageJsonPath, json, { appendNewLine: parseOptions.endsWithNewline, }); } @@ -1178,7 +1180,7 @@ async function updateInstallationDetails( } } - writeJsonFile(nxJsonPath, nxJson, { + await writeFormattedJsonFile(nxJsonPath, nxJson, { appendNewLine: parseOptions.endsWithNewline, }); } @@ -1238,11 +1240,11 @@ async function generateMigrationsJsonAndUpdatePackageJson( const { migrations, packageUpdates, minVersionWithSkippedUpdates } = await migrator.migrate(opts.targetPackage, opts.targetVersion); - updatePackageJson(root, packageUpdates); + await updatePackageJson(root, packageUpdates); await updateInstallationDetails(root, packageUpdates); if (migrations.length > 0) { - createMigrationsFile(root, [ + await createMigrationsFile(root, [ ...addSplitConfigurationMigrationIfAvailable(from, packageUpdates), ...migrations, ] as any); @@ -1318,6 +1320,26 @@ async function generateMigrationsJsonAndUpdatePackageJson( } } +async function writeFormattedJsonFile( + filePath: string, + content: any, + options?: JsonWriteOptions +): Promise { + const formattedContent = await formatFilesWithPrettierIfAvailable( + [{ path: filePath, content: JSON.stringify(content) }], + workspaceRoot, + { silent: true } + ); + + if (formattedContent.has(filePath)) { + writeFileSync(filePath, formattedContent.get(filePath)!, { + encoding: 'utf-8', + }); + } else { + writeJsonFile(filePath, content, options); + } +} + function addSplitConfigurationMigrationIfAvailable( from: string, packageJson: any diff --git a/packages/nx/src/generators/internal-utils/format-changed-files-with-prettier-if-available.ts b/packages/nx/src/generators/internal-utils/format-changed-files-with-prettier-if-available.ts index 06768575c726a..d3dd48593a729 100644 --- a/packages/nx/src/generators/internal-utils/format-changed-files-with-prettier-if-available.ts +++ b/packages/nx/src/generators/internal-utils/format-changed-files-with-prettier-if-available.ts @@ -12,20 +12,43 @@ export async function formatChangedFilesWithPrettierIfAvailable( silent?: boolean; } ): Promise { + const files = new Set( + tree.listChanges().filter((file) => file.type !== 'DELETE') + ); + + const results = await formatFilesWithPrettierIfAvailable( + Array.from(files), + tree.root, + options + ); + + for (const [path, content] of results) { + tree.write(path, content); + } +} + +export async function formatFilesWithPrettierIfAvailable( + files: { path: string; content: string | Buffer }[], + root: string, + options?: { + silent?: boolean; + } +): Promise> { + const results = new Map(); + let prettier: typeof Prettier; try { prettier = await import('prettier'); } catch {} - if (!prettier) return; + if (!prettier) { + return results; + } - const files = new Set( - tree.listChanges().filter((file) => file.type !== 'DELETE') - ); await Promise.all( Array.from(files).map(async (file) => { try { - const systemPath = path.join(tree.root, file.path); + const systemPath = path.join(root, file.path); let options: any = { filepath: systemPath, }; @@ -46,7 +69,7 @@ export async function formatChangedFilesWithPrettierIfAvailable( return; } - tree.write( + results.set( file.path, // In prettier v3 the format result is a promise await (prettier.format(file.content.toString('utf-8'), options) as @@ -60,4 +83,6 @@ export async function formatChangedFilesWithPrettierIfAvailable( } }) ); + + return results; }