@next/codemod 15.0.0-canary.18 → 15.0.0-canary.182
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 +33 -3
- package/bin/transform.js +110 -0
- package/bin/upgrade.js +179 -0
- package/lib/cra-to-next/global-css-transform.js +2 -3
- package/lib/cra-to-next/index-to-component.js +2 -3
- package/lib/handle-package.js +58 -0
- package/lib/install.js +2 -3
- package/lib/run-jscodeshift.js +22 -2
- package/lib/utils.js +115 -0
- package/package.json +11 -6
- package/transforms/add-missing-react-import.js +1 -1
- package/transforms/app-dir-runtime-config-experimental-edge.js +33 -0
- package/transforms/built-in-next-font.js +1 -1
- package/transforms/cra-to-next.js +238 -236
- package/transforms/lib/async-request-api/index.js +16 -0
- package/transforms/lib/async-request-api/next-async-dynamic-api.js +273 -0
- package/transforms/lib/async-request-api/next-async-dynamic-prop.js +686 -0
- package/transforms/lib/async-request-api/utils.js +344 -0
- package/transforms/metadata-to-viewport-export.js +1 -1
- package/transforms/name-default-component.js +3 -4
- package/transforms/new-link.js +5 -4
- package/transforms/next-async-request-api.js +9 -0
- package/transforms/next-dynamic-access-named-export.js +65 -0
- package/transforms/next-image-experimental.js +9 -13
- package/transforms/next-image-to-legacy-image.js +5 -7
- package/transforms/next-og-import.js +1 -1
- package/transforms/next-request-geo-ip.js +338 -0
- package/transforms/url-to-withrouter.js +1 -1
- package/transforms/withamp-to-config.js +1 -1
- package/bin/cli.js +0 -216
- package/lib/uninstall-package.js +0 -32
package/bin/next-codemod.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
2
3
|
/**
|
|
3
4
|
* Copyright 2015-present, Facebook, Inc.
|
|
4
5
|
*
|
|
@@ -6,7 +7,36 @@
|
|
|
6
7
|
* LICENSE file in the root directory of this source tree.
|
|
7
8
|
*
|
|
8
9
|
*/
|
|
9
|
-
// Based on https://github.com/reactjs/react-codemod/blob/dd8671c9a470a2c342b221ec903c574cf31e9f57/bin/
|
|
10
|
-
// next
|
|
11
|
-
|
|
10
|
+
// Based on https://github.com/reactjs/react-codemod/blob/dd8671c9a470a2c342b221ec903c574cf31e9f57/bin/cli.js
|
|
11
|
+
// @next/codemod optional-name-of-transform optional/path/to/src [...options]
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
const commander_1 = require("commander");
|
|
14
|
+
const upgrade_1 = require("./upgrade");
|
|
15
|
+
const transform_1 = require("./transform");
|
|
16
|
+
const packageJson = require('../package.json');
|
|
17
|
+
const program = new commander_1.Command(packageJson.name)
|
|
18
|
+
.description('Codemods for updating Next.js apps.')
|
|
19
|
+
.version(packageJson.version, '-v, --version', 'Output the current version of @next/codemod.')
|
|
20
|
+
.argument('[codemod]', 'Codemod slug to run. See "https://github.com/vercel/next.js/tree/canary/packages/next-codemod".')
|
|
21
|
+
.argument('[source]', 'Path to source files or directory to transform including glob patterns.')
|
|
22
|
+
.usage('[codemod] [source] [options]')
|
|
23
|
+
.helpOption('-h, --help', 'Display this help message.')
|
|
24
|
+
.option('-f, --force', 'Bypass Git safety checks and forcibly run codemods')
|
|
25
|
+
.option('-d, --dry', 'Dry run (no changes are made to files)')
|
|
26
|
+
.option('-p, --print', 'Print transformed files to your terminal')
|
|
27
|
+
.option('-j, --jscodeshift', '(Advanced) Pass options directly to jscodeshift')
|
|
28
|
+
.action(transform_1.runTransform)
|
|
29
|
+
.allowUnknownOption();
|
|
30
|
+
program
|
|
31
|
+
.command('upgrade')
|
|
32
|
+
.description('Upgrade Next.js apps to desired versions with a single command.')
|
|
33
|
+
.argument('[revision]', 'Specify the target Next.js version using an NPM dist tag (e.g. "latest", "canary", "rc") or an exact version number (e.g. "15.0.0").', packageJson.version.includes('-canary.')
|
|
34
|
+
? 'canary'
|
|
35
|
+
: packageJson.version.includes('-rc.')
|
|
36
|
+
? 'rc'
|
|
37
|
+
: 'latest')
|
|
38
|
+
.usage('[revision] [options]')
|
|
39
|
+
.option('--verbose', 'Verbose output', false)
|
|
40
|
+
.action(upgrade_1.runUpgrade);
|
|
41
|
+
program.parse(process.argv);
|
|
12
42
|
//# sourceMappingURL=next-codemod.js.map
|
package/bin/transform.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.transformerDirectory = exports.jscodeshiftExecutable = void 0;
|
|
7
|
+
exports.runTransform = runTransform;
|
|
8
|
+
const execa_1 = __importDefault(require("execa"));
|
|
9
|
+
const globby_1 = __importDefault(require("globby"));
|
|
10
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
const handle_package_1 = require("../lib/handle-package");
|
|
13
|
+
const utils_1 = require("../lib/utils");
|
|
14
|
+
function expandFilePathsIfNeeded(filesBeforeExpansion) {
|
|
15
|
+
const shouldExpandFiles = filesBeforeExpansion.some((file) => file.includes('*'));
|
|
16
|
+
return shouldExpandFiles
|
|
17
|
+
? globby_1.default.sync(filesBeforeExpansion)
|
|
18
|
+
: filesBeforeExpansion;
|
|
19
|
+
}
|
|
20
|
+
exports.jscodeshiftExecutable = require.resolve('.bin/jscodeshift');
|
|
21
|
+
exports.transformerDirectory = (0, node_path_1.join)(__dirname, '../', 'transforms');
|
|
22
|
+
async function runTransform(transform, path, options) {
|
|
23
|
+
let transformer = transform;
|
|
24
|
+
let directory = path;
|
|
25
|
+
if (!options.dry) {
|
|
26
|
+
(0, utils_1.checkGitStatus)(options.force);
|
|
27
|
+
}
|
|
28
|
+
if (transform &&
|
|
29
|
+
!utils_1.TRANSFORMER_INQUIRER_CHOICES.find((x) => x.value === transform)) {
|
|
30
|
+
console.error('Invalid transform choice, pick one of:');
|
|
31
|
+
console.error(utils_1.TRANSFORMER_INQUIRER_CHOICES.map((x) => '- ' + x.value).join('\n'));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
if (!path) {
|
|
35
|
+
const res = await (0, prompts_1.default)({
|
|
36
|
+
type: 'text',
|
|
37
|
+
name: 'path',
|
|
38
|
+
message: 'On which files or directory should the codemods be applied?',
|
|
39
|
+
initial: '.',
|
|
40
|
+
}, { onCancel: utils_1.onCancel });
|
|
41
|
+
directory = res.path;
|
|
42
|
+
}
|
|
43
|
+
if (!transform) {
|
|
44
|
+
const res = await (0, prompts_1.default)({
|
|
45
|
+
type: 'select',
|
|
46
|
+
name: 'transformer',
|
|
47
|
+
message: 'Which transform would you like to apply?',
|
|
48
|
+
choices: utils_1.TRANSFORMER_INQUIRER_CHOICES.reverse().map(({ title, value, version }) => {
|
|
49
|
+
return {
|
|
50
|
+
title: `(v${version}) ${value}`,
|
|
51
|
+
description: title,
|
|
52
|
+
value,
|
|
53
|
+
};
|
|
54
|
+
}),
|
|
55
|
+
}, { onCancel: utils_1.onCancel });
|
|
56
|
+
transformer = res.transformer;
|
|
57
|
+
}
|
|
58
|
+
const filesExpanded = expandFilePathsIfNeeded([directory]);
|
|
59
|
+
if (!filesExpanded.length) {
|
|
60
|
+
console.log(`No files found matching "${directory}"`);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const transformerPath = (0, node_path_1.join)(exports.transformerDirectory, `${transformer}.js`);
|
|
64
|
+
if (transformer === 'cra-to-next') {
|
|
65
|
+
// cra-to-next transform doesn't use jscodeshift directly
|
|
66
|
+
return require(transformerPath).default(filesExpanded, options);
|
|
67
|
+
}
|
|
68
|
+
let args = [];
|
|
69
|
+
const { dry, print, runInBand, jscodeshift } = options;
|
|
70
|
+
if (dry) {
|
|
71
|
+
args.push('--dry');
|
|
72
|
+
}
|
|
73
|
+
if (print) {
|
|
74
|
+
args.push('--print');
|
|
75
|
+
}
|
|
76
|
+
if (runInBand) {
|
|
77
|
+
args.push('--run-in-band');
|
|
78
|
+
}
|
|
79
|
+
args.push('--verbose=2');
|
|
80
|
+
args.push('--ignore-pattern=**/node_modules/**');
|
|
81
|
+
args.push('--ignore-pattern=**/.next/**');
|
|
82
|
+
args.push('--extensions=tsx,ts,jsx,js');
|
|
83
|
+
args = args.concat(['--transform', transformerPath]);
|
|
84
|
+
if (jscodeshift) {
|
|
85
|
+
args = args.concat(jscodeshift);
|
|
86
|
+
}
|
|
87
|
+
args = args.concat(filesExpanded);
|
|
88
|
+
console.log(`Executing command: jscodeshift ${args.join(' ')}`);
|
|
89
|
+
const result = execa_1.default.sync(exports.jscodeshiftExecutable, args, {
|
|
90
|
+
stdio: 'inherit',
|
|
91
|
+
stripFinalNewline: false,
|
|
92
|
+
});
|
|
93
|
+
if (result.failed) {
|
|
94
|
+
throw new Error(`jscodeshift exited with code ${result.exitCode}`);
|
|
95
|
+
}
|
|
96
|
+
if (!dry && transformer === 'built-in-next-font') {
|
|
97
|
+
console.log('Uninstalling `@next/font`');
|
|
98
|
+
try {
|
|
99
|
+
(0, handle_package_1.uninstallPackage)('@next/font');
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
console.error("Couldn't uninstall `@next/font`, please uninstall it manually");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!dry && transformer === 'next-request-geo-ip') {
|
|
106
|
+
console.log('Installing `@vercel/functions`...');
|
|
107
|
+
(0, handle_package_1.installPackages)(['@vercel/functions']);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=transform.js.map
|
package/bin/upgrade.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runUpgrade = runUpgrade;
|
|
7
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const compare_versions_1 = require("compare-versions");
|
|
12
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
13
|
+
const handle_package_1 = require("../lib/handle-package");
|
|
14
|
+
const transform_1 = require("./transform");
|
|
15
|
+
const utils_1 = require("../lib/utils");
|
|
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 versionOrVersions = JSON.parse(versionsJSON);
|
|
23
|
+
if (versionOrVersions.length < 1) {
|
|
24
|
+
throw new Error(`Found no React versions matching "${query}". This is a bug in the upgrade tool.`);
|
|
25
|
+
}
|
|
26
|
+
// npm-view returns an array if there are multiple versions matching the query.
|
|
27
|
+
if (Array.isArray(versionOrVersions)) {
|
|
28
|
+
// The last entry will be the latest version published.
|
|
29
|
+
return versionOrVersions[versionOrVersions.length - 1];
|
|
30
|
+
}
|
|
31
|
+
return versionOrVersions;
|
|
32
|
+
}
|
|
33
|
+
async function runUpgrade(revision, options) {
|
|
34
|
+
const { verbose } = options;
|
|
35
|
+
const appPackageJsonPath = path_1.default.resolve(process.cwd(), 'package.json');
|
|
36
|
+
let appPackageJson = JSON.parse(fs_1.default.readFileSync(appPackageJsonPath, 'utf8'));
|
|
37
|
+
let targetNextPackageJson;
|
|
38
|
+
const res = await fetch(`https://registry.npmjs.org/next/${revision}`);
|
|
39
|
+
if (res.status === 200) {
|
|
40
|
+
targetNextPackageJson = await res.json();
|
|
41
|
+
}
|
|
42
|
+
const validRevision = targetNextPackageJson !== null &&
|
|
43
|
+
typeof targetNextPackageJson === 'object' &&
|
|
44
|
+
'version' in targetNextPackageJson &&
|
|
45
|
+
'peerDependencies' in targetNextPackageJson;
|
|
46
|
+
if (!validRevision) {
|
|
47
|
+
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.`);
|
|
48
|
+
}
|
|
49
|
+
const installedNextVersion = getInstalledNextVersion();
|
|
50
|
+
console.log(`Current Next.js version: v${installedNextVersion}`);
|
|
51
|
+
const targetNextVersion = targetNextPackageJson.version;
|
|
52
|
+
if ((0, compare_versions_1.compareVersions)(installedNextVersion, targetNextVersion) >= 0) {
|
|
53
|
+
console.log(`${picocolors_1.default.green('✓')} Current Next.js version is already on or higher than the target version "v${targetNextVersion}".`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// We're resolving a specific version here to avoid including "ugly" version queries
|
|
57
|
+
// in the manifest.
|
|
58
|
+
// E.g. in peerDependencies we could have `^18.2.0 || ^19.0.0 || 20.0.0-canary`
|
|
59
|
+
// If we'd just `npm add` that, the manifest would read the same version query.
|
|
60
|
+
// This is basically a `npm --save-exact react@$versionQuery` that works for every package manager.
|
|
61
|
+
const targetReactVersion = await loadHighestNPMVersionMatching(`react@${targetNextPackageJson.peerDependencies['react']}`);
|
|
62
|
+
if ((0, compare_versions_1.compareVersions)(targetNextVersion, '15.0.0-canary') >= 0) {
|
|
63
|
+
await suggestTurbopack(appPackageJson);
|
|
64
|
+
}
|
|
65
|
+
const codemods = await suggestCodemods(installedNextVersion, targetNextVersion);
|
|
66
|
+
fs_1.default.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2));
|
|
67
|
+
const packageManager = (0, handle_package_1.getPkgManager)(process.cwd());
|
|
68
|
+
const nextDependency = `next@${targetNextVersion}`;
|
|
69
|
+
const reactDependencies = [
|
|
70
|
+
`react@${targetReactVersion}`,
|
|
71
|
+
`react-dom@${targetReactVersion}`,
|
|
72
|
+
];
|
|
73
|
+
if (targetReactVersion.startsWith('19.0.0-canary') ||
|
|
74
|
+
targetReactVersion.startsWith('19.0.0-beta') ||
|
|
75
|
+
targetReactVersion.startsWith('19.0.0-rc')) {
|
|
76
|
+
reactDependencies.push(`@types/react@npm:types-react@rc`);
|
|
77
|
+
reactDependencies.push(`@types/react-dom@npm:types-react-dom@rc`);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const [targetReactTypesVersion, targetReactDOMTypesVersion] = await Promise.all([
|
|
81
|
+
loadHighestNPMVersionMatching(`@types/react@${targetNextPackageJson.peerDependencies['react']}`),
|
|
82
|
+
loadHighestNPMVersionMatching(`@types/react-dom@${targetNextPackageJson.peerDependencies['react']}`),
|
|
83
|
+
]);
|
|
84
|
+
reactDependencies.push(`@types/react@${targetReactTypesVersion}`);
|
|
85
|
+
reactDependencies.push(`@types/react-dom@${targetReactDOMTypesVersion}`);
|
|
86
|
+
}
|
|
87
|
+
console.log(`Upgrading your project to ${picocolors_1.default.blue('Next.js ' + targetNextVersion)}...\n`);
|
|
88
|
+
(0, handle_package_1.installPackages)([nextDependency, ...reactDependencies], {
|
|
89
|
+
packageManager,
|
|
90
|
+
silent: !verbose,
|
|
91
|
+
});
|
|
92
|
+
for (const codemod of codemods) {
|
|
93
|
+
await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true });
|
|
94
|
+
}
|
|
95
|
+
console.log(); // new line
|
|
96
|
+
if (codemods.length > 0) {
|
|
97
|
+
console.log(`${picocolors_1.default.green('✔')} Codemods have been applied successfully.`);
|
|
98
|
+
}
|
|
99
|
+
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`);
|
|
100
|
+
}
|
|
101
|
+
function getInstalledNextVersion() {
|
|
102
|
+
try {
|
|
103
|
+
return require(require.resolve('next/package.json', {
|
|
104
|
+
paths: [process.cwd()],
|
|
105
|
+
})).version;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
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.`, {
|
|
109
|
+
cause: error,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/*
|
|
114
|
+
* Heuristics are used to determine whether to Turbopack is enabled or not and
|
|
115
|
+
* to determine how to update the dev script.
|
|
116
|
+
*
|
|
117
|
+
* 1. If the dev script contains `--turbo` option, we assume that Turbopack is
|
|
118
|
+
* already enabled.
|
|
119
|
+
* 2. If the dev script contains the string `next dev`, we replace it to
|
|
120
|
+
* `next dev --turbo`.
|
|
121
|
+
* 3. Otherwise, we ask the user to manually add `--turbo` to their dev command,
|
|
122
|
+
* showing the current dev command as the initial value.
|
|
123
|
+
*/
|
|
124
|
+
async function suggestTurbopack(packageJson) {
|
|
125
|
+
const devScript = packageJson.scripts['dev'];
|
|
126
|
+
if (devScript.includes('--turbo'))
|
|
127
|
+
return;
|
|
128
|
+
const responseTurbopack = await (0, prompts_1.default)({
|
|
129
|
+
type: 'confirm',
|
|
130
|
+
name: 'enable',
|
|
131
|
+
message: 'Enable Turbopack for next dev?',
|
|
132
|
+
initial: true,
|
|
133
|
+
}, { onCancel: utils_1.onCancel });
|
|
134
|
+
if (!responseTurbopack.enable) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (devScript.includes('next dev')) {
|
|
138
|
+
packageJson.scripts['dev'] = devScript.replace('next dev', 'next dev --turbo');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
console.log(`${picocolors_1.default.yellow('⚠')} Could not find "${picocolors_1.default.bold('next dev')}" in your dev script.`);
|
|
142
|
+
const responseCustomDevScript = await (0, prompts_1.default)({
|
|
143
|
+
type: 'text',
|
|
144
|
+
name: 'customDevScript',
|
|
145
|
+
message: 'Please manually add "--turbo" to your dev command.',
|
|
146
|
+
initial: devScript,
|
|
147
|
+
}, { onCancel: utils_1.onCancel });
|
|
148
|
+
packageJson.scripts['dev'] =
|
|
149
|
+
responseCustomDevScript.customDevScript || devScript;
|
|
150
|
+
}
|
|
151
|
+
async function suggestCodemods(initialNextVersion, targetNextVersion) {
|
|
152
|
+
const initialVersionIndex = utils_1.TRANSFORMER_INQUIRER_CHOICES.findIndex((versionCodemods) => (0, compare_versions_1.compareVersions)(versionCodemods.version, initialNextVersion) > 0);
|
|
153
|
+
if (initialVersionIndex === -1) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
let targetVersionIndex = utils_1.TRANSFORMER_INQUIRER_CHOICES.findIndex((versionCodemods) => (0, compare_versions_1.compareVersions)(versionCodemods.version, targetNextVersion) > 0);
|
|
157
|
+
if (targetVersionIndex === -1) {
|
|
158
|
+
targetVersionIndex = utils_1.TRANSFORMER_INQUIRER_CHOICES.length;
|
|
159
|
+
}
|
|
160
|
+
const relevantCodemods = utils_1.TRANSFORMER_INQUIRER_CHOICES.slice(initialVersionIndex, targetVersionIndex);
|
|
161
|
+
if (relevantCodemods.length === 0) {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
const { codemods } = await (0, prompts_1.default)({
|
|
165
|
+
type: 'multiselect',
|
|
166
|
+
name: 'codemods',
|
|
167
|
+
message: `The following ${picocolors_1.default.blue('codemods')} are recommended for your upgrade. Select the ones to apply.`,
|
|
168
|
+
choices: relevantCodemods.reverse().map(({ title, value, version }) => {
|
|
169
|
+
return {
|
|
170
|
+
title: `(v${version}) ${value}`,
|
|
171
|
+
description: title,
|
|
172
|
+
value,
|
|
173
|
+
selected: true,
|
|
174
|
+
};
|
|
175
|
+
}),
|
|
176
|
+
}, { onCancel: utils_1.onCancel });
|
|
177
|
+
return codemods;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.globalCssContext = void 0;
|
|
7
|
+
exports.default = transformer;
|
|
7
8
|
const path_1 = __importDefault(require("path"));
|
|
8
9
|
exports.globalCssContext = {
|
|
9
10
|
cssImports: new Set(),
|
|
@@ -37,8 +38,7 @@ function transformer(file, api, options) {
|
|
|
37
38
|
}
|
|
38
39
|
else if (value.endsWith('.svg')) {
|
|
39
40
|
const isComponentImport = path.node.specifiers.some((specifier) => {
|
|
40
|
-
|
|
41
|
-
return ((_a = specifier.imported) === null || _a === void 0 ? void 0 : _a.name) === 'ReactComponent';
|
|
41
|
+
return specifier.imported?.name === 'ReactComponent';
|
|
42
42
|
});
|
|
43
43
|
if (isComponentImport) {
|
|
44
44
|
exports.globalCssContext.reactSvgImports.add(file.path);
|
|
@@ -52,5 +52,4 @@ function transformer(file, api, options) {
|
|
|
52
52
|
? root.toSource(options)
|
|
53
53
|
: null;
|
|
54
54
|
}
|
|
55
|
-
exports.default = transformer;
|
|
56
55
|
//# sourceMappingURL=global-css-transform.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.indexContext = void 0;
|
|
4
|
+
exports.default = transformer;
|
|
4
5
|
exports.indexContext = {
|
|
5
6
|
multipleRenderRoots: false,
|
|
6
7
|
nestedRender: false,
|
|
@@ -28,7 +29,6 @@ function transformer(file, api, options) {
|
|
|
28
29
|
root
|
|
29
30
|
.find(j.CallExpression)
|
|
30
31
|
.filter((path) => {
|
|
31
|
-
var _a, _b;
|
|
32
32
|
const { node } = path;
|
|
33
33
|
let found = false;
|
|
34
34
|
if (defaultReactDomImport &&
|
|
@@ -43,7 +43,7 @@ function transformer(file, api, options) {
|
|
|
43
43
|
if (found) {
|
|
44
44
|
foundReactRender++;
|
|
45
45
|
hasModifications = true;
|
|
46
|
-
if (!Array.isArray(
|
|
46
|
+
if (!Array.isArray(path.parentPath?.parentPath?.value)) {
|
|
47
47
|
exports.indexContext.nestedRender = true;
|
|
48
48
|
return false;
|
|
49
49
|
}
|
|
@@ -73,5 +73,4 @@ function transformer(file, api, options) {
|
|
|
73
73
|
// }).remove()
|
|
74
74
|
return hasModifications ? root.toSource(options) : null;
|
|
75
75
|
}
|
|
76
|
-
exports.default = transformer;
|
|
77
76
|
//# sourceMappingURL=index-to-component.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getPkgManager = getPkgManager;
|
|
7
|
+
exports.uninstallPackage = uninstallPackage;
|
|
8
|
+
exports.installPackages = installPackages;
|
|
9
|
+
const find_up_1 = __importDefault(require("find-up"));
|
|
10
|
+
const execa_1 = __importDefault(require("execa"));
|
|
11
|
+
const node_path_1 = require("node:path");
|
|
12
|
+
function getPkgManager(baseDir) {
|
|
13
|
+
try {
|
|
14
|
+
const lockFile = find_up_1.default.sync(['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml', 'bun.lockb'], { cwd: baseDir });
|
|
15
|
+
if (lockFile) {
|
|
16
|
+
switch ((0, node_path_1.basename)(lockFile)) {
|
|
17
|
+
case 'package-lock.json':
|
|
18
|
+
return 'npm';
|
|
19
|
+
case 'yarn.lock':
|
|
20
|
+
return 'yarn';
|
|
21
|
+
case 'pnpm-lock.yaml':
|
|
22
|
+
return 'pnpm';
|
|
23
|
+
case 'bun.lockb':
|
|
24
|
+
return 'bun';
|
|
25
|
+
default:
|
|
26
|
+
return 'npm';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return 'npm';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function uninstallPackage(packageToUninstall, pkgManager) {
|
|
35
|
+
pkgManager ??= getPkgManager(process.cwd());
|
|
36
|
+
if (!pkgManager)
|
|
37
|
+
throw new Error('Failed to find package manager');
|
|
38
|
+
let command = 'uninstall';
|
|
39
|
+
if (pkgManager === 'yarn') {
|
|
40
|
+
command = 'remove';
|
|
41
|
+
}
|
|
42
|
+
execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
|
|
43
|
+
}
|
|
44
|
+
function installPackages(packageToInstall, options = {}) {
|
|
45
|
+
const { packageManager = getPkgManager(process.cwd()), silent = false } = options;
|
|
46
|
+
if (!packageManager)
|
|
47
|
+
throw new Error('Failed to find package manager');
|
|
48
|
+
try {
|
|
49
|
+
execa_1.default.sync(packageManager, ['add', ...packageToInstall], {
|
|
50
|
+
// Keeping stderr since it'll likely be relevant later when it fails.
|
|
51
|
+
stdio: silent ? ['ignore', 'ignore', 'inherit'] : 'inherit',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw new Error(`Failed to install "${packageToInstall}". Please install it manually.`, { cause: error });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=handle-package.js.map
|
package/lib/install.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.install =
|
|
6
|
+
exports.install = install;
|
|
7
7
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
8
8
|
const picocolors_1 = require("picocolors");
|
|
9
9
|
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
@@ -84,7 +84,7 @@ function install(root, dependencies, { useYarn, isOnline, devDependencies }) {
|
|
|
84
84
|
*/
|
|
85
85
|
const child = (0, cross_spawn_1.default)(command, args, {
|
|
86
86
|
stdio: 'inherit',
|
|
87
|
-
env:
|
|
87
|
+
env: { ...process.env, ADBLOCK: '1', DISABLE_OPENCOLLECTIVE: '1' },
|
|
88
88
|
});
|
|
89
89
|
child.on('close', (code) => {
|
|
90
90
|
if (code !== 0) {
|
|
@@ -95,5 +95,4 @@ function install(root, dependencies, { useYarn, isOnline, devDependencies }) {
|
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
|
-
exports.install = install;
|
|
99
98
|
//# sourceMappingURL=install.js.map
|
package/lib/run-jscodeshift.js
CHANGED
|
@@ -3,12 +3,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = runJscodeshift;
|
|
6
7
|
// @ts-ignore internal module
|
|
7
8
|
const Runner_1 = __importDefault(require("jscodeshift/src/Runner"));
|
|
8
9
|
function runJscodeshift(transformerPath, flags, files) {
|
|
9
10
|
// we run jscodeshift in the same process to be able to
|
|
10
11
|
// share state between the main CRA transform and sub-transforms
|
|
11
|
-
return Runner_1.default.run(transformerPath, files,
|
|
12
|
+
return Runner_1.default.run(transformerPath, files, {
|
|
13
|
+
ignorePattern: [
|
|
14
|
+
'**/node_modules/**',
|
|
15
|
+
'**/.next/**',
|
|
16
|
+
'**/build/**',
|
|
17
|
+
// type files
|
|
18
|
+
'**/*.d.ts',
|
|
19
|
+
'**/*.d.cts',
|
|
20
|
+
'**/*.d.mts',
|
|
21
|
+
// test files
|
|
22
|
+
'**/*.test.*',
|
|
23
|
+
'**/*.spec.*',
|
|
24
|
+
'**/__tests__/**',
|
|
25
|
+
'**/__mocks__/**',
|
|
26
|
+
],
|
|
27
|
+
extensions: 'tsx,ts,jsx,js',
|
|
28
|
+
parser: 'tsx',
|
|
29
|
+
verbose: 2,
|
|
30
|
+
runInBand: true,
|
|
31
|
+
...flags,
|
|
32
|
+
});
|
|
12
33
|
}
|
|
13
|
-
exports.default = runJscodeshift;
|
|
14
34
|
//# sourceMappingURL=run-jscodeshift.js.map
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TRANSFORMER_INQUIRER_CHOICES = void 0;
|
|
7
|
+
exports.checkGitStatus = checkGitStatus;
|
|
8
|
+
exports.onCancel = onCancel;
|
|
9
|
+
const picocolors_1 = require("picocolors");
|
|
10
|
+
const is_git_clean_1 = __importDefault(require("is-git-clean"));
|
|
11
|
+
function checkGitStatus(force) {
|
|
12
|
+
let clean = false;
|
|
13
|
+
let errorMessage = 'Unable to determine if git directory is clean';
|
|
14
|
+
try {
|
|
15
|
+
clean = is_git_clean_1.default.sync(process.cwd());
|
|
16
|
+
errorMessage = 'Git directory is not clean';
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err && err.stderr && err.stderr.includes('Not a git repository')) {
|
|
20
|
+
clean = true;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (!clean) {
|
|
24
|
+
if (force) {
|
|
25
|
+
console.log(`WARNING: ${errorMessage}. Forcibly continuing.`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log('Thank you for using @next/codemod!');
|
|
29
|
+
console.log((0, picocolors_1.yellow)('\nBut before we continue, please stash or commit your git changes.'));
|
|
30
|
+
console.log('\nYou may use the --force flag to override this safety check.');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function onCancel() {
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
exports.TRANSFORMER_INQUIRER_CHOICES = [
|
|
39
|
+
{
|
|
40
|
+
title: 'Transform the deprecated automatically injected url property on top level pages to using withRouter',
|
|
41
|
+
value: 'url-to-withrouter',
|
|
42
|
+
version: '6.0',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
title: 'Transforms the withAmp HOC into Next.js 9 page configuration',
|
|
46
|
+
value: 'withamp-to-config',
|
|
47
|
+
version: '8.0',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
title: 'Transforms anonymous components into named components to make sure they work with Fast Refresh',
|
|
51
|
+
value: 'name-default-component',
|
|
52
|
+
version: '9.0',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
title: 'Transforms files that do not import `React` to include the import in order for the new React JSX transform',
|
|
56
|
+
value: 'add-missing-react-import',
|
|
57
|
+
version: '10.0',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: 'Automatically migrates a Create React App project to Next.js (experimental)',
|
|
61
|
+
value: 'cra-to-next',
|
|
62
|
+
version: '11.0',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
title: 'Ensures your <Link> usage is backwards compatible',
|
|
66
|
+
value: 'new-link',
|
|
67
|
+
version: '13.0',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
title: 'Dangerously migrates from `next/legacy/image` to the new `next/image` by adding inline styles and removing unused props (experimental)',
|
|
71
|
+
value: 'next-image-experimental',
|
|
72
|
+
version: '13.0',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
title: 'Safely migrate Next.js 10, 11, 12 applications importing `next/image` to the renamed `next/legacy/image` import in Next.js 13',
|
|
76
|
+
value: 'next-image-to-legacy-image',
|
|
77
|
+
version: '13.0',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
title: 'Uninstall `@next/font` and transform imports to `next/font`',
|
|
81
|
+
value: 'built-in-next-font',
|
|
82
|
+
version: '13.2',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
title: 'Migrates certain viewport related metadata from the `metadata` export to a new `viewport` export',
|
|
86
|
+
value: 'metadata-to-viewport-export',
|
|
87
|
+
version: '14.0',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
title: 'Transforms imports from `next/server` to `next/og` for usage of Dynamic OG Image Generation',
|
|
91
|
+
value: 'next-og-import',
|
|
92
|
+
version: '14.0',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
title: 'Transform `next/dynamic` imports accessing named exports to return an object with a `default` property',
|
|
96
|
+
value: 'next-dynamic-access-named-export',
|
|
97
|
+
version: '15.0.0-canary.44',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
title: 'Install `@vercel/functions` to replace `geo` and `ip` properties on `NextRequest`',
|
|
101
|
+
value: 'next-request-geo-ip',
|
|
102
|
+
version: '15.0.0-canary.153',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
title: 'Transforms usage of Next.js async Request APIs',
|
|
106
|
+
value: 'next-async-request-api',
|
|
107
|
+
version: '15.0.0-canary.171',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
title: 'Transform App Router Route Segment Config `runtime` value from `experimental-edge` to `edge`',
|
|
111
|
+
value: 'app-dir-runtime-config-experimental-edge',
|
|
112
|
+
version: '15.0.0-canary.179',
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@next/codemod",
|
|
3
|
-
"version": "15.0.0-canary.
|
|
3
|
+
"version": "15.0.0-canary.182",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,16 +9,19 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"cheerio": "1.0.0-rc.9",
|
|
12
|
+
"commander": "12.1.0",
|
|
13
|
+
"compare-versions": "6.1.1",
|
|
12
14
|
"execa": "4.0.3",
|
|
15
|
+
"find-up": "4.1.0",
|
|
13
16
|
"globby": "11.0.1",
|
|
14
|
-
"inquirer": "7.3.3",
|
|
15
17
|
"is-git-clean": "1.1.0",
|
|
16
|
-
"jscodeshift": "0.
|
|
17
|
-
"
|
|
18
|
-
"
|
|
18
|
+
"jscodeshift": "17.0.0",
|
|
19
|
+
"picocolors": "1.0.0",
|
|
20
|
+
"prompts": "2.4.2"
|
|
19
21
|
},
|
|
20
22
|
"files": [
|
|
21
23
|
"transforms/*.js",
|
|
24
|
+
"transforms/lib/**/*.js",
|
|
22
25
|
"bin/*.js",
|
|
23
26
|
"lib/**/*.js",
|
|
24
27
|
"lib/cra-to-next/gitignore"
|
|
@@ -31,6 +34,8 @@
|
|
|
31
34
|
},
|
|
32
35
|
"bin": "./bin/next-codemod.js",
|
|
33
36
|
"devDependencies": {
|
|
34
|
-
"@types/
|
|
37
|
+
"@types/find-up": "4.0.0",
|
|
38
|
+
"@types/jscodeshift": "0.11.0",
|
|
39
|
+
"@types/prompts": "2.4.2"
|
|
35
40
|
}
|
|
36
41
|
}
|