@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.
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,106 @@
1
+ const DEP_FIELDS = [
2
+ 'dependencies',
3
+ 'devDependencies'
4
+ ];
5
+ export const isPayloadPackage = (name)=>name === 'payload' || name.startsWith('@payloadcms/');
6
+ /**
7
+ * The `@payloadcms/eslint-*` packages are versioned independently of the core
8
+ * payload packages, so they are tracked on `latest` rather than lockstep-pinned.
9
+ */ export const isPayloadEslintPackage = (name)=>name.startsWith('@payloadcms/eslint');
10
+ /**
11
+ * Mutate `data` in place for a v4 upgrade: exact-pin payload packages, drop
12
+ * payload dependency overrides, and write the toolchain floors. Never touches
13
+ * next/react — the Next.js upgrade is delegated to Next's own workflow.
14
+ * Returns a summary for the report. Idempotent.
15
+ */ export function rewritePackageJson({ data, resolved }) {
16
+ const pinnedPayload = pinPayloadPackages(data, resolved.payloadVersion);
17
+ const overridesRemoved = removePayloadOverrides(data);
18
+ const floorsWritten = writeFloors(data, resolved);
19
+ return {
20
+ floorsWritten,
21
+ overridesRemoved,
22
+ pinnedPayload
23
+ };
24
+ }
25
+ function pinPayloadPackages(data, version) {
26
+ const pinned = [];
27
+ for (const field of DEP_FIELDS){
28
+ const deps = data[field];
29
+ if (!isRecord(deps)) {
30
+ continue;
31
+ }
32
+ for (const name of Object.keys(deps)){
33
+ if (isPayloadEslintPackage(name)) {
34
+ deps[name] = 'latest';
35
+ continue;
36
+ }
37
+ if (isPayloadPackage(name)) {
38
+ deps[name] = version;
39
+ pinned.push(name);
40
+ }
41
+ }
42
+ }
43
+ return pinned;
44
+ }
45
+ function removePayloadOverrides(data) {
46
+ const removed = [];
47
+ const pnpm = data.pnpm;
48
+ if (isRecord(pnpm) && isRecord(pnpm.overrides)) {
49
+ pruneOverrideBlock(pnpm.overrides, 'pnpm.overrides', removed);
50
+ if (Object.keys(pnpm.overrides).length === 0) {
51
+ delete pnpm.overrides;
52
+ }
53
+ if (Object.keys(pnpm).length === 0) {
54
+ delete data.pnpm;
55
+ }
56
+ }
57
+ for (const key of [
58
+ 'overrides',
59
+ 'resolutions'
60
+ ]){
61
+ const block = data[key];
62
+ if (isRecord(block)) {
63
+ pruneOverrideBlock(block, key, removed);
64
+ if (Object.keys(block).length === 0) {
65
+ delete data[key];
66
+ }
67
+ }
68
+ }
69
+ return removed;
70
+ }
71
+ function pruneOverrideBlock(block, label, removed) {
72
+ for (const name of Object.keys(block)){
73
+ if (isPayloadPackage(name)) {
74
+ delete block[name];
75
+ removed.push(`${label}.${name}`);
76
+ }
77
+ }
78
+ }
79
+ function writeFloors(data, resolved) {
80
+ const written = [];
81
+ pinDep(data, 'typescript', resolved.typescript);
82
+ pinDep(data, '@types/node', resolved.typesNode);
83
+ written.push('typescript', '@types/node');
84
+ const engines = isRecord(data.engines) ? data.engines : {};
85
+ engines.node = resolved.enginesNode;
86
+ data.engines = engines;
87
+ written.push('engines.node');
88
+ return written;
89
+ }
90
+ /** Update a dep wherever it already lives, else add it to devDependencies. */ function pinDep(data, name, version) {
91
+ for (const field of DEP_FIELDS){
92
+ const deps = data[field];
93
+ if (isRecord(deps) && name in deps) {
94
+ deps[name] = version;
95
+ return;
96
+ }
97
+ }
98
+ const devDeps = isRecord(data.devDependencies) ? data.devDependencies : {};
99
+ devDeps[name] = version;
100
+ data.devDependencies = devDeps;
101
+ }
102
+ function isRecord(value) {
103
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
104
+ }
105
+
106
+ //# sourceMappingURL=rewritePackageJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/rewritePackageJson.ts"],"sourcesContent":["import type { ResolvedVersions } from './types.js'\n\ntype RewriteArgs = {\n data: Record<string, unknown>\n resolved: ResolvedVersions\n}\n\nexport type RewriteSummary = {\n floorsWritten: string[]\n overridesRemoved: string[]\n pinnedPayload: string[]\n}\n\nconst DEP_FIELDS = ['dependencies', 'devDependencies'] as const\n\nexport const isPayloadPackage = (name: string): boolean =>\n name === 'payload' || name.startsWith('@payloadcms/')\n\n/**\n * The `@payloadcms/eslint-*` packages are versioned independently of the core\n * payload packages, so they are tracked on `latest` rather than lockstep-pinned.\n */\nexport const isPayloadEslintPackage = (name: string): boolean =>\n name.startsWith('@payloadcms/eslint')\n\n/**\n * Mutate `data` in place for a v4 upgrade: exact-pin payload packages, drop\n * payload dependency overrides, and write the toolchain floors. Never touches\n * next/react — the Next.js upgrade is delegated to Next's own workflow.\n * Returns a summary for the report. Idempotent.\n */\nexport function rewritePackageJson({ data, resolved }: RewriteArgs): RewriteSummary {\n const pinnedPayload = pinPayloadPackages(data, resolved.payloadVersion)\n const overridesRemoved = removePayloadOverrides(data)\n const floorsWritten = writeFloors(data, resolved)\n return { floorsWritten, overridesRemoved, pinnedPayload }\n}\n\nfunction pinPayloadPackages(data: Record<string, unknown>, version: string): string[] {\n const pinned: string[] = []\n for (const field of DEP_FIELDS) {\n const deps = data[field]\n if (!isRecord(deps)) {\n continue\n }\n for (const name of Object.keys(deps)) {\n if (isPayloadEslintPackage(name)) {\n deps[name] = 'latest'\n continue\n }\n if (isPayloadPackage(name)) {\n deps[name] = version\n pinned.push(name)\n }\n }\n }\n return pinned\n}\n\nfunction removePayloadOverrides(data: Record<string, unknown>): string[] {\n const removed: string[] = []\n\n const pnpm = data.pnpm\n if (isRecord(pnpm) && isRecord(pnpm.overrides)) {\n pruneOverrideBlock(pnpm.overrides, 'pnpm.overrides', removed)\n if (Object.keys(pnpm.overrides).length === 0) {\n delete pnpm.overrides\n }\n if (Object.keys(pnpm).length === 0) {\n delete data.pnpm\n }\n }\n\n for (const key of ['overrides', 'resolutions'] as const) {\n const block = data[key]\n if (isRecord(block)) {\n pruneOverrideBlock(block, key, removed)\n if (Object.keys(block).length === 0) {\n delete data[key]\n }\n }\n }\n\n return removed\n}\n\nfunction pruneOverrideBlock(\n block: Record<string, unknown>,\n label: string,\n removed: string[],\n): void {\n for (const name of Object.keys(block)) {\n if (isPayloadPackage(name)) {\n delete block[name]\n removed.push(`${label}.${name}`)\n }\n }\n}\n\nfunction writeFloors(data: Record<string, unknown>, resolved: ResolvedVersions): string[] {\n const written: string[] = []\n pinDep(data, 'typescript', resolved.typescript)\n pinDep(data, '@types/node', resolved.typesNode)\n written.push('typescript', '@types/node')\n\n const engines = isRecord(data.engines) ? data.engines : {}\n engines.node = resolved.enginesNode\n data.engines = engines\n written.push('engines.node')\n\n return written\n}\n\n/** Update a dep wherever it already lives, else add it to devDependencies. */\nfunction pinDep(data: Record<string, unknown>, name: string, version: string): void {\n for (const field of DEP_FIELDS) {\n const deps = data[field]\n if (isRecord(deps) && name in deps) {\n deps[name] = version\n return\n }\n }\n const devDeps = isRecord(data.devDependencies) ? data.devDependencies : {}\n devDeps[name] = version\n data.devDependencies = devDeps\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n"],"names":["DEP_FIELDS","isPayloadPackage","name","startsWith","isPayloadEslintPackage","rewritePackageJson","data","resolved","pinnedPayload","pinPayloadPackages","payloadVersion","overridesRemoved","removePayloadOverrides","floorsWritten","writeFloors","version","pinned","field","deps","isRecord","Object","keys","push","removed","pnpm","overrides","pruneOverrideBlock","length","key","block","label","written","pinDep","typescript","typesNode","engines","node","enginesNode","devDeps","devDependencies","value","Array","isArray"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rewritePackageJson.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewritePackageJson.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/rewritePackageJson.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { rewritePackageJson } from './rewritePackageJson.js';
3
+ const resolved = {
4
+ enginesNode: '>=24.15.0',
5
+ nextTarget: '16.9.3',
6
+ payloadVersion: '4.0.0-canary.20',
7
+ typesNode: '24.12.3',
8
+ typescript: '6.0.3'
9
+ };
10
+ const baseInput = ()=>({
11
+ dependencies: {
12
+ '@payloadcms/next': '^3.0.0',
13
+ '@payloadcms/ui': '~3.0.0',
14
+ next: '15.5.0',
15
+ payload: '^3.0.0',
16
+ react: '19.0.0'
17
+ },
18
+ devDependencies: {
19
+ '@payloadcms/eslint-config': '^3.0.0',
20
+ '@payloadcms/eslint-plugin': '^3.0.0',
21
+ '@types/node': '22.9.0',
22
+ typescript: '5.7.3'
23
+ },
24
+ engines: {
25
+ node: '>=18.20.2'
26
+ },
27
+ pnpm: {
28
+ overrides: {
29
+ payload: '3.0.0',
30
+ 'some-other': '1.0.0'
31
+ }
32
+ },
33
+ resolutions: {
34
+ '@payloadcms/ui': '3.0.0'
35
+ }
36
+ });
37
+ describe('rewritePackageJson', ()=>{
38
+ it('pins payload packages exactly, deletes payload overrides, writes floors, leaves next/react', ()=>{
39
+ const data = baseInput();
40
+ const summary = rewritePackageJson({
41
+ data,
42
+ resolved
43
+ });
44
+ expect(data).toEqual({
45
+ dependencies: {
46
+ '@payloadcms/next': '4.0.0-canary.20',
47
+ '@payloadcms/ui': '4.0.0-canary.20',
48
+ next: '15.5.0',
49
+ payload: '4.0.0-canary.20',
50
+ react: '19.0.0'
51
+ },
52
+ devDependencies: {
53
+ '@payloadcms/eslint-config': 'latest',
54
+ '@payloadcms/eslint-plugin': 'latest',
55
+ '@types/node': '24.12.3',
56
+ typescript: '6.0.3'
57
+ },
58
+ engines: {
59
+ node: '>=24.15.0'
60
+ },
61
+ pnpm: {
62
+ overrides: {
63
+ 'some-other': '1.0.0'
64
+ }
65
+ }
66
+ });
67
+ expect(summary.overridesRemoved.sort()).toEqual([
68
+ 'pnpm.overrides.payload',
69
+ 'resolutions.@payloadcms/ui'
70
+ ].sort());
71
+ expect(summary.pinnedPayload).toContain('payload');
72
+ // eslint packages are not lockstep-pinned
73
+ expect(summary.pinnedPayload).not.toContain('@payloadcms/eslint-config');
74
+ });
75
+ it('adds floors to devDependencies when absent', ()=>{
76
+ const data = {
77
+ dependencies: {
78
+ payload: '^3.0.0'
79
+ }
80
+ };
81
+ rewritePackageJson({
82
+ data,
83
+ resolved
84
+ });
85
+ expect(data.devDependencies).toEqual({
86
+ '@types/node': '24.12.3',
87
+ typescript: '6.0.3'
88
+ });
89
+ expect(data.engines).toEqual({
90
+ node: '>=24.15.0'
91
+ });
92
+ });
93
+ it('is idempotent', ()=>{
94
+ const data = baseInput();
95
+ rewritePackageJson({
96
+ data,
97
+ resolved
98
+ });
99
+ const once = JSON.stringify(data);
100
+ rewritePackageJson({
101
+ data,
102
+ resolved
103
+ });
104
+ expect(JSON.stringify(data)).toBe(once);
105
+ });
106
+ });
107
+
108
+ //# sourceMappingURL=rewritePackageJson.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/rewritePackageJson.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport type { ResolvedVersions } from './types.js'\n\nimport { rewritePackageJson } from './rewritePackageJson.js'\n\nconst resolved: ResolvedVersions = {\n enginesNode: '>=24.15.0',\n nextTarget: '16.9.3',\n payloadVersion: '4.0.0-canary.20',\n typesNode: '24.12.3',\n typescript: '6.0.3',\n}\n\nconst baseInput = () => ({\n dependencies: {\n '@payloadcms/next': '^3.0.0',\n '@payloadcms/ui': '~3.0.0',\n next: '15.5.0',\n payload: '^3.0.0',\n react: '19.0.0',\n },\n devDependencies: {\n '@payloadcms/eslint-config': '^3.0.0',\n '@payloadcms/eslint-plugin': '^3.0.0',\n '@types/node': '22.9.0',\n typescript: '5.7.3',\n },\n engines: { node: '>=18.20.2' },\n pnpm: { overrides: { payload: '3.0.0', 'some-other': '1.0.0' } },\n resolutions: { '@payloadcms/ui': '3.0.0' },\n})\n\ndescribe('rewritePackageJson', () => {\n it('pins payload packages exactly, deletes payload overrides, writes floors, leaves next/react', () => {\n const data = baseInput() as Record<string, unknown>\n\n const summary = rewritePackageJson({ data, resolved })\n\n expect(data).toEqual({\n dependencies: {\n '@payloadcms/next': '4.0.0-canary.20',\n '@payloadcms/ui': '4.0.0-canary.20',\n next: '15.5.0', // untouched\n payload: '4.0.0-canary.20',\n react: '19.0.0', // untouched\n },\n devDependencies: {\n '@payloadcms/eslint-config': 'latest', // versioned independently\n '@payloadcms/eslint-plugin': 'latest', // versioned independently\n '@types/node': '24.12.3',\n typescript: '6.0.3',\n },\n engines: { node: '>=24.15.0' },\n pnpm: { overrides: { 'some-other': '1.0.0' } }, // payload override removed, unrelated kept\n // resolutions removed entirely (only key was a payload package)\n })\n expect(summary.overridesRemoved.sort()).toEqual(\n ['pnpm.overrides.payload', 'resolutions.@payloadcms/ui'].sort(),\n )\n expect(summary.pinnedPayload).toContain('payload')\n // eslint packages are not lockstep-pinned\n expect(summary.pinnedPayload).not.toContain('@payloadcms/eslint-config')\n })\n\n it('adds floors to devDependencies when absent', () => {\n const data: Record<string, unknown> = { dependencies: { payload: '^3.0.0' } }\n\n rewritePackageJson({ data, resolved })\n\n expect(data.devDependencies).toEqual({\n '@types/node': '24.12.3',\n typescript: '6.0.3',\n })\n expect(data.engines).toEqual({ node: '>=24.15.0' })\n })\n\n it('is idempotent', () => {\n const data = baseInput() as Record<string, unknown>\n\n rewritePackageJson({ data, resolved })\n const once = JSON.stringify(data)\n rewritePackageJson({ data, resolved })\n\n expect(JSON.stringify(data)).toBe(once)\n })\n})\n"],"names":["describe","expect","it","rewritePackageJson","resolved","enginesNode","nextTarget","payloadVersion","typesNode","typescript","baseInput","dependencies","next","payload","react","devDependencies","engines","node","pnpm","overrides","resolutions","data","summary","toEqual","overridesRemoved","sort","pinnedPayload","toContain","not","once","JSON","stringify","toBe"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAI7C,SAASC,kBAAkB,QAAQ,0BAAyB;AAE5D,MAAMC,WAA6B;IACjCC,aAAa;IACbC,YAAY;IACZC,gBAAgB;IAChBC,WAAW;IACXC,YAAY;AACd;AAEA,MAAMC,YAAY,IAAO,CAAA;QACvBC,cAAc;YACZ,oBAAoB;YACpB,kBAAkB;YAClBC,MAAM;YACNC,SAAS;YACTC,OAAO;QACT;QACAC,iBAAiB;YACf,6BAA6B;YAC7B,6BAA6B;YAC7B,eAAe;YACfN,YAAY;QACd;QACAO,SAAS;YAAEC,MAAM;QAAY;QAC7BC,MAAM;YAAEC,WAAW;gBAAEN,SAAS;gBAAS,cAAc;YAAQ;QAAE;QAC/DO,aAAa;YAAE,kBAAkB;QAAQ;IAC3C,CAAA;AAEApB,SAAS,sBAAsB;IAC7BE,GAAG,8FAA8F;QAC/F,MAAMmB,OAAOX;QAEb,MAAMY,UAAUnB,mBAAmB;YAAEkB;YAAMjB;QAAS;QAEpDH,OAAOoB,MAAME,OAAO,CAAC;YACnBZ,cAAc;gBACZ,oBAAoB;gBACpB,kBAAkB;gBAClBC,MAAM;gBACNC,SAAS;gBACTC,OAAO;YACT;YACAC,iBAAiB;gBACf,6BAA6B;gBAC7B,6BAA6B;gBAC7B,eAAe;gBACfN,YAAY;YACd;YACAO,SAAS;gBAAEC,MAAM;YAAY;YAC7BC,MAAM;gBAAEC,WAAW;oBAAE,cAAc;gBAAQ;YAAE;QAE/C;QACAlB,OAAOqB,QAAQE,gBAAgB,CAACC,IAAI,IAAIF,OAAO,CAC7C;YAAC;YAA0B;SAA6B,CAACE,IAAI;QAE/DxB,OAAOqB,QAAQI,aAAa,EAAEC,SAAS,CAAC;QACxC,0CAA0C;QAC1C1B,OAAOqB,QAAQI,aAAa,EAAEE,GAAG,CAACD,SAAS,CAAC;IAC9C;IAEAzB,GAAG,8CAA8C;QAC/C,MAAMmB,OAAgC;YAAEV,cAAc;gBAAEE,SAAS;YAAS;QAAE;QAE5EV,mBAAmB;YAAEkB;YAAMjB;QAAS;QAEpCH,OAAOoB,KAAKN,eAAe,EAAEQ,OAAO,CAAC;YACnC,eAAe;YACfd,YAAY;QACd;QACAR,OAAOoB,KAAKL,OAAO,EAAEO,OAAO,CAAC;YAAEN,MAAM;QAAY;IACnD;IAEAf,GAAG,iBAAiB;QAClB,MAAMmB,OAAOX;QAEbP,mBAAmB;YAAEkB;YAAMjB;QAAS;QACpC,MAAMyB,OAAOC,KAAKC,SAAS,CAACV;QAC5BlB,mBAAmB;YAAEkB;YAAMjB;QAAS;QAEpCH,OAAO6B,KAAKC,SAAS,CAACV,OAAOW,IAAI,CAACH;IACpC;AACF"}
@@ -0,0 +1,16 @@
1
+ import type { PackageManager, Spawn } from './types.js';
2
+ type RunInstallArgs = {
3
+ packageManager: PackageManager;
4
+ path: string;
5
+ spawn: Spawn;
6
+ };
7
+ /**
8
+ * Install dependencies with the detected package manager. `install` is the same
9
+ * subcommand across pnpm/npm/yarn/bun. Corepack's interactive download prompt is
10
+ * disabled so a non-interactive run cannot hang and abort the install.
11
+ */
12
+ export declare function runInstall({ packageManager, path, spawn, }: RunInstallArgs): Promise<{
13
+ code: number;
14
+ }>;
15
+ export {};
16
+ //# sourceMappingURL=runInstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runInstall.d.ts","sourceRoot":"","sources":["../../src/upgrade/runInstall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvD,KAAK,cAAc,GAAG;IACpB,cAAc,EAAE,cAAc,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACzB,cAAc,EACd,IAAI,EACJ,KAAK,GACN,EAAE,cAAc,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAK5C"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Install dependencies with the detected package manager. `install` is the same
3
+ * subcommand across pnpm/npm/yarn/bun. Corepack's interactive download prompt is
4
+ * disabled so a non-interactive run cannot hang and abort the install.
5
+ */ export function runInstall({ packageManager, path, spawn }) {
6
+ return spawn(packageManager, [
7
+ 'install'
8
+ ], {
9
+ cwd: path,
10
+ env: {
11
+ ...process.env,
12
+ COREPACK_ENABLE_DOWNLOAD_PROMPT: '0'
13
+ }
14
+ });
15
+ }
16
+
17
+ //# sourceMappingURL=runInstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/runInstall.ts"],"sourcesContent":["import type { PackageManager, Spawn } from './types.js'\n\ntype RunInstallArgs = {\n packageManager: PackageManager\n path: string\n spawn: Spawn\n}\n\n/**\n * Install dependencies with the detected package manager. `install` is the same\n * subcommand across pnpm/npm/yarn/bun. Corepack's interactive download prompt is\n * disabled so a non-interactive run cannot hang and abort the install.\n */\nexport function runInstall({\n packageManager,\n path,\n spawn,\n}: RunInstallArgs): Promise<{ code: number }> {\n return spawn(packageManager, ['install'], {\n cwd: path,\n env: { ...process.env, COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' },\n })\n}\n"],"names":["runInstall","packageManager","path","spawn","cwd","env","process","COREPACK_ENABLE_DOWNLOAD_PROMPT"],"mappings":"AAQA;;;;CAIC,GACD,OAAO,SAASA,WAAW,EACzBC,cAAc,EACdC,IAAI,EACJC,KAAK,EACU;IACf,OAAOA,MAAMF,gBAAgB;QAAC;KAAU,EAAE;QACxCG,KAAKF;QACLG,KAAK;YAAE,GAAGC,QAAQD,GAAG;YAAEE,iCAAiC;QAAI;IAC9D;AACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runInstall.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runInstall.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/runInstall.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { runInstall } from './runInstall.js';
3
+ describe('runInstall', ()=>{
4
+ it('invokes the detected package manager install with corepack prompt disabled', async ()=>{
5
+ const spawn = vi.fn().mockResolvedValue({
6
+ code: 0
7
+ });
8
+ const result = await runInstall({
9
+ packageManager: 'pnpm',
10
+ path: '/project',
11
+ spawn
12
+ });
13
+ expect(result).toEqual({
14
+ code: 0
15
+ });
16
+ expect(spawn).toHaveBeenCalledWith('pnpm', [
17
+ 'install'
18
+ ], {
19
+ cwd: '/project',
20
+ env: expect.objectContaining({
21
+ COREPACK_ENABLE_DOWNLOAD_PROMPT: '0'
22
+ })
23
+ });
24
+ });
25
+ it('uses the right binary for each package manager', async ()=>{
26
+ const spawn = vi.fn().mockResolvedValue({
27
+ code: 0
28
+ });
29
+ for (const pm of [
30
+ 'npm',
31
+ 'yarn',
32
+ 'bun'
33
+ ]){
34
+ await runInstall({
35
+ packageManager: pm,
36
+ path: '/p',
37
+ spawn
38
+ });
39
+ }
40
+ expect(spawn.mock.calls.map((c)=>c[0])).toEqual([
41
+ 'npm',
42
+ 'yarn',
43
+ 'bun'
44
+ ]);
45
+ });
46
+ });
47
+
48
+ //# sourceMappingURL=runInstall.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/runInstall.spec.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest'\n\nimport { runInstall } from './runInstall.js'\n\ndescribe('runInstall', () => {\n it('invokes the detected package manager install with corepack prompt disabled', async () => {\n const spawn = vi.fn().mockResolvedValue({ code: 0 })\n\n const result = await runInstall({ packageManager: 'pnpm', path: '/project', spawn })\n\n expect(result).toEqual({ code: 0 })\n expect(spawn).toHaveBeenCalledWith('pnpm', ['install'], {\n cwd: '/project',\n env: expect.objectContaining({ COREPACK_ENABLE_DOWNLOAD_PROMPT: '0' }),\n })\n })\n\n it('uses the right binary for each package manager', async () => {\n const spawn = vi.fn().mockResolvedValue({ code: 0 })\n\n for (const pm of ['npm', 'yarn', 'bun'] as const) {\n await runInstall({ packageManager: pm, path: '/p', spawn })\n }\n\n expect(spawn.mock.calls.map((c) => c[0])).toEqual(['npm', 'yarn', 'bun'])\n })\n})\n"],"names":["describe","expect","it","vi","runInstall","spawn","fn","mockResolvedValue","code","result","packageManager","path","toEqual","toHaveBeenCalledWith","cwd","env","objectContaining","COREPACK_ENABLE_DOWNLOAD_PROMPT","pm","mock","calls","map","c"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAEjD,SAASC,UAAU,QAAQ,kBAAiB;AAE5CJ,SAAS,cAAc;IACrBE,GAAG,8EAA8E;QAC/E,MAAMG,QAAQF,GAAGG,EAAE,GAAGC,iBAAiB,CAAC;YAAEC,MAAM;QAAE;QAElD,MAAMC,SAAS,MAAML,WAAW;YAAEM,gBAAgB;YAAQC,MAAM;YAAYN;QAAM;QAElFJ,OAAOQ,QAAQG,OAAO,CAAC;YAAEJ,MAAM;QAAE;QACjCP,OAAOI,OAAOQ,oBAAoB,CAAC,QAAQ;YAAC;SAAU,EAAE;YACtDC,KAAK;YACLC,KAAKd,OAAOe,gBAAgB,CAAC;gBAAEC,iCAAiC;YAAI;QACtE;IACF;IAEAf,GAAG,kDAAkD;QACnD,MAAMG,QAAQF,GAAGG,EAAE,GAAGC,iBAAiB,CAAC;YAAEC,MAAM;QAAE;QAElD,KAAK,MAAMU,MAAM;YAAC;YAAO;YAAQ;SAAM,CAAW;YAChD,MAAMd,WAAW;gBAAEM,gBAAgBQ;gBAAIP,MAAM;gBAAMN;YAAM;QAC3D;QAEAJ,OAAOI,MAAMc,IAAI,CAACC,KAAK,CAACC,GAAG,CAAC,CAACC,IAAMA,CAAC,CAAC,EAAE,GAAGV,OAAO,CAAC;YAAC;YAAO;YAAQ;SAAM;IAC1E;AACF"}
@@ -0,0 +1,42 @@
1
+ /** Minimal shape of an npm registry packument we read. */
2
+ export type RegistryPackument = {
3
+ 'dist-tags'?: Record<string, string>;
4
+ versions?: Record<string, {
5
+ engines?: Record<string, string>;
6
+ peerDependencies?: Record<string, string>;
7
+ }>;
8
+ };
9
+ export type FetchRegistry = (packageName: string) => Promise<RegistryPackument>;
10
+ export type Spawn = (command: string, args: string[], options: {
11
+ cwd: string;
12
+ env: NodeJS.ProcessEnv;
13
+ }) => Promise<{
14
+ code: number;
15
+ }>;
16
+ export type PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn';
17
+ /** Target versions the command resolves. Only some are written; see `written`. */
18
+ export type ResolvedVersions = {
19
+ /** Copied verbatim into engines.node. */
20
+ enginesNode: string;
21
+ /** Newest patch within @payloadcms/next's peer range. REPORT ONLY, never written. */
22
+ nextTarget: null | string;
23
+ /** Exact canary, applied in lockstep to payload + every @payloadcms/*. */
24
+ payloadVersion: string;
25
+ /** TypeScript floor (guide-sourced constant). */
26
+ typescript: string;
27
+ /** Newest @types/node patch within the Node major. */
28
+ typesNode: string;
29
+ };
30
+ export type UpgradeDeps = {
31
+ exists: (path: string) => boolean;
32
+ fetchRegistry: FetchRegistry;
33
+ spawn: Spawn;
34
+ };
35
+ /**
36
+ * TypeScript floor for Payload v4. Nothing machine-readable declares it, so it
37
+ * lives here, sourced from the v4 migration guide prose. Bump alongside the guide.
38
+ */
39
+ export declare const TS_FLOOR = "6.0.3";
40
+ /** Path (relative to dist/) of the bundled runbook the command points users to. */
41
+ export declare const RUNBOOK_RELATIVE_PATH = "runbook/payload-v4-upgrade.md";
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/upgrade/types.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,QAAQ,CAAC,EAAE,MAAM,CACf,MAAM,EACN;QACE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAC1C,CACF,CAAA;CACF,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE/E,MAAM,MAAM,KAAK,GAAG,CAClB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAC7C,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE9B,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AAE5D,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,qFAAqF;IACrF,UAAU,EAAE,IAAI,GAAG,MAAM,CAAA;IACzB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IACjC,aAAa,EAAE,aAAa,CAAA;IAC5B,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,UAAU,CAAA;AAE/B,mFAAmF;AACnF,eAAO,MAAM,qBAAqB,kCAAkC,CAAA"}
@@ -0,0 +1,7 @@
1
+ /** Minimal shape of an npm registry packument we read. */ /**
2
+ * TypeScript floor for Payload v4. Nothing machine-readable declares it, so it
3
+ * lives here, sourced from the v4 migration guide prose. Bump alongside the guide.
4
+ */ export const TS_FLOOR = '6.0.3';
5
+ /** Path (relative to dist/) of the bundled runbook the command points users to. */ export const RUNBOOK_RELATIVE_PATH = 'runbook/payload-v4-upgrade.md';
6
+
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/upgrade/types.ts"],"sourcesContent":["/** Minimal shape of an npm registry packument we read. */\nexport type RegistryPackument = {\n 'dist-tags'?: Record<string, string>\n versions?: Record<\n string,\n {\n engines?: Record<string, string>\n peerDependencies?: Record<string, string>\n }\n >\n}\n\nexport type FetchRegistry = (packageName: string) => Promise<RegistryPackument>\n\nexport type Spawn = (\n command: string,\n args: string[],\n options: { cwd: string; env: NodeJS.ProcessEnv },\n) => Promise<{ code: number }>\n\nexport type PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn'\n\n/** Target versions the command resolves. Only some are written; see `written`. */\nexport type ResolvedVersions = {\n /** Copied verbatim into engines.node. */\n enginesNode: string\n /** Newest patch within @payloadcms/next's peer range. REPORT ONLY, never written. */\n nextTarget: null | string\n /** Exact canary, applied in lockstep to payload + every @payloadcms/*. */\n payloadVersion: string\n /** TypeScript floor (guide-sourced constant). */\n typescript: string\n /** Newest @types/node patch within the Node major. */\n typesNode: string\n}\n\nexport type UpgradeDeps = {\n exists: (path: string) => boolean\n fetchRegistry: FetchRegistry\n spawn: Spawn\n}\n\n/**\n * TypeScript floor for Payload v4. Nothing machine-readable declares it, so it\n * lives here, sourced from the v4 migration guide prose. Bump alongside the guide.\n */\nexport const TS_FLOOR = '6.0.3'\n\n/** Path (relative to dist/) of the bundled runbook the command points users to. */\nexport const RUNBOOK_RELATIVE_PATH = 'runbook/payload-v4-upgrade.md'\n"],"names":["TS_FLOOR","RUNBOOK_RELATIVE_PATH"],"mappings":"AAAA,wDAAwD,GA0CxD;;;CAGC,GACD,OAAO,MAAMA,WAAW,QAAO;AAE/B,iFAAiF,GACjF,OAAO,MAAMC,wBAAwB,gCAA+B"}
@@ -0,0 +1,4 @@
1
+ import { Project } from 'ts-morph';
2
+ /** Load a ts-morph Project rooted at `path`, using its tsconfig.json if present. */
3
+ export declare function loadProject(path: string): Project;
4
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,OAAO,EAAa,MAAM,UAAU,CAAA;AAE9D,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmBjD"}
@@ -0,0 +1,30 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { IndentationText, Project, QuoteKind } from 'ts-morph';
4
+ /** Load a ts-morph Project rooted at `path`, using its tsconfig.json if present. */ export function loadProject(path) {
5
+ const manipulationSettings = {
6
+ indentationText: IndentationText.TwoSpaces,
7
+ quoteKind: QuoteKind.Single,
8
+ useTrailingCommas: true
9
+ };
10
+ const tsconfigPath = resolve(path, 'tsconfig.json');
11
+ if (existsSync(tsconfigPath)) {
12
+ return new Project({
13
+ manipulationSettings,
14
+ tsConfigFilePath: tsconfigPath
15
+ });
16
+ }
17
+ const project = new Project({
18
+ manipulationSettings
19
+ });
20
+ project.addSourceFilesAtPaths([
21
+ `${path}/**/*.{ts,tsx,js,jsx}`,
22
+ '!**/node_modules/**',
23
+ '!**/dist/**',
24
+ '!**/.next/**',
25
+ '!**/build/**'
26
+ ]);
27
+ return project;
28
+ }
29
+
30
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/project.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { IndentationText, Project, QuoteKind } from 'ts-morph'\n\n/** Load a ts-morph Project rooted at `path`, using its tsconfig.json if present. */\nexport function loadProject(path: string): Project {\n const manipulationSettings = {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Single,\n useTrailingCommas: true,\n }\n const tsconfigPath = resolve(path, 'tsconfig.json')\n if (existsSync(tsconfigPath)) {\n return new Project({ manipulationSettings, tsConfigFilePath: tsconfigPath })\n }\n const project = new Project({ manipulationSettings })\n project.addSourceFilesAtPaths([\n `${path}/**/*.{ts,tsx,js,jsx}`,\n '!**/node_modules/**',\n '!**/dist/**',\n '!**/.next/**',\n '!**/build/**',\n ])\n return project\n}\n"],"names":["existsSync","resolve","IndentationText","Project","QuoteKind","loadProject","path","manipulationSettings","indentationText","TwoSpaces","quoteKind","Single","useTrailingCommas","tsconfigPath","tsConfigFilePath","project","addSourceFilesAtPaths"],"mappings":"AAAA,SAASA,UAAU,QAAQ,UAAS;AACpC,SAASC,OAAO,QAAQ,YAAW;AACnC,SAASC,eAAe,EAAEC,OAAO,EAAEC,SAAS,QAAQ,WAAU;AAE9D,kFAAkF,GAClF,OAAO,SAASC,YAAYC,IAAY;IACtC,MAAMC,uBAAuB;QAC3BC,iBAAiBN,gBAAgBO,SAAS;QAC1CC,WAAWN,UAAUO,MAAM;QAC3BC,mBAAmB;IACrB;IACA,MAAMC,eAAeZ,QAAQK,MAAM;IACnC,IAAIN,WAAWa,eAAe;QAC5B,OAAO,IAAIV,QAAQ;YAAEI;YAAsBO,kBAAkBD;QAAa;IAC5E;IACA,MAAME,UAAU,IAAIZ,QAAQ;QAAEI;IAAqB;IACnDQ,QAAQC,qBAAqB,CAAC;QAC5B,GAAGV,KAAK,qBAAqB,CAAC;QAC9B;QACA;QACA;QACA;KACD;IACD,OAAOS;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/codemod",
3
- "version": "4.0.0-internal.167c7cd",
3
+ "version": "4.0.0-internal.2f0d313",
4
4
  "description": "Codemods for migrating Payload projects across versions.",
5
5
  "homepage": "https://payloadcms.com",
6
6
  "repository": {
@@ -29,11 +29,13 @@
29
29
  "README.md"
30
30
  ],
31
31
  "dependencies": {
32
+ "semver": "^7.8.5",
32
33
  "ts-morph": "^21.0.1"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@swc/core": "1.15.3",
36
37
  "@types/node": "24.12.3",
38
+ "@types/semver": "^7.7.1",
37
39
  "rimraf": "6.0.1",
38
40
  "typescript": "6.0.3",
39
41
  "vitest": "4.1.6"
@@ -42,7 +44,8 @@
42
44
  "node": ">=24.15.0"
43
45
  },
44
46
  "scripts": {
45
- "build": "pnpm typecheck && pnpm build:swc",
47
+ "build": "pnpm typecheck && pnpm build:swc && pnpm build:copy-docs",
48
+ "build:copy-docs": "node scripts/copy-migration-guide.mjs",
46
49
  "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
47
50
  "clean": "rimraf -g {dist,*.tsbuildinfo}",
48
51
  "lint": "eslint .",