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

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,22 @@ 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
+ }
40
+ function addDependencyIfNeeded(packageName, version, appPackageJson, dependenciesToInstall, devDependenciesToInstall) {
41
+ const specifiedDependency = `${packageName}@${version}`;
42
+ // First check if it's dev dependencies, then add into dev deps;
43
+ // If it's not, fallback into dependencies.
44
+ if (appPackageJson.devDependencies?.[packageName]) {
45
+ devDependenciesToInstall.push(specifiedDependency);
46
+ }
47
+ else if (appPackageJson.dependencies?.[packageName]) {
48
+ dependenciesToInstall.push(specifiedDependency);
49
+ }
50
+ }
34
51
  async function runUpgrade(revision, options) {
35
52
  const { verbose } = options;
36
53
  const appPackageJsonPath = path_1.default.resolve(process.cwd(), 'package.json');
@@ -45,21 +62,25 @@ async function runUpgrade(revision, options) {
45
62
  'version' in targetNextPackageJson &&
46
63
  'peerDependencies' in targetNextPackageJson;
47
64
  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.`);
65
+ 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
66
  }
50
67
  const installedNextVersion = getInstalledNextVersion();
51
- console.log(`Current Next.js version: v${installedNextVersion}`);
52
68
  const targetNextVersion = targetNextPackageJson.version;
53
69
  if ((0, compare_1.default)(installedNextVersion, targetNextVersion) === 0) {
54
70
  console.log(`${picocolors_1.default.green('✓')} Current Next.js version is already on the target version "v${targetNextVersion}".`);
71
+ endMessage();
55
72
  return;
56
73
  }
57
74
  if ((0, compare_1.default)(installedNextVersion, targetNextVersion) > 0) {
58
75
  console.log(`${picocolors_1.default.green('✓')} Current Next.js version is higher than the target version "v${targetNextVersion}".`);
76
+ endMessage();
59
77
  return;
60
78
  }
61
79
  const installedReactVersion = getInstalledReactVersion();
62
- console.log(`Current React version: v${installedReactVersion}`);
80
+ // Align the prefix spaces
81
+ console.log(` Detected installed versions:`);
82
+ console.log(` - React: v${installedReactVersion}`);
83
+ console.log(` - Next.js: v${installedNextVersion}`);
63
84
  let shouldStayOnReact18 = false;
64
85
  if (
65
86
  // From release v14.3.0-canary.45, Next.js expects the React version to be 19.0.0-beta.0
@@ -111,29 +132,40 @@ async function runUpgrade(revision, options) {
111
132
  execCommand = execCommandMap[packageManager];
112
133
  }
113
134
  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
- ];
135
+ const dependenciesToInstall = [];
136
+ const devDependenciesToInstall = [];
137
+ const corePackageNameVersionMapping = {
138
+ react: targetReactVersion,
139
+ 'react-dom': targetReactVersion,
140
+ next: targetNextVersion,
141
+ };
142
+ for (const packageName of Object.keys(corePackageNameVersionMapping)) {
143
+ addDependencyIfNeeded(packageName, corePackageNameVersionMapping[packageName], appPackageJson, dependenciesToInstall, devDependenciesToInstall);
144
+ }
119
145
  if (targetReactVersion.startsWith('19.0.0-canary') ||
120
146
  targetReactVersion.startsWith('19.0.0-beta') ||
121
147
  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`);
148
+ corePackageNameVersionMapping['@types/react'] = 'npm:types-react@rc';
149
+ corePackageNameVersionMapping['@types/react-dom'] = 'npm:types-react-dom@rc';
124
150
  }
125
151
  else {
126
152
  const [targetReactTypesVersion, targetReactDOMTypesVersion] = await Promise.all([
127
153
  loadHighestNPMVersionMatching(`@types/react@${targetNextPackageJson.peerDependencies['react']}`),
128
154
  loadHighestNPMVersionMatching(`@types/react-dom@${targetNextPackageJson.peerDependencies['react']}`),
129
155
  ]);
130
- reactDependencies.push(`@types/react@${targetReactTypesVersion}`);
131
- reactDependencies.push(`@types/react-dom@${targetReactDOMTypesVersion}`);
156
+ corePackageNameVersionMapping['@types/react'] = targetReactTypesVersion;
157
+ corePackageNameVersionMapping['@types/react-dom'] =
158
+ targetReactDOMTypesVersion;
132
159
  }
133
160
  console.log(`Upgrading your project to ${picocolors_1.default.blue('Next.js ' + targetNextVersion)}...\n`);
134
- (0, handle_package_1.installPackages)([nextDependency, ...reactDependencies], {
161
+ (0, handle_package_1.installPackages)(dependenciesToInstall, {
162
+ packageManager,
163
+ silent: !verbose,
164
+ });
165
+ (0, handle_package_1.installPackages)(devDependenciesToInstall, {
135
166
  packageManager,
136
167
  silent: !verbose,
168
+ dev: true,
137
169
  });
138
170
  for (const codemod of codemods) {
139
171
  await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true, verbose });
@@ -159,7 +191,7 @@ async function runUpgrade(revision, options) {
159
191
  if (codemods.length > 0) {
160
192
  console.log(`${picocolors_1.default.green('✔')} Codemods have been applied successfully.`);
161
193
  }
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`);
194
+ endMessage();
163
195
  }
164
196
  function getInstalledNextVersion() {
165
197
  try {
@@ -168,7 +200,7 @@ function getInstalledNextVersion() {
168
200
  })).version;
169
201
  }
170
202
  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.`, {
203
+ 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
204
  cause: error,
173
205
  });
174
206
  }
@@ -180,7 +212,7 @@ function getInstalledReactVersion() {
180
212
  })).version;
181
213
  }
182
214
  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.`, {
215
+ 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
216
  cause: error,
185
217
  });
186
218
  }
@@ -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.191",
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
  }