@next/codemod 15.0.0-canary.190 → 15.0.0-canary.192

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
13
13
  const commander_1 = require("commander");
14
14
  const upgrade_1 = require("./upgrade");
15
15
  const transform_1 = require("./transform");
16
+ const shared_1 = require("./shared");
16
17
  const packageJson = require('../package.json');
17
18
  const program = new commander_1.Command(packageJson.name)
18
19
  .description('Codemods for updating Next.js apps.')
@@ -45,6 +46,19 @@ program
45
46
  : 'latest')
46
47
  .usage('[revision] [options]')
47
48
  .option('--verbose', 'Verbose output', false)
48
- .action(upgrade_1.runUpgrade);
49
+ .action(async (revision, options) => {
50
+ try {
51
+ await (0, upgrade_1.runUpgrade)(revision, options);
52
+ }
53
+ catch (error) {
54
+ if (!options.verbose && error instanceof shared_1.BadInput) {
55
+ console.error(error.message);
56
+ }
57
+ else {
58
+ console.error(error);
59
+ }
60
+ process.exit(1);
61
+ }
62
+ });
49
63
  program.parse(process.argv);
50
64
  //# sourceMappingURL=next-codemod.js.map
package/bin/shared.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BadInput = void 0;
4
+ class BadInput extends Error {
5
+ }
6
+ exports.BadInput = BadInput;
7
+ //# sourceMappingURL=shared.js.map
package/bin/upgrade.js CHANGED
@@ -14,6 +14,7 @@ const picocolors_1 = __importDefault(require("picocolors"));
14
14
  const handle_package_1 = require("../lib/handle-package");
15
15
  const transform_1 = require("./transform");
16
16
  const utils_1 = require("../lib/utils");
17
+ const shared_1 = require("./shared");
17
18
  /**
18
19
  * @param query
19
20
  * @example loadHighestNPMVersionMatching("react@^18.3.0 || ^19.0.0") === Promise<"19.0.0">
@@ -31,6 +32,11 @@ async function loadHighestNPMVersionMatching(query) {
31
32
  }
32
33
  return versionOrVersions;
33
34
  }
35
+ function endMessage() {
36
+ console.log();
37
+ console.log(picocolors_1.default.white(picocolors_1.default.bold(`Please review the local changes and read the Next.js 15 migration guide to complete the migration.`)));
38
+ console.log(picocolors_1.default.underline('https://nextjs.org/docs/canary/app/building-your-application/upgrading/version-15'));
39
+ }
34
40
  async function runUpgrade(revision, options) {
35
41
  const { verbose } = options;
36
42
  const appPackageJsonPath = path_1.default.resolve(process.cwd(), 'package.json');
@@ -45,21 +51,25 @@ async function runUpgrade(revision, options) {
45
51
  'version' in targetNextPackageJson &&
46
52
  'peerDependencies' in targetNextPackageJson;
47
53
  if (!validRevision) {
48
- throw new Error(`Invalid revision provided: "${revision}". Please provide a valid Next.js version or dist-tag (e.g. "latest", "canary", "rc", or "15.0.0").\nCheck available versions at https://www.npmjs.com/package/next?activeTab=versions.`);
54
+ throw new shared_1.BadInput(`Invalid revision provided: "${revision}". Please provide a valid Next.js version or dist-tag (e.g. "latest", "canary", "rc", or "15.0.0").\nCheck available versions at https://www.npmjs.com/package/next?activeTab=versions.`);
49
55
  }
50
56
  const installedNextVersion = getInstalledNextVersion();
51
- console.log(`Current Next.js version: v${installedNextVersion}`);
52
57
  const targetNextVersion = targetNextPackageJson.version;
53
58
  if ((0, compare_1.default)(installedNextVersion, targetNextVersion) === 0) {
54
59
  console.log(`${picocolors_1.default.green('✓')} Current Next.js version is already on the target version "v${targetNextVersion}".`);
60
+ endMessage();
55
61
  return;
56
62
  }
57
63
  if ((0, compare_1.default)(installedNextVersion, targetNextVersion) > 0) {
58
64
  console.log(`${picocolors_1.default.green('✓')} Current Next.js version is higher than the target version "v${targetNextVersion}".`);
65
+ endMessage();
59
66
  return;
60
67
  }
61
68
  const installedReactVersion = getInstalledReactVersion();
62
- console.log(`Current React version: v${installedReactVersion}`);
69
+ // Align the prefix spaces
70
+ console.log(` Detected installed versions:`);
71
+ console.log(` - React: v${installedReactVersion}`);
72
+ console.log(` - Next.js: v${installedNextVersion}`);
63
73
  let shouldStayOnReact18 = false;
64
74
  if (
65
75
  // From release v14.3.0-canary.45, Next.js expects the React version to be 19.0.0-beta.0
@@ -111,29 +121,57 @@ async function runUpgrade(revision, options) {
111
121
  execCommand = execCommandMap[packageManager];
112
122
  }
113
123
  fs_1.default.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2));
114
- const nextDependency = `next@${targetNextVersion}`;
115
- const reactDependencies = [
116
- `react@${targetReactVersion}`,
117
- `react-dom@${targetReactVersion}`,
118
- ];
124
+ const dependenciesToInstall = [];
125
+ const devDependenciesToInstall = [];
126
+ const versionMapping = {
127
+ next: { version: targetNextVersion, required: true },
128
+ react: { version: targetReactVersion, required: true },
129
+ 'react-dom': { version: targetReactVersion, required: true },
130
+ 'react-is': { version: targetReactVersion, required: false },
131
+ };
119
132
  if (targetReactVersion.startsWith('19.0.0-canary') ||
120
133
  targetReactVersion.startsWith('19.0.0-beta') ||
121
134
  targetReactVersion.startsWith('19.0.0-rc')) {
122
- reactDependencies.push(`@types/react@npm:types-react@rc`);
123
- reactDependencies.push(`@types/react-dom@npm:types-react-dom@rc`);
135
+ versionMapping['@types/react'] = {
136
+ version: `npm:types-react@rc`,
137
+ required: false,
138
+ };
139
+ versionMapping['@types/react-dom'] = {
140
+ version: `npm:types-react-dom@rc`,
141
+ required: false,
142
+ };
124
143
  }
125
144
  else {
126
145
  const [targetReactTypesVersion, targetReactDOMTypesVersion] = await Promise.all([
127
146
  loadHighestNPMVersionMatching(`@types/react@${targetNextPackageJson.peerDependencies['react']}`),
128
147
  loadHighestNPMVersionMatching(`@types/react-dom@${targetNextPackageJson.peerDependencies['react']}`),
129
148
  ]);
130
- reactDependencies.push(`@types/react@${targetReactTypesVersion}`);
131
- reactDependencies.push(`@types/react-dom@${targetReactDOMTypesVersion}`);
149
+ versionMapping['@types/react'] = {
150
+ version: targetReactTypesVersion,
151
+ required: false,
152
+ };
153
+ versionMapping['@types/react-dom'] = {
154
+ version: targetReactDOMTypesVersion,
155
+ required: false,
156
+ };
157
+ }
158
+ for (const [packageName, { version, required }] of Object.entries(versionMapping)) {
159
+ if (appPackageJson.devDependencies?.[packageName]) {
160
+ devDependenciesToInstall.push(`${packageName}@${version}`);
161
+ }
162
+ else if (required || appPackageJson.dependencies?.[packageName]) {
163
+ dependenciesToInstall.push(`${packageName}@${version}`);
164
+ }
132
165
  }
133
166
  console.log(`Upgrading your project to ${picocolors_1.default.blue('Next.js ' + targetNextVersion)}...\n`);
134
- (0, handle_package_1.installPackages)([nextDependency, ...reactDependencies], {
167
+ (0, handle_package_1.installPackages)(dependenciesToInstall, {
168
+ packageManager,
169
+ silent: !verbose,
170
+ });
171
+ (0, handle_package_1.installPackages)(devDependenciesToInstall, {
135
172
  packageManager,
136
173
  silent: !verbose,
174
+ dev: true,
137
175
  });
138
176
  for (const codemod of codemods) {
139
177
  await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true, verbose });
@@ -159,7 +197,7 @@ async function runUpgrade(revision, options) {
159
197
  if (codemods.length > 0) {
160
198
  console.log(`${picocolors_1.default.green('✔')} Codemods have been applied successfully.`);
161
199
  }
162
- console.log(`Please review the local changes and read the Next.js 15 migration guide to complete the migration. https://nextjs.org/docs/canary/app/building-your-application/upgrading/version-15`);
200
+ endMessage();
163
201
  }
164
202
  function getInstalledNextVersion() {
165
203
  try {
@@ -168,7 +206,7 @@ function getInstalledNextVersion() {
168
206
  })).version;
169
207
  }
170
208
  catch (error) {
171
- throw new Error(`Failed to get the installed Next.js version at "${process.cwd()}".\nIf you're using a monorepo, please run this command from the Next.js app directory.`, {
209
+ throw new shared_1.BadInput(`Failed to get the installed Next.js version at "${process.cwd()}".\nIf you're using a monorepo, please run this command from the Next.js app directory.`, {
172
210
  cause: error,
173
211
  });
174
212
  }
@@ -180,7 +218,7 @@ function getInstalledReactVersion() {
180
218
  })).version;
181
219
  }
182
220
  catch (error) {
183
- throw new Error(`Failed to detect the installed React version in "${process.cwd()}".\nIf you're working in a monorepo, please run this command from the Next.js app directory.`, {
221
+ throw new shared_1.BadInput(`Failed to detect the installed React version in "${process.cwd()}".\nIf you're working in a monorepo, please run this command from the Next.js app directory.`, {
184
222
  cause: error,
185
223
  });
186
224
  }
@@ -40,20 +40,44 @@ function uninstallPackage(packageToUninstall, pkgManager) {
40
40
  command = 'remove';
41
41
  }
42
42
  try {
43
- execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
43
+ execa_1.default.sync(pkgManager, [command, packageToUninstall], {
44
+ stdio: 'inherit',
45
+ shell: true,
46
+ });
44
47
  }
45
48
  catch (error) {
46
49
  throw new Error(`Failed to uninstall "${packageToUninstall}". Please uninstall it manually.`, { cause: error });
47
50
  }
48
51
  }
52
+ const ADD_CMD_FLAG = {
53
+ npm: 'install',
54
+ yarn: 'add',
55
+ pnpm: 'add',
56
+ bun: 'add',
57
+ };
58
+ const DEV_DEP_FLAG = {
59
+ npm: '--save-dev',
60
+ yarn: '--dev',
61
+ pnpm: '--save-dev',
62
+ bun: '--dev',
63
+ };
49
64
  function installPackages(packageToInstall, options = {}) {
50
- const { packageManager = getPkgManager(process.cwd()), silent = false } = options;
65
+ if (packageToInstall.length === 0)
66
+ return;
67
+ const { packageManager = getPkgManager(process.cwd()), silent = false, dev = false, } = options;
51
68
  if (!packageManager)
52
69
  throw new Error('Failed to find package manager');
70
+ const addCmd = ADD_CMD_FLAG[packageManager];
71
+ const devDepFlag = dev ? DEV_DEP_FLAG[packageManager] : undefined;
72
+ const installFlags = [addCmd];
73
+ if (devDepFlag) {
74
+ installFlags.push(devDepFlag);
75
+ }
53
76
  try {
54
- execa_1.default.sync(packageManager, ['add', ...packageToInstall], {
77
+ execa_1.default.sync(packageManager, [...installFlags, ...packageToInstall], {
55
78
  // Keeping stderr since it'll likely be relevant later when it fails.
56
79
  stdio: silent ? ['ignore', 'ignore', 'inherit'] : 'inherit',
80
+ shell: true,
57
81
  });
58
82
  }
59
83
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next/codemod",
3
- "version": "15.0.0-canary.190",
3
+ "version": "15.0.0-canary.192",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,6 +37,7 @@
37
37
  "@types/find-up": "4.0.0",
38
38
  "@types/jscodeshift": "0.11.0",
39
39
  "@types/prompts": "2.4.2",
40
- "@types/semver": "7.3.1"
40
+ "@types/semver": "7.3.1",
41
+ "typescript": "5.5.3"
41
42
  }
42
43
  }