@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.
@@ -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 your terminal')
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
- args.push('--verbose=2');
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
- console.log('Uninstalling `@next/font`');
98
- try {
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
- console.log('Installing `@vercel/functions`...');
107
- (0, handle_package_1.installPackages)(['@vercel/functions']);
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) {
@@ -39,7 +39,12 @@ function uninstallPackage(packageToUninstall, pkgManager) {
39
39
  if (pkgManager === 'yarn') {
40
40
  command = 'remove';
41
41
  }
42
- execa_1.default.sync(pkgManager, [command, packageToUninstall], { stdio: 'inherit' });
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next/codemod",
3
- "version": "15.0.0-canary.182",
3
+ "version": "15.0.0-canary.183",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -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 propRenamedId = j.Identifier.check(paramsProperty)
503
+ const paramsPropertyName = j.Identifier.check(paramsProperty)
498
504
  ? paramsProperty.name
499
505
  : null;
500
- const propName = propRenamedId || matchedPropName;
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: propName,
512
+ name: paramPropertyName,
507
513
  })
508
514
  .size() > 0;
509
- if (!hasUsedInBody && propName.startsWith('_'))
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 + ':' + propName;
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(propName), j.awaitExpression(accessedPropIdExpr)),
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(propName), j.awaitExpression(accessedPropIdExpr)),
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(propName), j.callExpression(j.identifier('use'), [accessedPropIdExpr])),
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;