@payloadcms/codemod 4.0.0-internal.44ac9c8 → 4.0.0-internal.4a6b4c3

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 (84) hide show
  1. package/README.md +6 -2
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.help.d.ts +4 -0
  4. package/dist/cli.help.d.ts.map +1 -0
  5. package/dist/cli.help.js +29 -0
  6. package/dist/cli.help.js.map +1 -0
  7. package/dist/cli.js +8 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/cli.parseFlags.d.ts +1 -0
  10. package/dist/cli.parseFlags.d.ts.map +1 -1
  11. package/dist/cli.parseFlags.js +6 -0
  12. package/dist/cli.parseFlags.js.map +1 -1
  13. package/dist/registry.d.ts.map +1 -1
  14. package/dist/registry.js +6 -0
  15. package/dist/registry.js.map +1 -1
  16. package/dist/runbook/payload-v4-upgrade.md +2 -2
  17. package/dist/runbook/v4.mdx +370 -80
  18. package/dist/transforms/migrate-admin-context-properties/basic.input.js +32 -0
  19. package/dist/transforms/migrate-admin-context-properties/basic.input.js.map +1 -0
  20. package/dist/transforms/migrate-admin-context-properties/basic.output.js +30 -0
  21. package/dist/transforms/migrate-admin-context-properties/basic.output.js.map +1 -0
  22. package/dist/transforms/migrate-admin-context-properties/index.d.ts +3 -0
  23. package/dist/transforms/migrate-admin-context-properties/index.d.ts.map +1 -0
  24. package/dist/transforms/migrate-admin-context-properties/index.js +302 -0
  25. package/dist/transforms/migrate-admin-context-properties/index.js.map +1 -0
  26. package/dist/transforms/migrate-admin-context-properties/no-match.input.js +30 -0
  27. package/dist/transforms/migrate-admin-context-properties/no-match.input.js.map +1 -0
  28. package/dist/transforms/migrate-admin-context-properties/no-match.output.js +30 -0
  29. package/dist/transforms/migrate-admin-context-properties/no-match.output.js.map +1 -0
  30. package/dist/transforms/migrate-displayed-field-value-args/basic.input.js +4 -0
  31. package/dist/transforms/migrate-displayed-field-value-args/basic.input.js.map +1 -0
  32. package/dist/transforms/migrate-displayed-field-value-args/basic.output.js +8 -0
  33. package/dist/transforms/migrate-displayed-field-value-args/basic.output.js.map +1 -0
  34. package/dist/transforms/migrate-displayed-field-value-args/index.d.ts +3 -0
  35. package/dist/transforms/migrate-displayed-field-value-args/index.d.ts.map +1 -0
  36. package/dist/transforms/migrate-displayed-field-value-args/index.js +84 -0
  37. package/dist/transforms/migrate-displayed-field-value-args/index.js.map +1 -0
  38. package/dist/transforms/migrate-displayed-field-value-args/namespace.input.js +4 -0
  39. package/dist/transforms/migrate-displayed-field-value-args/namespace.input.js.map +1 -0
  40. package/dist/transforms/migrate-displayed-field-value-args/namespace.output.js +8 -0
  41. package/dist/transforms/migrate-displayed-field-value-args/namespace.output.js.map +1 -0
  42. package/dist/transforms/migrate-displayed-field-value-args/no-match.input.js +4 -0
  43. package/dist/transforms/migrate-displayed-field-value-args/no-match.input.js.map +1 -0
  44. package/dist/transforms/migrate-displayed-field-value-args/no-match.output.js +4 -0
  45. package/dist/transforms/migrate-displayed-field-value-args/no-match.output.js.map +1 -0
  46. package/dist/transforms/migrate-field-component-types/index.d.ts.map +1 -1
  47. package/dist/transforms/migrate-field-component-types/index.js +4 -0
  48. package/dist/transforms/migrate-field-component-types/index.js.map +1 -1
  49. package/dist/transforms/migrate-sharp-to-transformer/basic.output.js +1 -1
  50. package/dist/transforms/migrate-sharp-to-transformer/basic.output.js.map +1 -1
  51. package/dist/transforms/migrate-sharp-to-transformer/existing-transformers.output.js +1 -1
  52. package/dist/transforms/migrate-sharp-to-transformer/existing-transformers.output.js.map +1 -1
  53. package/dist/transforms/migrate-sharp-to-transformer/index.d.ts.map +1 -1
  54. package/dist/transforms/migrate-sharp-to-transformer/index.js +232 -82
  55. package/dist/transforms/migrate-sharp-to-transformer/index.js.map +1 -1
  56. package/dist/transforms/remove-storage-always-insert-fields/index.d.ts.map +1 -1
  57. package/dist/transforms/remove-storage-always-insert-fields/index.js +4 -0
  58. package/dist/transforms/remove-storage-always-insert-fields/index.js.map +1 -1
  59. package/dist/transforms/rename-diff-value-props/basic.input.js +38 -0
  60. package/dist/transforms/rename-diff-value-props/basic.input.js.map +1 -0
  61. package/dist/transforms/rename-diff-value-props/basic.output.js +38 -0
  62. package/dist/transforms/rename-diff-value-props/basic.output.js.map +1 -0
  63. package/dist/transforms/rename-diff-value-props/index.d.ts +3 -0
  64. package/dist/transforms/rename-diff-value-props/index.d.ts.map +1 -0
  65. package/dist/transforms/rename-diff-value-props/index.js +328 -0
  66. package/dist/transforms/rename-diff-value-props/index.js.map +1 -0
  67. package/dist/transforms/rename-diff-value-props/no-match.input.js +8 -0
  68. package/dist/transforms/rename-diff-value-props/no-match.input.js.map +1 -0
  69. package/dist/transforms/rename-experimental-table-feature/index.d.ts.map +1 -1
  70. package/dist/transforms/rename-experimental-table-feature/index.js +7 -1
  71. package/dist/transforms/rename-experimental-table-feature/index.js.map +1 -1
  72. package/dist/upgrade/defaultTag.d.ts +1 -1
  73. package/dist/upgrade/defaultTag.js +2 -2
  74. package/dist/upgrade/defaultTag.js.map +1 -1
  75. package/dist/upgrade/prompt.js +2 -2
  76. package/dist/upgrade/prompt.js.map +1 -1
  77. package/dist/upgrade/rewritePackageJson.d.ts.map +1 -1
  78. package/dist/upgrade/rewritePackageJson.js +52 -11
  79. package/dist/upgrade/rewritePackageJson.js.map +1 -1
  80. package/dist/utils/project.d.ts +7 -1
  81. package/dist/utils/project.d.ts.map +1 -1
  82. package/dist/utils/project.js +20 -7
  83. package/dist/utils/project.js.map +1 -1
  84. package/package.json +2 -2
@@ -1,3 +1,4 @@
1
+ import semver from 'semver';
1
2
  const DEP_FIELDS = [
2
3
  'dependencies',
3
4
  'devDependencies'
@@ -95,26 +96,66 @@ function pruneOverrideBlock(block, label, removed) {
95
96
  }
96
97
  function writeFloors(data, resolved) {
97
98
  const written = [];
98
- pinDep(data, 'typescript', resolved.typescript);
99
- pinDep(data, '@types/node', resolved.typesNode);
100
- written.push('typescript', '@types/node');
99
+ if (writeDepFloor({
100
+ name: 'typescript',
101
+ data,
102
+ floor: resolved.typescript
103
+ })) {
104
+ written.push('typescript');
105
+ }
106
+ if (writeDepFloor({
107
+ name: '@types/node',
108
+ data,
109
+ floor: resolved.typesNode
110
+ })) {
111
+ written.push('@types/node');
112
+ }
101
113
  const engines = isRecord(data.engines) ? data.engines : {};
102
- engines.node = resolved.enginesNode;
103
- data.engines = engines;
104
- written.push('engines.node');
114
+ if (engines.node === undefined || isBelowFloor({
115
+ floor: resolved.enginesNode,
116
+ spec: engines.node
117
+ })) {
118
+ engines.node = resolved.enginesNode;
119
+ data.engines = engines;
120
+ written.push('engines.node');
121
+ }
105
122
  return written;
106
123
  }
107
- /** Update a dep wherever it already lives, else add it to devDependencies. */ function pinDep(data, name, version) {
124
+ /**
125
+ * Raise a dep to `floor` wherever it already lives, else add it to devDependencies.
126
+ * Placeholder specs, non-semver specs (e.g. `latest`), and ranges already at or
127
+ * above the floor are left as-is. Returns whether the dep was written.
128
+ */ function writeDepFloor({ name, data, floor }) {
108
129
  for (const field of DEP_FIELDS){
109
130
  const deps = data[field];
110
- if (isRecord(deps) && name in deps) {
111
- deps[name] = version;
112
- return;
131
+ if (!isRecord(deps) || !(name in deps)) {
132
+ continue;
133
+ }
134
+ const spec = deps[name];
135
+ if (isPlaceholderSpec(spec) || !isBelowFloor({
136
+ floor,
137
+ spec
138
+ })) {
139
+ return false;
113
140
  }
141
+ deps[name] = floor;
142
+ return true;
114
143
  }
115
144
  const devDeps = isRecord(data.devDependencies) ? data.devDependencies : {};
116
- devDeps[name] = version;
145
+ devDeps[name] = floor;
117
146
  data.devDependencies = devDeps;
147
+ return true;
148
+ }
149
+ /** True only when `spec` is a semver range whose lowest version is below the floor's. */ function isBelowFloor({ floor, spec }) {
150
+ if (typeof spec !== 'string' || !semver.validRange(spec)) {
151
+ return false;
152
+ }
153
+ const specMin = semver.minVersion(spec);
154
+ const floorMin = semver.minVersion(floor);
155
+ if (!specMin || !floorMin) {
156
+ return false;
157
+ }
158
+ return semver.lt(specMin, floorMin);
118
159
  }
119
160
  function isRecord(value) {
120
161
  return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -1 +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 placeholdersSkipped: string[]\n}\n\nconst DEP_FIELDS = ['dependencies', 'devDependencies'] as const\n\n/** Any protocol-prefixed specifier (`workspace:*`, `catalog:`, `link:`, `file:`, `npm:`, a URL). */\nconst PLACEHOLDER_SPEC = /^[a-z][a-z0-9+.-]*:/i\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 * A dependency whose version is resolved by the package manager, not a semver\n * range: `workspace:*`, `catalog:`, `link:`, `file:`, `npm:` aliases, URLs.\n * Overwriting one with an exact version would break the link, so it is left as-is.\n */\nexport const isPlaceholderSpec = (spec: unknown): boolean =>\n typeof spec === 'string' && PLACEHOLDER_SPEC.test(spec)\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, placeholdersSkipped } = pinPayloadPackages(data, resolved.payloadVersion)\n const overridesRemoved = removePayloadOverrides(data)\n const floorsWritten = writeFloors(data, resolved)\n return { floorsWritten, overridesRemoved, pinnedPayload, placeholdersSkipped }\n}\n\nfunction pinPayloadPackages(\n data: Record<string, unknown>,\n version: string,\n): { pinnedPayload: string[]; placeholdersSkipped: string[] } {\n const pinned: string[] = []\n const skipped: 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 (!isPayloadPackage(name)) {\n continue\n }\n // A workspace/catalog/link spec resolves itself; pinning it breaks the link.\n if (isPlaceholderSpec(deps[name])) {\n skipped.push(name)\n continue\n }\n if (isPayloadEslintPackage(name)) {\n deps[name] = 'latest'\n continue\n }\n deps[name] = version\n pinned.push(name)\n }\n }\n return { pinnedPayload: pinned, placeholdersSkipped: skipped }\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","PLACEHOLDER_SPEC","isPayloadPackage","name","startsWith","isPayloadEslintPackage","isPlaceholderSpec","spec","test","rewritePackageJson","data","resolved","pinnedPayload","placeholdersSkipped","pinPayloadPackages","payloadVersion","overridesRemoved","removePayloadOverrides","floorsWritten","writeFloors","version","pinned","skipped","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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"}
1
+ {"version":3,"sources":["../../src/upgrade/rewritePackageJson.ts"],"sourcesContent":["import semver from 'semver'\n\nimport 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 placeholdersSkipped: string[]\n}\n\nconst DEP_FIELDS = ['dependencies', 'devDependencies'] as const\n\n/** Any protocol-prefixed specifier (`workspace:*`, `catalog:`, `link:`, `file:`, `npm:`, a URL). */\nconst PLACEHOLDER_SPEC = /^[a-z][a-z0-9+.-]*:/i\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 * A dependency whose version is resolved by the package manager, not a semver\n * range: `workspace:*`, `catalog:`, `link:`, `file:`, `npm:` aliases, URLs.\n * Overwriting one with an exact version would break the link, so it is left as-is.\n */\nexport const isPlaceholderSpec = (spec: unknown): boolean =>\n typeof spec === 'string' && PLACEHOLDER_SPEC.test(spec)\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, placeholdersSkipped } = pinPayloadPackages(data, resolved.payloadVersion)\n const overridesRemoved = removePayloadOverrides(data)\n const floorsWritten = writeFloors(data, resolved)\n return { floorsWritten, overridesRemoved, pinnedPayload, placeholdersSkipped }\n}\n\nfunction pinPayloadPackages(\n data: Record<string, unknown>,\n version: string,\n): { pinnedPayload: string[]; placeholdersSkipped: string[] } {\n const pinned: string[] = []\n const skipped: 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 (!isPayloadPackage(name)) {\n continue\n }\n // A workspace/catalog/link spec resolves itself; pinning it breaks the link.\n if (isPlaceholderSpec(deps[name])) {\n skipped.push(name)\n continue\n }\n if (isPayloadEslintPackage(name)) {\n deps[name] = 'latest'\n continue\n }\n deps[name] = version\n pinned.push(name)\n }\n }\n return { pinnedPayload: pinned, placeholdersSkipped: skipped }\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 if (writeDepFloor({ name: 'typescript', data, floor: resolved.typescript })) {\n written.push('typescript')\n }\n if (writeDepFloor({ name: '@types/node', data, floor: resolved.typesNode })) {\n written.push('@types/node')\n }\n\n const engines = isRecord(data.engines) ? data.engines : {}\n if (\n engines.node === undefined ||\n isBelowFloor({ floor: resolved.enginesNode, spec: engines.node })\n ) {\n engines.node = resolved.enginesNode\n data.engines = engines\n written.push('engines.node')\n }\n\n return written\n}\n\n/**\n * Raise a dep to `floor` wherever it already lives, else add it to devDependencies.\n * Placeholder specs, non-semver specs (e.g. `latest`), and ranges already at or\n * above the floor are left as-is. Returns whether the dep was written.\n */\nfunction writeDepFloor({\n name,\n data,\n floor,\n}: {\n data: Record<string, unknown>\n floor: string\n name: string\n}): boolean {\n for (const field of DEP_FIELDS) {\n const deps = data[field]\n if (!isRecord(deps) || !(name in deps)) {\n continue\n }\n const spec = deps[name]\n if (isPlaceholderSpec(spec) || !isBelowFloor({ floor, spec })) {\n return false\n }\n deps[name] = floor\n return true\n }\n const devDeps = isRecord(data.devDependencies) ? data.devDependencies : {}\n devDeps[name] = floor\n data.devDependencies = devDeps\n return true\n}\n\n/** True only when `spec` is a semver range whose lowest version is below the floor's. */\nfunction isBelowFloor({ floor, spec }: { floor: string; spec: unknown }): boolean {\n if (typeof spec !== 'string' || !semver.validRange(spec)) {\n return false\n }\n const specMin = semver.minVersion(spec)\n const floorMin = semver.minVersion(floor)\n if (!specMin || !floorMin) {\n return false\n }\n return semver.lt(specMin, floorMin)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n"],"names":["semver","DEP_FIELDS","PLACEHOLDER_SPEC","isPayloadPackage","name","startsWith","isPayloadEslintPackage","isPlaceholderSpec","spec","test","rewritePackageJson","data","resolved","pinnedPayload","placeholdersSkipped","pinPayloadPackages","payloadVersion","overridesRemoved","removePayloadOverrides","floorsWritten","writeFloors","version","pinned","skipped","field","deps","isRecord","Object","keys","push","removed","pnpm","overrides","pruneOverrideBlock","length","key","block","label","written","writeDepFloor","floor","typescript","typesNode","engines","node","undefined","isBelowFloor","enginesNode","devDeps","devDependencies","validRange","specMin","minVersion","floorMin","lt","value","Array","isArray"],"mappings":"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"}
@@ -1,4 +1,10 @@
1
1
  import { Project } from 'ts-morph';
2
- /** Load a ts-morph Project rooted at `path`, using its tsconfig.json if present. */
2
+ /**
3
+ * Load a ts-morph Project rooted at `path`, using its tsconfig.json if present.
4
+ *
5
+ * Falls back to globbing when the tsconfig resolves no source files (e.g. a
6
+ * solution-style config with only `references`), so transforms never silently
7
+ * run against an empty project.
8
+ */
3
9
  export declare function loadProject(path: string): Project;
4
10
  //# sourceMappingURL=project.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/utils/project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,OAAO,EAAa,MAAM,UAAU,CAAA;AAQ9D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgBjD"}
@@ -1,19 +1,32 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
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
- };
4
+ const manipulationSettings = {
5
+ indentationText: IndentationText.TwoSpaces,
6
+ quoteKind: QuoteKind.Single,
7
+ useTrailingCommas: true
8
+ };
9
+ /**
10
+ * Load a ts-morph Project rooted at `path`, using its tsconfig.json if present.
11
+ *
12
+ * Falls back to globbing when the tsconfig resolves no source files (e.g. a
13
+ * solution-style config with only `references`), so transforms never silently
14
+ * run against an empty project.
15
+ */ export function loadProject(path) {
10
16
  const tsconfigPath = resolve(path, 'tsconfig.json');
11
17
  if (existsSync(tsconfigPath)) {
12
- return new Project({
18
+ const project = new Project({
13
19
  manipulationSettings,
14
20
  tsConfigFilePath: tsconfigPath
15
21
  });
22
+ if (project.getSourceFiles().length > 0) {
23
+ return project;
24
+ }
25
+ console.warn(`Warning: ${tsconfigPath} resolved no source files. Falling back to globbing ${path}.`);
16
26
  }
27
+ return loadProjectFromGlob(path);
28
+ }
29
+ function loadProjectFromGlob(path) {
17
30
  const project = new Project({
18
31
  manipulationSettings
19
32
  });
@@ -1 +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"}
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\nconst manipulationSettings = {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Single,\n useTrailingCommas: true,\n}\n\n/**\n * Load a ts-morph Project rooted at `path`, using its tsconfig.json if present.\n *\n * Falls back to globbing when the tsconfig resolves no source files (e.g. a\n * solution-style config with only `references`), so transforms never silently\n * run against an empty project.\n */\nexport function loadProject(path: string): Project {\n const tsconfigPath = resolve(path, 'tsconfig.json')\n\n if (existsSync(tsconfigPath)) {\n const project = new Project({ manipulationSettings, tsConfigFilePath: tsconfigPath })\n\n if (project.getSourceFiles().length > 0) {\n return project\n }\n\n console.warn(\n `Warning: ${tsconfigPath} resolved no source files. Falling back to globbing ${path}.`,\n )\n }\n\n return loadProjectFromGlob(path)\n}\n\nfunction loadProjectFromGlob(path: string): Project {\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","manipulationSettings","indentationText","TwoSpaces","quoteKind","Single","useTrailingCommas","loadProject","path","tsconfigPath","project","tsConfigFilePath","getSourceFiles","length","console","warn","loadProjectFromGlob","addSourceFilesAtPaths"],"mappings":"AAAA,SAASA,UAAU,QAAQ,UAAS;AACpC,SAASC,OAAO,QAAQ,YAAW;AACnC,SAASC,eAAe,EAAEC,OAAO,EAAEC,SAAS,QAAQ,WAAU;AAE9D,MAAMC,uBAAuB;IAC3BC,iBAAiBJ,gBAAgBK,SAAS;IAC1CC,WAAWJ,UAAUK,MAAM;IAC3BC,mBAAmB;AACrB;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,YAAYC,IAAY;IACtC,MAAMC,eAAeZ,QAAQW,MAAM;IAEnC,IAAIZ,WAAWa,eAAe;QAC5B,MAAMC,UAAU,IAAIX,QAAQ;YAAEE;YAAsBU,kBAAkBF;QAAa;QAEnF,IAAIC,QAAQE,cAAc,GAAGC,MAAM,GAAG,GAAG;YACvC,OAAOH;QACT;QAEAI,QAAQC,IAAI,CACV,CAAC,SAAS,EAAEN,aAAa,oDAAoD,EAAED,KAAK,CAAC,CAAC;IAE1F;IAEA,OAAOQ,oBAAoBR;AAC7B;AAEA,SAASQ,oBAAoBR,IAAY;IACvC,MAAME,UAAU,IAAIX,QAAQ;QAAEE;IAAqB;IACnDS,QAAQO,qBAAqB,CAAC;QAC5B,GAAGT,KAAK,qBAAqB,CAAC;QAC9B;QACA;QACA;QACA;KACD;IACD,OAAOE;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/codemod",
3
- "version": "4.0.0-internal.44ac9c8",
3
+ "version": "4.0.0-internal.4a6b4c3",
4
4
  "description": "Codemods for migrating Payload projects across versions.",
5
5
  "homepage": "https://payloadcms.com",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@clack/prompts": "1.2.0",
33
33
  "semver": "^7.8.5",
34
- "ts-morph": "^21.0.1"
34
+ "ts-morph": "^28.0.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@swc/core": "1.15.3",