@next/codemod 15.0.0-canary.173 → 15.0.0-canary.174
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.
- package/bin/next-codemod.js +2 -1
- package/bin/transform.js +1 -1
- package/bin/upgrade.js +58 -30
- package/lib/codemods.js +10 -5
- package/lib/handle-package.js +8 -8
- package/package.json +1 -1
package/bin/next-codemod.js
CHANGED
|
@@ -30,7 +30,8 @@ const program = new commander_1.Command(packageJson.name)
|
|
|
30
30
|
program
|
|
31
31
|
.command('upgrade')
|
|
32
32
|
.description('Upgrade Next.js apps to desired versions with a single command.')
|
|
33
|
-
.
|
|
33
|
+
.argument('[revision]', 'NPM dist tag or exact version to upgrade to (e.g. "latest" or "15.0.0-canary.167"). Prompts to choose a dist tag if omitted.')
|
|
34
|
+
.option('--verbose', 'Verbose output', false)
|
|
34
35
|
.action(upgrade_1.runUpgrade);
|
|
35
36
|
program.parse(process.argv);
|
|
36
37
|
//# sourceMappingURL=next-codemod.js.map
|
package/bin/transform.js
CHANGED
|
@@ -98,7 +98,7 @@ async function runTransform(transform, path, options) {
|
|
|
98
98
|
}
|
|
99
99
|
if (!dry && transformer === 'next-request-geo-ip') {
|
|
100
100
|
console.log('Installing `@vercel/functions`...');
|
|
101
|
-
(0, handle_package_1.
|
|
101
|
+
(0, handle_package_1.installPackages)(['@vercel/functions']);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
//# sourceMappingURL=transform.js.map
|
package/bin/upgrade.js
CHANGED
|
@@ -12,21 +12,34 @@ const compare_versions_1 = require("compare-versions");
|
|
|
12
12
|
const chalk_1 = __importDefault(require("chalk"));
|
|
13
13
|
const codemods_1 = require("../lib/codemods");
|
|
14
14
|
const handle_package_1 = require("../lib/handle-package");
|
|
15
|
-
|
|
15
|
+
const transform_1 = require("./transform");
|
|
16
|
+
/**
|
|
17
|
+
* @param query
|
|
18
|
+
* @example loadHighestNPMVersionMatching("react@^18.3.0 || ^19.0.0") === Promise<"19.0.0">
|
|
19
|
+
*/
|
|
20
|
+
async function loadHighestNPMVersionMatching(query) {
|
|
21
|
+
const versionsJSON = (0, child_process_1.execSync)(`npm --silent view "${query}" --json --field version`, { encoding: 'utf-8' });
|
|
22
|
+
const versions = JSON.parse(versionsJSON);
|
|
23
|
+
if (versions.length < 1) {
|
|
24
|
+
throw new Error(`Found no React versions matching "${query}". This is a bug in the upgrade tool.`);
|
|
25
|
+
}
|
|
26
|
+
return versions[versions.length - 1];
|
|
27
|
+
}
|
|
28
|
+
async function runUpgrade(revision, options) {
|
|
29
|
+
const { verbose } = options;
|
|
16
30
|
const appPackageJsonPath = path_1.default.resolve(process.cwd(), 'package.json');
|
|
17
31
|
let appPackageJson = JSON.parse(fs_1.default.readFileSync(appPackageJsonPath, 'utf8'));
|
|
18
32
|
await detectWorkspace(appPackageJson);
|
|
19
33
|
let targetNextPackageJson;
|
|
20
34
|
let targetVersionSpecifier = '';
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const res = await fetch(`https://registry.npmjs.org/next/${shortcutVersion}`);
|
|
35
|
+
if (revision !== undefined) {
|
|
36
|
+
const res = await fetch(`https://registry.npmjs.org/next/${revision}`);
|
|
24
37
|
if (res.status === 200) {
|
|
25
38
|
targetNextPackageJson = await res.json();
|
|
26
39
|
targetVersionSpecifier = targetNextPackageJson.version;
|
|
27
40
|
}
|
|
28
41
|
else {
|
|
29
|
-
console.error(`${chalk_1.default.yellow(
|
|
42
|
+
console.error(`${chalk_1.default.yellow(`next@${revision}`)} does not exist. Check available versions at ${chalk_1.default.underline('https://www.npmjs.com/package/next?activeTab=versions')}, or choose one from below\n`);
|
|
30
43
|
}
|
|
31
44
|
}
|
|
32
45
|
const installedNextVersion = await getInstalledNextVersion();
|
|
@@ -83,21 +96,41 @@ async function runUpgrade() {
|
|
|
83
96
|
targetVersionSpecifier = response.version;
|
|
84
97
|
}
|
|
85
98
|
const targetNextVersion = targetNextPackageJson.version;
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
// We're resolving a specific version here to avoid including "ugly" version queries
|
|
100
|
+
// in the manifest.
|
|
101
|
+
// E.g. in peerDependencies we could have `^18.2.0 || ^19.0.0 || 20.0.0-canary`
|
|
102
|
+
// If we'd just `npm add` that, the manifest would read the same version query.
|
|
103
|
+
// This is basically a `npm --save-exact react@$versionQuery` that works for every package manager.
|
|
104
|
+
const [targetReactVersion, targetReactTypesVersion, targetReactDOMTypesVersion,] = await Promise.all([
|
|
105
|
+
loadHighestNPMVersionMatching(`react@${targetNextPackageJson.peerDependencies['react']}`),
|
|
106
|
+
loadHighestNPMVersionMatching(`@types/react@${targetNextPackageJson.peerDependencies['react']}`),
|
|
107
|
+
loadHighestNPMVersionMatching(`@types/react-dom@${targetNextPackageJson.peerDependencies['react']}`),
|
|
108
|
+
]);
|
|
109
|
+
if ((0, compare_versions_1.compareVersions)(targetNextVersion, '15.0.0-canary') >= 0) {
|
|
88
110
|
await suggestTurbopack(appPackageJson);
|
|
89
111
|
}
|
|
90
112
|
fs_1.default.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2));
|
|
91
113
|
const packageManager = (0, handle_package_1.getPkgManager)(process.cwd());
|
|
92
114
|
const nextDependency = `next@${targetNextVersion}`;
|
|
93
115
|
const reactDependencies = [
|
|
94
|
-
`react@${
|
|
95
|
-
|
|
96
|
-
`react-dom@${targetNextPackageJson.peerDependencies['react-dom']}`,
|
|
97
|
-
`@types/react-dom@${targetNextPackageJson.devDependencies['@types/react-dom']}`,
|
|
116
|
+
`react@${targetReactVersion}`,
|
|
117
|
+
`react-dom@${targetReactVersion}`,
|
|
98
118
|
];
|
|
99
|
-
(0
|
|
119
|
+
if (targetReactVersion.startsWith('19.0.0-canary') ||
|
|
120
|
+
targetReactVersion.startsWith('19.0.0-beta') ||
|
|
121
|
+
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`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
reactDependencies.push(`@types/react@${targetReactTypesVersion}`);
|
|
127
|
+
reactDependencies.push(`@types/react-dom@${targetReactDOMTypesVersion}`);
|
|
128
|
+
}
|
|
100
129
|
console.log(`Upgrading your project to ${chalk_1.default.blue('Next.js ' + targetVersionSpecifier)}...\n`);
|
|
130
|
+
(0, handle_package_1.installPackages)([nextDependency, ...reactDependencies], {
|
|
131
|
+
packageManager,
|
|
132
|
+
silent: !verbose,
|
|
133
|
+
});
|
|
101
134
|
await suggestCodemods(installedNextVersion, targetNextVersion);
|
|
102
135
|
console.log(`\n${chalk_1.default.green('✔')} Your Next.js project has been upgraded successfully. ${chalk_1.default.bold('Time to ship! 🚢')}`);
|
|
103
136
|
}
|
|
@@ -196,29 +229,24 @@ async function suggestCodemods(initialNextVersion, targetNextVersion) {
|
|
|
196
229
|
if (relevantCodemods.length === 0) {
|
|
197
230
|
return;
|
|
198
231
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
const { codemods } = await (0, prompts_1.default)({
|
|
233
|
+
type: 'multiselect',
|
|
234
|
+
name: 'codemods',
|
|
235
|
+
message: `\nThe following ${chalk_1.default.blue('codemods')} are recommended for your upgrade. Would you like to apply them?`,
|
|
236
|
+
choices: relevantCodemods.map((codemod) => {
|
|
237
|
+
return {
|
|
238
|
+
title: `${codemod.title} ${chalk_1.default.grey(`(${codemod.value})`)}`,
|
|
239
|
+
value: codemod.value,
|
|
240
|
+
selected: true,
|
|
241
|
+
};
|
|
242
|
+
}),
|
|
210
243
|
}, {
|
|
211
244
|
onCancel: () => {
|
|
212
245
|
process.exit(0);
|
|
213
246
|
},
|
|
214
247
|
});
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
for (const codemod of relevantCodemods) {
|
|
219
|
-
(0, child_process_1.execSync)(`npx @next/codemod@latest ${codemod.value} ${process.cwd()} --force`, {
|
|
220
|
-
stdio: 'inherit',
|
|
221
|
-
});
|
|
248
|
+
for (const codemod of codemods) {
|
|
249
|
+
await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true });
|
|
222
250
|
}
|
|
223
251
|
}
|
|
224
252
|
//# sourceMappingURL=upgrade.js.map
|
package/lib/codemods.js
CHANGED
|
@@ -87,17 +87,22 @@ exports.availableCodemods = [
|
|
|
87
87
|
],
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
|
-
version: '15.0',
|
|
90
|
+
version: '15.0.0-canary.153',
|
|
91
91
|
codemods: [
|
|
92
|
-
{
|
|
93
|
-
title: 'Transforms usage of Next.js async Request APIs',
|
|
94
|
-
value: 'next-async-request-api',
|
|
95
|
-
},
|
|
96
92
|
{
|
|
97
93
|
title: 'Migrate `geo` and `ip` properties on `NextRequest`',
|
|
98
94
|
value: 'next-request-geo-ip',
|
|
99
95
|
},
|
|
100
96
|
],
|
|
101
97
|
},
|
|
98
|
+
{
|
|
99
|
+
version: '15.0.0-canary.171',
|
|
100
|
+
codemods: [
|
|
101
|
+
{
|
|
102
|
+
title: 'Transforms usage of Next.js async Request APIs',
|
|
103
|
+
value: 'next-async-request-api',
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
102
107
|
];
|
|
103
108
|
//# sourceMappingURL=codemods.js.map
|
package/lib/handle-package.js
CHANGED
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getPkgManager = getPkgManager;
|
|
7
7
|
exports.uninstallPackage = uninstallPackage;
|
|
8
|
-
exports.
|
|
8
|
+
exports.installPackages = installPackages;
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const execa_1 = __importDefault(require("execa"));
|
|
@@ -59,15 +59,15 @@ function uninstallPackage(packageToUninstall, pkgManager) {
|
|
|
59
59
|
}
|
|
60
60
|
execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
|
|
61
61
|
}
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
if (!
|
|
62
|
+
function installPackages(packageToInstall, options = {}) {
|
|
63
|
+
const { packageManager = getPkgManager(process.cwd()), silent = false } = options;
|
|
64
|
+
if (!packageManager)
|
|
65
65
|
throw new Error('Failed to find package manager');
|
|
66
|
-
if (Array.isArray(packageToInstall)) {
|
|
67
|
-
packageToInstall = packageToInstall.join(' ');
|
|
68
|
-
}
|
|
69
66
|
try {
|
|
70
|
-
execa_1.default.sync(
|
|
67
|
+
execa_1.default.sync(packageManager, ['add', ...packageToInstall], {
|
|
68
|
+
// Keeping stderr since it'll likely be relevant later when it fails.
|
|
69
|
+
stdio: silent ? ['ignore', 'ignore', 'inherit'] : 'inherit',
|
|
70
|
+
});
|
|
71
71
|
}
|
|
72
72
|
catch (error) {
|
|
73
73
|
throw new Error(`Failed to install "${packageToInstall}". Please install it manually.`, { cause: error });
|