@payloadcms/codemod 4.0.0-internal.2f0d313 → 4.0.0-internal.314c594

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 (103) hide show
  1. package/README.md +1 -34
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +27 -22
  4. package/dist/cli.js.map +1 -1
  5. package/dist/cli.parseFlags.d.ts +0 -5
  6. package/dist/cli.parseFlags.d.ts.map +1 -1
  7. package/dist/cli.parseFlags.js +1 -20
  8. package/dist/cli.parseFlags.js.map +1 -1
  9. package/dist/cli.parseFlags.spec.js +0 -72
  10. package/dist/cli.parseFlags.spec.js.map +1 -1
  11. package/dist/registry.d.ts.map +1 -1
  12. package/dist/registry.js +3 -1
  13. package/dist/registry.js.map +1 -1
  14. package/dist/transforms/rename-experimental-table-feature/alias.input.js +6 -0
  15. package/dist/transforms/rename-experimental-table-feature/alias.input.js.map +1 -0
  16. package/dist/transforms/rename-experimental-table-feature/alias.output.js +6 -0
  17. package/dist/transforms/rename-experimental-table-feature/alias.output.js.map +1 -0
  18. package/dist/transforms/rename-experimental-table-feature/basic.input.js +19 -0
  19. package/dist/transforms/rename-experimental-table-feature/basic.input.js.map +1 -0
  20. package/dist/transforms/rename-experimental-table-feature/basic.output.js +19 -0
  21. package/dist/transforms/rename-experimental-table-feature/basic.output.js.map +1 -0
  22. package/dist/transforms/rename-experimental-table-feature/collision.input.js +7 -0
  23. package/dist/transforms/rename-experimental-table-feature/collision.input.js.map +1 -0
  24. package/dist/transforms/rename-experimental-table-feature/index.d.ts +3 -0
  25. package/dist/transforms/rename-experimental-table-feature/index.d.ts.map +1 -0
  26. package/dist/transforms/rename-experimental-table-feature/index.js +44 -0
  27. package/dist/transforms/rename-experimental-table-feature/index.js.map +1 -0
  28. package/dist/transforms/rename-experimental-table-feature/index.spec.d.ts.map +1 -0
  29. package/dist/transforms/rename-experimental-table-feature/index.spec.js +54 -0
  30. package/dist/transforms/rename-experimental-table-feature/index.spec.js.map +1 -0
  31. package/dist/transforms/rename-experimental-table-feature/no-match.input.js +9 -0
  32. package/dist/transforms/rename-experimental-table-feature/no-match.input.js.map +1 -0
  33. package/package.json +2 -5
  34. package/dist/runbook/payload-v4-upgrade.md +0 -55
  35. package/dist/runbook/v4.mdx +0 -1652
  36. package/dist/upgrade/detectPackageManager.d.ts +0 -8
  37. package/dist/upgrade/detectPackageManager.d.ts.map +0 -1
  38. package/dist/upgrade/detectPackageManager.js +0 -38
  39. package/dist/upgrade/detectPackageManager.js.map +0 -1
  40. package/dist/upgrade/detectPackageManager.spec.d.ts +0 -2
  41. package/dist/upgrade/detectPackageManager.spec.d.ts.map +0 -1
  42. package/dist/upgrade/detectPackageManager.spec.js +0 -41
  43. package/dist/upgrade/detectPackageManager.spec.js.map +0 -1
  44. package/dist/upgrade/index.d.ts +0 -24
  45. package/dist/upgrade/index.d.ts.map +0 -1
  46. package/dist/upgrade/index.js +0 -184
  47. package/dist/upgrade/index.js.map +0 -1
  48. package/dist/upgrade/index.spec.d.ts.map +0 -1
  49. package/dist/upgrade/index.spec.js +0 -132
  50. package/dist/upgrade/index.spec.js.map +0 -1
  51. package/dist/upgrade/packaging.spec.d.ts +0 -2
  52. package/dist/upgrade/packaging.spec.d.ts.map +0 -1
  53. package/dist/upgrade/packaging.spec.js +0 -29
  54. package/dist/upgrade/packaging.spec.js.map +0 -1
  55. package/dist/upgrade/prompt.d.ts +0 -11
  56. package/dist/upgrade/prompt.d.ts.map +0 -1
  57. package/dist/upgrade/prompt.js +0 -75
  58. package/dist/upgrade/prompt.js.map +0 -1
  59. package/dist/upgrade/prompt.spec.d.ts +0 -2
  60. package/dist/upgrade/prompt.spec.d.ts.map +0 -1
  61. package/dist/upgrade/prompt.spec.js +0 -51
  62. package/dist/upgrade/prompt.spec.js.map +0 -1
  63. package/dist/upgrade/report.d.ts +0 -18
  64. package/dist/upgrade/report.d.ts.map +0 -1
  65. package/dist/upgrade/report.js +0 -41
  66. package/dist/upgrade/report.js.map +0 -1
  67. package/dist/upgrade/report.spec.d.ts +0 -2
  68. package/dist/upgrade/report.spec.d.ts.map +0 -1
  69. package/dist/upgrade/report.spec.js +0 -87
  70. package/dist/upgrade/report.spec.js.map +0 -1
  71. package/dist/upgrade/resolveVersions.d.ts +0 -13
  72. package/dist/upgrade/resolveVersions.d.ts.map +0 -1
  73. package/dist/upgrade/resolveVersions.js +0 -55
  74. package/dist/upgrade/resolveVersions.js.map +0 -1
  75. package/dist/upgrade/resolveVersions.spec.d.ts +0 -2
  76. package/dist/upgrade/resolveVersions.spec.d.ts.map +0 -1
  77. package/dist/upgrade/resolveVersions.spec.js +0 -82
  78. package/dist/upgrade/resolveVersions.spec.js.map +0 -1
  79. package/dist/upgrade/rewritePackageJson.d.ts +0 -25
  80. package/dist/upgrade/rewritePackageJson.d.ts.map +0 -1
  81. package/dist/upgrade/rewritePackageJson.js +0 -106
  82. package/dist/upgrade/rewritePackageJson.js.map +0 -1
  83. package/dist/upgrade/rewritePackageJson.spec.d.ts +0 -2
  84. package/dist/upgrade/rewritePackageJson.spec.d.ts.map +0 -1
  85. package/dist/upgrade/rewritePackageJson.spec.js +0 -108
  86. package/dist/upgrade/rewritePackageJson.spec.js.map +0 -1
  87. package/dist/upgrade/runInstall.d.ts +0 -16
  88. package/dist/upgrade/runInstall.d.ts.map +0 -1
  89. package/dist/upgrade/runInstall.js +0 -17
  90. package/dist/upgrade/runInstall.js.map +0 -1
  91. package/dist/upgrade/runInstall.spec.d.ts +0 -2
  92. package/dist/upgrade/runInstall.spec.d.ts.map +0 -1
  93. package/dist/upgrade/runInstall.spec.js +0 -48
  94. package/dist/upgrade/runInstall.spec.js.map +0 -1
  95. package/dist/upgrade/types.d.ts +0 -42
  96. package/dist/upgrade/types.d.ts.map +0 -1
  97. package/dist/upgrade/types.js +0 -7
  98. package/dist/upgrade/types.js.map +0 -1
  99. package/dist/utils/project.d.ts +0 -4
  100. package/dist/utils/project.d.ts.map +0 -1
  101. package/dist/utils/project.js +0 -30
  102. package/dist/utils/project.js.map +0 -1
  103. /package/dist/{upgrade → transforms/rename-experimental-table-feature}/index.spec.d.ts +0 -0
@@ -1,8 +0,0 @@
1
- import type { PackageManager } from './types.js';
2
- /**
3
- * Map a project directory's lockfile to its package manager. `exists` is
4
- * injectable so callers can test offline; it defaults to the real filesystem.
5
- * pnpm is checked first, so it wins in a multi-lockfile repo.
6
- */
7
- export declare function detectPackageManager(projectPath: string, exists?: (path: string) => boolean): PackageManager;
8
- //# sourceMappingURL=detectPackageManager.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detectPackageManager.d.ts","sourceRoot":"","sources":["../../src/upgrade/detectPackageManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAUhD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAoB,GAC7C,cAAc,CAOhB"}
@@ -1,38 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- const LOCKFILES = [
4
- {
5
- file: 'pnpm-lock.yaml',
6
- pm: 'pnpm'
7
- },
8
- {
9
- file: 'yarn.lock',
10
- pm: 'yarn'
11
- },
12
- {
13
- file: 'bun.lockb',
14
- pm: 'bun'
15
- },
16
- {
17
- file: 'bun.lock',
18
- pm: 'bun'
19
- },
20
- {
21
- file: 'package-lock.json',
22
- pm: 'npm'
23
- }
24
- ];
25
- /**
26
- * Map a project directory's lockfile to its package manager. `exists` is
27
- * injectable so callers can test offline; it defaults to the real filesystem.
28
- * pnpm is checked first, so it wins in a multi-lockfile repo.
29
- */ export function detectPackageManager(projectPath, exists = existsSync) {
30
- for (const { file, pm } of LOCKFILES){
31
- if (exists(join(projectPath, file))) {
32
- return pm;
33
- }
34
- }
35
- return 'npm';
36
- }
37
-
38
- //# sourceMappingURL=detectPackageManager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/upgrade/detectPackageManager.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { PackageManager } from './types.js'\n\nconst LOCKFILES: { file: string; pm: PackageManager }[] = [\n { file: 'pnpm-lock.yaml', pm: 'pnpm' },\n { file: 'yarn.lock', pm: 'yarn' },\n { file: 'bun.lockb', pm: 'bun' },\n { file: 'bun.lock', pm: 'bun' },\n { file: 'package-lock.json', pm: 'npm' },\n]\n\n/**\n * Map a project directory's lockfile to its package manager. `exists` is\n * injectable so callers can test offline; it defaults to the real filesystem.\n * pnpm is checked first, so it wins in a multi-lockfile repo.\n */\nexport function detectPackageManager(\n projectPath: string,\n exists: (path: string) => boolean = existsSync,\n): PackageManager {\n for (const { file, pm } of LOCKFILES) {\n if (exists(join(projectPath, file))) {\n return pm\n }\n }\n return 'npm'\n}\n"],"names":["existsSync","join","LOCKFILES","file","pm","detectPackageManager","projectPath","exists"],"mappings":"AAAA,SAASA,UAAU,QAAQ,UAAS;AACpC,SAASC,IAAI,QAAQ,YAAW;AAIhC,MAAMC,YAAoD;IACxD;QAAEC,MAAM;QAAkBC,IAAI;IAAO;IACrC;QAAED,MAAM;QAAaC,IAAI;IAAO;IAChC;QAAED,MAAM;QAAaC,IAAI;IAAM;IAC/B;QAAED,MAAM;QAAYC,IAAI;IAAM;IAC9B;QAAED,MAAM;QAAqBC,IAAI;IAAM;CACxC;AAED;;;;CAIC,GACD,OAAO,SAASC,qBACdC,WAAmB,EACnBC,SAAoCP,UAAU;IAE9C,KAAK,MAAM,EAAEG,IAAI,EAAEC,EAAE,EAAE,IAAIF,UAAW;QACpC,IAAIK,OAAON,KAAKK,aAAaH,QAAQ;YACnC,OAAOC;QACT;IACF;IACA,OAAO;AACT"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=detectPackageManager.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detectPackageManager.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/detectPackageManager.spec.ts"],"names":[],"mappings":""}
@@ -1,41 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { detectPackageManager } from './detectPackageManager.js';
3
- const existsFor = (present)=>(path)=>present.some((name)=>path.endsWith(name));
4
- describe('detectPackageManager', ()=>{
5
- it('detects pnpm', ()=>{
6
- expect(detectPackageManager('/p', existsFor([
7
- 'pnpm-lock.yaml'
8
- ]))).toBe('pnpm');
9
- });
10
- it('detects yarn', ()=>{
11
- expect(detectPackageManager('/p', existsFor([
12
- 'yarn.lock'
13
- ]))).toBe('yarn');
14
- });
15
- it('detects bun', ()=>{
16
- expect(detectPackageManager('/p', existsFor([
17
- 'bun.lock'
18
- ]))).toBe('bun');
19
- });
20
- it('detects bun via bun.lockb', ()=>{
21
- expect(detectPackageManager('/p', existsFor([
22
- 'bun.lockb'
23
- ]))).toBe('bun');
24
- });
25
- it('detects npm', ()=>{
26
- expect(detectPackageManager('/p', existsFor([
27
- 'package-lock.json'
28
- ]))).toBe('npm');
29
- });
30
- it('defaults to npm when no lockfile exists', ()=>{
31
- expect(detectPackageManager('/p', ()=>false)).toBe('npm');
32
- });
33
- it('prefers pnpm when multiple lockfiles exist', ()=>{
34
- expect(detectPackageManager('/p', existsFor([
35
- 'pnpm-lock.yaml',
36
- 'yarn.lock'
37
- ]))).toBe('pnpm');
38
- });
39
- });
40
-
41
- //# sourceMappingURL=detectPackageManager.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/upgrade/detectPackageManager.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { detectPackageManager } from './detectPackageManager.js'\n\nconst existsFor = (present: string[]) => (path: string) =>\n present.some((name) => path.endsWith(name))\n\ndescribe('detectPackageManager', () => {\n it('detects pnpm', () => {\n expect(detectPackageManager('/p', existsFor(['pnpm-lock.yaml']))).toBe('pnpm')\n })\n\n it('detects yarn', () => {\n expect(detectPackageManager('/p', existsFor(['yarn.lock']))).toBe('yarn')\n })\n\n it('detects bun', () => {\n expect(detectPackageManager('/p', existsFor(['bun.lock']))).toBe('bun')\n })\n\n it('detects bun via bun.lockb', () => {\n expect(detectPackageManager('/p', existsFor(['bun.lockb']))).toBe('bun')\n })\n\n it('detects npm', () => {\n expect(detectPackageManager('/p', existsFor(['package-lock.json']))).toBe('npm')\n })\n\n it('defaults to npm when no lockfile exists', () => {\n expect(detectPackageManager('/p', () => false)).toBe('npm')\n })\n\n it('prefers pnpm when multiple lockfiles exist', () => {\n expect(detectPackageManager('/p', existsFor(['pnpm-lock.yaml', 'yarn.lock']))).toBe('pnpm')\n })\n})\n"],"names":["describe","expect","it","detectPackageManager","existsFor","present","path","some","name","endsWith","toBe"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,oBAAoB,QAAQ,4BAA2B;AAEhE,MAAMC,YAAY,CAACC,UAAsB,CAACC,OACxCD,QAAQE,IAAI,CAAC,CAACC,OAASF,KAAKG,QAAQ,CAACD;AAEvCR,SAAS,wBAAwB;IAC/BE,GAAG,gBAAgB;QACjBD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;SAAiB,IAAIM,IAAI,CAAC;IACzE;IAEAR,GAAG,gBAAgB;QACjBD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;SAAY,IAAIM,IAAI,CAAC;IACpE;IAEAR,GAAG,eAAe;QAChBD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;SAAW,IAAIM,IAAI,CAAC;IACnE;IAEAR,GAAG,6BAA6B;QAC9BD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;SAAY,IAAIM,IAAI,CAAC;IACpE;IAEAR,GAAG,eAAe;QAChBD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;SAAoB,IAAIM,IAAI,CAAC;IAC5E;IAEAR,GAAG,2CAA2C;QAC5CD,OAAOE,qBAAqB,MAAM,IAAM,QAAQO,IAAI,CAAC;IACvD;IAEAR,GAAG,8CAA8C;QAC/CD,OAAOE,qBAAqB,MAAMC,UAAU;YAAC;YAAkB;SAAY,IAAIM,IAAI,CAAC;IACtF;AACF"}
@@ -1,24 +0,0 @@
1
- import type { UpgradeDeps } from './types.js';
2
- import { runTransforms as defaultRunTransforms } from '../runner.js';
3
- export type UpgradeFlags = {
4
- dry: boolean;
5
- force: boolean;
6
- tag: string;
7
- };
8
- type RunUpgradeArgs = {
9
- flags: UpgradeFlags;
10
- path: string;
11
- };
12
- type RunUpgradeOverrides = {
13
- runTransforms?: typeof defaultRunTransforms;
14
- };
15
- /**
16
- * Compose the upgrade pipeline: preflight -> resolve -> rewrite -> install ->
17
- * verify -> transforms -> report. Install runs before transforms so a failed
18
- * install aborts before any codemod touches source files.
19
- */
20
- export declare function runUpgrade({ flags, path }: RunUpgradeArgs, deps?: UpgradeDeps, overrides?: RunUpgradeOverrides): Promise<{
21
- failed: boolean;
22
- }>;
23
- export {};
24
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upgrade/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAuC,WAAW,EAAE,MAAM,YAAY,CAAA;AAGlF,OAAO,EAAE,aAAa,IAAI,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAUpE,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,OAAO,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,KAAK,EAAE,YAAY,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,KAAK,mBAAmB,GAAG;IACzB,aAAa,CAAC,EAAE,OAAO,oBAAoB,CAAA;CAC5C,CAAA;AAsBD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,cAAc,EAC/B,IAAI,GAAE,WAA2B,EACjC,SAAS,GAAE,mBAAwB,GAClC,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CAqF9B"}
@@ -1,184 +0,0 @@
1
- /* eslint-disable no-console */ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { dirname, join, resolve } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import semver from 'semver';
5
- import { transforms as registry } from '../registry.js';
6
- import { runTransforms as defaultRunTransforms } from '../runner.js';
7
- import { loadPackageJsons, serializePackageJson } from '../utils/packageJson.js';
8
- import { loadProject } from '../utils/project.js';
9
- import { detectPackageManager } from './detectPackageManager.js';
10
- import { renderReport } from './report.js';
11
- import { resolveVersions } from './resolveVersions.js';
12
- import { isPayloadEslintPackage, rewritePackageJson } from './rewritePackageJson.js';
13
- import { runInstall } from './runInstall.js';
14
- import { RUNBOOK_RELATIVE_PATH } from './types.js';
15
- const defaultDeps = ()=>({
16
- exists: existsSync,
17
- fetchRegistry: async (name)=>{
18
- const res = await fetch(`https://registry.npmjs.org/${name}`);
19
- if (!res.ok) {
20
- throw new Error(`Registry lookup failed for ${name}: ${res.status}`);
21
- }
22
- return await res.json();
23
- },
24
- spawn: (command, args, options)=>import('node:child_process').then(({ spawn })=>new Promise((resolveSpawn)=>{
25
- const child = spawn(command, args, {
26
- ...options,
27
- shell: false,
28
- stdio: 'inherit'
29
- });
30
- child.on('close', (code)=>resolveSpawn({
31
- code: code ?? 1
32
- }));
33
- child.on('error', ()=>resolveSpawn({
34
- code: 1
35
- }));
36
- }))
37
- });
38
- /**
39
- * Compose the upgrade pipeline: preflight -> resolve -> rewrite -> install ->
40
- * verify -> transforms -> report. Install runs before transforms so a failed
41
- * install aborts before any codemod touches source files.
42
- */ export async function runUpgrade({ flags, path }, deps = defaultDeps(), overrides = {}) {
43
- const runTransforms = overrides.runTransforms ?? defaultRunTransforms;
44
- const projectPath = resolve(path);
45
- // 1. PREFLIGHT
46
- const packageManager = detectPackageManager(projectPath, deps.exists);
47
- const packageJsonPath = join(projectPath, 'package.json');
48
- if (!deps.exists(packageJsonPath)) {
49
- console.error(`No package.json found at ${packageJsonPath}.`);
50
- return {
51
- failed: true
52
- };
53
- }
54
- if (!flags.force && isGitTreeDirty(projectPath)) {
55
- console.warn('Warning: git tree is dirty. Commit or stash first, or pass --force.');
56
- }
57
- // 2. RESOLVE VERSIONS
58
- const resolved = await resolveVersions({
59
- fetchRegistry: deps.fetchRegistry,
60
- tag: flags.tag
61
- });
62
- warnStaleNode(resolved);
63
- // 3. REWRITE package.json
64
- const original = readFileSync(packageJsonPath, 'utf8');
65
- const data = JSON.parse(original);
66
- const summary = rewritePackageJson({
67
- data,
68
- resolved
69
- });
70
- const nextText = serializePackageJson(data, original);
71
- if (flags.dry) {
72
- console.log('[dry] package.json changes:');
73
- console.log(nextText);
74
- console.log(`[dry] would run: ${packageManager} install`);
75
- console.log('[dry] would then run Payload transforms.');
76
- return {
77
- failed: false
78
- };
79
- }
80
- writeFileSync(packageJsonPath, nextText);
81
- // 4. INSTALL
82
- const install = await runInstall({
83
- packageManager,
84
- path: projectPath,
85
- spawn: deps.spawn
86
- });
87
- if (install.code !== 0) {
88
- console.error(`Install failed (exit ${install.code}). Aborting before transforms.`);
89
- return {
90
- failed: true
91
- };
92
- }
93
- // 5. VERIFY RESOLUTION
94
- const versions = verifyResolution(projectPath, data, resolved);
95
- // 6. RUN PAYLOAD TRANSFORMS
96
- // Reload package.jsons from disk so transforms see the rewritten root file
97
- // (and any other package.json files in the tree) with the same reference
98
- // semantics the bare transform path relies on for in-place mutation.
99
- const packageJsons = loadPackageJsons(projectPath);
100
- const project = loadProject(projectPath);
101
- const snapshot = new Map(project.getSourceFiles().map((f)=>[
102
- f.getFilePath(),
103
- f.getFullText()
104
- ]));
105
- const { failed, results } = await runTransforms({
106
- packageJsons: packageJsons.map(({ data: pkgData, path: pkgPath })=>({
107
- data: pkgData,
108
- path: pkgPath
109
- })),
110
- project,
111
- transforms: registry
112
- });
113
- await Promise.all(project.getSourceFiles().filter((f)=>snapshot.get(f.getFilePath()) !== f.getFullText()).map((f)=>f.save()));
114
- for (const pkg of packageJsons){
115
- const text = serializePackageJson(pkg.data, pkg.originalText);
116
- if (text !== pkg.originalText) {
117
- writeFileSync(pkg.path, text);
118
- }
119
- }
120
- // 7. REPORT
121
- const model = {
122
- floorsWritten: summary.floorsWritten,
123
- nextTarget: resolved.nextTarget,
124
- overridesRemoved: summary.overridesRemoved,
125
- runbookPath: resolve(dirname(fileURLToPath(import.meta.url)), '..', RUNBOOK_RELATIVE_PATH),
126
- transforms: results,
127
- versions
128
- };
129
- console.log(renderReport(model));
130
- return {
131
- failed
132
- };
133
- }
134
- function warnStaleNode(resolved) {
135
- const running = process.versions.node;
136
- if (!semver.satisfies(running, resolved.enginesNode)) {
137
- console.warn(`Warning: running Node ${running} does not satisfy ${resolved.enginesNode}. ` + 'Install may resolve incorrectly; switch Node before continuing.');
138
- }
139
- }
140
- function verifyResolution(projectPath, data, resolved) {
141
- const rows = [];
142
- const deps = {
143
- ...asRecord(data.dependencies),
144
- ...asRecord(data.devDependencies)
145
- };
146
- for (const name of Object.keys(deps)){
147
- if (name !== 'payload' && !name.startsWith('@payloadcms/')) {
148
- continue;
149
- }
150
- // eslint packages are versioned independently, so they are not part of the
151
- // lockstep-pinned set and cannot be verified against the payload version.
152
- if (isPayloadEslintPackage(name)) {
153
- continue;
154
- }
155
- const installed = readInstalledVersion(projectPath, name);
156
- rows.push({
157
- name,
158
- ok: installed === resolved.payloadVersion,
159
- resolved: installed,
160
- wrote: resolved.payloadVersion
161
- });
162
- }
163
- return rows;
164
- }
165
- function readInstalledVersion(projectPath, name) {
166
- try {
167
- const pkgPath = join(projectPath, 'node_modules', name, 'package.json');
168
- return JSON.parse(readFileSync(pkgPath, 'utf8')).version;
169
- } catch {
170
- return undefined;
171
- }
172
- }
173
- /**
174
- * Best-effort dirty-tree check. Real detection would shell out to `git
175
- * status`; until that lands, absence of a signal is treated as clean so the
176
- * warning never produces a false alarm.
177
- */ function isGitTreeDirty(_projectPath) {
178
- return false;
179
- }
180
- function asRecord(value) {
181
- return typeof value === 'object' && value !== null ? value : {};
182
- }
183
-
184
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/upgrade/index.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport semver from 'semver'\n\nimport type { ReportModel, VersionReportRow } from './report.js'\nimport type { RegistryPackument, ResolvedVersions, UpgradeDeps } from './types.js'\n\nimport { transforms as registry } from '../registry.js'\nimport { runTransforms as defaultRunTransforms } from '../runner.js'\nimport { loadPackageJsons, serializePackageJson } from '../utils/packageJson.js'\nimport { loadProject } from '../utils/project.js'\nimport { detectPackageManager } from './detectPackageManager.js'\nimport { renderReport } from './report.js'\nimport { resolveVersions } from './resolveVersions.js'\nimport { isPayloadEslintPackage, rewritePackageJson } from './rewritePackageJson.js'\nimport { runInstall } from './runInstall.js'\nimport { RUNBOOK_RELATIVE_PATH } from './types.js'\n\nexport type UpgradeFlags = {\n dry: boolean\n force: boolean\n tag: string\n}\n\ntype RunUpgradeArgs = {\n flags: UpgradeFlags\n path: string\n}\n\ntype RunUpgradeOverrides = {\n runTransforms?: typeof defaultRunTransforms\n}\n\nconst defaultDeps = (): UpgradeDeps => ({\n exists: existsSync,\n fetchRegistry: async (name) => {\n const res = await fetch(`https://registry.npmjs.org/${name}`)\n if (!res.ok) {\n throw new Error(`Registry lookup failed for ${name}: ${res.status}`)\n }\n return (await res.json()) as RegistryPackument\n },\n spawn: (command, args, options) =>\n import('node:child_process').then(\n ({ spawn }) =>\n new Promise((resolveSpawn) => {\n const child = spawn(command, args, { ...options, shell: false, stdio: 'inherit' })\n child.on('close', (code) => resolveSpawn({ code: code ?? 1 }))\n child.on('error', () => resolveSpawn({ code: 1 }))\n }),\n ),\n})\n\n/**\n * Compose the upgrade pipeline: preflight -> resolve -> rewrite -> install ->\n * verify -> transforms -> report. Install runs before transforms so a failed\n * install aborts before any codemod touches source files.\n */\nexport async function runUpgrade(\n { flags, path }: RunUpgradeArgs,\n deps: UpgradeDeps = defaultDeps(),\n overrides: RunUpgradeOverrides = {},\n): Promise<{ failed: boolean }> {\n const runTransforms = overrides.runTransforms ?? defaultRunTransforms\n const projectPath = resolve(path)\n\n // 1. PREFLIGHT\n const packageManager = detectPackageManager(projectPath, deps.exists)\n const packageJsonPath = join(projectPath, 'package.json')\n if (!deps.exists(packageJsonPath)) {\n console.error(`No package.json found at ${packageJsonPath}.`)\n return { failed: true }\n }\n if (!flags.force && isGitTreeDirty(projectPath)) {\n console.warn('Warning: git tree is dirty. Commit or stash first, or pass --force.')\n }\n\n // 2. RESOLVE VERSIONS\n const resolved = await resolveVersions({ fetchRegistry: deps.fetchRegistry, tag: flags.tag })\n warnStaleNode(resolved)\n\n // 3. REWRITE package.json\n const original = readFileSync(packageJsonPath, 'utf8')\n const data = JSON.parse(original) as Record<string, unknown>\n const summary = rewritePackageJson({ data, resolved })\n const nextText = serializePackageJson(data, original)\n\n if (flags.dry) {\n console.log('[dry] package.json changes:')\n console.log(nextText)\n console.log(`[dry] would run: ${packageManager} install`)\n console.log('[dry] would then run Payload transforms.')\n return { failed: false }\n }\n\n writeFileSync(packageJsonPath, nextText)\n\n // 4. INSTALL\n const install = await runInstall({ packageManager, path: projectPath, spawn: deps.spawn })\n if (install.code !== 0) {\n console.error(`Install failed (exit ${install.code}). Aborting before transforms.`)\n return { failed: true }\n }\n\n // 5. VERIFY RESOLUTION\n const versions = verifyResolution(projectPath, data, resolved)\n\n // 6. RUN PAYLOAD TRANSFORMS\n // Reload package.jsons from disk so transforms see the rewritten root file\n // (and any other package.json files in the tree) with the same reference\n // semantics the bare transform path relies on for in-place mutation.\n const packageJsons = loadPackageJsons(projectPath)\n const project = loadProject(projectPath)\n const snapshot = new Map(project.getSourceFiles().map((f) => [f.getFilePath(), f.getFullText()]))\n const { failed, results } = await runTransforms({\n packageJsons: packageJsons.map(({ data: pkgData, path: pkgPath }) => ({\n data: pkgData,\n path: pkgPath,\n })),\n project,\n transforms: registry,\n })\n await Promise.all(\n project\n .getSourceFiles()\n .filter((f) => snapshot.get(f.getFilePath()) !== f.getFullText())\n .map((f) => f.save()),\n )\n for (const pkg of packageJsons) {\n const text = serializePackageJson(pkg.data, pkg.originalText)\n if (text !== pkg.originalText) {\n writeFileSync(pkg.path, text)\n }\n }\n\n // 7. REPORT\n const model: ReportModel = {\n floorsWritten: summary.floorsWritten,\n nextTarget: resolved.nextTarget,\n overridesRemoved: summary.overridesRemoved,\n runbookPath: resolve(dirname(fileURLToPath(import.meta.url)), '..', RUNBOOK_RELATIVE_PATH),\n transforms: results,\n versions,\n }\n console.log(renderReport(model))\n\n return { failed }\n}\n\nfunction warnStaleNode(resolved: ResolvedVersions): void {\n const running = process.versions.node\n if (!semver.satisfies(running, resolved.enginesNode)) {\n console.warn(\n `Warning: running Node ${running} does not satisfy ${resolved.enginesNode}. ` +\n 'Install may resolve incorrectly; switch Node before continuing.',\n )\n }\n}\n\nfunction verifyResolution(\n projectPath: string,\n data: Record<string, unknown>,\n resolved: ResolvedVersions,\n): VersionReportRow[] {\n const rows: VersionReportRow[] = []\n const deps = { ...asRecord(data.dependencies), ...asRecord(data.devDependencies) }\n for (const name of Object.keys(deps)) {\n if (name !== 'payload' && !name.startsWith('@payloadcms/')) {\n continue\n }\n // eslint packages are versioned independently, so they are not part of the\n // lockstep-pinned set and cannot be verified against the payload version.\n if (isPayloadEslintPackage(name)) {\n continue\n }\n const installed = readInstalledVersion(projectPath, name)\n rows.push({\n name,\n ok: installed === resolved.payloadVersion,\n resolved: installed,\n wrote: resolved.payloadVersion,\n })\n }\n return rows\n}\n\nfunction readInstalledVersion(projectPath: string, name: string): string | undefined {\n try {\n const pkgPath = join(projectPath, 'node_modules', name, 'package.json')\n return JSON.parse(readFileSync(pkgPath, 'utf8')).version as string\n } catch {\n return undefined\n }\n}\n\n/**\n * Best-effort dirty-tree check. Real detection would shell out to `git\n * status`; until that lands, absence of a signal is treated as clean so the\n * warning never produces a false alarm.\n */\nfunction isGitTreeDirty(_projectPath: string): boolean {\n return false\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {}\n}\n"],"names":["existsSync","readFileSync","writeFileSync","dirname","join","resolve","fileURLToPath","semver","transforms","registry","runTransforms","defaultRunTransforms","loadPackageJsons","serializePackageJson","loadProject","detectPackageManager","renderReport","resolveVersions","isPayloadEslintPackage","rewritePackageJson","runInstall","RUNBOOK_RELATIVE_PATH","defaultDeps","exists","fetchRegistry","name","res","fetch","ok","Error","status","json","spawn","command","args","options","then","Promise","resolveSpawn","child","shell","stdio","on","code","runUpgrade","flags","path","deps","overrides","projectPath","packageManager","packageJsonPath","console","error","failed","force","isGitTreeDirty","warn","resolved","tag","warnStaleNode","original","data","JSON","parse","summary","nextText","dry","log","install","versions","verifyResolution","packageJsons","project","snapshot","Map","getSourceFiles","map","f","getFilePath","getFullText","results","pkgData","pkgPath","all","filter","get","save","pkg","text","originalText","model","floorsWritten","nextTarget","overridesRemoved","runbookPath","url","running","process","node","satisfies","enginesNode","rows","asRecord","dependencies","devDependencies","Object","keys","startsWith","installed","readInstalledVersion","push","payloadVersion","wrote","version","undefined","_projectPath","value"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/index.spec.ts"],"names":[],"mappings":""}
@@ -1,132 +0,0 @@
1
- import { existsSync, mkdtempSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { describe, expect, it, vi } from 'vitest';
5
- import { runUpgrade } from './index.js';
6
- const packuments = {
7
- '@payloadcms/next': {
8
- 'dist-tags': {
9
- canary: '4.0.0-canary.20'
10
- },
11
- versions: {
12
- '4.0.0-canary.20': {
13
- peerDependencies: {
14
- next: '>=16.2.6 <17.0.0'
15
- }
16
- }
17
- }
18
- },
19
- '@types/node': {
20
- versions: {
21
- '24.12.3': {}
22
- }
23
- },
24
- next: {
25
- versions: {
26
- '16.9.3': {}
27
- }
28
- },
29
- payload: {
30
- 'dist-tags': {
31
- canary: '4.0.0-canary.20'
32
- },
33
- versions: {
34
- '4.0.0-canary.20': {
35
- engines: {
36
- node: '>=24.15.0'
37
- }
38
- }
39
- }
40
- }
41
- };
42
- const makeDeps = (overrides = {})=>({
43
- // Real fs so the temp-project package.json is found; no lockfile -> npm.
44
- exists: existsSync,
45
- fetchRegistry: (name)=>Promise.resolve(packuments[name] ?? {}),
46
- spawn: vi.fn().mockResolvedValue({
47
- code: 0
48
- }),
49
- ...overrides
50
- });
51
- const makeProject = ()=>{
52
- const dir = mkdtempSync(join(tmpdir(), 'codemod-upgrade-'));
53
- writeFileSync(join(dir, 'package.json'), JSON.stringify({
54
- dependencies: {
55
- payload: '^3.0.0'
56
- }
57
- }, null, 2) + '\n');
58
- return dir;
59
- };
60
- describe('runUpgrade', ()=>{
61
- it('installs before running transforms', async ()=>{
62
- const order = [];
63
- const spawn = vi.fn().mockImplementation(()=>{
64
- order.push('install');
65
- return Promise.resolve({
66
- code: 0
67
- });
68
- });
69
- const runTransforms = vi.fn().mockImplementation(()=>{
70
- order.push('transforms');
71
- return Promise.resolve({
72
- failed: false,
73
- results: []
74
- });
75
- });
76
- await runUpgrade({
77
- flags: {
78
- dry: false,
79
- force: true,
80
- tag: 'canary'
81
- },
82
- path: makeProject()
83
- }, makeDeps({
84
- spawn
85
- }), {
86
- runTransforms
87
- });
88
- expect(order).toEqual([
89
- 'install',
90
- 'transforms'
91
- ]);
92
- });
93
- it('aborts before transforms when install fails', async ()=>{
94
- const runTransforms = vi.fn();
95
- const result = await runUpgrade({
96
- flags: {
97
- dry: false,
98
- force: true,
99
- tag: 'canary'
100
- },
101
- path: makeProject()
102
- }, makeDeps({
103
- spawn: vi.fn().mockResolvedValue({
104
- code: 1
105
- })
106
- }), {
107
- runTransforms
108
- });
109
- expect(runTransforms).not.toHaveBeenCalled();
110
- expect(result.failed).toBe(true);
111
- });
112
- it('dry run writes nothing, does not install or transform', async ()=>{
113
- const spawn = vi.fn();
114
- const runTransforms = vi.fn();
115
- await runUpgrade({
116
- flags: {
117
- dry: true,
118
- force: true,
119
- tag: 'canary'
120
- },
121
- path: makeProject()
122
- }, makeDeps({
123
- spawn
124
- }), {
125
- runTransforms
126
- });
127
- expect(spawn).not.toHaveBeenCalled();
128
- expect(runTransforms).not.toHaveBeenCalled();
129
- });
130
- });
131
-
132
- //# sourceMappingURL=index.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/upgrade/index.spec.ts"],"sourcesContent":["import { existsSync, mkdtempSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { describe, expect, it, vi } from 'vitest'\n\nimport type { RegistryPackument, UpgradeDeps } from './types.js'\n\nimport { runUpgrade } from './index.js'\n\nconst packuments: Record<string, RegistryPackument> = {\n '@payloadcms/next': {\n 'dist-tags': { canary: '4.0.0-canary.20' },\n versions: { '4.0.0-canary.20': { peerDependencies: { next: '>=16.2.6 <17.0.0' } } },\n },\n '@types/node': { versions: { '24.12.3': {} } },\n next: { versions: { '16.9.3': {} } },\n payload: {\n 'dist-tags': { canary: '4.0.0-canary.20' },\n versions: { '4.0.0-canary.20': { engines: { node: '>=24.15.0' } } },\n },\n}\n\nconst makeDeps = (overrides: Partial<UpgradeDeps> = {}): UpgradeDeps => ({\n // Real fs so the temp-project package.json is found; no lockfile -> npm.\n exists: existsSync,\n fetchRegistry: (name) => Promise.resolve(packuments[name] ?? {}),\n spawn: vi.fn().mockResolvedValue({ code: 0 }),\n ...overrides,\n})\n\nconst makeProject = (): string => {\n const dir = mkdtempSync(join(tmpdir(), 'codemod-upgrade-'))\n writeFileSync(\n join(dir, 'package.json'),\n JSON.stringify({ dependencies: { payload: '^3.0.0' } }, null, 2) + '\\n',\n )\n return dir\n}\n\ndescribe('runUpgrade', () => {\n it('installs before running transforms', async () => {\n const order: string[] = []\n const spawn = vi.fn().mockImplementation(() => {\n order.push('install')\n return Promise.resolve({ code: 0 })\n })\n const runTransforms = vi.fn().mockImplementation(() => {\n order.push('transforms')\n return Promise.resolve({ failed: false, results: [] })\n })\n\n await runUpgrade(\n { flags: { dry: false, force: true, tag: 'canary' }, path: makeProject() },\n makeDeps({ spawn }),\n { runTransforms },\n )\n\n expect(order).toEqual(['install', 'transforms'])\n })\n\n it('aborts before transforms when install fails', async () => {\n const runTransforms = vi.fn()\n\n const result = await runUpgrade(\n {\n flags: { dry: false, force: true, tag: 'canary' },\n path: makeProject(),\n },\n makeDeps({ spawn: vi.fn().mockResolvedValue({ code: 1 }) }),\n { runTransforms },\n )\n\n expect(runTransforms).not.toHaveBeenCalled()\n expect(result.failed).toBe(true)\n })\n\n it('dry run writes nothing, does not install or transform', async () => {\n const spawn = vi.fn()\n const runTransforms = vi.fn()\n\n await runUpgrade(\n { flags: { dry: true, force: true, tag: 'canary' }, path: makeProject() },\n makeDeps({ spawn }),\n { runTransforms },\n )\n\n expect(spawn).not.toHaveBeenCalled()\n expect(runTransforms).not.toHaveBeenCalled()\n })\n})\n"],"names":["existsSync","mkdtempSync","writeFileSync","tmpdir","join","describe","expect","it","vi","runUpgrade","packuments","canary","versions","peerDependencies","next","payload","engines","node","makeDeps","overrides","exists","fetchRegistry","name","Promise","resolve","spawn","fn","mockResolvedValue","code","makeProject","dir","JSON","stringify","dependencies","order","mockImplementation","push","runTransforms","failed","results","flags","dry","force","tag","path","toEqual","result","not","toHaveBeenCalled","toBe"],"mappings":"AAAA,SAASA,UAAU,EAAEC,WAAW,EAAEC,aAAa,QAAQ,UAAS;AAChE,SAASC,MAAM,QAAQ,UAAS;AAChC,SAASC,IAAI,QAAQ,YAAW;AAChC,SAASC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ,SAAQ;AAIjD,SAASC,UAAU,QAAQ,aAAY;AAEvC,MAAMC,aAAgD;IACpD,oBAAoB;QAClB,aAAa;YAAEC,QAAQ;QAAkB;QACzCC,UAAU;YAAE,mBAAmB;gBAAEC,kBAAkB;oBAAEC,MAAM;gBAAmB;YAAE;QAAE;IACpF;IACA,eAAe;QAAEF,UAAU;YAAE,WAAW,CAAC;QAAE;IAAE;IAC7CE,MAAM;QAAEF,UAAU;YAAE,UAAU,CAAC;QAAE;IAAE;IACnCG,SAAS;QACP,aAAa;YAAEJ,QAAQ;QAAkB;QACzCC,UAAU;YAAE,mBAAmB;gBAAEI,SAAS;oBAAEC,MAAM;gBAAY;YAAE;QAAE;IACpE;AACF;AAEA,MAAMC,WAAW,CAACC,YAAkC,CAAC,CAAC,GAAmB,CAAA;QACvE,yEAAyE;QACzEC,QAAQpB;QACRqB,eAAe,CAACC,OAASC,QAAQC,OAAO,CAACd,UAAU,CAACY,KAAK,IAAI,CAAC;QAC9DG,OAAOjB,GAAGkB,EAAE,GAAGC,iBAAiB,CAAC;YAAEC,MAAM;QAAE;QAC3C,GAAGT,SAAS;IACd,CAAA;AAEA,MAAMU,cAAc;IAClB,MAAMC,MAAM7B,YAAYG,KAAKD,UAAU;IACvCD,cACEE,KAAK0B,KAAK,iBACVC,KAAKC,SAAS,CAAC;QAAEC,cAAc;YAAElB,SAAS;QAAS;IAAE,GAAG,MAAM,KAAK;IAErE,OAAOe;AACT;AAEAzB,SAAS,cAAc;IACrBE,GAAG,sCAAsC;QACvC,MAAM2B,QAAkB,EAAE;QAC1B,MAAMT,QAAQjB,GAAGkB,EAAE,GAAGS,kBAAkB,CAAC;YACvCD,MAAME,IAAI,CAAC;YACX,OAAOb,QAAQC,OAAO,CAAC;gBAAEI,MAAM;YAAE;QACnC;QACA,MAAMS,gBAAgB7B,GAAGkB,EAAE,GAAGS,kBAAkB,CAAC;YAC/CD,MAAME,IAAI,CAAC;YACX,OAAOb,QAAQC,OAAO,CAAC;gBAAEc,QAAQ;gBAAOC,SAAS,EAAE;YAAC;QACtD;QAEA,MAAM9B,WACJ;YAAE+B,OAAO;gBAAEC,KAAK;gBAAOC,OAAO;gBAAMC,KAAK;YAAS;YAAGC,MAAMf;QAAc,GACzEX,SAAS;YAAEO;QAAM,IACjB;YAAEY;QAAc;QAGlB/B,OAAO4B,OAAOW,OAAO,CAAC;YAAC;YAAW;SAAa;IACjD;IAEAtC,GAAG,+CAA+C;QAChD,MAAM8B,gBAAgB7B,GAAGkB,EAAE;QAE3B,MAAMoB,SAAS,MAAMrC,WACnB;YACE+B,OAAO;gBAAEC,KAAK;gBAAOC,OAAO;gBAAMC,KAAK;YAAS;YAChDC,MAAMf;QACR,GACAX,SAAS;YAAEO,OAAOjB,GAAGkB,EAAE,GAAGC,iBAAiB,CAAC;gBAAEC,MAAM;YAAE;QAAG,IACzD;YAAES;QAAc;QAGlB/B,OAAO+B,eAAeU,GAAG,CAACC,gBAAgB;QAC1C1C,OAAOwC,OAAOR,MAAM,EAAEW,IAAI,CAAC;IAC7B;IAEA1C,GAAG,yDAAyD;QAC1D,MAAMkB,QAAQjB,GAAGkB,EAAE;QACnB,MAAMW,gBAAgB7B,GAAGkB,EAAE;QAE3B,MAAMjB,WACJ;YAAE+B,OAAO;gBAAEC,KAAK;gBAAMC,OAAO;gBAAMC,KAAK;YAAS;YAAGC,MAAMf;QAAc,GACxEX,SAAS;YAAEO;QAAM,IACjB;YAAEY;QAAc;QAGlB/B,OAAOmB,OAAOsB,GAAG,CAACC,gBAAgB;QAClC1C,OAAO+B,eAAeU,GAAG,CAACC,gBAAgB;IAC5C;AACF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=packaging.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packaging.spec.d.ts","sourceRoot":"","sources":["../../src/upgrade/packaging.spec.ts"],"names":[],"mappings":""}
@@ -1,29 +0,0 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { existsSync, mkdtempSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { dirname, join } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { describe, expect, it } from 'vitest';
7
- const here = dirname(fileURLToPath(import.meta.url));
8
- const pkgDir = join(here, '..', '..');
9
- describe('runbook packaging', ()=>{
10
- it('ships the hand-written runbook in src', ()=>{
11
- expect(existsSync(join(here, '..', 'runbook', 'payload-v4-upgrade.md'))).toBe(true);
12
- });
13
- it('copy script places the runbook and v4.mdx into the target runbook dir', ()=>{
14
- const scratch = mkdtempSync(join(tmpdir(), 'codemod-pkg-'));
15
- // Redirect the copy script's dist target so this test never touches the real dist/.
16
- execFileSync('node', [
17
- join(pkgDir, 'scripts', 'copy-migration-guide.mjs')
18
- ], {
19
- env: {
20
- ...process.env,
21
- CODEMOD_DIST_DIR: scratch
22
- }
23
- });
24
- expect(existsSync(join(scratch, 'runbook', 'payload-v4-upgrade.md'))).toBe(true);
25
- expect(existsSync(join(scratch, 'runbook', 'v4.mdx'))).toBe(true);
26
- });
27
- });
28
-
29
- //# sourceMappingURL=packaging.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/upgrade/packaging.spec.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process'\nimport { existsSync, mkdtempSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { describe, expect, it } from 'vitest'\n\nconst here = dirname(fileURLToPath(import.meta.url))\nconst pkgDir = join(here, '..', '..')\n\ndescribe('runbook packaging', () => {\n it('ships the hand-written runbook in src', () => {\n expect(existsSync(join(here, '..', 'runbook', 'payload-v4-upgrade.md'))).toBe(true)\n })\n\n it('copy script places the runbook and v4.mdx into the target runbook dir', () => {\n const scratch = mkdtempSync(join(tmpdir(), 'codemod-pkg-'))\n\n // Redirect the copy script's dist target so this test never touches the real dist/.\n execFileSync('node', [join(pkgDir, 'scripts', 'copy-migration-guide.mjs')], {\n env: { ...process.env, CODEMOD_DIST_DIR: scratch },\n })\n\n expect(existsSync(join(scratch, 'runbook', 'payload-v4-upgrade.md'))).toBe(true)\n expect(existsSync(join(scratch, 'runbook', 'v4.mdx'))).toBe(true)\n })\n})\n"],"names":["execFileSync","existsSync","mkdtempSync","tmpdir","dirname","join","fileURLToPath","describe","expect","it","here","url","pkgDir","toBe","scratch","env","process","CODEMOD_DIST_DIR"],"mappings":"AAAA,SAASA,YAAY,QAAQ,qBAAoB;AACjD,SAASC,UAAU,EAAEC,WAAW,QAAQ,UAAS;AACjD,SAASC,MAAM,QAAQ,UAAS;AAChC,SAASC,OAAO,EAAEC,IAAI,QAAQ,YAAW;AACzC,SAASC,aAAa,QAAQ,WAAU;AACxC,SAASC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,MAAMC,OAAON,QAAQE,cAAc,YAAYK,GAAG;AAClD,MAAMC,SAASP,KAAKK,MAAM,MAAM;AAEhCH,SAAS,qBAAqB;IAC5BE,GAAG,yCAAyC;QAC1CD,OAAOP,WAAWI,KAAKK,MAAM,MAAM,WAAW,2BAA2BG,IAAI,CAAC;IAChF;IAEAJ,GAAG,yEAAyE;QAC1E,MAAMK,UAAUZ,YAAYG,KAAKF,UAAU;QAE3C,oFAAoF;QACpFH,aAAa,QAAQ;YAACK,KAAKO,QAAQ,WAAW;SAA4B,EAAE;YAC1EG,KAAK;gBAAE,GAAGC,QAAQD,GAAG;gBAAEE,kBAAkBH;YAAQ;QACnD;QAEAN,OAAOP,WAAWI,KAAKS,SAAS,WAAW,2BAA2BD,IAAI,CAAC;QAC3EL,OAAOP,WAAWI,KAAKS,SAAS,WAAW,YAAYD,IAAI,CAAC;IAC9D;AACF"}
@@ -1,11 +0,0 @@
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
- */
10
- export declare function renderUpgradePrompt(): string;
11
- //# sourceMappingURL=prompt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/upgrade/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAgE5C"}
@@ -1,75 +0,0 @@
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