@next/codemod 16.1.0-canary.3 → 16.1.0-canary.30

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.
@@ -39,15 +39,7 @@ const program = new commander_1.Command(packageJson.name)
39
39
  program
40
40
  .command('upgrade')
41
41
  .description('Upgrade Next.js apps to desired versions with a single command.')
42
- // The CLI interface must be backwards compatible at all times so that older
43
- // versions of Next.js can still run the codemod successfully.
44
- .argument('[revision]', 'Specify the target Next.js version using an NPM dist tag (e.g. "latest", "canary", "rc", "beta") or an exact version number (e.g. "15.0.0").', packageJson.version.includes('-canary.')
45
- ? 'canary'
46
- : packageJson.version.includes('-rc.')
47
- ? 'rc'
48
- : packageJson.version.includes('-beta.')
49
- ? 'beta'
50
- : 'latest')
42
+ .argument('[revision]', 'Specify the upgrade type ("patch", "minor", "major"), an NPM dist tag (e.g. "latest", "canary", "rc"), or an exact version (e.g. "15.0.0"). Defaults to "minor".')
51
43
  .usage('[revision] [options]')
52
44
  .option('--verbose', 'Verbose output', false)
53
45
  .action(async (revision, options) => {
package/bin/upgrade.js CHANGED
@@ -90,24 +90,70 @@ function endMessage(targetNextVersion) {
90
90
  }
91
91
  }
92
92
  const cwd = process.cwd();
93
+ /**
94
+ * Resolves semantic version keywords (patch, minor, major) to npm version queries.
95
+ * - patch: latest patch within current minor (e.g., 15.0.x -> 15.0.y)
96
+ * - minor: latest minor within current major (e.g., 15.0.x -> 15.1.x)
97
+ * - major: latest stable version (equivalent to "latest")
98
+ */
99
+ function resolveSemanticRevision(revision, installedVersion) {
100
+ const installedMajor = (0, semver_1.major)(installedVersion);
101
+ const installedMinor = (0, semver_1.minor)(installedVersion);
102
+ switch (revision) {
103
+ case 'patch':
104
+ // ~15.0.0 matches >=15.0.0 <15.1.0
105
+ return `~${installedMajor}.${installedMinor}.0`;
106
+ case 'minor':
107
+ // ^15.0.0 matches >=15.0.0 <16.0.0
108
+ return `^${installedMajor}.0.0`;
109
+ case 'major':
110
+ return 'latest';
111
+ default:
112
+ return revision;
113
+ }
114
+ }
93
115
  async function runUpgrade(revision, options) {
94
116
  const { verbose } = options;
95
117
  const appPackageJsonPath = path_1.default.resolve(cwd, 'package.json');
96
118
  let appPackageJson = JSON.parse(fs_1.default.readFileSync(appPackageJsonPath, 'utf8'));
119
+ const installedNextVersion = getInstalledNextVersion();
120
+ // Resolve semantic keywords to npm version queries
121
+ const resolvedRevision = resolveSemanticRevision(revision ?? 'minor', installedNextVersion);
122
+ if (options.verbose) {
123
+ console.log(` Resolved upgrade target: ${resolvedRevision}`);
124
+ }
97
125
  let targetNextPackageJson;
98
126
  try {
99
- const targetNextPackage = (0, child_process_1.execSync)(`npm --silent view "next@${revision}" --json`, { encoding: 'utf-8' });
127
+ // First, find the highest matching version
128
+ const versionsJSON = (0, child_process_1.execSync)(`npm --silent view "next@${resolvedRevision}" --json --field version`, { encoding: 'utf-8' });
129
+ const versionOrVersions = JSON.parse(versionsJSON);
130
+ let targetVersion;
131
+ if (Array.isArray(versionOrVersions)) {
132
+ versionOrVersions.sort(semver_1.compare);
133
+ targetVersion = versionOrVersions[versionOrVersions.length - 1];
134
+ }
135
+ else {
136
+ targetVersion = versionOrVersions;
137
+ }
138
+ if (options.verbose) {
139
+ console.log(` Target version: ${targetVersion}`);
140
+ }
141
+ // Then fetch the full package info for that specific version
142
+ const targetNextPackage = (0, child_process_1.execSync)(`npm --silent view "next@${targetVersion}" --json`, { encoding: 'utf-8' });
100
143
  targetNextPackageJson = JSON.parse(targetNextPackage);
101
144
  }
102
- catch { }
145
+ catch (e) {
146
+ if (options.verbose) {
147
+ console.error(' Error fetching package info:', e);
148
+ }
149
+ }
103
150
  const validRevision = targetNextPackageJson !== null &&
104
151
  typeof targetNextPackageJson === 'object' &&
105
152
  'version' in targetNextPackageJson &&
106
153
  'peerDependencies' in targetNextPackageJson;
107
154
  if (!validRevision) {
108
- throw new shared_1.BadInput(`Invalid revision provided: "${revision}". Please provide a valid Next.js version or dist-tag (e.g. "latest", "canary", "beta", "rc", or "15.0.0").\nCheck available versions at https://www.npmjs.com/package/next?activeTab=versions.`);
155
+ throw new shared_1.BadInput(`Invalid revision provided: "${revision ?? 'minor'}" (resolved to "${resolvedRevision}"). Please provide a valid Next.js version, dist-tag (e.g. "latest", "canary", "rc"), or upgrade type ("patch", "minor", "major").\nCheck available versions at https://www.npmjs.com/package/next?activeTab=versions.`);
109
156
  }
110
- const installedNextVersion = getInstalledNextVersion();
111
157
  const targetNextVersion = targetNextPackageJson.version;
112
158
  if ((0, semver_1.compare)(installedNextVersion, targetNextVersion) === 0) {
113
159
  console.log(`${picocolors_1.default.green('✓')} Current Next.js version is already on the target version "v${targetNextVersion}".`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next/codemod",
3
- "version": "16.1.0-canary.3",
3
+ "version": "16.1.0-canary.30",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",