@next/codemod 15.0.0-canary.182 → 15.0.0-canary.183
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
CHANGED
|
@@ -23,10 +23,18 @@ const program = new commander_1.Command(packageJson.name)
|
|
|
23
23
|
.helpOption('-h, --help', 'Display this help message.')
|
|
24
24
|
.option('-f, --force', 'Bypass Git safety checks and forcibly run codemods')
|
|
25
25
|
.option('-d, --dry', 'Dry run (no changes are made to files)')
|
|
26
|
-
.option('-p, --print', 'Print transformed files to
|
|
26
|
+
.option('-p, --print', 'Print transformed files to stdout, useful for development')
|
|
27
|
+
.option('--verbose', 'Show more information about the transform process')
|
|
27
28
|
.option('-j, --jscodeshift', '(Advanced) Pass options directly to jscodeshift')
|
|
28
29
|
.action(transform_1.runTransform)
|
|
29
|
-
.allowUnknownOption()
|
|
30
|
+
.allowUnknownOption()
|
|
31
|
+
// This is needed for options for subcommands to be passed correctly.
|
|
32
|
+
// Because by default the options are not positional, which will pass options
|
|
33
|
+
// to the main command "@next/codemod" even if it was passed after subcommands,
|
|
34
|
+
// e.g. "@next/codemod upgrade --verbose" will be treated as "next-codemod --verbose upgrade"
|
|
35
|
+
// By enabling this, it will respect the position of the options and pass it to subcommands.
|
|
36
|
+
// x-ref: https://github.com/tj/commander.js/pull/1427
|
|
37
|
+
.enablePositionalOptions();
|
|
30
38
|
program
|
|
31
39
|
.command('upgrade')
|
|
32
40
|
.description('Upgrade Next.js apps to desired versions with a single command.')
|
package/bin/transform.js
CHANGED
|
@@ -66,7 +66,7 @@ async function runTransform(transform, path, options) {
|
|
|
66
66
|
return require(transformerPath).default(filesExpanded, options);
|
|
67
67
|
}
|
|
68
68
|
let args = [];
|
|
69
|
-
const { dry, print, runInBand, jscodeshift } = options;
|
|
69
|
+
const { dry, print, runInBand, jscodeshift, verbose } = options;
|
|
70
70
|
if (dry) {
|
|
71
71
|
args.push('--dry');
|
|
72
72
|
}
|
|
@@ -76,7 +76,10 @@ async function runTransform(transform, path, options) {
|
|
|
76
76
|
if (runInBand) {
|
|
77
77
|
args.push('--run-in-band');
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
if (verbose) {
|
|
80
|
+
args.push('--verbose=2');
|
|
81
|
+
}
|
|
82
|
+
args.push('--no-babel');
|
|
80
83
|
args.push('--ignore-pattern=**/node_modules/**');
|
|
81
84
|
args.push('--ignore-pattern=**/.next/**');
|
|
82
85
|
args.push('--extensions=tsx,ts,jsx,js');
|
|
@@ -94,17 +97,28 @@ async function runTransform(transform, path, options) {
|
|
|
94
97
|
throw new Error(`jscodeshift exited with code ${result.exitCode}`);
|
|
95
98
|
}
|
|
96
99
|
if (!dry && transformer === 'built-in-next-font') {
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
const { uninstallNextFont } = await (0, prompts_1.default)({
|
|
101
|
+
type: 'confirm',
|
|
102
|
+
name: 'uninstallNextFont',
|
|
103
|
+
message: 'Do you want to uninstall `@next/font`?',
|
|
104
|
+
initial: true,
|
|
105
|
+
});
|
|
106
|
+
if (uninstallNextFont) {
|
|
107
|
+
console.log('Uninstalling `@next/font`');
|
|
99
108
|
(0, handle_package_1.uninstallPackage)('@next/font');
|
|
100
109
|
}
|
|
101
|
-
catch {
|
|
102
|
-
console.error("Couldn't uninstall `@next/font`, please uninstall it manually");
|
|
103
|
-
}
|
|
104
110
|
}
|
|
105
111
|
if (!dry && transformer === 'next-request-geo-ip') {
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
const { installVercelFunctions } = await (0, prompts_1.default)({
|
|
113
|
+
type: 'confirm',
|
|
114
|
+
name: 'installVercelFunctions',
|
|
115
|
+
message: 'Do you want to install `@vercel/functions`?',
|
|
116
|
+
initial: true,
|
|
117
|
+
});
|
|
118
|
+
if (installVercelFunctions) {
|
|
119
|
+
console.log('Installing `@vercel/functions`...');
|
|
120
|
+
(0, handle_package_1.installPackages)(['@vercel/functions']);
|
|
121
|
+
}
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
124
|
//# sourceMappingURL=transform.js.map
|
package/bin/upgrade.js
CHANGED
|
@@ -90,7 +90,7 @@ async function runUpgrade(revision, options) {
|
|
|
90
90
|
silent: !verbose,
|
|
91
91
|
});
|
|
92
92
|
for (const codemod of codemods) {
|
|
93
|
-
await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true });
|
|
93
|
+
await (0, transform_1.runTransform)(codemod, process.cwd(), { force: true, verbose });
|
|
94
94
|
}
|
|
95
95
|
console.log(); // new line
|
|
96
96
|
if (codemods.length > 0) {
|
package/lib/handle-package.js
CHANGED
|
@@ -39,7 +39,12 @@ function uninstallPackage(packageToUninstall, pkgManager) {
|
|
|
39
39
|
if (pkgManager === 'yarn') {
|
|
40
40
|
command = 'remove';
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
try {
|
|
43
|
+
execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw new Error(`Failed to uninstall "${packageToUninstall}". Please uninstall it manually.`, { cause: error });
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
function installPackages(packageToInstall, options = {}) {
|
|
45
50
|
const { packageManager = getPkgManager(process.cwd()), silent = false } = options;
|
package/lib/utils.js
CHANGED
|
@@ -76,6 +76,11 @@ exports.TRANSFORMER_INQUIRER_CHOICES = [
|
|
|
76
76
|
value: 'next-image-to-legacy-image',
|
|
77
77
|
version: '13.0',
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
title: 'Transform App Router Route Segment Config `runtime` value from `experimental-edge` to `edge`',
|
|
81
|
+
value: 'app-dir-runtime-config-experimental-edge',
|
|
82
|
+
version: '13.1.2',
|
|
83
|
+
},
|
|
79
84
|
{
|
|
80
85
|
title: 'Uninstall `@next/font` and transform imports to `next/font`',
|
|
81
86
|
value: 'built-in-next-font',
|
|
@@ -106,10 +111,5 @@ exports.TRANSFORMER_INQUIRER_CHOICES = [
|
|
|
106
111
|
value: 'next-async-request-api',
|
|
107
112
|
version: '15.0.0-canary.171',
|
|
108
113
|
},
|
|
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
114
|
];
|
|
115
115
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -23,6 +23,12 @@ function awaitMemberAccessOfProp(propIdName, path, j) {
|
|
|
23
23
|
// await each member access
|
|
24
24
|
memberAccess.forEach((memberAccessPath) => {
|
|
25
25
|
const member = memberAccessPath.value;
|
|
26
|
+
const memberProperty = member.property;
|
|
27
|
+
const isAccessingMatchedProperty = j.Identifier.check(memberProperty) &&
|
|
28
|
+
utils_1.TARGET_PROP_NAMES.has(memberProperty.name);
|
|
29
|
+
if (!isAccessingMatchedProperty) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
26
32
|
if (isParentPromiseAllCallExpression(memberAccessPath, j)) {
|
|
27
33
|
return;
|
|
28
34
|
}
|
|
@@ -494,20 +500,42 @@ function transformDynamicProps(source, api, filePath) {
|
|
|
494
500
|
continue;
|
|
495
501
|
}
|
|
496
502
|
}
|
|
497
|
-
const
|
|
503
|
+
const paramsPropertyName = j.Identifier.check(paramsProperty)
|
|
498
504
|
? paramsProperty.name
|
|
499
505
|
: null;
|
|
500
|
-
const
|
|
506
|
+
const paramPropertyName = paramsPropertyName || matchedPropName;
|
|
501
507
|
// if propName is not used in lower scope, and it stars with unused prefix `_`,
|
|
502
508
|
// also skip the transformation
|
|
503
509
|
const functionBodyPath = path.get('body');
|
|
504
510
|
const hasUsedInBody = j(functionBodyPath)
|
|
505
511
|
.find(j.Identifier, {
|
|
506
|
-
name:
|
|
512
|
+
name: paramPropertyName,
|
|
507
513
|
})
|
|
508
514
|
.size() > 0;
|
|
509
|
-
if (!hasUsedInBody &&
|
|
515
|
+
if (!hasUsedInBody && paramPropertyName.startsWith('_'))
|
|
510
516
|
continue;
|
|
517
|
+
// Search the usage of propName in the function body,
|
|
518
|
+
// if they're all awaited or wrapped with use(), skip the transformation
|
|
519
|
+
const propUsages = j(functionBodyPath).find(j.Identifier, {
|
|
520
|
+
name: paramPropertyName,
|
|
521
|
+
});
|
|
522
|
+
// if there's usage of the propName, then do the check
|
|
523
|
+
if (propUsages.size()) {
|
|
524
|
+
let hasMissingAwaited = false;
|
|
525
|
+
propUsages.forEach((propUsage) => {
|
|
526
|
+
// If the parent is not AwaitExpression, it's not awaited
|
|
527
|
+
const isAwaited = propUsage.parentPath?.value.type === 'AwaitExpression';
|
|
528
|
+
const isAwaitedByUse = isParentUseCallExpression(propUsage, j);
|
|
529
|
+
if (!isAwaited && !isAwaitedByUse) {
|
|
530
|
+
hasMissingAwaited = true;
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
// If all the usages of parm are awaited, skip the transformation
|
|
535
|
+
if (!hasMissingAwaited) {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
511
539
|
modifiedPropertyCount++;
|
|
512
540
|
const propNameIdentifier = j.identifier(matchedPropName);
|
|
513
541
|
const propsIdentifier = j.identifier(propsIdentifierName);
|
|
@@ -516,7 +544,7 @@ function transformDynamicProps(source, api, filePath) {
|
|
|
516
544
|
// e.g.
|
|
517
545
|
// input: Page({ params: { slug } })
|
|
518
546
|
// output: const { slug } = await props.params; rather than const props = await props.params;
|
|
519
|
-
const uid = functionName + ':' +
|
|
547
|
+
const uid = functionName + ':' + paramPropertyName;
|
|
520
548
|
if (paramsProperty?.type === 'ObjectPattern') {
|
|
521
549
|
const objectPattern = paramsProperty;
|
|
522
550
|
const objectPatternProperties = objectPattern.properties;
|
|
@@ -538,7 +566,7 @@ function transformDynamicProps(source, api, filePath) {
|
|
|
538
566
|
if (isAsyncFunc) {
|
|
539
567
|
// If it's async function, add await to the async props.<propName>
|
|
540
568
|
const paramAssignment = j.variableDeclaration('const', [
|
|
541
|
-
j.variableDeclarator(j.identifier(
|
|
569
|
+
j.variableDeclarator(j.identifier(paramPropertyName), j.awaitExpression(accessedPropIdExpr)),
|
|
542
570
|
]);
|
|
543
571
|
if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
|
|
544
572
|
functionBody.unshift(paramAssignment);
|
|
@@ -556,7 +584,7 @@ function transformDynamicProps(source, api, filePath) {
|
|
|
556
584
|
(0, utils_1.turnFunctionReturnTypeToAsync)(node, j);
|
|
557
585
|
// Insert `const <propName> = await props.<propName>;` at the beginning of the function body
|
|
558
586
|
const paramAssignment = j.variableDeclaration('const', [
|
|
559
|
-
j.variableDeclarator(j.identifier(
|
|
587
|
+
j.variableDeclarator(j.identifier(paramPropertyName), j.awaitExpression(accessedPropIdExpr)),
|
|
560
588
|
]);
|
|
561
589
|
if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
|
|
562
590
|
functionBody.unshift(paramAssignment);
|
|
@@ -566,7 +594,7 @@ function transformDynamicProps(source, api, filePath) {
|
|
|
566
594
|
}
|
|
567
595
|
else {
|
|
568
596
|
const paramAssignment = j.variableDeclaration('const', [
|
|
569
|
-
j.variableDeclarator(j.identifier(
|
|
597
|
+
j.variableDeclarator(j.identifier(paramPropertyName), j.callExpression(j.identifier('use'), [accessedPropIdExpr])),
|
|
570
598
|
]);
|
|
571
599
|
if (!insertedRenamedPropFunctionNames.has(uid) && functionBody) {
|
|
572
600
|
needsReactUseImport = true;
|