From 41ad4f86c9012143fc4ba6e34a63ea55c8d2d75e Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 26 Apr 2023 12:46:51 -0400 Subject: [PATCH] fix(misc): add a migration to update or remove references to @nrwl/web/babel --- packages/workspace/migrations.json | 6 ++ .../update-16-0-0/fix-invalid-babelrc.spec.ts | 100 ++++++++++++++++++ .../update-16-0-0/fix-invalid-babelrc.ts | 51 +++++++++ 3 files changed, 157 insertions(+) create mode 100644 packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.spec.ts create mode 100644 packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.ts diff --git a/packages/workspace/migrations.json b/packages/workspace/migrations.json index 152bd96f7f14a..1856ae85160cc 100644 --- a/packages/workspace/migrations.json +++ b/packages/workspace/migrations.json @@ -95,6 +95,12 @@ "description": "Generates a plugin called 'workspace-plugin' containing your workspace generators.", "cli": "nx", "implementation": "./src/migrations/update-16-0-0/move-workspace-generators-to-local-plugin" + }, + "16-0-0-fix-invalid-babelrc": { + "version": "16.0.0-beta.9", + "description": "Fix .babelrc presets if it contains an invalid entry for @nx/web/babel.", + "cli": "nx", + "implementation": "./src/migrations/update-16-0-0/fix-invalid-babelrc" } }, "packageJsonUpdates": { diff --git a/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.spec.ts b/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.spec.ts new file mode 100644 index 0000000000000..6725e1dfc9637 --- /dev/null +++ b/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.spec.ts @@ -0,0 +1,100 @@ +import { + addProjectConfiguration, + readJson, + Tree, + updateJson, + writeJson, +} from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import update from './fix-invalid-babelrc'; + +describe('fix-invalid-babelrc', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it.each` + webPlugin + ${'@nrwl/web'} + ${'@nx/web'} + `('should skip update if Web plugin is installed', ({ webPlugin }) => { + addProjectConfiguration(tree, 'proj', { + root: 'proj', + name: 'proj', + }); + updateJson(tree, 'package.json', (json) => { + json.devDependencies[webPlugin] = '16.0.0'; + return json; + }); + writeJson(tree, 'proj/.babelrc', { + presets: [['@nx/web/babel', {}]], + }); + + update(tree); + + expect(readJson(tree, 'proj/.babelrc')).toEqual({ + presets: [['@nx/web/babel', {}]], + }); + }); + + it.each` + jsPlugin | originalPreset + ${'@nrwl/js'} | ${'@nrwl/web/babel'} + ${'@nrwl/js'} | ${'@nx/web/babel'} + ${'@nx/js'} | ${'@nrwl/web/babel'} + ${'@nx/js'} | ${'@nx/web/babel'} + `( + 'should rename @nrwl/web/babel to @nx/js/babel when JS plugin is installed', + ({ jsPlugin, originalPreset }) => { + addProjectConfiguration(tree, 'proj1', { + root: 'proj1', + name: 'proj1', + }); + addProjectConfiguration(tree, 'proj2', { + root: 'proj2', + name: 'proj2', + }); + updateJson(tree, 'package.json', (json) => { + json.devDependencies[jsPlugin] = '16.0.0'; + return json; + }); + writeJson(tree, 'proj1/.babelrc', { + presets: [[originalPreset, {}]], + }); + writeJson(tree, 'proj2/.babelrc', { + presets: [originalPreset], + }); + + update(tree); + + expect(readJson(tree, 'proj1/.babelrc')).toEqual({ + presets: [['@nx/js/babel', {}]], + }); + expect(readJson(tree, 'proj2/.babelrc')).toEqual({ + presets: ['@nx/js/babel'], + }); + } + ); + + it('should remove the invalid preset if neither Web nor JS plugins are present', () => { + addProjectConfiguration(tree, 'proj', { + root: 'proj', + name: 'proj', + }); + writeJson(tree, 'proj/.babelrc', { + presets: [ + '@babel/preset-env', + ['@nx/web/babel', {}], + '@babel/preset-typescript', + ], + }); + + update(tree); + + expect(readJson(tree, 'proj/.babelrc')).toEqual({ + presets: ['@babel/preset-env', '@babel/preset-typescript'], + }); + }); +}); diff --git a/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.ts b/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.ts new file mode 100644 index 0000000000000..f7f4cbc1f735d --- /dev/null +++ b/packages/workspace/src/migrations/update-16-0-0/fix-invalid-babelrc.ts @@ -0,0 +1,51 @@ +import { + getProjects, + joinPathFragments, + readJson, + Tree, + writeJson, +} from '@nx/devkit'; + +export default function update(tree: Tree) { + const projects = getProjects(tree); + const packageJson = readJson(tree, 'package.json'); + + // In case user installed as prod dep. + const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; + + // If web package is installed, skip update. + if (deps['@nrwl/web'] || deps['@nx/web']) { + return; + } + + projects.forEach((config, name) => { + const babelRcPath = joinPathFragments(config.root, '.babelrc'); + if (!tree.exists(babelRcPath)) return; + + const babelRc = readJson(tree, babelRcPath); + const nrwlWebBabelPresetIdx = babelRc.presets?.findIndex((p) => + // Babel preset could be specified as a string or a tuple with options. + // Account for rescope migration running before or after this one. + Array.isArray(p) + ? p[0] === '@nrwl/web/babel' || p[0] === '@nx/web/babel' + : p === '@nrwl/web/babel' || p === '@nx/web/babel' + ); + + if (nrwlWebBabelPresetIdx === undefined || nrwlWebBabelPresetIdx === -1) { + return; + } + + if (deps['@nrwl/js'] || deps['@nx/js']) { + // If JS plugin is installed, then rename to @nx/js/babel. + const found = babelRc.presets[nrwlWebBabelPresetIdx]; + babelRc.presets[nrwlWebBabelPresetIdx] = Array.isArray(found) + ? ['@nx/js/babel', found[1]] + : '@nx/js/babel'; + } else { + // Otherwise, remove from config. + babelRc.presets.splice(nrwlWebBabelPresetIdx, 1); + } + + writeJson(tree, babelRcPath, babelRc); + }); +}