@payloadcms/codemod 4.0.0-internal.167c7cd → 4.0.0-internal.2f0d313
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/README.md +34 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +22 -27
- package/dist/cli.js.map +1 -1
- package/dist/cli.parseFlags.d.ts +5 -0
- package/dist/cli.parseFlags.d.ts.map +1 -1
- package/dist/cli.parseFlags.js +20 -1
- package/dist/cli.parseFlags.js.map +1 -1
- package/dist/cli.parseFlags.spec.js +72 -0
- package/dist/cli.parseFlags.spec.js.map +1 -1
- package/dist/runbook/payload-v4-upgrade.md +55 -0
- package/dist/runbook/v4.mdx +1652 -0
- package/dist/upgrade/detectPackageManager.d.ts +8 -0
- package/dist/upgrade/detectPackageManager.d.ts.map +1 -0
- package/dist/upgrade/detectPackageManager.js +38 -0
- package/dist/upgrade/detectPackageManager.js.map +1 -0
- package/dist/upgrade/detectPackageManager.spec.d.ts +2 -0
- package/dist/upgrade/detectPackageManager.spec.d.ts.map +1 -0
- package/dist/upgrade/detectPackageManager.spec.js +41 -0
- package/dist/upgrade/detectPackageManager.spec.js.map +1 -0
- package/dist/upgrade/index.d.ts +24 -0
- package/dist/upgrade/index.d.ts.map +1 -0
- package/dist/upgrade/index.js +184 -0
- package/dist/upgrade/index.js.map +1 -0
- package/dist/upgrade/index.spec.d.ts +2 -0
- package/dist/upgrade/index.spec.d.ts.map +1 -0
- package/dist/upgrade/index.spec.js +132 -0
- package/dist/upgrade/index.spec.js.map +1 -0
- package/dist/upgrade/packaging.spec.d.ts +2 -0
- package/dist/upgrade/packaging.spec.d.ts.map +1 -0
- package/dist/upgrade/packaging.spec.js +29 -0
- package/dist/upgrade/packaging.spec.js.map +1 -0
- package/dist/upgrade/prompt.d.ts +11 -0
- package/dist/upgrade/prompt.d.ts.map +1 -0
- package/dist/upgrade/prompt.js +75 -0
- package/dist/upgrade/prompt.js.map +1 -0
- package/dist/upgrade/prompt.spec.d.ts +2 -0
- package/dist/upgrade/prompt.spec.d.ts.map +1 -0
- package/dist/upgrade/prompt.spec.js +51 -0
- package/dist/upgrade/prompt.spec.js.map +1 -0
- package/dist/upgrade/report.d.ts +18 -0
- package/dist/upgrade/report.d.ts.map +1 -0
- package/dist/upgrade/report.js +41 -0
- package/dist/upgrade/report.js.map +1 -0
- package/dist/upgrade/report.spec.d.ts +2 -0
- package/dist/upgrade/report.spec.d.ts.map +1 -0
- package/dist/upgrade/report.spec.js +87 -0
- package/dist/upgrade/report.spec.js.map +1 -0
- package/dist/upgrade/resolveVersions.d.ts +13 -0
- package/dist/upgrade/resolveVersions.d.ts.map +1 -0
- package/dist/upgrade/resolveVersions.js +55 -0
- package/dist/upgrade/resolveVersions.js.map +1 -0
- package/dist/upgrade/resolveVersions.spec.d.ts +2 -0
- package/dist/upgrade/resolveVersions.spec.d.ts.map +1 -0
- package/dist/upgrade/resolveVersions.spec.js +82 -0
- package/dist/upgrade/resolveVersions.spec.js.map +1 -0
- package/dist/upgrade/rewritePackageJson.d.ts +25 -0
- package/dist/upgrade/rewritePackageJson.d.ts.map +1 -0
- package/dist/upgrade/rewritePackageJson.js +106 -0
- package/dist/upgrade/rewritePackageJson.js.map +1 -0
- package/dist/upgrade/rewritePackageJson.spec.d.ts +2 -0
- package/dist/upgrade/rewritePackageJson.spec.d.ts.map +1 -0
- package/dist/upgrade/rewritePackageJson.spec.js +108 -0
- package/dist/upgrade/rewritePackageJson.spec.js.map +1 -0
- package/dist/upgrade/runInstall.d.ts +16 -0
- package/dist/upgrade/runInstall.d.ts.map +1 -0
- package/dist/upgrade/runInstall.js +17 -0
- package/dist/upgrade/runInstall.js.map +1 -0
- package/dist/upgrade/runInstall.spec.d.ts +2 -0
- package/dist/upgrade/runInstall.spec.d.ts.map +1 -0
- package/dist/upgrade/runInstall.spec.js +48 -0
- package/dist/upgrade/runInstall.spec.js.map +1 -0
- package/dist/upgrade/types.d.ts +42 -0
- package/dist/upgrade/types.d.ts.map +1 -0
- package/dist/upgrade/types.js +7 -0
- package/dist/upgrade/types.js.map +1 -0
- package/dist/utils/project.d.ts +4 -0
- package/dist/utils/project.d.ts.map +1 -0
- package/dist/utils/project.js +30 -0
- package/dist/utils/project.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -19,6 +19,40 @@ With no arguments, runs every registered transform against the current directory
|
|
|
19
19
|
- `--dry` — analyze only; write nothing.
|
|
20
20
|
- `--print` — print transformed sources to stdout instead of writing.
|
|
21
21
|
|
|
22
|
+
## `upgrade` command
|
|
23
|
+
|
|
24
|
+
`npx @payloadcms/codemod upgrade [path]` performs the mechanical v3 -> v4 slice:
|
|
25
|
+
|
|
26
|
+
1. Resolves the current Payload canary from the npm registry (override with `--tag <dist-tag>`).
|
|
27
|
+
2. Rewrites `package.json`: pins `payload` + every `@payloadcms/*` to that exact version in
|
|
28
|
+
lockstep, removes dependency overrides pinning them, converts their carets to exact, and writes
|
|
29
|
+
the TypeScript / `@types/node` / `engines.node` floors. The `@payloadcms/eslint-*` packages are
|
|
30
|
+
versioned independently, so they are set to `latest` rather than lockstep-pinned.
|
|
31
|
+
3. Installs with your detected package manager.
|
|
32
|
+
4. Runs every registered transform against the now-v4 tree.
|
|
33
|
+
5. Prints a report and points you at the bundled runbook for the rest.
|
|
34
|
+
|
|
35
|
+
It does NOT upgrade Next.js. Payload v4 requires Next 16; run Next's own recommended agent
|
|
36
|
+
workflow (linked from the bundled runbook) to bump Next and migrate the code together. The report
|
|
37
|
+
prints the required Next target.
|
|
38
|
+
|
|
39
|
+
### `upgrade` flags
|
|
40
|
+
|
|
41
|
+
- `--tag <dist-tag>` — dist-tag to resolve Payload versions from (default `canary`).
|
|
42
|
+
- `--dry` — preview the `package.json` changes and planned steps; write and install nothing.
|
|
43
|
+
- `--force` — skip the dirty-git-tree warning.
|
|
44
|
+
|
|
45
|
+
### `upgrade prompt`
|
|
46
|
+
|
|
47
|
+
`npx @payloadcms/codemod upgrade prompt` prints an orchestration prompt for a coding agent to run
|
|
48
|
+
the full v3 -> v4 upgrade, Next.js 16 included. It is offline and stateless: it writes nothing and
|
|
49
|
+
makes no network calls. The text is project-agnostic, so pipe it to your agent and run it from the
|
|
50
|
+
project root.
|
|
51
|
+
|
|
52
|
+
The prompt sequences the upgrade (mechanical slice via this command, then Next.js via Next's own
|
|
53
|
+
codemods and agent workflow, then regeneration, judgment work, and verification) and points at the
|
|
54
|
+
bundled runbook and migration guide for detail rather than restating them.
|
|
55
|
+
|
|
22
56
|
## How it works
|
|
23
57
|
|
|
24
58
|
The tool loads your project via [ts-morph](https://ts-morph.com/), using your `tsconfig.json` when present, otherwise globbing `**/*.{ts,tsx,js,jsx}` (excluding `node_modules`, `dist`, `.next`, `build`). Each registered transform is applied in order against the shared project; changes are saved at the end unless `--dry` or `--print` is passed.
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAiBA,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhF"}
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
|
-
/* eslint-disable no-console */ import {
|
|
1
|
+
/* eslint-disable no-console */ import { writeFileSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { IndentationText, Project, QuoteKind } from 'ts-morph';
|
|
4
3
|
import { parseFlags } from './cli.parseFlags.js';
|
|
5
4
|
import { transforms as registry } from './registry.js';
|
|
6
5
|
import { runTransforms } from './runner.js';
|
|
6
|
+
import { runUpgrade } from './upgrade/index.js';
|
|
7
|
+
import { renderUpgradePrompt } from './upgrade/prompt.js';
|
|
7
8
|
import { loadPackageJsons, serializePackageJson } from './utils/packageJson.js';
|
|
9
|
+
import { loadProject } from './utils/project.js';
|
|
8
10
|
export async function main(argv = process.argv.slice(2)) {
|
|
9
11
|
const flags = parseFlags(argv);
|
|
12
|
+
if (flags.command === 'upgrade' && flags.emitPrompt) {
|
|
13
|
+
console.log(renderUpgradePrompt());
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (flags.command === 'upgrade') {
|
|
17
|
+
const { failed } = await runUpgrade({
|
|
18
|
+
flags: {
|
|
19
|
+
dry: flags.dry,
|
|
20
|
+
force: flags.force,
|
|
21
|
+
tag: flags.tag ?? 'canary'
|
|
22
|
+
},
|
|
23
|
+
path: flags.path
|
|
24
|
+
});
|
|
25
|
+
if (failed) {
|
|
26
|
+
process.exitCode = 1;
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
10
30
|
if (flags.list) {
|
|
11
31
|
printList();
|
|
12
32
|
return;
|
|
@@ -71,31 +91,6 @@ function printList() {
|
|
|
71
91
|
console.log(`${t.name} ${t.description}`);
|
|
72
92
|
}
|
|
73
93
|
}
|
|
74
|
-
function loadProject(path) {
|
|
75
|
-
const manipulationSettings = {
|
|
76
|
-
indentationText: IndentationText.TwoSpaces,
|
|
77
|
-
quoteKind: QuoteKind.Single,
|
|
78
|
-
useTrailingCommas: true
|
|
79
|
-
};
|
|
80
|
-
const tsconfigPath = resolve(path, 'tsconfig.json');
|
|
81
|
-
if (existsSync(tsconfigPath)) {
|
|
82
|
-
return new Project({
|
|
83
|
-
manipulationSettings,
|
|
84
|
-
tsConfigFilePath: tsconfigPath
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
const project = new Project({
|
|
88
|
-
manipulationSettings
|
|
89
|
-
});
|
|
90
|
-
project.addSourceFilesAtPaths([
|
|
91
|
-
`${path}/**/*.{ts,tsx,js,jsx}`,
|
|
92
|
-
'!**/node_modules/**',
|
|
93
|
-
'!**/dist/**',
|
|
94
|
-
'!**/.next/**',
|
|
95
|
-
'!**/build/**'
|
|
96
|
-
]);
|
|
97
|
-
return project;
|
|
98
|
-
}
|
|
99
94
|
function snapshotProject(project) {
|
|
100
95
|
return new Map(project.getSourceFiles().map((file)=>[
|
|
101
96
|
file.getFilePath(),
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import type { Project } from 'ts-morph'\n\n/* eslint-disable no-console */\nimport { writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { TransformRunResult } from './runner.js'\nimport type { Transform } from './types.js'\n\nimport { parseFlags } from './cli.parseFlags.js'\nimport { transforms as registry } from './registry.js'\nimport { runTransforms } from './runner.js'\nimport { runUpgrade } from './upgrade/index.js'\nimport { renderUpgradePrompt } from './upgrade/prompt.js'\nimport { loadPackageJsons, serializePackageJson } from './utils/packageJson.js'\nimport { loadProject } from './utils/project.js'\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<void> {\n const flags = parseFlags(argv)\n\n if (flags.command === 'upgrade' && flags.emitPrompt) {\n console.log(renderUpgradePrompt())\n return\n }\n\n if (flags.command === 'upgrade') {\n const { failed } = await runUpgrade({\n flags: { dry: flags.dry, force: flags.force, tag: flags.tag ?? 'canary' },\n path: flags.path,\n })\n if (failed) {\n process.exitCode = 1\n }\n return\n }\n\n if (flags.list) {\n printList()\n return\n }\n\n const selected = selectTransforms(registry, flags.transform)\n if (selected.length === 0) {\n console.error(`No transforms matched${flags.transform ? ` \"${flags.transform}\"` : ''}.`)\n process.exitCode = 1\n return\n }\n\n const project = loadProject(resolve(flags.path))\n const snapshot = snapshotProject(project)\n\n const packageJsons = loadPackageJsons(resolve(flags.path))\n\n const { failed, results } = await runTransforms({\n // Shares the same `data` reference, so transform mutations are visible\n // below for change detection (do not clone here).\n packageJsons: packageJsons.map(({ data, path }) => ({ data, path })),\n project,\n transforms: selected,\n })\n\n const changed = project\n .getSourceFiles()\n .filter((file) => snapshot.get(file.getFilePath()) !== file.getFullText())\n\n const changedPackageJsons = packageJsons.filter(\n (pkg) => serializePackageJson(pkg.data, pkg.originalText) !== pkg.originalText,\n )\n\n if (flags.print) {\n if (changed.length === 0 && changedPackageJsons.length === 0) {\n console.log('(no files changed)')\n } else {\n for (const file of changed) {\n console.log(`// ${file.getFilePath()}`)\n console.log(file.getFullText())\n }\n for (const pkg of changedPackageJsons) {\n console.log(`// ${pkg.path}`)\n console.log(serializePackageJson(pkg.data, pkg.originalText))\n }\n }\n } else if (!flags.dry) {\n await Promise.all(changed.map((file) => file.save()))\n for (const pkg of changedPackageJsons) {\n writeFileSync(pkg.path, serializePackageJson(pkg.data, pkg.originalText))\n }\n }\n\n printSummary(results)\n\n if (failed) {\n process.exitCode = 1\n }\n}\n\nfunction selectTransforms(available: Transform[], name: string | undefined): Transform[] {\n if (!name) {\n return available\n }\n return available.filter((t) => t.name === name)\n}\n\nfunction printList(): void {\n if (registry.length === 0) {\n console.log('No transforms registered.')\n return\n }\n for (const t of registry) {\n console.log(`${t.name} ${t.description}`)\n }\n}\n\nfunction snapshotProject(project: Project): Map<string, string> {\n return new Map(project.getSourceFiles().map((file) => [file.getFilePath(), file.getFullText()]))\n}\n\nfunction printSummary(results: TransformRunResult[]): void {\n console.log('')\n console.log('Codemod summary:')\n for (const r of results) {\n if (r.error) {\n console.log(` [FAIL] ${r.name} — ${r.error.message}`)\n continue\n }\n console.log(` [ok] ${r.name} — ${r.filesChanged.length} file(s) changed`)\n for (const note of r.notes ?? []) {\n console.log(` note: ${note}`)\n }\n }\n}\n"],"names":["writeFileSync","resolve","parseFlags","transforms","registry","runTransforms","runUpgrade","renderUpgradePrompt","loadPackageJsons","serializePackageJson","loadProject","main","argv","process","slice","flags","command","emitPrompt","console","log","failed","dry","force","tag","path","exitCode","list","printList","selected","selectTransforms","transform","length","error","project","snapshot","snapshotProject","packageJsons","results","map","data","changed","getSourceFiles","filter","file","get","getFilePath","getFullText","changedPackageJsons","pkg","originalText","print","Promise","all","save","printSummary","available","name","t","description","Map","r","message","filesChanged","note","notes"],"mappings":"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"}
|
package/dist/cli.parseFlags.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
export type CliCommand = 'upgrade';
|
|
1
2
|
export type CliFlags = {
|
|
3
|
+
command?: CliCommand;
|
|
2
4
|
dry: boolean;
|
|
5
|
+
emitPrompt: boolean;
|
|
6
|
+
force: boolean;
|
|
3
7
|
list: boolean;
|
|
4
8
|
path: string;
|
|
5
9
|
print: boolean;
|
|
10
|
+
tag?: string;
|
|
6
11
|
transform?: string;
|
|
7
12
|
};
|
|
8
13
|
export declare function parseFlags(argv: string[]): CliFlags;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.parseFlags.d.ts","sourceRoot":"","sources":["../src/cli.parseFlags.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,EAAE,OAAO,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"cli.parseFlags.d.ts","sourceRoot":"","sources":["../src/cli.parseFlags.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,SAAS,CAAA;AAElC,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,CAAC,EAAE,UAAU,CAAA;IACpB,GAAG,EAAE,OAAO,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAmCnD"}
|
package/dist/cli.parseFlags.js
CHANGED
|
@@ -12,6 +12,10 @@ export function parseFlags(argv) {
|
|
|
12
12
|
type: 'boolean',
|
|
13
13
|
default: false
|
|
14
14
|
},
|
|
15
|
+
force: {
|
|
16
|
+
type: 'boolean',
|
|
17
|
+
default: false
|
|
18
|
+
},
|
|
15
19
|
list: {
|
|
16
20
|
type: 'boolean',
|
|
17
21
|
default: false
|
|
@@ -20,16 +24,31 @@ export function parseFlags(argv) {
|
|
|
20
24
|
type: 'boolean',
|
|
21
25
|
default: false
|
|
22
26
|
},
|
|
27
|
+
tag: {
|
|
28
|
+
type: 'string'
|
|
29
|
+
},
|
|
23
30
|
transform: {
|
|
24
31
|
type: 'string'
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
});
|
|
35
|
+
const isUpgrade = positionals[0] === 'upgrade';
|
|
36
|
+
const command = isUpgrade ? 'upgrade' : undefined;
|
|
37
|
+
// `upgrade prompt [path]` emits the orchestration prompt; `prompt` consumes
|
|
38
|
+
// positional 1, shifting the path to positional 2.
|
|
39
|
+
const emitPrompt = isUpgrade && positionals[1] === 'prompt';
|
|
40
|
+
const upgradePath = emitPrompt ? positionals[2] : positionals[1];
|
|
41
|
+
// When `upgrade` is present it consumes positional 0; the path shifts to positional 1.
|
|
42
|
+
const path = (isUpgrade ? upgradePath : positionals[0]) ?? process.cwd();
|
|
28
43
|
return {
|
|
44
|
+
command,
|
|
29
45
|
dry: Boolean(values.dry) || Boolean(values['dry-run']),
|
|
46
|
+
emitPrompt,
|
|
47
|
+
force: Boolean(values.force),
|
|
30
48
|
list: Boolean(values.list),
|
|
31
|
-
path
|
|
49
|
+
path,
|
|
32
50
|
print: Boolean(values.print),
|
|
51
|
+
tag: values.tag,
|
|
33
52
|
transform: values.transform
|
|
34
53
|
};
|
|
35
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.parseFlags.ts"],"sourcesContent":["import { parseArgs } from 'node:util'\n\nexport type CliFlags = {\n dry: boolean\n list: boolean\n path: string\n print: boolean\n transform?: string\n}\n\nexport function parseFlags(argv: string[]): CliFlags {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n args: argv,\n options: {\n dry: { type: 'boolean', default: false },\n 'dry-run': { type: 'boolean', default: false },\n list: { type: 'boolean', default: false },\n print: { type: 'boolean', default: false },\n transform: { type: 'string' },\n },\n })\n\n return {\n dry: Boolean(values.dry) || Boolean(values['dry-run']),\n
|
|
1
|
+
{"version":3,"sources":["../src/cli.parseFlags.ts"],"sourcesContent":["import { parseArgs } from 'node:util'\n\nexport type CliCommand = 'upgrade'\n\nexport type CliFlags = {\n command?: CliCommand\n dry: boolean\n emitPrompt: boolean\n force: boolean\n list: boolean\n path: string\n print: boolean\n tag?: string\n transform?: string\n}\n\nexport function parseFlags(argv: string[]): CliFlags {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n args: argv,\n options: {\n dry: { type: 'boolean', default: false },\n 'dry-run': { type: 'boolean', default: false },\n force: { type: 'boolean', default: false },\n list: { type: 'boolean', default: false },\n print: { type: 'boolean', default: false },\n tag: { type: 'string' },\n transform: { type: 'string' },\n },\n })\n\n const isUpgrade = positionals[0] === 'upgrade'\n const command = isUpgrade ? 'upgrade' : undefined\n // `upgrade prompt [path]` emits the orchestration prompt; `prompt` consumes\n // positional 1, shifting the path to positional 2.\n const emitPrompt = isUpgrade && positionals[1] === 'prompt'\n const upgradePath = emitPrompt ? positionals[2] : positionals[1]\n // When `upgrade` is present it consumes positional 0; the path shifts to positional 1.\n const path = (isUpgrade ? upgradePath : positionals[0]) ?? process.cwd()\n\n return {\n command,\n dry: Boolean(values.dry) || Boolean(values['dry-run']),\n emitPrompt,\n force: Boolean(values.force),\n list: Boolean(values.list),\n path,\n print: Boolean(values.print),\n tag: values.tag,\n transform: values.transform,\n }\n}\n"],"names":["parseArgs","parseFlags","argv","positionals","values","allowPositionals","args","options","dry","type","default","force","list","print","tag","transform","isUpgrade","command","undefined","emitPrompt","upgradePath","path","process","cwd","Boolean"],"mappings":"AAAA,SAASA,SAAS,QAAQ,YAAW;AAgBrC,OAAO,SAASC,WAAWC,IAAc;IACvC,MAAM,EAAEC,WAAW,EAAEC,MAAM,EAAE,GAAGJ,UAAU;QACxCK,kBAAkB;QAClBC,MAAMJ;QACNK,SAAS;YACPC,KAAK;gBAAEC,MAAM;gBAAWC,SAAS;YAAM;YACvC,WAAW;gBAAED,MAAM;gBAAWC,SAAS;YAAM;YAC7CC,OAAO;gBAAEF,MAAM;gBAAWC,SAAS;YAAM;YACzCE,MAAM;gBAAEH,MAAM;gBAAWC,SAAS;YAAM;YACxCG,OAAO;gBAAEJ,MAAM;gBAAWC,SAAS;YAAM;YACzCI,KAAK;gBAAEL,MAAM;YAAS;YACtBM,WAAW;gBAAEN,MAAM;YAAS;QAC9B;IACF;IAEA,MAAMO,YAAYb,WAAW,CAAC,EAAE,KAAK;IACrC,MAAMc,UAAUD,YAAY,YAAYE;IACxC,4EAA4E;IAC5E,mDAAmD;IACnD,MAAMC,aAAaH,aAAab,WAAW,CAAC,EAAE,KAAK;IACnD,MAAMiB,cAAcD,aAAahB,WAAW,CAAC,EAAE,GAAGA,WAAW,CAAC,EAAE;IAChE,uFAAuF;IACvF,MAAMkB,OAAO,AAACL,CAAAA,YAAYI,cAAcjB,WAAW,CAAC,EAAE,AAAD,KAAMmB,QAAQC,GAAG;IAEtE,OAAO;QACLN;QACAT,KAAKgB,QAAQpB,OAAOI,GAAG,KAAKgB,QAAQpB,MAAM,CAAC,UAAU;QACrDe;QACAR,OAAOa,QAAQpB,OAAOO,KAAK;QAC3BC,MAAMY,QAAQpB,OAAOQ,IAAI;QACzBS;QACAR,OAAOW,QAAQpB,OAAOS,KAAK;QAC3BC,KAAKV,OAAOU,GAAG;QACfC,WAAWX,OAAOW,SAAS;IAC7B;AACF"}
|
|
@@ -3,10 +3,14 @@ import { parseFlags } from './cli.parseFlags.js';
|
|
|
3
3
|
describe('parseFlags', ()=>{
|
|
4
4
|
it('defaults path to cwd when no positional arg is given', ()=>{
|
|
5
5
|
expect(parseFlags([])).toEqual({
|
|
6
|
+
command: undefined,
|
|
6
7
|
dry: false,
|
|
8
|
+
emitPrompt: false,
|
|
9
|
+
force: false,
|
|
7
10
|
list: false,
|
|
8
11
|
path: process.cwd(),
|
|
9
12
|
print: false,
|
|
13
|
+
tag: undefined,
|
|
10
14
|
transform: undefined
|
|
11
15
|
});
|
|
12
16
|
});
|
|
@@ -44,6 +48,74 @@ describe('parseFlags', ()=>{
|
|
|
44
48
|
'--dry-run'
|
|
45
49
|
]).dry).toBe(true);
|
|
46
50
|
});
|
|
51
|
+
it('parses the upgrade subcommand with default path', ()=>{
|
|
52
|
+
expect(parseFlags([
|
|
53
|
+
'upgrade'
|
|
54
|
+
])).toMatchObject({
|
|
55
|
+
command: 'upgrade',
|
|
56
|
+
path: process.cwd()
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
it('parses upgrade with path, tag, force, and dry', ()=>{
|
|
60
|
+
expect(parseFlags([
|
|
61
|
+
'upgrade',
|
|
62
|
+
'./app',
|
|
63
|
+
'--tag',
|
|
64
|
+
'latest',
|
|
65
|
+
'--force',
|
|
66
|
+
'--dry'
|
|
67
|
+
])).toMatchObject({
|
|
68
|
+
command: 'upgrade',
|
|
69
|
+
dry: true,
|
|
70
|
+
force: true,
|
|
71
|
+
path: './app',
|
|
72
|
+
tag: 'latest'
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
it('parses `upgrade prompt` with default path', ()=>{
|
|
76
|
+
expect(parseFlags([
|
|
77
|
+
'upgrade',
|
|
78
|
+
'prompt'
|
|
79
|
+
])).toMatchObject({
|
|
80
|
+
command: 'upgrade',
|
|
81
|
+
emitPrompt: true,
|
|
82
|
+
path: process.cwd()
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
it('parses `upgrade prompt <path>` with tag', ()=>{
|
|
86
|
+
expect(parseFlags([
|
|
87
|
+
'upgrade',
|
|
88
|
+
'prompt',
|
|
89
|
+
'./app',
|
|
90
|
+
'--tag',
|
|
91
|
+
'latest'
|
|
92
|
+
])).toMatchObject({
|
|
93
|
+
command: 'upgrade',
|
|
94
|
+
emitPrompt: true,
|
|
95
|
+
path: './app',
|
|
96
|
+
tag: 'latest'
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
it('leaves emitPrompt false for a plain upgrade run', ()=>{
|
|
100
|
+
expect(parseFlags([
|
|
101
|
+
'upgrade',
|
|
102
|
+
'./app'
|
|
103
|
+
])).toMatchObject({
|
|
104
|
+
command: 'upgrade',
|
|
105
|
+
emitPrompt: false,
|
|
106
|
+
path: './app'
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
it('leaves command undefined for a bare path invocation', ()=>{
|
|
110
|
+
expect(parseFlags([
|
|
111
|
+
'./src',
|
|
112
|
+
'--dry'
|
|
113
|
+
])).toMatchObject({
|
|
114
|
+
command: undefined,
|
|
115
|
+
dry: true,
|
|
116
|
+
path: './src'
|
|
117
|
+
});
|
|
118
|
+
});
|
|
47
119
|
});
|
|
48
120
|
|
|
49
121
|
//# sourceMappingURL=cli.parseFlags.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.parseFlags.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { parseFlags } from './cli.parseFlags.js'\n\ndescribe('parseFlags', () => {\n it('defaults path to cwd when no positional arg is given', () => {\n expect(parseFlags([])).toEqual({\n dry: false,\n list: false,\n path: process.cwd(),\n print: false,\n transform: undefined,\n })\n })\n\n it('reads positional path', () => {\n expect(parseFlags(['./src']).path).toBe('./src')\n })\n\n it('parses flags', () => {\n expect(parseFlags(['./src', '--dry', '--print'])).toMatchObject({\n dry: true,\n path: './src',\n print: true,\n })\n })\n\n it('parses --transform', () => {\n expect(parseFlags(['--transform', 'rename-slate-export'])).toMatchObject({\n transform: 'rename-slate-export',\n })\n })\n\n it('parses --list', () => {\n expect(parseFlags(['--list']).list).toBe(true)\n })\n\n it('treats --dry-run as an alias for --dry', () => {\n expect(parseFlags(['--dry-run']).dry).toBe(true)\n })\n})\n"],"names":["describe","expect","it","parseFlags","toEqual","dry","list","path","process","cwd","print","
|
|
1
|
+
{"version":3,"sources":["../src/cli.parseFlags.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { parseFlags } from './cli.parseFlags.js'\n\ndescribe('parseFlags', () => {\n it('defaults path to cwd when no positional arg is given', () => {\n expect(parseFlags([])).toEqual({\n command: undefined,\n dry: false,\n emitPrompt: false,\n force: false,\n list: false,\n path: process.cwd(),\n print: false,\n tag: undefined,\n transform: undefined,\n })\n })\n\n it('reads positional path', () => {\n expect(parseFlags(['./src']).path).toBe('./src')\n })\n\n it('parses flags', () => {\n expect(parseFlags(['./src', '--dry', '--print'])).toMatchObject({\n dry: true,\n path: './src',\n print: true,\n })\n })\n\n it('parses --transform', () => {\n expect(parseFlags(['--transform', 'rename-slate-export'])).toMatchObject({\n transform: 'rename-slate-export',\n })\n })\n\n it('parses --list', () => {\n expect(parseFlags(['--list']).list).toBe(true)\n })\n\n it('treats --dry-run as an alias for --dry', () => {\n expect(parseFlags(['--dry-run']).dry).toBe(true)\n })\n\n it('parses the upgrade subcommand with default path', () => {\n expect(parseFlags(['upgrade'])).toMatchObject({\n command: 'upgrade',\n path: process.cwd(),\n })\n })\n\n it('parses upgrade with path, tag, force, and dry', () => {\n expect(parseFlags(['upgrade', './app', '--tag', 'latest', '--force', '--dry'])).toMatchObject({\n command: 'upgrade',\n dry: true,\n force: true,\n path: './app',\n tag: 'latest',\n })\n })\n\n it('parses `upgrade prompt` with default path', () => {\n expect(parseFlags(['upgrade', 'prompt'])).toMatchObject({\n command: 'upgrade',\n emitPrompt: true,\n path: process.cwd(),\n })\n })\n\n it('parses `upgrade prompt <path>` with tag', () => {\n expect(parseFlags(['upgrade', 'prompt', './app', '--tag', 'latest'])).toMatchObject({\n command: 'upgrade',\n emitPrompt: true,\n path: './app',\n tag: 'latest',\n })\n })\n\n it('leaves emitPrompt false for a plain upgrade run', () => {\n expect(parseFlags(['upgrade', './app'])).toMatchObject({\n command: 'upgrade',\n emitPrompt: false,\n path: './app',\n })\n })\n\n it('leaves command undefined for a bare path invocation', () => {\n expect(parseFlags(['./src', '--dry'])).toMatchObject({\n command: undefined,\n dry: true,\n path: './src',\n })\n })\n})\n"],"names":["describe","expect","it","parseFlags","toEqual","command","undefined","dry","emitPrompt","force","list","path","process","cwd","print","tag","transform","toBe","toMatchObject"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,UAAU,QAAQ,sBAAqB;AAEhDH,SAAS,cAAc;IACrBE,GAAG,wDAAwD;QACzDD,OAAOE,WAAW,EAAE,GAAGC,OAAO,CAAC;YAC7BC,SAASC;YACTC,KAAK;YACLC,YAAY;YACZC,OAAO;YACPC,MAAM;YACNC,MAAMC,QAAQC,GAAG;YACjBC,OAAO;YACPC,KAAKT;YACLU,WAAWV;QACb;IACF;IAEAJ,GAAG,yBAAyB;QAC1BD,OAAOE,WAAW;YAAC;SAAQ,EAAEQ,IAAI,EAAEM,IAAI,CAAC;IAC1C;IAEAf,GAAG,gBAAgB;QACjBD,OAAOE,WAAW;YAAC;YAAS;YAAS;SAAU,GAAGe,aAAa,CAAC;YAC9DX,KAAK;YACLI,MAAM;YACNG,OAAO;QACT;IACF;IAEAZ,GAAG,sBAAsB;QACvBD,OAAOE,WAAW;YAAC;YAAe;SAAsB,GAAGe,aAAa,CAAC;YACvEF,WAAW;QACb;IACF;IAEAd,GAAG,iBAAiB;QAClBD,OAAOE,WAAW;YAAC;SAAS,EAAEO,IAAI,EAAEO,IAAI,CAAC;IAC3C;IAEAf,GAAG,0CAA0C;QAC3CD,OAAOE,WAAW;YAAC;SAAY,EAAEI,GAAG,EAAEU,IAAI,CAAC;IAC7C;IAEAf,GAAG,mDAAmD;QACpDD,OAAOE,WAAW;YAAC;SAAU,GAAGe,aAAa,CAAC;YAC5Cb,SAAS;YACTM,MAAMC,QAAQC,GAAG;QACnB;IACF;IAEAX,GAAG,iDAAiD;QAClDD,OAAOE,WAAW;YAAC;YAAW;YAAS;YAAS;YAAU;YAAW;SAAQ,GAAGe,aAAa,CAAC;YAC5Fb,SAAS;YACTE,KAAK;YACLE,OAAO;YACPE,MAAM;YACNI,KAAK;QACP;IACF;IAEAb,GAAG,6CAA6C;QAC9CD,OAAOE,WAAW;YAAC;YAAW;SAAS,GAAGe,aAAa,CAAC;YACtDb,SAAS;YACTG,YAAY;YACZG,MAAMC,QAAQC,GAAG;QACnB;IACF;IAEAX,GAAG,2CAA2C;QAC5CD,OAAOE,WAAW;YAAC;YAAW;YAAU;YAAS;YAAS;SAAS,GAAGe,aAAa,CAAC;YAClFb,SAAS;YACTG,YAAY;YACZG,MAAM;YACNI,KAAK;QACP;IACF;IAEAb,GAAG,mDAAmD;QACpDD,OAAOE,WAAW;YAAC;YAAW;SAAQ,GAAGe,aAAa,CAAC;YACrDb,SAAS;YACTG,YAAY;YACZG,MAAM;QACR;IACF;IAEAT,GAAG,uDAAuD;QACxDD,OAAOE,WAAW;YAAC;YAAS;SAAQ,GAAGe,aAAa,CAAC;YACnDb,SAASC;YACTC,KAAK;YACLI,MAAM;QACR;IACF;AACF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Payload v3 -> v4: remaining steps
|
|
2
|
+
|
|
3
|
+
`payload-codemod upgrade` has done the mechanical slice: pinned Payload packages to v4,
|
|
4
|
+
removed conflicting overrides, written the toolchain floors, installed, and run the AST
|
|
5
|
+
transforms. This checklist is what it did NOT do. The authoritative breaking-change list is
|
|
6
|
+
the migration guide (`docs/migration-guide/v4.mdx`, also bundled at `dist/runbook/v4.mdx`):
|
|
7
|
+
<https://github.com/payloadcms/payload/blob/main/docs/migration-guide/v4.mdx>
|
|
8
|
+
|
|
9
|
+
Report each item as verified / cannot-confirm / broken. Do not call the upgrade complete while
|
|
10
|
+
any gate fails or any generated file is stale.
|
|
11
|
+
|
|
12
|
+
## 0. Before upgrading (do on v3)
|
|
13
|
+
|
|
14
|
+
Some migrations need v3 tooling that v4 removes, so they must run BEFORE `payload-codemod upgrade`,
|
|
15
|
+
while the v3 packages are still installed:
|
|
16
|
+
|
|
17
|
+
- Slate richtext is deleted in v4. Migrate Slate -> Lexical on v3; the migration path is gone once
|
|
18
|
+
packages are pinned to v4.
|
|
19
|
+
|
|
20
|
+
## 1. Next.js 16
|
|
21
|
+
|
|
22
|
+
Payload v4 requires Next 16. The command did not touch Next. Run Next's own recommended agent
|
|
23
|
+
workflow, which bumps Next + React and migrates the code as one unit:
|
|
24
|
+
<https://nextjs.org/docs/app/guides/upgrading/version-16#use-an-ai-agent-recommended>
|
|
25
|
+
|
|
26
|
+
Keep the resulting Next version within `>=16.2.6 <17` (the exact target is printed in the
|
|
27
|
+
upgrade report), since Next's `upgrade latest` may point past 16 in future.
|
|
28
|
+
|
|
29
|
+
## 2. Regenerate generated files
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
payload generate:types && payload generate:importmap
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Never hand-edit `payload-types.ts` or `importMap.js` — regenerate them. If a credential wall
|
|
36
|
+
blocks generation, set dummy env values and re-run.
|
|
37
|
+
|
|
38
|
+
## 3. Manual v4 items (not covered by transforms)
|
|
39
|
+
|
|
40
|
+
- SCSS is gone: move `@payloadcms/ui/scss` to `@payloadcms/ui/css`; rename `--theme-*` -> `--color-*`.
|
|
41
|
+
- Sweep agent/editor instruction files (`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/*`) for APIs v4 removed.
|
|
42
|
+
- Cron parsing is strict now: `/10 * * * *` -> `*/10 * * * *`.
|
|
43
|
+
- Jobs: run DB migrations for the new lease/stats fields.
|
|
44
|
+
- Review per-transform notes printed in the upgrade report for spots needing manual review.
|
|
45
|
+
|
|
46
|
+
## 4. Verify
|
|
47
|
+
|
|
48
|
+
- `tsc --noEmit` (delete `tsconfig.tsbuildinfo` first; set `checkJs: true` so `importMap.js` is covered).
|
|
49
|
+
- Run integration tests and e2e separately.
|
|
50
|
+
- Build.
|
|
51
|
+
- Confirm native modules (e.g. `sharp`) still load.
|
|
52
|
+
|
|
53
|
+
## 5. Report honestly
|
|
54
|
+
|
|
55
|
+
Distinguish verified, cannot-confirm, and broken. A silent gap reads as "checked and fine".
|