@payloadcms/codemod 4.0.0-internal.164164a → 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.
Files changed (81) hide show
  1. package/README.md +34 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +22 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cli.parseFlags.d.ts +5 -0
  6. package/dist/cli.parseFlags.d.ts.map +1 -1
  7. package/dist/cli.parseFlags.js +20 -1
  8. package/dist/cli.parseFlags.js.map +1 -1
  9. package/dist/cli.parseFlags.spec.js +72 -0
  10. package/dist/cli.parseFlags.spec.js.map +1 -1
  11. package/dist/runbook/payload-v4-upgrade.md +55 -0
  12. package/dist/runbook/v4.mdx +1652 -0
  13. package/dist/upgrade/detectPackageManager.d.ts +8 -0
  14. package/dist/upgrade/detectPackageManager.d.ts.map +1 -0
  15. package/dist/upgrade/detectPackageManager.js +38 -0
  16. package/dist/upgrade/detectPackageManager.js.map +1 -0
  17. package/dist/upgrade/detectPackageManager.spec.d.ts +2 -0
  18. package/dist/upgrade/detectPackageManager.spec.d.ts.map +1 -0
  19. package/dist/upgrade/detectPackageManager.spec.js +41 -0
  20. package/dist/upgrade/detectPackageManager.spec.js.map +1 -0
  21. package/dist/upgrade/index.d.ts +24 -0
  22. package/dist/upgrade/index.d.ts.map +1 -0
  23. package/dist/upgrade/index.js +184 -0
  24. package/dist/upgrade/index.js.map +1 -0
  25. package/dist/upgrade/index.spec.d.ts +2 -0
  26. package/dist/upgrade/index.spec.d.ts.map +1 -0
  27. package/dist/upgrade/index.spec.js +132 -0
  28. package/dist/upgrade/index.spec.js.map +1 -0
  29. package/dist/upgrade/packaging.spec.d.ts +2 -0
  30. package/dist/upgrade/packaging.spec.d.ts.map +1 -0
  31. package/dist/upgrade/packaging.spec.js +29 -0
  32. package/dist/upgrade/packaging.spec.js.map +1 -0
  33. package/dist/upgrade/prompt.d.ts +11 -0
  34. package/dist/upgrade/prompt.d.ts.map +1 -0
  35. package/dist/upgrade/prompt.js +75 -0
  36. package/dist/upgrade/prompt.js.map +1 -0
  37. package/dist/upgrade/prompt.spec.d.ts +2 -0
  38. package/dist/upgrade/prompt.spec.d.ts.map +1 -0
  39. package/dist/upgrade/prompt.spec.js +51 -0
  40. package/dist/upgrade/prompt.spec.js.map +1 -0
  41. package/dist/upgrade/report.d.ts +18 -0
  42. package/dist/upgrade/report.d.ts.map +1 -0
  43. package/dist/upgrade/report.js +41 -0
  44. package/dist/upgrade/report.js.map +1 -0
  45. package/dist/upgrade/report.spec.d.ts +2 -0
  46. package/dist/upgrade/report.spec.d.ts.map +1 -0
  47. package/dist/upgrade/report.spec.js +87 -0
  48. package/dist/upgrade/report.spec.js.map +1 -0
  49. package/dist/upgrade/resolveVersions.d.ts +13 -0
  50. package/dist/upgrade/resolveVersions.d.ts.map +1 -0
  51. package/dist/upgrade/resolveVersions.js +55 -0
  52. package/dist/upgrade/resolveVersions.js.map +1 -0
  53. package/dist/upgrade/resolveVersions.spec.d.ts +2 -0
  54. package/dist/upgrade/resolveVersions.spec.d.ts.map +1 -0
  55. package/dist/upgrade/resolveVersions.spec.js +82 -0
  56. package/dist/upgrade/resolveVersions.spec.js.map +1 -0
  57. package/dist/upgrade/rewritePackageJson.d.ts +25 -0
  58. package/dist/upgrade/rewritePackageJson.d.ts.map +1 -0
  59. package/dist/upgrade/rewritePackageJson.js +106 -0
  60. package/dist/upgrade/rewritePackageJson.js.map +1 -0
  61. package/dist/upgrade/rewritePackageJson.spec.d.ts +2 -0
  62. package/dist/upgrade/rewritePackageJson.spec.d.ts.map +1 -0
  63. package/dist/upgrade/rewritePackageJson.spec.js +108 -0
  64. package/dist/upgrade/rewritePackageJson.spec.js.map +1 -0
  65. package/dist/upgrade/runInstall.d.ts +16 -0
  66. package/dist/upgrade/runInstall.d.ts.map +1 -0
  67. package/dist/upgrade/runInstall.js +17 -0
  68. package/dist/upgrade/runInstall.js.map +1 -0
  69. package/dist/upgrade/runInstall.spec.d.ts +2 -0
  70. package/dist/upgrade/runInstall.spec.d.ts.map +1 -0
  71. package/dist/upgrade/runInstall.spec.js +48 -0
  72. package/dist/upgrade/runInstall.spec.js.map +1 -0
  73. package/dist/upgrade/types.d.ts +42 -0
  74. package/dist/upgrade/types.d.ts.map +1 -0
  75. package/dist/upgrade/types.js +7 -0
  76. package/dist/upgrade/types.js.map +1 -0
  77. package/dist/utils/project.d.ts +4 -0
  78. package/dist/utils/project.d.ts.map +1 -0
  79. package/dist/utils/project.js +30 -0
  80. package/dist/utils/project.js.map +1 -0
  81. package/package.json +5 -2
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Render the overarching agent prompt for a full Payload v3 -> v4 upgrade,
3
+ * Next.js 16 included. The prompt is a thin orchestrator: it sequences the
4
+ * gates, runs this package's `upgrade` command for the deterministic slice,
5
+ * delegates Next.js to Next's own agent workflow, and points at the migration
6
+ * guide for the judgment work rather than restating any of it. The text is
7
+ * static and project-agnostic — the agent runs it from the project root. Pure:
8
+ * the caller prints it.
9
+ */ export function renderUpgradePrompt() {
10
+ return `You are upgrading this project from Payload v3 to v4, Next.js 16 included.
11
+
12
+ Ground rule: resolution over intent. A step is done only when it installs, builds, and boots.
13
+ Never report a task complete because the edit looks right — confirm it. A silent gap reads as
14
+ "checked and fine".
15
+
16
+ ## 0. Preconditions
17
+ - Work on a clean git tree or a fresh branch.
18
+ - Use Node >=24.15 (the exact engines floor is printed by the command in step 2).
19
+
20
+ ## 1. Pre-upgrade migrations (do these on v3, before touching versions)
21
+ Some migrations need the v3 tooling that v4 deletes, so they MUST run before the upgrade:
22
+ - Slate richtext is removed in v4. Migrate Slate -> Lexical while still on v3; the migration path
23
+ is gone once the packages are pinned to v4.
24
+
25
+ Do not proceed to step 2 until these are complete and committed.
26
+
27
+ ## 2. Payload mechanical slice
28
+ Run this from the project root:
29
+
30
+ npx @payloadcms/codemod upgrade .
31
+
32
+ Add \`--tag <dist-tag>\` to resolve Payload from a non-default dist-tag (default is \`canary\`).
33
+ This pins the Payload packages to v4, removes conflicting overrides, writes the toolchain
34
+ floors, installs, and runs the AST transforms. Read its report:
35
+ - It prints the resolved payload version, the required Next target, and the path to the
36
+ bundled runbook and migration guide. Use those paths below.
37
+ - The unmet \`@payloadcms/next\` peer against Next 15 is EXPECTED at this point. Do NOT downgrade
38
+ payload to satisfy it — step 3 resolves it by upgrading Next.
39
+ - Do not hand-edit the versions it pinned.
40
+
41
+ ## 3. Next.js 16 (delegate to Next's workflow)
42
+ Payload v4 requires Next 16. The command above did not touch Next. Run Next's own recommended
43
+ agent workflow, which bumps Next + React and migrates the code as one unit:
44
+ <https://nextjs.org/docs/app/guides/upgrading/version-16#use-an-ai-agent-recommended>
45
+
46
+ In short: run \`npx @next/codemod@canary upgrade latest\`, then
47
+ \`npx @next/codemod@canary next-async-request-api .\`, and follow Next's AGENTS.md workflow for
48
+ the rest. Keep the result within the Next target range printed in step 2's report. Reinstall
49
+ afterward so the \`@payloadcms/next\` peer resolves.
50
+
51
+ ## 4. Regenerate generated files
52
+ \`payload generate:types && payload generate:importmap\`. Never hand-edit \`payload-types.ts\` or
53
+ \`importMap.js\` — regenerate them.
54
+
55
+ ## 5. Fix-forward judgment work (against the now-v4 tree)
56
+ These depend on the v4 APIs and types existing, so they follow the upgrade. Open the bundled
57
+ migration guide (\`v4.mdx\`, path printed in step 2) and the bundled runbook
58
+ (\`runbook/payload-v4-upgrade.md\`) and work the items they list — SCSS -> CSS and \`--theme-*\` ->
59
+ \`--color-*\` token renames, Lexical union type-narrowing, jobs DB migrations, strict cron parsing,
60
+ and anything flagged in the per-transform notes. Consult the guide for each; do not guess from
61
+ memory.
62
+
63
+ ## 6. Verify
64
+ - \`tsc --noEmit\` (delete \`tsconfig.tsbuildinfo\` first; set \`checkJs: true\` so \`importMap.js\` is covered).
65
+ - Run integration and e2e tests separately.
66
+ - Build.
67
+ - Confirm native modules (e.g. \`sharp\`) still load.
68
+
69
+ ## 7. Report
70
+ Distinguish verified, cannot-confirm, and broken. Do not call the upgrade complete while any
71
+ gate fails or any generated file is stale.
72
+ `;
73
+ }
74
+
75
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/prompt.ts"],"sourcesContent":["/**\n * Render the overarching agent prompt for a full Payload v3 -> v4 upgrade,\n * Next.js 16 included. The prompt is a thin orchestrator: it sequences the\n * gates, runs this package's `upgrade` command for the deterministic slice,\n * delegates Next.js to Next's own agent workflow, and points at the migration\n * guide for the judgment work rather than restating any of it. The text is\n * static and project-agnostic — the agent runs it from the project root. Pure:\n * the caller prints it.\n */\nexport function renderUpgradePrompt(): string {\n return `You are upgrading this project from Payload v3 to v4, Next.js 16 included.\n\nGround rule: resolution over intent. A step is done only when it installs, builds, and boots.\nNever report a task complete because the edit looks right — confirm it. A silent gap reads as\n\"checked and fine\".\n\n## 0. Preconditions\n- Work on a clean git tree or a fresh branch.\n- Use Node >=24.15 (the exact engines floor is printed by the command in step 2).\n\n## 1. Pre-upgrade migrations (do these on v3, before touching versions)\nSome migrations need the v3 tooling that v4 deletes, so they MUST run before the upgrade:\n- Slate richtext is removed in v4. Migrate Slate -> Lexical while still on v3; the migration path\n is gone once the packages are pinned to v4.\n\nDo not proceed to step 2 until these are complete and committed.\n\n## 2. Payload mechanical slice\nRun this from the project root:\n\n npx @payloadcms/codemod upgrade .\n\nAdd \\`--tag <dist-tag>\\` to resolve Payload from a non-default dist-tag (default is \\`canary\\`).\nThis pins the Payload packages to v4, removes conflicting overrides, writes the toolchain\nfloors, installs, and runs the AST transforms. Read its report:\n- It prints the resolved payload version, the required Next target, and the path to the\n bundled runbook and migration guide. Use those paths below.\n- The unmet \\`@payloadcms/next\\` peer against Next 15 is EXPECTED at this point. Do NOT downgrade\n payload to satisfy it — step 3 resolves it by upgrading Next.\n- Do not hand-edit the versions it pinned.\n\n## 3. Next.js 16 (delegate to Next's workflow)\nPayload v4 requires Next 16. The command above did not touch Next. Run Next's own recommended\nagent workflow, which bumps Next + React and migrates the code as one unit:\n<https://nextjs.org/docs/app/guides/upgrading/version-16#use-an-ai-agent-recommended>\n\nIn short: run \\`npx @next/codemod@canary upgrade latest\\`, then\n\\`npx @next/codemod@canary next-async-request-api .\\`, and follow Next's AGENTS.md workflow for\nthe rest. Keep the result within the Next target range printed in step 2's report. Reinstall\nafterward so the \\`@payloadcms/next\\` peer resolves.\n\n## 4. Regenerate generated files\n\\`payload generate:types && payload generate:importmap\\`. Never hand-edit \\`payload-types.ts\\` or\n\\`importMap.js\\` — regenerate them.\n\n## 5. Fix-forward judgment work (against the now-v4 tree)\nThese depend on the v4 APIs and types existing, so they follow the upgrade. Open the bundled\nmigration guide (\\`v4.mdx\\`, path printed in step 2) and the bundled runbook\n(\\`runbook/payload-v4-upgrade.md\\`) and work the items they list — SCSS -> CSS and \\`--theme-*\\` ->\n\\`--color-*\\` token renames, Lexical union type-narrowing, jobs DB migrations, strict cron parsing,\nand anything flagged in the per-transform notes. Consult the guide for each; do not guess from\nmemory.\n\n## 6. Verify\n- \\`tsc --noEmit\\` (delete \\`tsconfig.tsbuildinfo\\` first; set \\`checkJs: true\\` so \\`importMap.js\\` is covered).\n- Run integration and e2e tests separately.\n- Build.\n- Confirm native modules (e.g. \\`sharp\\`) still load.\n\n## 7. Report\nDistinguish verified, cannot-confirm, and broken. Do not call the upgrade complete while any\ngate fails or any generated file is stale.\n`\n}\n"],"names":["renderUpgradePrompt"],"mappings":"AAAA;;;;;;;;CAQC,GACD,OAAO,SAASA;IACd,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DV,CAAC;AACD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=prompt.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/prompt.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { renderUpgradePrompt } from './prompt.js';
3
+ describe('renderUpgradePrompt', ()=>{
4
+ it('emits a project-agnostic upgrade command', ()=>{
5
+ const out = renderUpgradePrompt();
6
+ expect(out).toContain('npx @payloadcms/codemod upgrade .');
7
+ });
8
+ it('documents --tag as an inline option rather than baking a value', ()=>{
9
+ const out = renderUpgradePrompt();
10
+ expect(out).toContain('--tag <dist-tag>');
11
+ });
12
+ it('orders the steps: pre-upgrade before payload slice before Next before verify', ()=>{
13
+ const out = renderUpgradePrompt();
14
+ const preUpgradeStep = out.indexOf('## 1. Pre-upgrade migrations');
15
+ const payloadStep = out.indexOf('## 2. Payload mechanical slice');
16
+ const nextStep = out.indexOf('## 3. Next.js 16');
17
+ const verifyStep = out.indexOf('## 6. Verify');
18
+ expect(preUpgradeStep).toBeGreaterThan(-1);
19
+ expect(preUpgradeStep).toBeLessThan(payloadStep);
20
+ expect(payloadStep).toBeLessThan(nextStep);
21
+ expect(nextStep).toBeLessThan(verifyStep);
22
+ });
23
+ it('places Slate -> Lexical in the pre-upgrade gate, not the post-upgrade work', ()=>{
24
+ const out = renderUpgradePrompt();
25
+ const slate = out.indexOf('Slate -> Lexical');
26
+ const mechanicalSlice = out.indexOf('## 2. Payload mechanical slice');
27
+ expect(slate).toBeGreaterThan(-1);
28
+ expect(slate).toBeLessThan(mechanicalSlice);
29
+ });
30
+ it('delegates Next.js to Next own codemods rather than restating them', ()=>{
31
+ const out = renderUpgradePrompt();
32
+ expect(out).toContain('@next/codemod@canary upgrade latest');
33
+ expect(out).toContain('next-async-request-api');
34
+ });
35
+ it('encodes the expected-unmet-peer invariant', ()=>{
36
+ const out = renderUpgradePrompt();
37
+ expect(out).toContain('EXPECTED');
38
+ expect(out).toMatch(/do not downgrade\s+payload/i);
39
+ });
40
+ it('points at the migration guide and runbook without duplicating them', ()=>{
41
+ const out = renderUpgradePrompt();
42
+ expect(out).toContain('v4.mdx');
43
+ expect(out).toContain('runbook/payload-v4-upgrade.md');
44
+ });
45
+ it('contains no figma references', ()=>{
46
+ const out = renderUpgradePrompt();
47
+ expect(out.toLowerCase()).not.toContain('figma');
48
+ });
49
+ });
50
+
51
+ //# sourceMappingURL=prompt.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/prompt.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { renderUpgradePrompt } from './prompt.js'\n\ndescribe('renderUpgradePrompt', () => {\n it('emits a project-agnostic upgrade command', () => {\n const out = renderUpgradePrompt()\n\n expect(out).toContain('npx @payloadcms/codemod upgrade .')\n })\n\n it('documents --tag as an inline option rather than baking a value', () => {\n const out = renderUpgradePrompt()\n\n expect(out).toContain('--tag <dist-tag>')\n })\n\n it('orders the steps: pre-upgrade before payload slice before Next before verify', () => {\n const out = renderUpgradePrompt()\n const preUpgradeStep = out.indexOf('## 1. Pre-upgrade migrations')\n const payloadStep = out.indexOf('## 2. Payload mechanical slice')\n const nextStep = out.indexOf('## 3. Next.js 16')\n const verifyStep = out.indexOf('## 6. Verify')\n\n expect(preUpgradeStep).toBeGreaterThan(-1)\n expect(preUpgradeStep).toBeLessThan(payloadStep)\n expect(payloadStep).toBeLessThan(nextStep)\n expect(nextStep).toBeLessThan(verifyStep)\n })\n\n it('places Slate -> Lexical in the pre-upgrade gate, not the post-upgrade work', () => {\n const out = renderUpgradePrompt()\n const slate = out.indexOf('Slate -> Lexical')\n const mechanicalSlice = out.indexOf('## 2. Payload mechanical slice')\n\n expect(slate).toBeGreaterThan(-1)\n expect(slate).toBeLessThan(mechanicalSlice)\n })\n\n it('delegates Next.js to Next own codemods rather than restating them', () => {\n const out = renderUpgradePrompt()\n\n expect(out).toContain('@next/codemod@canary upgrade latest')\n expect(out).toContain('next-async-request-api')\n })\n\n it('encodes the expected-unmet-peer invariant', () => {\n const out = renderUpgradePrompt()\n\n expect(out).toContain('EXPECTED')\n expect(out).toMatch(/do not downgrade\\s+payload/i)\n })\n\n it('points at the migration guide and runbook without duplicating them', () => {\n const out = renderUpgradePrompt()\n\n expect(out).toContain('v4.mdx')\n expect(out).toContain('runbook/payload-v4-upgrade.md')\n })\n\n it('contains no figma references', () => {\n const out = renderUpgradePrompt()\n\n expect(out.toLowerCase()).not.toContain('figma')\n })\n})\n"],"names":["describe","expect","it","renderUpgradePrompt","out","toContain","preUpgradeStep","indexOf","payloadStep","nextStep","verifyStep","toBeGreaterThan","toBeLessThan","slate","mechanicalSlice","toMatch","toLowerCase","not"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,mBAAmB,QAAQ,cAAa;AAEjDH,SAAS,uBAAuB;IAC9BE,GAAG,4CAA4C;QAC7C,MAAME,MAAMD;QAEZF,OAAOG,KAAKC,SAAS,CAAC;IACxB;IAEAH,GAAG,kEAAkE;QACnE,MAAME,MAAMD;QAEZF,OAAOG,KAAKC,SAAS,CAAC;IACxB;IAEAH,GAAG,gFAAgF;QACjF,MAAME,MAAMD;QACZ,MAAMG,iBAAiBF,IAAIG,OAAO,CAAC;QACnC,MAAMC,cAAcJ,IAAIG,OAAO,CAAC;QAChC,MAAME,WAAWL,IAAIG,OAAO,CAAC;QAC7B,MAAMG,aAAaN,IAAIG,OAAO,CAAC;QAE/BN,OAAOK,gBAAgBK,eAAe,CAAC,CAAC;QACxCV,OAAOK,gBAAgBM,YAAY,CAACJ;QACpCP,OAAOO,aAAaI,YAAY,CAACH;QACjCR,OAAOQ,UAAUG,YAAY,CAACF;IAChC;IAEAR,GAAG,8EAA8E;QAC/E,MAAME,MAAMD;QACZ,MAAMU,QAAQT,IAAIG,OAAO,CAAC;QAC1B,MAAMO,kBAAkBV,IAAIG,OAAO,CAAC;QAEpCN,OAAOY,OAAOF,eAAe,CAAC,CAAC;QAC/BV,OAAOY,OAAOD,YAAY,CAACE;IAC7B;IAEAZ,GAAG,qEAAqE;QACtE,MAAME,MAAMD;QAEZF,OAAOG,KAAKC,SAAS,CAAC;QACtBJ,OAAOG,KAAKC,SAAS,CAAC;IACxB;IAEAH,GAAG,6CAA6C;QAC9C,MAAME,MAAMD;QAEZF,OAAOG,KAAKC,SAAS,CAAC;QACtBJ,OAAOG,KAAKW,OAAO,CAAC;IACtB;IAEAb,GAAG,sEAAsE;QACvE,MAAME,MAAMD;QAEZF,OAAOG,KAAKC,SAAS,CAAC;QACtBJ,OAAOG,KAAKC,SAAS,CAAC;IACxB;IAEAH,GAAG,gCAAgC;QACjC,MAAME,MAAMD;QAEZF,OAAOG,IAAIY,WAAW,IAAIC,GAAG,CAACZ,SAAS,CAAC;IAC1C;AACF"}
@@ -0,0 +1,18 @@
1
+ import type { TransformRunResult } from '../runner.js';
2
+ export type VersionReportRow = {
3
+ name: string;
4
+ ok: boolean;
5
+ resolved?: string;
6
+ wrote: string;
7
+ };
8
+ export type ReportModel = {
9
+ floorsWritten: string[];
10
+ nextTarget: null | string;
11
+ overridesRemoved: string[];
12
+ runbookPath: string;
13
+ transforms: TransformRunResult[];
14
+ versions: VersionReportRow[];
15
+ };
16
+ /** Build the honest end-of-run report string. Pure — the caller prints it. */
17
+ export declare function renderReport(model: ReportModel): string;
18
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/upgrade/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEtD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,kBAAkB,EAAE,CAAA;IAChC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B,CAAA;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA+CvD"}
@@ -0,0 +1,41 @@
1
+ /** Build the honest end-of-run report string. Pure — the caller prints it. */ export function renderReport(model) {
2
+ const lines = [];
3
+ lines.push('Payload v4 upgrade — mechanical steps complete', '');
4
+ lines.push('Versions written -> resolved');
5
+ for (const v of model.versions){
6
+ const resolved = v.resolved ?? '(unresolved)';
7
+ lines.push(` ${v.name} ${v.wrote} -> ${resolved} ${v.ok ? 'ok' : 'MISMATCH'}`);
8
+ }
9
+ const anyMismatch = model.versions.some((v)=>!v.ok);
10
+ if (anyMismatch) {
11
+ lines.push(' ! Resolution mismatch — tree is NOT confirmed v4. Investigate before continuing.');
12
+ }
13
+ lines.push('');
14
+ if (model.overridesRemoved.length > 0) {
15
+ lines.push(`Overrides removed: ${model.overridesRemoved.join(', ')}`, '');
16
+ }
17
+ if (model.floorsWritten.length > 0) {
18
+ lines.push(`Floors written: ${model.floorsWritten.join(', ')}`, '');
19
+ }
20
+ lines.push('Transforms');
21
+ for (const r of model.transforms){
22
+ if (r.error) {
23
+ lines.push(` [FAIL] ${r.name} — ${r.error.message}`);
24
+ continue;
25
+ }
26
+ lines.push(` [ok] ${r.name} — ${r.filesChanged.length} file(s) changed`);
27
+ for (const note of r.notes ?? []){
28
+ lines.push(` note: ${note}`);
29
+ }
30
+ }
31
+ lines.push('');
32
+ lines.push('Next.js: not upgraded by this command');
33
+ lines.push(` Target Next version: ${model.nextTarget ?? '(see @payloadcms/next peer range)'}`);
34
+ lines.push(' The unmet @payloadcms/next peer is expected until you upgrade Next — that is the immediate next step.');
35
+ lines.push('');
36
+ lines.push('Not done by this command — see the runbook for the remaining steps:');
37
+ lines.push(` ${model.runbookPath}`);
38
+ return lines.join('\n');
39
+ }
40
+
41
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/report.ts"],"sourcesContent":["import type { TransformRunResult } from '../runner.js'\n\nexport type VersionReportRow = {\n name: string\n ok: boolean\n resolved?: string\n wrote: string\n}\n\nexport type ReportModel = {\n floorsWritten: string[]\n nextTarget: null | string\n overridesRemoved: string[]\n runbookPath: string\n transforms: TransformRunResult[]\n versions: VersionReportRow[]\n}\n\n/** Build the honest end-of-run report string. Pure — the caller prints it. */\nexport function renderReport(model: ReportModel): string {\n const lines: string[] = []\n lines.push('Payload v4 upgrade — mechanical steps complete', '')\n\n lines.push('Versions written -> resolved')\n for (const v of model.versions) {\n const resolved = v.resolved ?? '(unresolved)'\n lines.push(` ${v.name} ${v.wrote} -> ${resolved} ${v.ok ? 'ok' : 'MISMATCH'}`)\n }\n const anyMismatch = model.versions.some((v) => !v.ok)\n if (anyMismatch) {\n lines.push(' ! Resolution mismatch — tree is NOT confirmed v4. Investigate before continuing.')\n }\n lines.push('')\n\n if (model.overridesRemoved.length > 0) {\n lines.push(`Overrides removed: ${model.overridesRemoved.join(', ')}`, '')\n }\n\n if (model.floorsWritten.length > 0) {\n lines.push(`Floors written: ${model.floorsWritten.join(', ')}`, '')\n }\n\n lines.push('Transforms')\n for (const r of model.transforms) {\n if (r.error) {\n lines.push(` [FAIL] ${r.name} — ${r.error.message}`)\n continue\n }\n lines.push(` [ok] ${r.name} — ${r.filesChanged.length} file(s) changed`)\n for (const note of r.notes ?? []) {\n lines.push(` note: ${note}`)\n }\n }\n lines.push('')\n\n lines.push('Next.js: not upgraded by this command')\n lines.push(` Target Next version: ${model.nextTarget ?? '(see @payloadcms/next peer range)'}`)\n lines.push(\n ' The unmet @payloadcms/next peer is expected until you upgrade Next — that is the immediate next step.',\n )\n lines.push('')\n\n lines.push('Not done by this command — see the runbook for the remaining steps:')\n lines.push(` ${model.runbookPath}`)\n\n return lines.join('\\n')\n}\n"],"names":["renderReport","model","lines","push","v","versions","resolved","name","wrote","ok","anyMismatch","some","overridesRemoved","length","join","floorsWritten","r","transforms","error","message","filesChanged","note","notes","nextTarget","runbookPath"],"mappings":"AAkBA,4EAA4E,GAC5E,OAAO,SAASA,aAAaC,KAAkB;IAC7C,MAAMC,QAAkB,EAAE;IAC1BA,MAAMC,IAAI,CAAC,kDAAkD;IAE7DD,MAAMC,IAAI,CAAC;IACX,KAAK,MAAMC,KAAKH,MAAMI,QAAQ,CAAE;QAC9B,MAAMC,WAAWF,EAAEE,QAAQ,IAAI;QAC/BJ,MAAMC,IAAI,CAAC,CAAC,EAAE,EAAEC,EAAEG,IAAI,CAAC,EAAE,EAAEH,EAAEI,KAAK,CAAC,IAAI,EAAEF,SAAS,EAAE,EAAEF,EAAEK,EAAE,GAAG,OAAO,YAAY;IAClF;IACA,MAAMC,cAAcT,MAAMI,QAAQ,CAACM,IAAI,CAAC,CAACP,IAAM,CAACA,EAAEK,EAAE;IACpD,IAAIC,aAAa;QACfR,MAAMC,IAAI,CAAC;IACb;IACAD,MAAMC,IAAI,CAAC;IAEX,IAAIF,MAAMW,gBAAgB,CAACC,MAAM,GAAG,GAAG;QACrCX,MAAMC,IAAI,CAAC,CAAC,mBAAmB,EAAEF,MAAMW,gBAAgB,CAACE,IAAI,CAAC,OAAO,EAAE;IACxE;IAEA,IAAIb,MAAMc,aAAa,CAACF,MAAM,GAAG,GAAG;QAClCX,MAAMC,IAAI,CAAC,CAAC,gBAAgB,EAAEF,MAAMc,aAAa,CAACD,IAAI,CAAC,OAAO,EAAE;IAClE;IAEAZ,MAAMC,IAAI,CAAC;IACX,KAAK,MAAMa,KAAKf,MAAMgB,UAAU,CAAE;QAChC,IAAID,EAAEE,KAAK,EAAE;YACXhB,MAAMC,IAAI,CAAC,CAAC,SAAS,EAAEa,EAAET,IAAI,CAAC,GAAG,EAAES,EAAEE,KAAK,CAACC,OAAO,EAAE;YACpD;QACF;QACAjB,MAAMC,IAAI,CAAC,CAAC,OAAO,EAAEa,EAAET,IAAI,CAAC,GAAG,EAAES,EAAEI,YAAY,CAACP,MAAM,CAAC,gBAAgB,CAAC;QACxE,KAAK,MAAMQ,QAAQL,EAAEM,KAAK,IAAI,EAAE,CAAE;YAChCpB,MAAMC,IAAI,CAAC,CAAC,YAAY,EAAEkB,MAAM;QAClC;IACF;IACAnB,MAAMC,IAAI,CAAC;IAEXD,MAAMC,IAAI,CAAC;IACXD,MAAMC,IAAI,CAAC,CAAC,uBAAuB,EAAEF,MAAMsB,UAAU,IAAI,qCAAqC;IAC9FrB,MAAMC,IAAI,CACR;IAEFD,MAAMC,IAAI,CAAC;IAEXD,MAAMC,IAAI,CAAC;IACXD,MAAMC,IAAI,CAAC,CAAC,EAAE,EAAEF,MAAMuB,WAAW,EAAE;IAEnC,OAAOtB,MAAMY,IAAI,CAAC;AACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=report.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/report.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { renderReport } from './report.js';
3
+ describe('renderReport', ()=>{
4
+ it('renders versions, overrides, transforms, next line, and runbook pointer', ()=>{
5
+ const out = renderReport({
6
+ floorsWritten: [
7
+ 'typescript',
8
+ '@types/node',
9
+ 'engines.node'
10
+ ],
11
+ nextTarget: '16.9.3',
12
+ overridesRemoved: [
13
+ 'pnpm.overrides.payload'
14
+ ],
15
+ runbookPath: '/x/dist/runbook/payload-v4-upgrade.md',
16
+ transforms: [
17
+ {
18
+ filesChanged: [
19
+ 'a.ts'
20
+ ],
21
+ name: 'migrate-versions-default',
22
+ notes: [
23
+ 'review X'
24
+ ]
25
+ }
26
+ ],
27
+ versions: [
28
+ {
29
+ name: 'payload',
30
+ ok: true,
31
+ resolved: '4.0.0-canary.20',
32
+ wrote: '4.0.0-canary.20'
33
+ }
34
+ ]
35
+ });
36
+ expect(out).toContain('payload');
37
+ expect(out).toContain('4.0.0-canary.20');
38
+ expect(out).toContain('pnpm.overrides.payload');
39
+ expect(out).toContain('migrate-versions-default');
40
+ expect(out).toContain('review X');
41
+ expect(out).toContain('16.9.3');
42
+ expect(out).toContain('payload-v4-upgrade.md');
43
+ expect(out).toContain('Floors written');
44
+ expect(out).toContain('typescript');
45
+ });
46
+ it('flags a resolution mismatch as not confirmed v4', ()=>{
47
+ const out = renderReport({
48
+ floorsWritten: [],
49
+ nextTarget: null,
50
+ overridesRemoved: [],
51
+ runbookPath: '/x/runbook.md',
52
+ transforms: [],
53
+ versions: [
54
+ {
55
+ name: 'payload',
56
+ ok: false,
57
+ resolved: '3.40.0',
58
+ wrote: '4.0.0-canary.20'
59
+ }
60
+ ]
61
+ });
62
+ expect(out).toContain('MISMATCH');
63
+ expect(out).toContain('NOT confirmed v4');
64
+ expect(out).not.toContain('Floors written');
65
+ });
66
+ it('renders a failed transform with [FAIL] and its error message', ()=>{
67
+ const out = renderReport({
68
+ floorsWritten: [],
69
+ nextTarget: null,
70
+ overridesRemoved: [],
71
+ runbookPath: '/x/runbook.md',
72
+ transforms: [
73
+ {
74
+ error: new Error('boom'),
75
+ filesChanged: [],
76
+ name: 'broken-transform'
77
+ }
78
+ ],
79
+ versions: []
80
+ });
81
+ expect(out).toContain('[FAIL]');
82
+ expect(out).toContain('broken-transform');
83
+ expect(out).toContain('boom');
84
+ });
85
+ });
86
+
87
+ //# sourceMappingURL=report.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/report.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { renderReport } from './report.js'\n\ndescribe('renderReport', () => {\n it('renders versions, overrides, transforms, next line, and runbook pointer', () => {\n const out = renderReport({\n floorsWritten: ['typescript', '@types/node', 'engines.node'],\n nextTarget: '16.9.3',\n overridesRemoved: ['pnpm.overrides.payload'],\n runbookPath: '/x/dist/runbook/payload-v4-upgrade.md',\n transforms: [\n { filesChanged: ['a.ts'], name: 'migrate-versions-default', notes: ['review X'] },\n ],\n versions: [\n { name: 'payload', ok: true, resolved: '4.0.0-canary.20', wrote: '4.0.0-canary.20' },\n ],\n })\n\n expect(out).toContain('payload')\n expect(out).toContain('4.0.0-canary.20')\n expect(out).toContain('pnpm.overrides.payload')\n expect(out).toContain('migrate-versions-default')\n expect(out).toContain('review X')\n expect(out).toContain('16.9.3')\n expect(out).toContain('payload-v4-upgrade.md')\n expect(out).toContain('Floors written')\n expect(out).toContain('typescript')\n })\n\n it('flags a resolution mismatch as not confirmed v4', () => {\n const out = renderReport({\n floorsWritten: [],\n nextTarget: null,\n overridesRemoved: [],\n runbookPath: '/x/runbook.md',\n transforms: [],\n versions: [{ name: 'payload', ok: false, resolved: '3.40.0', wrote: '4.0.0-canary.20' }],\n })\n\n expect(out).toContain('MISMATCH')\n expect(out).toContain('NOT confirmed v4')\n expect(out).not.toContain('Floors written')\n })\n\n it('renders a failed transform with [FAIL] and its error message', () => {\n const out = renderReport({\n floorsWritten: [],\n nextTarget: null,\n overridesRemoved: [],\n runbookPath: '/x/runbook.md',\n transforms: [{ error: new Error('boom'), filesChanged: [], name: 'broken-transform' }],\n versions: [],\n })\n\n expect(out).toContain('[FAIL]')\n expect(out).toContain('broken-transform')\n expect(out).toContain('boom')\n })\n})\n"],"names":["describe","expect","it","renderReport","out","floorsWritten","nextTarget","overridesRemoved","runbookPath","transforms","filesChanged","name","notes","versions","ok","resolved","wrote","toContain","not","error","Error"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,YAAY,QAAQ,cAAa;AAE1CH,SAAS,gBAAgB;IACvBE,GAAG,2EAA2E;QAC5E,MAAME,MAAMD,aAAa;YACvBE,eAAe;gBAAC;gBAAc;gBAAe;aAAe;YAC5DC,YAAY;YACZC,kBAAkB;gBAAC;aAAyB;YAC5CC,aAAa;YACbC,YAAY;gBACV;oBAAEC,cAAc;wBAAC;qBAAO;oBAAEC,MAAM;oBAA4BC,OAAO;wBAAC;qBAAW;gBAAC;aACjF;YACDC,UAAU;gBACR;oBAAEF,MAAM;oBAAWG,IAAI;oBAAMC,UAAU;oBAAmBC,OAAO;gBAAkB;aACpF;QACH;QAEAf,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;IACxB;IAEAf,GAAG,mDAAmD;QACpD,MAAME,MAAMD,aAAa;YACvBE,eAAe,EAAE;YACjBC,YAAY;YACZC,kBAAkB,EAAE;YACpBC,aAAa;YACbC,YAAY,EAAE;YACdI,UAAU;gBAAC;oBAAEF,MAAM;oBAAWG,IAAI;oBAAOC,UAAU;oBAAUC,OAAO;gBAAkB;aAAE;QAC1F;QAEAf,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKc,GAAG,CAACD,SAAS,CAAC;IAC5B;IAEAf,GAAG,gEAAgE;QACjE,MAAME,MAAMD,aAAa;YACvBE,eAAe,EAAE;YACjBC,YAAY;YACZC,kBAAkB,EAAE;YACpBC,aAAa;YACbC,YAAY;gBAAC;oBAAEU,OAAO,IAAIC,MAAM;oBAASV,cAAc,EAAE;oBAAEC,MAAM;gBAAmB;aAAE;YACtFE,UAAU,EAAE;QACd;QAEAZ,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;QACtBhB,OAAOG,KAAKa,SAAS,CAAC;IACxB;AACF"}
@@ -0,0 +1,13 @@
1
+ import type { FetchRegistry, ResolvedVersions } from './types.js';
2
+ type ResolveVersionsArgs = {
3
+ fetchRegistry: FetchRegistry;
4
+ tag: string;
5
+ };
6
+ /**
7
+ * Resolve the v4 target version set from the registry. Reads payload's engines
8
+ * and @payloadcms/next's peer range at their `tag` dist-tag, then picks the
9
+ * newest satisfying patch for @types/node and next. `nextTarget` is report-only.
10
+ */
11
+ export declare function resolveVersions({ fetchRegistry, tag, }: ResolveVersionsArgs): Promise<ResolvedVersions>;
12
+ export {};
13
+ //# sourceMappingURL=resolveVersions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveVersions.d.ts","sourceRoot":"","sources":["../../src/upgrade/resolveVersions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIjE,KAAK,mBAAmB,GAAG;IACzB,aAAa,EAAE,aAAa,CAAA;IAC5B,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,EACpC,aAAa,EACb,GAAG,GACJ,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsBjD"}
@@ -0,0 +1,55 @@
1
+ import semver from 'semver';
2
+ import { TS_FLOOR } from './types.js';
3
+ /**
4
+ * Resolve the v4 target version set from the registry. Reads payload's engines
5
+ * and @payloadcms/next's peer range at their `tag` dist-tag, then picks the
6
+ * newest satisfying patch for @types/node and next. `nextTarget` is report-only.
7
+ */ export async function resolveVersions({ fetchRegistry, tag }) {
8
+ const payloadDoc = await fetchRegistry('payload');
9
+ const payloadVersion = payloadDoc['dist-tags']?.[tag];
10
+ if (!payloadVersion) {
11
+ throw new Error(`payload has no dist-tag "${tag}" on the npm registry.`);
12
+ }
13
+ const enginesNode = payloadDoc.versions?.[payloadVersion]?.engines?.node;
14
+ if (!enginesNode) {
15
+ throw new Error(`payload@${payloadVersion} does not declare engines.node.`);
16
+ }
17
+ const typesNode = await newestWithinMajor(fetchRegistry, '@types/node', nodeMajor(enginesNode));
18
+ const nextTarget = await resolveNextTarget(fetchRegistry, tag);
19
+ return {
20
+ enginesNode,
21
+ nextTarget,
22
+ payloadVersion,
23
+ typescript: TS_FLOOR,
24
+ typesNode
25
+ };
26
+ }
27
+ function nodeMajor(enginesNode) {
28
+ const min = semver.minVersion(enginesNode);
29
+ if (!min) {
30
+ throw new Error(`Could not parse a Node major from engines.node "${enginesNode}".`);
31
+ }
32
+ return min.major;
33
+ }
34
+ async function newestWithinMajor(fetchRegistry, packageName, major) {
35
+ const doc = await fetchRegistry(packageName);
36
+ const versions = Object.keys(doc.versions ?? {});
37
+ const range = `>=${major}.0.0 <${major + 1}.0.0`;
38
+ const best = semver.maxSatisfying(versions, range);
39
+ if (!best) {
40
+ throw new Error(`No ${packageName} version found within major ${major}.`);
41
+ }
42
+ return best;
43
+ }
44
+ async function resolveNextTarget(fetchRegistry, tag) {
45
+ const nextDoc = await fetchRegistry('@payloadcms/next');
46
+ const version = nextDoc['dist-tags']?.[tag];
47
+ const range = version ? nextDoc.versions?.[version]?.peerDependencies?.next : undefined;
48
+ if (!range) {
49
+ return null;
50
+ }
51
+ const versions = Object.keys((await fetchRegistry('next')).versions ?? {});
52
+ return semver.maxSatisfying(versions, range);
53
+ }
54
+
55
+ //# sourceMappingURL=resolveVersions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/resolveVersions.ts"],"sourcesContent":["import semver from 'semver'\n\nimport type { FetchRegistry, ResolvedVersions } from './types.js'\n\nimport { TS_FLOOR } from './types.js'\n\ntype ResolveVersionsArgs = {\n fetchRegistry: FetchRegistry\n tag: string\n}\n\n/**\n * Resolve the v4 target version set from the registry. Reads payload's engines\n * and @payloadcms/next's peer range at their `tag` dist-tag, then picks the\n * newest satisfying patch for @types/node and next. `nextTarget` is report-only.\n */\nexport async function resolveVersions({\n fetchRegistry,\n tag,\n}: ResolveVersionsArgs): Promise<ResolvedVersions> {\n const payloadDoc = await fetchRegistry('payload')\n const payloadVersion = payloadDoc['dist-tags']?.[tag]\n if (!payloadVersion) {\n throw new Error(`payload has no dist-tag \"${tag}\" on the npm registry.`)\n }\n\n const enginesNode = payloadDoc.versions?.[payloadVersion]?.engines?.node\n if (!enginesNode) {\n throw new Error(`payload@${payloadVersion} does not declare engines.node.`)\n }\n\n const typesNode = await newestWithinMajor(fetchRegistry, '@types/node', nodeMajor(enginesNode))\n const nextTarget = await resolveNextTarget(fetchRegistry, tag)\n\n return {\n enginesNode,\n nextTarget,\n payloadVersion,\n typescript: TS_FLOOR,\n typesNode,\n }\n}\n\nfunction nodeMajor(enginesNode: string): number {\n const min = semver.minVersion(enginesNode)\n if (!min) {\n throw new Error(`Could not parse a Node major from engines.node \"${enginesNode}\".`)\n }\n return min.major\n}\n\nasync function newestWithinMajor(\n fetchRegistry: FetchRegistry,\n packageName: string,\n major: number,\n): Promise<string> {\n const doc = await fetchRegistry(packageName)\n const versions = Object.keys(doc.versions ?? {})\n const range = `>=${major}.0.0 <${major + 1}.0.0`\n const best = semver.maxSatisfying(versions, range)\n if (!best) {\n throw new Error(`No ${packageName} version found within major ${major}.`)\n }\n return best\n}\n\nasync function resolveNextTarget(\n fetchRegistry: FetchRegistry,\n tag: string,\n): Promise<null | string> {\n const nextDoc = await fetchRegistry('@payloadcms/next')\n const version = nextDoc['dist-tags']?.[tag]\n const range = version ? nextDoc.versions?.[version]?.peerDependencies?.next : undefined\n if (!range) {\n return null\n }\n const versions = Object.keys((await fetchRegistry('next')).versions ?? {})\n return semver.maxSatisfying(versions, range)\n}\n"],"names":["semver","TS_FLOOR","resolveVersions","fetchRegistry","tag","payloadDoc","payloadVersion","Error","enginesNode","versions","engines","node","typesNode","newestWithinMajor","nodeMajor","nextTarget","resolveNextTarget","typescript","min","minVersion","major","packageName","doc","Object","keys","range","best","maxSatisfying","nextDoc","version","peerDependencies","next","undefined"],"mappings":"AAAA,OAAOA,YAAY,SAAQ;AAI3B,SAASC,QAAQ,QAAQ,aAAY;AAOrC;;;;CAIC,GACD,OAAO,eAAeC,gBAAgB,EACpCC,aAAa,EACbC,GAAG,EACiB;IACpB,MAAMC,aAAa,MAAMF,cAAc;IACvC,MAAMG,iBAAiBD,UAAU,CAAC,YAAY,EAAE,CAACD,IAAI;IACrD,IAAI,CAACE,gBAAgB;QACnB,MAAM,IAAIC,MAAM,CAAC,yBAAyB,EAAEH,IAAI,sBAAsB,CAAC;IACzE;IAEA,MAAMI,cAAcH,WAAWI,QAAQ,EAAE,CAACH,eAAe,EAAEI,SAASC;IACpE,IAAI,CAACH,aAAa;QAChB,MAAM,IAAID,MAAM,CAAC,QAAQ,EAAED,eAAe,+BAA+B,CAAC;IAC5E;IAEA,MAAMM,YAAY,MAAMC,kBAAkBV,eAAe,eAAeW,UAAUN;IAClF,MAAMO,aAAa,MAAMC,kBAAkBb,eAAeC;IAE1D,OAAO;QACLI;QACAO;QACAT;QACAW,YAAYhB;QACZW;IACF;AACF;AAEA,SAASE,UAAUN,WAAmB;IACpC,MAAMU,MAAMlB,OAAOmB,UAAU,CAACX;IAC9B,IAAI,CAACU,KAAK;QACR,MAAM,IAAIX,MAAM,CAAC,gDAAgD,EAAEC,YAAY,EAAE,CAAC;IACpF;IACA,OAAOU,IAAIE,KAAK;AAClB;AAEA,eAAeP,kBACbV,aAA4B,EAC5BkB,WAAmB,EACnBD,KAAa;IAEb,MAAME,MAAM,MAAMnB,cAAckB;IAChC,MAAMZ,WAAWc,OAAOC,IAAI,CAACF,IAAIb,QAAQ,IAAI,CAAC;IAC9C,MAAMgB,QAAQ,CAAC,EAAE,EAAEL,MAAM,MAAM,EAAEA,QAAQ,EAAE,IAAI,CAAC;IAChD,MAAMM,OAAO1B,OAAO2B,aAAa,CAAClB,UAAUgB;IAC5C,IAAI,CAACC,MAAM;QACT,MAAM,IAAInB,MAAM,CAAC,GAAG,EAAEc,YAAY,4BAA4B,EAAED,MAAM,CAAC,CAAC;IAC1E;IACA,OAAOM;AACT;AAEA,eAAeV,kBACbb,aAA4B,EAC5BC,GAAW;IAEX,MAAMwB,UAAU,MAAMzB,cAAc;IACpC,MAAM0B,UAAUD,OAAO,CAAC,YAAY,EAAE,CAACxB,IAAI;IAC3C,MAAMqB,QAAQI,UAAUD,QAAQnB,QAAQ,EAAE,CAACoB,QAAQ,EAAEC,kBAAkBC,OAAOC;IAC9E,IAAI,CAACP,OAAO;QACV,OAAO;IACT;IACA,MAAMhB,WAAWc,OAAOC,IAAI,CAAC,AAAC,CAAA,MAAMrB,cAAc,OAAM,EAAGM,QAAQ,IAAI,CAAC;IACxE,OAAOT,OAAO2B,aAAa,CAAClB,UAAUgB;AACxC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resolveVersions.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveVersions.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/resolveVersions.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,82 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { resolveVersions } from './resolveVersions.js';
3
+ const packuments = {
4
+ '@payloadcms/next': {
5
+ 'dist-tags': {
6
+ canary: '4.0.0-canary.20'
7
+ },
8
+ versions: {
9
+ '4.0.0-canary.20': {
10
+ peerDependencies: {
11
+ next: '>=16.2.6 <17.0.0'
12
+ }
13
+ }
14
+ }
15
+ },
16
+ '@types/node': {
17
+ 'dist-tags': {
18
+ latest: '24.12.3'
19
+ },
20
+ versions: {
21
+ '22.9.0': {},
22
+ '24.10.0': {},
23
+ '24.12.3': {},
24
+ '25.0.0': {}
25
+ }
26
+ },
27
+ next: {
28
+ 'dist-tags': {
29
+ latest: '16.9.3'
30
+ },
31
+ versions: {
32
+ '15.5.0': {},
33
+ '16.2.6': {},
34
+ '16.9.3': {},
35
+ '17.0.0': {}
36
+ }
37
+ },
38
+ payload: {
39
+ 'dist-tags': {
40
+ canary: '4.0.0-canary.20'
41
+ },
42
+ versions: {
43
+ '4.0.0-canary.20': {
44
+ engines: {
45
+ node: '>=24.15.0'
46
+ }
47
+ }
48
+ }
49
+ }
50
+ };
51
+ const fetchRegistry = (name)=>{
52
+ const found = packuments[name];
53
+ if (!found) {
54
+ throw new Error(`unexpected fetch: ${name}`);
55
+ }
56
+ return Promise.resolve(found);
57
+ };
58
+ describe('resolveVersions', ()=>{
59
+ it('computes the written targets and the report-only Next target', async ()=>{
60
+ const resolved = await resolveVersions({
61
+ fetchRegistry,
62
+ tag: 'canary'
63
+ });
64
+ expect(resolved).toEqual({
65
+ enginesNode: '>=24.15.0',
66
+ nextTarget: '16.9.3',
67
+ payloadVersion: '4.0.0-canary.20',
68
+ typesNode: '24.12.3',
69
+ typescript: '6.0.3'
70
+ });
71
+ });
72
+ it('throws when the dist-tag is missing', async ()=>{
73
+ await expect(resolveVersions({
74
+ fetchRegistry: ()=>Promise.resolve({
75
+ 'dist-tags': {}
76
+ }),
77
+ tag: 'canary'
78
+ })).rejects.toThrow(/dist-tag "canary"/);
79
+ });
80
+ });
81
+
82
+ //# sourceMappingURL=resolveVersions.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/resolveVersions.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport type { FetchRegistry, RegistryPackument } from './types.js'\n\nimport { resolveVersions } from './resolveVersions.js'\n\nconst packuments: Record<string, RegistryPackument> = {\n '@payloadcms/next': {\n 'dist-tags': { canary: '4.0.0-canary.20' },\n versions: {\n '4.0.0-canary.20': { peerDependencies: { next: '>=16.2.6 <17.0.0' } },\n },\n },\n '@types/node': {\n 'dist-tags': { latest: '24.12.3' },\n versions: {\n '22.9.0': {},\n '24.10.0': {},\n '24.12.3': {},\n '25.0.0': {},\n },\n },\n next: {\n 'dist-tags': { latest: '16.9.3' },\n versions: {\n '15.5.0': {},\n '16.2.6': {},\n '16.9.3': {},\n '17.0.0': {},\n },\n },\n payload: {\n 'dist-tags': { canary: '4.0.0-canary.20' },\n versions: {\n '4.0.0-canary.20': { engines: { node: '>=24.15.0' } },\n },\n },\n}\n\nconst fetchRegistry: FetchRegistry = (name) => {\n const found = packuments[name]\n if (!found) {\n throw new Error(`unexpected fetch: ${name}`)\n }\n return Promise.resolve(found)\n}\n\ndescribe('resolveVersions', () => {\n it('computes the written targets and the report-only Next target', async () => {\n const resolved = await resolveVersions({ fetchRegistry, tag: 'canary' })\n\n expect(resolved).toEqual({\n enginesNode: '>=24.15.0',\n nextTarget: '16.9.3', // newest within >=16.2.6 <17, excludes 17.0.0\n payloadVersion: '4.0.0-canary.20',\n typesNode: '24.12.3', // newest within major 24, excludes 25.0.0\n typescript: '6.0.3',\n })\n })\n\n it('throws when the dist-tag is missing', async () => {\n await expect(\n resolveVersions({\n fetchRegistry: () => Promise.resolve({ 'dist-tags': {} }),\n tag: 'canary',\n }),\n ).rejects.toThrow(/dist-tag \"canary\"/)\n })\n})\n"],"names":["describe","expect","it","resolveVersions","packuments","canary","versions","peerDependencies","next","latest","payload","engines","node","fetchRegistry","name","found","Error","Promise","resolve","resolved","tag","toEqual","enginesNode","nextTarget","payloadVersion","typesNode","typescript","rejects","toThrow"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAI7C,SAASC,eAAe,QAAQ,uBAAsB;AAEtD,MAAMC,aAAgD;IACpD,oBAAoB;QAClB,aAAa;YAAEC,QAAQ;QAAkB;QACzCC,UAAU;YACR,mBAAmB;gBAAEC,kBAAkB;oBAAEC,MAAM;gBAAmB;YAAE;QACtE;IACF;IACA,eAAe;QACb,aAAa;YAAEC,QAAQ;QAAU;QACjCH,UAAU;YACR,UAAU,CAAC;YACX,WAAW,CAAC;YACZ,WAAW,CAAC;YACZ,UAAU,CAAC;QACb;IACF;IACAE,MAAM;QACJ,aAAa;YAAEC,QAAQ;QAAS;QAChCH,UAAU;YACR,UAAU,CAAC;YACX,UAAU,CAAC;YACX,UAAU,CAAC;YACX,UAAU,CAAC;QACb;IACF;IACAI,SAAS;QACP,aAAa;YAAEL,QAAQ;QAAkB;QACzCC,UAAU;YACR,mBAAmB;gBAAEK,SAAS;oBAAEC,MAAM;gBAAY;YAAE;QACtD;IACF;AACF;AAEA,MAAMC,gBAA+B,CAACC;IACpC,MAAMC,QAAQX,UAAU,CAACU,KAAK;IAC9B,IAAI,CAACC,OAAO;QACV,MAAM,IAAIC,MAAM,CAAC,kBAAkB,EAAEF,MAAM;IAC7C;IACA,OAAOG,QAAQC,OAAO,CAACH;AACzB;AAEAf,SAAS,mBAAmB;IAC1BE,GAAG,gEAAgE;QACjE,MAAMiB,WAAW,MAAMhB,gBAAgB;YAAEU;YAAeO,KAAK;QAAS;QAEtEnB,OAAOkB,UAAUE,OAAO,CAAC;YACvBC,aAAa;YACbC,YAAY;YACZC,gBAAgB;YAChBC,WAAW;YACXC,YAAY;QACd;IACF;IAEAxB,GAAG,uCAAuC;QACxC,MAAMD,OACJE,gBAAgB;YACdU,eAAe,IAAMI,QAAQC,OAAO,CAAC;oBAAE,aAAa,CAAC;gBAAE;YACvDE,KAAK;QACP,IACAO,OAAO,CAACC,OAAO,CAAC;IACpB;AACF"}
@@ -0,0 +1,25 @@
1
+ import type { ResolvedVersions } from './types.js';
2
+ type RewriteArgs = {
3
+ data: Record<string, unknown>;
4
+ resolved: ResolvedVersions;
5
+ };
6
+ export type RewriteSummary = {
7
+ floorsWritten: string[];
8
+ overridesRemoved: string[];
9
+ pinnedPayload: string[];
10
+ };
11
+ export declare const isPayloadPackage: (name: string) => boolean;
12
+ /**
13
+ * The `@payloadcms/eslint-*` packages are versioned independently of the core
14
+ * payload packages, so they are tracked on `latest` rather than lockstep-pinned.
15
+ */
16
+ export declare const isPayloadEslintPackage: (name: string) => boolean;
17
+ /**
18
+ * Mutate `data` in place for a v4 upgrade: exact-pin payload packages, drop
19
+ * payload dependency overrides, and write the toolchain floors. Never touches
20
+ * next/react — the Next.js upgrade is delegated to Next's own workflow.
21
+ * Returns a summary for the report. Idempotent.
22
+ */
23
+ export declare function rewritePackageJson({ data, resolved }: RewriteArgs): RewriteSummary;
24
+ export {};
25
+ //# sourceMappingURL=rewritePackageJson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewritePackageJson.d.ts","sourceRoot":"","sources":["../../src/upgrade/rewritePackageJson.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,gBAAgB,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AAID,eAAO,MAAM,gBAAgB,SAAU,MAAM,KAAG,OACO,CAAA;AAEvD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,SAAU,MAAM,KAAG,OACf,CAAA;AAEvC;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,GAAG,cAAc,CAKlF"}