@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,57 +1,10 @@
1
1
  import { Node, SyntaxKind } from 'ts-morph';
2
2
  const TRANSFORMER_MODULE = '@payloadcms/transformer-sharp';
3
3
  const TRANSFORMER_NAME = 'sharpTransformer';
4
+ const VARIANTS_KEY = 'variants';
4
5
  const IDENTIFIER_PATTERN = /^[A-Z_$][\w$]*$/i;
5
- const RESERVED_WORDS = new Set([
6
- 'await',
7
- 'break',
8
- 'case',
9
- 'catch',
10
- 'class',
11
- 'const',
12
- 'continue',
13
- 'debugger',
14
- 'default',
15
- 'delete',
16
- 'do',
17
- 'else',
18
- 'enum',
19
- 'export',
20
- 'extends',
21
- 'false',
22
- 'finally',
23
- 'for',
24
- 'function',
25
- 'if',
26
- 'implements',
27
- 'import',
28
- 'in',
29
- 'instanceof',
30
- 'interface',
31
- 'let',
32
- 'new',
33
- 'null',
34
- 'package',
35
- 'private',
36
- 'protected',
37
- 'public',
38
- 'return',
39
- 'static',
40
- 'super',
41
- 'switch',
42
- 'this',
43
- 'throw',
44
- 'true',
45
- 'try',
46
- 'typeof',
47
- 'var',
48
- 'void',
49
- 'while',
50
- 'with',
51
- 'yield'
52
- ]);
53
6
  /** Whether `value` can be used as a plain (unquoted, non-bracketed) object literal key. */ function isSafePlainObjectKey(value) {
54
- return IDENTIFIER_PATTERN.test(value) && !RESERVED_WORDS.has(value);
7
+ return IDENTIFIER_PATTERN.test(value);
55
8
  }
56
9
  /** Fields moved from a collection's `upload` object into `sharpTransformer({ collections })`. */ const MOVED_UPLOAD_FIELDS = [
57
10
  'constructorOptions',
@@ -77,15 +30,49 @@ const findBuildConfigLocalNames = (file)=>{
77
30
  }
78
31
  return localNames;
79
32
  };
80
- function ensureSharpTransformerImport(sourceFile) {
81
- const existing = sourceFile.getImportDeclarations().find((decl)=>decl.getModuleSpecifierValue() === TRANSFORMER_MODULE);
33
+ /**
34
+ * Resolves the local binding of the imported `sharpTransformer`, honoring an alias such as
35
+ * `import { sharpTransformer as st }`. When it isn't imported yet, picks a name no other
36
+ * identifier in the file uses, so a local `sharpTransformer` function is never mistaken for it.
37
+ */ function resolveSharpTransformerBinding(sourceFile) {
38
+ const namedImports = sourceFile.getImportDeclarations().filter((decl)=>decl.getModuleSpecifierValue() === TRANSFORMER_MODULE && !decl.isTypeOnly()).flatMap((decl)=>decl.getNamedImports()).filter((named)=>named.getName() === TRANSFORMER_NAME && !named.isTypeOnly());
39
+ const unaliasedImport = namedImports.find((named)=>!named.getAliasNode());
40
+ const aliasedImport = namedImports.find((named)=>named.getAliasNode());
41
+ if (unaliasedImport) {
42
+ return {
43
+ isImported: true,
44
+ localName: TRANSFORMER_NAME
45
+ };
46
+ }
47
+ if (aliasedImport) {
48
+ return {
49
+ isImported: true,
50
+ localName: aliasedImport.getAliasNode().getText()
51
+ };
52
+ }
53
+ const usedIdentifiers = new Set(sourceFile.getDescendantsOfKind(SyntaxKind.Identifier).map((identifier)=>identifier.getText()));
54
+ let localName = TRANSFORMER_NAME;
55
+ for(let suffix = 2; usedIdentifiers.has(localName); suffix++){
56
+ localName = `${TRANSFORMER_NAME}${suffix}`;
57
+ }
58
+ return {
59
+ isImported: false,
60
+ localName
61
+ };
62
+ }
63
+ function ensureSharpTransformerImport({ localName, sourceFile }) {
64
+ const namedImport = localName === TRANSFORMER_NAME ? TRANSFORMER_NAME : {
65
+ name: TRANSFORMER_NAME,
66
+ alias: localName
67
+ };
68
+ const existing = sourceFile.getImportDeclarations().find((decl)=>decl.getModuleSpecifierValue() === TRANSFORMER_MODULE && !decl.isTypeOnly());
82
69
  if (!existing) {
83
70
  const otherImports = sourceFile.getImportDeclarations();
84
71
  const fileOmitsSemicolonsOnImports = otherImports.length > 0 && otherImports.every((decl)=>!decl.getText().endsWith(';'));
85
72
  const insertedImport = sourceFile.addImportDeclaration({
86
73
  moduleSpecifier: TRANSFORMER_MODULE,
87
74
  namedImports: [
88
- TRANSFORMER_NAME
75
+ namedImport
89
76
  ]
90
77
  });
91
78
  // ts-morph always appends a semicolon; strip it when the file's other imports don't use them.
@@ -97,16 +84,18 @@ function ensureSharpTransformerImport(sourceFile) {
97
84
  }
98
85
  return;
99
86
  }
100
- const alreadyImported = existing.getNamedImports().some((named)=>named.getName() === TRANSFORMER_NAME);
87
+ const alreadyImported = existing.getNamedImports().some((named)=>named.getName() === TRANSFORMER_NAME && !named.isTypeOnly() && (named.getAliasNode()?.getText() ?? TRANSFORMER_NAME) === localName);
101
88
  if (!alreadyImported) {
102
- existing.addNamedImport(TRANSFORMER_NAME);
89
+ existing.addNamedImport(namedImport);
103
90
  }
104
91
  }
105
92
  /**
106
- * Extracts Sharp-owned fields off one collection's `upload` object literal into
107
- * a `<slug>: { ... }` entry text for the `sharpTransformer({ collections })` map.
108
- * Returns `undefined` when the collection has nothing to migrate.
109
- */ function extractCollectionSharpEntry({ collectionObj, filePath, notes }) {
93
+ * Reads Sharp-owned fields off one collection's `upload` object literal into
94
+ * a `<slug>: { ... }` entry text for the `sharpTransformer({ collections })` map,
95
+ * without modifying the collection. Returns `undefined` when the collection has nothing to migrate.
96
+ */ function extractCollectionSharpEntry({ collectionObj, configFile, notes }) {
97
+ const filePath = collectionObj.getSourceFile().getFilePath();
98
+ const isExternal = collectionObj.getSourceFile() !== configFile;
110
99
  const slugProp = collectionObj.getProperty('slug');
111
100
  const slugAssignment = slugProp?.asKind(SyntaxKind.PropertyAssignment);
112
101
  const slugInitializer = slugAssignment?.getInitializer();
@@ -129,29 +118,123 @@ function ensureSharpTransformerImport(sourceFile) {
129
118
  notes.push(`${filePath}: collection ${slugInitializer.getText()}'s \`upload\` object contains a spread — Sharp-specific fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) hidden inside it need manual review.`);
130
119
  }
131
120
  const movedTexts = [];
121
+ const movedProps = [];
132
122
  for (const name of MOVED_UPLOAD_FIELDS){
133
123
  const prop = uploadObj.getProperty(name);
134
- if (prop && Node.isPropertyAssignment(prop)) {
135
- movedTexts.push(prop.print());
136
- prop.remove();
124
+ if (!prop) {
125
+ continue;
126
+ }
127
+ // A shorthand `imageSizes` reads the same binding from `buildConfig`'s argument,
128
+ // where the `sharpTransformer` call is inserted, so it moves verbatim.
129
+ if (Node.isPropertyAssignment(prop) || Node.isShorthandPropertyAssignment(prop)) {
130
+ const localReference = isExternal ? findLocalReference({
131
+ node: prop
132
+ }) : undefined;
133
+ // Moving the text into the config file would leave this reference unresolved there.
134
+ if (localReference) {
135
+ notes.push(`${filePath}: collection ${slugInitializer.getText()}'s \`upload.${name}\` refers to \`${localReference.getText()}\`, which isn't available in ${configFile.getFilePath()} — move this collection's Sharp-specific \`upload\` fields into \`sharpTransformer({ collections })\` manually.`);
136
+ return undefined;
137
+ }
138
+ movedTexts.push(name === 'imageSizes' ? printAsVariants(prop) : prop.print());
139
+ movedProps.push(prop);
140
+ continue;
137
141
  }
142
+ notes.push(`${filePath}: collection ${slugInitializer.getText()}'s \`upload.${name}\` isn't a plain property — move it into \`sharpTransformer({ collections })\` manually.`);
138
143
  }
139
144
  if (movedTexts.length === 0) {
140
145
  return undefined;
141
146
  }
147
+ const slugLiteralValue = getSlugLiteralValue({
148
+ isExternal,
149
+ slugInitializer
150
+ });
151
+ if (isExternal && slugLiteralValue === undefined) {
152
+ notes.push(`${filePath}: collection ${slugInitializer.getText()}'s slug isn't a string constant — move its Sharp-specific \`upload\` fields into \`sharpTransformer({ collections })\` manually.`);
153
+ return undefined;
154
+ }
155
+ // A slug constant from another file isn't in scope in the config file, so it's keyed by value.
156
+ const keyText = slugLiteralValue !== undefined && isSafePlainObjectKey(slugLiteralValue) ? slugLiteralValue : isExternal && !isStringLiteralNode(slugInitializer) ? `'${slugLiteralValue.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'` : `[${slugInitializer.getText()}]`;
157
+ return {
158
+ entryText: `${keyText}: { ${movedTexts.join(', ')} }`,
159
+ movedProps,
160
+ uploadObj
161
+ };
162
+ }
163
+ function isStringLiteralNode(node) {
164
+ return Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node);
165
+ }
166
+ /**
167
+ * A slug written as a string literal or, for a collection in another file, a constant whose
168
+ * type is a string literal (e.g. `slug: mediaSlug` with `const mediaSlug = 'media'`).
169
+ */ function getSlugLiteralValue({ isExternal, slugInitializer }) {
170
+ if (isStringLiteralNode(slugInitializer)) {
171
+ return slugInitializer.getLiteralValue();
172
+ }
173
+ if (!isExternal) {
174
+ return undefined;
175
+ }
176
+ const slugType = slugInitializer.getType();
177
+ return slugType.isStringLiteral() ? slugType.getLiteralValue() : undefined;
178
+ }
179
+ /**
180
+ * The first identifier inside `node` bound to a declaration elsewhere in the project, such as an
181
+ * import or a local variable. Declarations inside `node` itself (parameters, its own property
182
+ * names) and ambient/library ones (`undefined`, `Math`) don't count.
183
+ */ function findLocalReference({ node }) {
184
+ const sourceFile = node.getSourceFile();
185
+ return node.getDescendantsOfKind(SyntaxKind.Identifier).find((identifier)=>(identifier.getSymbol()?.getDeclarations() ?? []).some((declaration)=>{
186
+ const declarationFile = declaration.getSourceFile();
187
+ if (declarationFile.isDeclarationFile() || declarationFile.isFromExternalLibrary()) {
188
+ return false;
189
+ }
190
+ return declarationFile !== sourceFile || declaration.getPos() < node.getPos() || declaration.getEnd() > node.getEnd();
191
+ }));
192
+ }
193
+ /**
194
+ * Follows a `collections` array element written as an identifier (usually an imported
195
+ * collection, e.g. `import { Media } from './collections/Media'`) to the object literal it's
196
+ * declared as, unwrapping `satisfies`/`as`/parentheses. Returns `undefined` for anything else,
197
+ * such as a factory call.
198
+ */ function resolveCollectionObject({ expression }) {
199
+ let current = expression;
200
+ for(let depth = 0; current && depth < 5; depth++){
201
+ while(Node.isSatisfiesExpression(current) || Node.isAsExpression(current) || Node.isParenthesizedExpression(current)){
202
+ current = current.getExpression();
203
+ }
204
+ if (Node.isObjectLiteralExpression(current)) {
205
+ return current;
206
+ }
207
+ if (!Node.isIdentifier(current)) {
208
+ return undefined;
209
+ }
210
+ const symbol = current.getSymbol();
211
+ const declaration = (symbol?.isAlias() ? symbol.getAliasedSymbol() : symbol)?.getDeclarations()[0];
212
+ if (Node.isVariableDeclaration(declaration)) {
213
+ current = declaration.getInitializer();
214
+ } else if (Node.isExportAssignment(declaration)) {
215
+ current = declaration.getExpression();
216
+ } else {
217
+ return undefined;
218
+ }
219
+ }
220
+ return undefined;
221
+ }
222
+ function removeMovedCollectionProps({ movedProps, uploadObj }) {
223
+ for (const prop of movedProps){
224
+ prop.remove();
225
+ }
142
226
  // Avoid leaving `upload: {\n}` spread across two lines once every property moves out.
143
227
  if (uploadObj.getProperties().length === 0) {
144
228
  uploadObj.replaceWithText('{}');
145
229
  }
146
- const slugLiteralValue = Node.isStringLiteral(slugInitializer) ? slugInitializer.getLiteralValue() : undefined;
147
- const keyText = slugLiteralValue !== undefined && isSafePlainObjectKey(slugLiteralValue) ? slugLiteralValue : `[${slugInitializer.getText()}]`;
148
- return `${keyText}: { ${movedTexts.join(', ')} }`;
149
230
  }
150
231
  /**
151
232
  * Builds every `<slug>: { ... }` entry for a `buildConfig({ collections })` array,
152
233
  * skipping (and, for a present `sharp` signal, noting) entries that aren't inline
153
234
  * object literals or whose `collections` array isn't statically analyzable.
154
- */ function extractSharpCollectionEntries({ configObj, filePath, notes }) {
235
+ */ function extractSharpCollectionEntries({ configObj, notes }) {
236
+ const configFile = configObj.getSourceFile();
237
+ const filePath = configFile.getFilePath();
155
238
  const collectionsProp = configObj.getProperty('collections');
156
239
  if (!collectionsProp || !Node.isPropertyAssignment(collectionsProp)) {
157
240
  return [];
@@ -163,13 +246,16 @@ function ensureSharpTransformerImport(sourceFile) {
163
246
  }
164
247
  const entries = [];
165
248
  for (const el of arrayLiteral.getElements()){
166
- if (!Node.isObjectLiteralExpression(el)) {
167
- notes.push(`${filePath}: a collection in \`collections\` is defined externally — check it for Sharp-specific \`upload\` fields and move them into \`sharpTransformer({ collections })\` manually.`);
249
+ const collectionObj = resolveCollectionObject({
250
+ expression: el
251
+ });
252
+ if (!collectionObj) {
253
+ notes.push(`${filePath}: a collection in \`collections\` (\`${el.getText()}\`) is defined externally — check it for Sharp-specific \`upload\` fields and move them into \`sharpTransformer({ collections })\` manually.`);
168
254
  continue;
169
255
  }
170
256
  const entry = extractCollectionSharpEntry({
171
- collectionObj: el,
172
- filePath,
257
+ collectionObj,
258
+ configFile,
173
259
  notes
174
260
  });
175
261
  if (entry) {
@@ -178,13 +264,46 @@ function ensureSharpTransformerImport(sourceFile) {
178
264
  }
179
265
  return entries;
180
266
  }
181
- function findSharpTransformerCall(transformersArray) {
267
+ /** `sharpTransformer` authors image sizes as `variants`; the collection's `imageSizes` is renamed on the way in. */ function printAsVariants(prop) {
268
+ return Node.isShorthandPropertyAssignment(prop) ? `${VARIANTS_KEY}: ${prop.getName()}` : `${VARIANTS_KEY}: ${prop.getInitializerOrThrow().print()}`;
269
+ }
270
+ /**
271
+ * Renames `imageSizes` to `variants` inside every inline `sharpTransformer({ collections })`
272
+ * entry in the file — configs migrated before `variants` existed. Returns whether it changed
273
+ * anything.
274
+ */ function renameImageSizesInSharpTransformerCalls({ notes, sourceFile, transformerLocalName }) {
275
+ let hasChanged = false;
276
+ const sharpTransformerCalls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call)=>{
277
+ const callee = call.getExpression();
278
+ return Node.isIdentifier(callee) && callee.getText() === transformerLocalName;
279
+ });
280
+ for (const call of sharpTransformerCalls){
281
+ const collectionsObj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression)?.getProperty('collections')?.asKind(SyntaxKind.PropertyAssignment)?.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
282
+ for (const entry of collectionsObj?.getProperties() ?? []){
283
+ const entryObj = Node.isPropertyAssignment(entry) ? entry.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression) : undefined;
284
+ if (!entryObj) {
285
+ notes.push(`${sourceFile.getFilePath()}: a \`${TRANSFORMER_NAME}({ collections })\` entry isn't an inline object — rename any \`imageSizes\` in it to \`${VARIANTS_KEY}\` manually.`);
286
+ continue;
287
+ }
288
+ const imageSizesProp = entryObj.getProperty('imageSizes');
289
+ if (imageSizesProp && Node.isPropertyAssignment(imageSizesProp)) {
290
+ imageSizesProp.getNameNode().replaceWithText(VARIANTS_KEY);
291
+ hasChanged = true;
292
+ } else if (imageSizesProp && Node.isShorthandPropertyAssignment(imageSizesProp)) {
293
+ imageSizesProp.replaceWithText(printAsVariants(imageSizesProp));
294
+ hasChanged = true;
295
+ }
296
+ }
297
+ }
298
+ return hasChanged;
299
+ }
300
+ function findSharpTransformerCall({ transformerLocalName, transformersArray }) {
182
301
  return transformersArray.getElements().find((el)=>{
183
302
  if (!Node.isCallExpression(el)) {
184
303
  return false;
185
304
  }
186
305
  const callee = el.getExpression();
187
- return Node.isIdentifier(callee) && callee.getText() === TRANSFORMER_NAME;
306
+ return Node.isIdentifier(callee) && callee.getText() === transformerLocalName;
188
307
  });
189
308
  }
190
309
  export const migrateSharpToTransformer = {
@@ -193,6 +312,14 @@ export const migrateSharpToTransformer = {
193
312
  const filesChanged = new Set();
194
313
  const notes = [];
195
314
  for (const sourceFile of project.getSourceFiles()){
315
+ const { isImported, localName: transformerLocalName } = resolveSharpTransformerBinding(sourceFile);
316
+ if (isImported && renameImageSizesInSharpTransformerCalls({
317
+ notes,
318
+ sourceFile,
319
+ transformerLocalName
320
+ })) {
321
+ filesChanged.add(sourceFile.getFilePath());
322
+ }
196
323
  const buildConfigLocalNames = findBuildConfigLocalNames(sourceFile);
197
324
  if (buildConfigLocalNames.size === 0) {
198
325
  continue;
@@ -212,7 +339,10 @@ export const migrateSharpToTransformer = {
212
339
  const uploadObj = uploadProp?.asKind(SyntaxKind.PropertyAssignment)?.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
213
340
  const existingTransformersProp = uploadObj?.getProperty('transformers');
214
341
  const existingTransformersArray = existingTransformersProp?.asKind(SyntaxKind.PropertyAssignment)?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);
215
- if (existingTransformersArray && findSharpTransformerCall(existingTransformersArray)) {
342
+ if (existingTransformersArray && findSharpTransformerCall({
343
+ transformerLocalName,
344
+ transformersArray: existingTransformersArray
345
+ })) {
216
346
  // Already migrated, but a leftover `sharp` property would fail a later
217
347
  // type-check with no signal from this codemod — flag it here.
218
348
  if (configObj.getProperty('sharp')) {
@@ -227,13 +357,8 @@ export const migrateSharpToTransformer = {
227
357
  } else if (sharpProp && Node.isShorthandPropertyAssignment(sharpProp)) {
228
358
  sharpExpressionText = sharpProp.getName();
229
359
  }
230
- // Remove `sharp` before extracting collection entries — later removals
231
- // shift node positions, and ts-morph node references taken before a
232
- // sibling removal can go stale.
233
- sharpProp?.remove();
234
360
  const collectionEntries = extractSharpCollectionEntries({
235
361
  configObj,
236
- filePath: sourceFile.getFilePath(),
237
362
  notes
238
363
  });
239
364
  if (!sharpExpressionText && collectionEntries.length === 0) {
@@ -244,25 +369,50 @@ export const migrateSharpToTransformer = {
244
369
  transformerArgs.push(sharpExpressionText === 'sharp' ? 'sharp' : `sharp: ${sharpExpressionText}`);
245
370
  }
246
371
  if (collectionEntries.length > 0) {
247
- transformerArgs.push(`collections: { ${collectionEntries.join(', ')} }`);
372
+ transformerArgs.push(`collections: { ${collectionEntries.map((entry)=>entry.entryText).join(', ')} }`);
248
373
  }
249
- const transformerCallText = `${TRANSFORMER_NAME}({ ${transformerArgs.join(', ')} })`;
374
+ const transformerCallText = `${transformerLocalName}({ ${transformerArgs.join(', ')} })`;
375
+ // Adding a `transformers` property next to a non-array one, or after a spread
376
+ // that may already set it, would create a duplicate key whose last value wins
377
+ // at runtime — silently dropping the existing transformers.
378
+ const uploadHasSpread = uploadObj?.getProperties().some((prop)=>Node.isSpreadAssignment(prop));
379
+ // The old settings are only removed once the replacement call is registered —
380
+ // otherwise the migrated config would silently lose its image processing.
381
+ let isRegistered = true;
250
382
  if (existingTransformersArray) {
251
383
  existingTransformersArray.addElement(transformerCallText);
384
+ } else if (existingTransformersProp) {
385
+ isRegistered = false;
386
+ notes.push(`${sourceFile.getFilePath()}: \`upload.transformers\` isn't an inline array — add \`${transformerCallText}\` to it manually, then remove the migrated Sharp settings.`);
387
+ } else if (uploadHasSpread) {
388
+ isRegistered = false;
389
+ notes.push(`${sourceFile.getFilePath()}: \`upload\` contains a spread that may already set \`transformers\` — add \`${transformerCallText}\` to its transformers manually, then remove the migrated Sharp settings.`);
252
390
  } else if (uploadObj) {
253
391
  uploadObj.addPropertyAssignment({
254
392
  name: 'transformers',
255
393
  initializer: `[${transformerCallText}]`
256
394
  });
257
395
  } else if (uploadProp) {
258
- notes.push(`${sourceFile.getFilePath()}: \`upload\` isn't an inline object — add \`transformers: [${transformerCallText}]\` to it manually.`);
396
+ isRegistered = false;
397
+ notes.push(`${sourceFile.getFilePath()}: \`upload\` isn't an inline object — add \`transformers: [${transformerCallText}]\` to it manually, then remove the migrated Sharp settings.`);
259
398
  } else {
260
399
  configObj.addPropertyAssignment({
261
400
  name: 'upload',
262
401
  initializer: `{ transformers: [${transformerCallText}] }`
263
402
  });
264
403
  }
265
- ensureSharpTransformerImport(sourceFile);
404
+ if (!isRegistered) {
405
+ continue;
406
+ }
407
+ sharpProp?.remove();
408
+ for (const entry of collectionEntries){
409
+ removeMovedCollectionProps(entry);
410
+ filesChanged.add(entry.uploadObj.getSourceFile().getFilePath());
411
+ }
412
+ ensureSharpTransformerImport({
413
+ localName: transformerLocalName,
414
+ sourceFile
415
+ });
266
416
  filesChanged.add(sourceFile.getFilePath());
267
417
  }
268
418
  }
@@ -274,7 +424,7 @@ export const migrateSharpToTransformer = {
274
424
  notes: notes.length ? notes : undefined
275
425
  };
276
426
  },
277
- description: 'Move a top-level `sharp` dependency and per-collection Sharp-specific `upload` options (resizeOptions, imageSizes, formatOptions, trimOptions, constructorOptions, withMetadata, crop, focalPoint) into `sharpTransformer({ collections })`, registered under `upload.transformers`.'
427
+ description: 'Move a top-level `sharp` dependency and per-collection Sharp-specific `upload` options (resizeOptions, imageSizes, formatOptions, trimOptions, constructorOptions, withMetadata, crop, focalPoint) into `sharpTransformer({ collections })`, registered under `upload.transformers`, with `imageSizes` renamed to `variants`. Also renames `imageSizes` to `variants` in existing `sharpTransformer({ collections })` entries.'
278
428
  };
279
429
 
280
430
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/transforms/migrate-sharp-to-transformer/index.ts"],"sourcesContent":["import type { ArrayLiteralExpression, ObjectLiteralExpression, SourceFile } from 'ts-morph'\n\nimport { Node, SyntaxKind } from 'ts-morph'\n\nimport type { Transform } from '../../types.js'\n\nconst TRANSFORMER_MODULE = '@payloadcms/transformer-sharp'\nconst TRANSFORMER_NAME = 'sharpTransformer'\n\nconst IDENTIFIER_PATTERN = /^[A-Z_$][\\w$]*$/i\nconst RESERVED_WORDS = new Set([\n 'await',\n 'break',\n 'case',\n 'catch',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'else',\n 'enum',\n 'export',\n 'extends',\n 'false',\n 'finally',\n 'for',\n 'function',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'interface',\n 'let',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'static',\n 'super',\n 'switch',\n 'this',\n 'throw',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'while',\n 'with',\n 'yield',\n])\n\n/** Whether `value` can be used as a plain (unquoted, non-bracketed) object literal key. */\nfunction isSafePlainObjectKey(value: string): boolean {\n return IDENTIFIER_PATTERN.test(value) && !RESERVED_WORDS.has(value)\n}\n\n/** Fields moved from a collection's `upload` object into `sharpTransformer({ collections })`. */\nconst MOVED_UPLOAD_FIELDS = [\n 'constructorOptions',\n 'formatOptions',\n 'resizeOptions',\n 'trimOptions',\n 'withMetadata',\n 'imageSizes',\n 'crop',\n 'focalPoint',\n]\n\nconst findBuildConfigLocalNames = (file: SourceFile): Set<string> => {\n const localNames = new Set<string>()\n\n for (const importDecl of file.getImportDeclarations()) {\n if (importDecl.getModuleSpecifierValue() !== 'payload') {\n continue\n }\n for (const spec of importDecl.getNamedImports()) {\n if (spec.getName() === 'buildConfig') {\n localNames.add(spec.getAliasNode()?.getText() ?? spec.getName())\n }\n }\n }\n\n return localNames\n}\n\nfunction ensureSharpTransformerImport(sourceFile: SourceFile): void {\n const existing = sourceFile\n .getImportDeclarations()\n .find((decl) => decl.getModuleSpecifierValue() === TRANSFORMER_MODULE)\n\n if (!existing) {\n const otherImports = sourceFile.getImportDeclarations()\n const fileOmitsSemicolonsOnImports =\n otherImports.length > 0 && otherImports.every((decl) => !decl.getText().endsWith(';'))\n\n const insertedImport = sourceFile.addImportDeclaration({\n moduleSpecifier: TRANSFORMER_MODULE,\n namedImports: [TRANSFORMER_NAME],\n })\n\n // ts-morph always appends a semicolon; strip it when the file's other imports don't use them.\n if (fileOmitsSemicolonsOnImports) {\n const insertedImportText = insertedImport.getText()\n if (insertedImportText.endsWith(';')) {\n insertedImport.replaceWithText(insertedImportText.slice(0, -1))\n }\n }\n\n return\n }\n\n const alreadyImported = existing\n .getNamedImports()\n .some((named) => named.getName() === TRANSFORMER_NAME)\n\n if (!alreadyImported) {\n existing.addNamedImport(TRANSFORMER_NAME)\n }\n}\n\n/**\n * Extracts Sharp-owned fields off one collection's `upload` object literal into\n * a `<slug>: { ... }` entry text for the `sharpTransformer({ collections })` map.\n * Returns `undefined` when the collection has nothing to migrate.\n */\nfunction extractCollectionSharpEntry({\n collectionObj,\n filePath,\n notes,\n}: {\n collectionObj: ObjectLiteralExpression\n filePath: string\n notes: string[]\n}): string | undefined {\n const slugProp = collectionObj.getProperty('slug')\n const slugAssignment = slugProp?.asKind(SyntaxKind.PropertyAssignment)\n const slugInitializer = slugAssignment?.getInitializer()\n\n if (!slugInitializer) {\n return undefined\n }\n\n const uploadProp = collectionObj.getProperty('upload')\n if (!uploadProp || !Node.isPropertyAssignment(uploadProp)) {\n return undefined\n }\n\n const uploadObj = uploadProp.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n if (!uploadObj) {\n if (uploadProp.getInitializer()?.getKind() !== SyntaxKind.TrueKeyword) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload\\` option is not an inline object — check it for Sharp-specific fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) manually.`,\n )\n }\n return undefined\n }\n\n const uploadHasSpread = uploadObj.getProperties().some((prop) => Node.isSpreadAssignment(prop))\n if (uploadHasSpread) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload\\` object contains a spread — Sharp-specific fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) hidden inside it need manual review.`,\n )\n }\n\n const movedTexts: string[] = []\n for (const name of MOVED_UPLOAD_FIELDS) {\n const prop = uploadObj.getProperty(name)\n if (prop && Node.isPropertyAssignment(prop)) {\n movedTexts.push(prop.print())\n prop.remove()\n }\n }\n\n if (movedTexts.length === 0) {\n return undefined\n }\n\n // Avoid leaving `upload: {\\n}` spread across two lines once every property moves out.\n if (uploadObj.getProperties().length === 0) {\n uploadObj.replaceWithText('{}')\n }\n\n const slugLiteralValue = Node.isStringLiteral(slugInitializer)\n ? slugInitializer.getLiteralValue()\n : undefined\n const keyText =\n slugLiteralValue !== undefined && isSafePlainObjectKey(slugLiteralValue)\n ? slugLiteralValue\n : `[${slugInitializer.getText()}]`\n\n return `${keyText}: { ${movedTexts.join(', ')} }`\n}\n\n/**\n * Builds every `<slug>: { ... }` entry for a `buildConfig({ collections })` array,\n * skipping (and, for a present `sharp` signal, noting) entries that aren't inline\n * object literals or whose `collections` array isn't statically analyzable.\n */\nfunction extractSharpCollectionEntries({\n configObj,\n filePath,\n notes,\n}: {\n configObj: ObjectLiteralExpression\n filePath: string\n notes: string[]\n}): string[] {\n const collectionsProp = configObj.getProperty('collections')\n if (!collectionsProp || !Node.isPropertyAssignment(collectionsProp)) {\n return []\n }\n\n const arrayLiteral = collectionsProp.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) {\n notes.push(\n `${filePath}: \\`collections\\` isn't an inline array — check each collection for Sharp-specific \\`upload\\` fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) and move them into \\`sharpTransformer({ collections })\\` manually.`,\n )\n return []\n }\n\n const entries: string[] = []\n\n for (const el of arrayLiteral.getElements()) {\n if (!Node.isObjectLiteralExpression(el)) {\n notes.push(\n `${filePath}: a collection in \\`collections\\` is defined externally — check it for Sharp-specific \\`upload\\` fields and move them into \\`sharpTransformer({ collections })\\` manually.`,\n )\n continue\n }\n\n const entry = extractCollectionSharpEntry({ collectionObj: el, filePath, notes })\n if (entry) {\n entries.push(entry)\n }\n }\n\n return entries\n}\n\nfunction findSharpTransformerCall(transformersArray: ArrayLiteralExpression) {\n return transformersArray.getElements().find((el) => {\n if (!Node.isCallExpression(el)) {\n return false\n }\n const callee = el.getExpression()\n return Node.isIdentifier(callee) && callee.getText() === TRANSFORMER_NAME\n })\n}\n\nexport const migrateSharpToTransformer: Transform = {\n name: 'migrate-sharp-to-transformer',\n apply: ({ project }) => {\n const filesChanged = new Set<string>()\n const notes: string[] = []\n\n for (const sourceFile of project.getSourceFiles()) {\n const buildConfigLocalNames = findBuildConfigLocalNames(sourceFile)\n if (buildConfigLocalNames.size === 0) {\n continue\n }\n\n const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {\n const expr = call.getExpression()\n return Node.isIdentifier(expr) && buildConfigLocalNames.has(expr.getText())\n })\n\n for (const call of calls) {\n const [arg] = call.getArguments()\n const configObj = arg?.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!configObj) {\n notes.push(\n `${sourceFile.getFilePath()}: \\`buildConfig\\` argument is not an inline object literal — check it manually for a top-level \\`sharp\\` dependency and per-collection Sharp-specific \\`upload\\` options.`,\n )\n continue\n }\n\n const uploadProp = configObj.getProperty('upload')\n const uploadObj = uploadProp\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n const existingTransformersProp = uploadObj?.getProperty('transformers')\n const existingTransformersArray = existingTransformersProp\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n\n if (existingTransformersArray && findSharpTransformerCall(existingTransformersArray)) {\n // Already migrated, but a leftover `sharp` property would fail a later\n // type-check with no signal from this codemod — flag it here.\n if (configObj.getProperty('sharp')) {\n notes.push(\n `${sourceFile.getFilePath()}: a top-level \\`sharp\\` property remains even though \\`sharpTransformer\\` is already registered — move any value you still need into the existing \\`sharpTransformer\\` call, then remove \\`sharp\\` manually.`,\n )\n }\n continue\n }\n\n const sharpProp = configObj.getProperty('sharp')\n let sharpExpressionText: string | undefined\n if (sharpProp && Node.isPropertyAssignment(sharpProp)) {\n sharpExpressionText = sharpProp.getInitializer()?.getText()\n } else if (sharpProp && Node.isShorthandPropertyAssignment(sharpProp)) {\n sharpExpressionText = sharpProp.getName()\n }\n\n // Remove `sharp` before extracting collection entries — later removals\n // shift node positions, and ts-morph node references taken before a\n // sibling removal can go stale.\n sharpProp?.remove()\n\n const collectionEntries = extractSharpCollectionEntries({\n configObj,\n filePath: sourceFile.getFilePath(),\n notes,\n })\n\n if (!sharpExpressionText && collectionEntries.length === 0) {\n continue\n }\n\n const transformerArgs: string[] = []\n if (sharpExpressionText) {\n transformerArgs.push(\n sharpExpressionText === 'sharp' ? 'sharp' : `sharp: ${sharpExpressionText}`,\n )\n }\n if (collectionEntries.length > 0) {\n transformerArgs.push(`collections: { ${collectionEntries.join(', ')} }`)\n }\n\n const transformerCallText = `${TRANSFORMER_NAME}({ ${transformerArgs.join(', ')} })`\n\n if (existingTransformersArray) {\n existingTransformersArray.addElement(transformerCallText)\n } else if (uploadObj) {\n uploadObj.addPropertyAssignment({\n name: 'transformers',\n initializer: `[${transformerCallText}]`,\n })\n } else if (uploadProp) {\n notes.push(\n `${sourceFile.getFilePath()}: \\`upload\\` isn't an inline object — add \\`transformers: [${transformerCallText}]\\` to it manually.`,\n )\n } else {\n configObj.addPropertyAssignment({\n name: 'upload',\n initializer: `{ transformers: [${transformerCallText}] }`,\n })\n }\n\n ensureSharpTransformerImport(sourceFile)\n filesChanged.add(sourceFile.getFilePath())\n }\n }\n\n if (filesChanged.size > 0) {\n notes.push(\n `Install the new dependency this migration relies on: pnpm add @payloadcms/transformer-sharp`,\n )\n }\n\n return { filesChanged: Array.from(filesChanged), notes: notes.length ? notes : undefined }\n },\n description:\n 'Move a top-level `sharp` dependency and per-collection Sharp-specific `upload` options (resizeOptions, imageSizes, formatOptions, trimOptions, constructorOptions, withMetadata, crop, focalPoint) into `sharpTransformer({ collections })`, registered under `upload.transformers`.',\n}\n"],"names":["Node","SyntaxKind","TRANSFORMER_MODULE","TRANSFORMER_NAME","IDENTIFIER_PATTERN","RESERVED_WORDS","Set","isSafePlainObjectKey","value","test","has","MOVED_UPLOAD_FIELDS","findBuildConfigLocalNames","file","localNames","importDecl","getImportDeclarations","getModuleSpecifierValue","spec","getNamedImports","getName","add","getAliasNode","getText","ensureSharpTransformerImport","sourceFile","existing","find","decl","otherImports","fileOmitsSemicolonsOnImports","length","every","endsWith","insertedImport","addImportDeclaration","moduleSpecifier","namedImports","insertedImportText","replaceWithText","slice","alreadyImported","some","named","addNamedImport","extractCollectionSharpEntry","collectionObj","filePath","notes","slugProp","getProperty","slugAssignment","asKind","PropertyAssignment","slugInitializer","getInitializer","undefined","uploadProp","isPropertyAssignment","uploadObj","getInitializerIfKind","ObjectLiteralExpression","getKind","TrueKeyword","push","uploadHasSpread","getProperties","prop","isSpreadAssignment","movedTexts","name","print","remove","slugLiteralValue","isStringLiteral","getLiteralValue","keyText","join","extractSharpCollectionEntries","configObj","collectionsProp","arrayLiteral","ArrayLiteralExpression","entries","el","getElements","isObjectLiteralExpression","entry","findSharpTransformerCall","transformersArray","isCallExpression","callee","getExpression","isIdentifier","migrateSharpToTransformer","apply","project","filesChanged","getSourceFiles","buildConfigLocalNames","size","calls","getDescendantsOfKind","CallExpression","filter","call","expr","arg","getArguments","getFilePath","existingTransformersProp","existingTransformersArray","sharpProp","sharpExpressionText","isShorthandPropertyAssignment","collectionEntries","transformerArgs","transformerCallText","addElement","addPropertyAssignment","initializer","Array","from","description"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/transforms/migrate-sharp-to-transformer/index.ts"],"sourcesContent":["import type {\n ArrayLiteralExpression,\n Expression,\n Identifier,\n Symbol as MorphSymbol,\n ObjectLiteralExpression,\n PropertyAssignment,\n ShorthandPropertyAssignment,\n SourceFile,\n StringLiteral,\n} from 'ts-morph'\n\nimport { Node, SyntaxKind } from 'ts-morph'\n\nimport type { Transform } from '../../types.js'\n\nconst TRANSFORMER_MODULE = '@payloadcms/transformer-sharp'\nconst TRANSFORMER_NAME = 'sharpTransformer'\nconst VARIANTS_KEY = 'variants'\n\nconst IDENTIFIER_PATTERN = /^[A-Z_$][\\w$]*$/i\n/** Whether `value` can be used as a plain (unquoted, non-bracketed) object literal key. */\nfunction isSafePlainObjectKey(value: string): boolean {\n return IDENTIFIER_PATTERN.test(value)\n}\n\n/** Fields moved from a collection's `upload` object into `sharpTransformer({ collections })`. */\nconst MOVED_UPLOAD_FIELDS = [\n 'constructorOptions',\n 'formatOptions',\n 'resizeOptions',\n 'trimOptions',\n 'withMetadata',\n 'imageSizes',\n 'crop',\n 'focalPoint',\n]\n\nconst findBuildConfigLocalNames = (file: SourceFile): Set<string> => {\n const localNames = new Set<string>()\n\n for (const importDecl of file.getImportDeclarations()) {\n if (importDecl.getModuleSpecifierValue() !== 'payload') {\n continue\n }\n for (const spec of importDecl.getNamedImports()) {\n if (spec.getName() === 'buildConfig') {\n localNames.add(spec.getAliasNode()?.getText() ?? spec.getName())\n }\n }\n }\n\n return localNames\n}\n\ntype SharpTransformerBinding = {\n /** Whether `localName` is a value import of `sharpTransformer` from `@payloadcms/transformer-sharp`. */\n isImported: boolean\n /** The identifier `sharpTransformer` is (or will be) called through in this file. */\n localName: string\n}\n\n/**\n * Resolves the local binding of the imported `sharpTransformer`, honoring an alias such as\n * `import { sharpTransformer as st }`. When it isn't imported yet, picks a name no other\n * identifier in the file uses, so a local `sharpTransformer` function is never mistaken for it.\n */\nfunction resolveSharpTransformerBinding(sourceFile: SourceFile): SharpTransformerBinding {\n const namedImports = sourceFile\n .getImportDeclarations()\n .filter((decl) => decl.getModuleSpecifierValue() === TRANSFORMER_MODULE && !decl.isTypeOnly())\n .flatMap((decl) => decl.getNamedImports())\n .filter((named) => named.getName() === TRANSFORMER_NAME && !named.isTypeOnly())\n\n const unaliasedImport = namedImports.find((named) => !named.getAliasNode())\n const aliasedImport = namedImports.find((named) => named.getAliasNode())\n\n if (unaliasedImport) {\n return { isImported: true, localName: TRANSFORMER_NAME }\n }\n\n if (aliasedImport) {\n return { isImported: true, localName: aliasedImport.getAliasNode()!.getText() }\n }\n\n const usedIdentifiers = new Set(\n sourceFile\n .getDescendantsOfKind(SyntaxKind.Identifier)\n .map((identifier) => identifier.getText()),\n )\n\n let localName = TRANSFORMER_NAME\n for (let suffix = 2; usedIdentifiers.has(localName); suffix++) {\n localName = `${TRANSFORMER_NAME}${suffix}`\n }\n\n return { isImported: false, localName }\n}\n\nfunction ensureSharpTransformerImport({\n localName,\n sourceFile,\n}: {\n localName: string\n sourceFile: SourceFile\n}): void {\n const namedImport =\n localName === TRANSFORMER_NAME ? TRANSFORMER_NAME : { name: TRANSFORMER_NAME, alias: localName }\n\n const existing = sourceFile\n .getImportDeclarations()\n .find((decl) => decl.getModuleSpecifierValue() === TRANSFORMER_MODULE && !decl.isTypeOnly())\n\n if (!existing) {\n const otherImports = sourceFile.getImportDeclarations()\n const fileOmitsSemicolonsOnImports =\n otherImports.length > 0 && otherImports.every((decl) => !decl.getText().endsWith(';'))\n\n const insertedImport = sourceFile.addImportDeclaration({\n moduleSpecifier: TRANSFORMER_MODULE,\n namedImports: [namedImport],\n })\n\n // ts-morph always appends a semicolon; strip it when the file's other imports don't use them.\n if (fileOmitsSemicolonsOnImports) {\n const insertedImportText = insertedImport.getText()\n if (insertedImportText.endsWith(';')) {\n insertedImport.replaceWithText(insertedImportText.slice(0, -1))\n }\n }\n\n return\n }\n\n const alreadyImported = existing\n .getNamedImports()\n .some(\n (named) =>\n named.getName() === TRANSFORMER_NAME &&\n !named.isTypeOnly() &&\n (named.getAliasNode()?.getText() ?? TRANSFORMER_NAME) === localName,\n )\n\n if (!alreadyImported) {\n existing.addNamedImport(namedImport)\n }\n}\n\ntype CollectionSharpEntry = {\n /** `<slug>: { ... }` text for the `sharpTransformer({ collections })` map. */\n entryText: string\n /** Moved properties, removed from the collection only once `sharpTransformer` is registered. */\n movedProps: (PropertyAssignment | ShorthandPropertyAssignment)[]\n uploadObj: ObjectLiteralExpression\n}\n\n/**\n * Reads Sharp-owned fields off one collection's `upload` object literal into\n * a `<slug>: { ... }` entry text for the `sharpTransformer({ collections })` map,\n * without modifying the collection. Returns `undefined` when the collection has nothing to migrate.\n */\nfunction extractCollectionSharpEntry({\n collectionObj,\n configFile,\n notes,\n}: {\n collectionObj: ObjectLiteralExpression\n /** The file the `sharpTransformer` call is written to; a collection declared elsewhere is moved across files. */\n configFile: SourceFile\n notes: string[]\n}): CollectionSharpEntry | undefined {\n const filePath = collectionObj.getSourceFile().getFilePath()\n const isExternal = collectionObj.getSourceFile() !== configFile\n const slugProp = collectionObj.getProperty('slug')\n const slugAssignment = slugProp?.asKind(SyntaxKind.PropertyAssignment)\n const slugInitializer = slugAssignment?.getInitializer()\n\n if (!slugInitializer) {\n return undefined\n }\n\n const uploadProp = collectionObj.getProperty('upload')\n if (!uploadProp || !Node.isPropertyAssignment(uploadProp)) {\n return undefined\n }\n\n const uploadObj = uploadProp.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n if (!uploadObj) {\n if (uploadProp.getInitializer()?.getKind() !== SyntaxKind.TrueKeyword) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload\\` option is not an inline object — check it for Sharp-specific fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) manually.`,\n )\n }\n return undefined\n }\n\n const uploadHasSpread = uploadObj.getProperties().some((prop) => Node.isSpreadAssignment(prop))\n if (uploadHasSpread) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload\\` object contains a spread — Sharp-specific fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) hidden inside it need manual review.`,\n )\n }\n\n const movedTexts: string[] = []\n const movedProps: CollectionSharpEntry['movedProps'] = []\n for (const name of MOVED_UPLOAD_FIELDS) {\n const prop = uploadObj.getProperty(name)\n if (!prop) {\n continue\n }\n\n // A shorthand `imageSizes` reads the same binding from `buildConfig`'s argument,\n // where the `sharpTransformer` call is inserted, so it moves verbatim.\n if (Node.isPropertyAssignment(prop) || Node.isShorthandPropertyAssignment(prop)) {\n const localReference = isExternal ? findLocalReference({ node: prop }) : undefined\n\n // Moving the text into the config file would leave this reference unresolved there.\n if (localReference) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload.${name}\\` refers to \\`${localReference.getText()}\\`, which isn't available in ${configFile.getFilePath()} — move this collection's Sharp-specific \\`upload\\` fields into \\`sharpTransformer({ collections })\\` manually.`,\n )\n return undefined\n }\n\n movedTexts.push(name === 'imageSizes' ? printAsVariants(prop) : prop.print())\n movedProps.push(prop)\n continue\n }\n\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s \\`upload.${name}\\` isn't a plain property — move it into \\`sharpTransformer({ collections })\\` manually.`,\n )\n }\n\n if (movedTexts.length === 0) {\n return undefined\n }\n\n const slugLiteralValue = getSlugLiteralValue({ isExternal, slugInitializer })\n\n if (isExternal && slugLiteralValue === undefined) {\n notes.push(\n `${filePath}: collection ${slugInitializer.getText()}'s slug isn't a string constant — move its Sharp-specific \\`upload\\` fields into \\`sharpTransformer({ collections })\\` manually.`,\n )\n return undefined\n }\n\n // A slug constant from another file isn't in scope in the config file, so it's keyed by value.\n const keyText =\n slugLiteralValue !== undefined && isSafePlainObjectKey(slugLiteralValue)\n ? slugLiteralValue\n : isExternal && !isStringLiteralNode(slugInitializer)\n ? `'${slugLiteralValue!.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n : `[${slugInitializer.getText()}]`\n\n return { entryText: `${keyText}: { ${movedTexts.join(', ')} }`, movedProps, uploadObj }\n}\n\nfunction isStringLiteralNode(node: Node): boolean {\n return Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)\n}\n\n/**\n * A slug written as a string literal or, for a collection in another file, a constant whose\n * type is a string literal (e.g. `slug: mediaSlug` with `const mediaSlug = 'media'`).\n */\nfunction getSlugLiteralValue({\n isExternal,\n slugInitializer,\n}: {\n isExternal: boolean\n slugInitializer: Expression\n}): string | undefined {\n if (isStringLiteralNode(slugInitializer)) {\n return (slugInitializer as StringLiteral).getLiteralValue()\n }\n\n if (!isExternal) {\n return undefined\n }\n\n const slugType = slugInitializer.getType()\n\n return slugType.isStringLiteral() ? (slugType.getLiteralValue() as string) : undefined\n}\n\n/**\n * The first identifier inside `node` bound to a declaration elsewhere in the project, such as an\n * import or a local variable. Declarations inside `node` itself (parameters, its own property\n * names) and ambient/library ones (`undefined`, `Math`) don't count.\n */\nfunction findLocalReference({ node }: { node: Node }): Identifier | undefined {\n const sourceFile = node.getSourceFile()\n\n return node.getDescendantsOfKind(SyntaxKind.Identifier).find((identifier) =>\n (identifier.getSymbol()?.getDeclarations() ?? []).some((declaration) => {\n const declarationFile = declaration.getSourceFile()\n\n if (declarationFile.isDeclarationFile() || declarationFile.isFromExternalLibrary()) {\n return false\n }\n\n return (\n declarationFile !== sourceFile ||\n declaration.getPos() < node.getPos() ||\n declaration.getEnd() > node.getEnd()\n )\n }),\n )\n}\n\n/**\n * Follows a `collections` array element written as an identifier (usually an imported\n * collection, e.g. `import { Media } from './collections/Media'`) to the object literal it's\n * declared as, unwrapping `satisfies`/`as`/parentheses. Returns `undefined` for anything else,\n * such as a factory call.\n */\nfunction resolveCollectionObject({\n expression,\n}: {\n expression: Node\n}): ObjectLiteralExpression | undefined {\n let current: Node | undefined = expression\n\n for (let depth = 0; current && depth < 5; depth++) {\n while (\n Node.isSatisfiesExpression(current) ||\n Node.isAsExpression(current) ||\n Node.isParenthesizedExpression(current)\n ) {\n current = current.getExpression()\n }\n\n if (Node.isObjectLiteralExpression(current)) {\n return current\n }\n\n if (!Node.isIdentifier(current)) {\n return undefined\n }\n\n const symbol: MorphSymbol | undefined = current.getSymbol()\n const declaration: Node | undefined = (\n symbol?.isAlias() ? symbol.getAliasedSymbol() : symbol\n )?.getDeclarations()[0]\n\n if (Node.isVariableDeclaration(declaration)) {\n current = declaration.getInitializer()\n } else if (Node.isExportAssignment(declaration)) {\n current = declaration.getExpression()\n } else {\n return undefined\n }\n }\n\n return undefined\n}\n\nfunction removeMovedCollectionProps({ movedProps, uploadObj }: CollectionSharpEntry): void {\n for (const prop of movedProps) {\n prop.remove()\n }\n\n // Avoid leaving `upload: {\\n}` spread across two lines once every property moves out.\n if (uploadObj.getProperties().length === 0) {\n uploadObj.replaceWithText('{}')\n }\n}\n\n/**\n * Builds every `<slug>: { ... }` entry for a `buildConfig({ collections })` array,\n * skipping (and, for a present `sharp` signal, noting) entries that aren't inline\n * object literals or whose `collections` array isn't statically analyzable.\n */\nfunction extractSharpCollectionEntries({\n configObj,\n notes,\n}: {\n configObj: ObjectLiteralExpression\n notes: string[]\n}): CollectionSharpEntry[] {\n const configFile = configObj.getSourceFile()\n const filePath = configFile.getFilePath()\n const collectionsProp = configObj.getProperty('collections')\n if (!collectionsProp || !Node.isPropertyAssignment(collectionsProp)) {\n return []\n }\n\n const arrayLiteral = collectionsProp.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n if (!arrayLiteral) {\n notes.push(\n `${filePath}: \\`collections\\` isn't an inline array — check each collection for Sharp-specific \\`upload\\` fields (resizeOptions/imageSizes/formatOptions/trimOptions/constructorOptions/withMetadata/crop/focalPoint) and move them into \\`sharpTransformer({ collections })\\` manually.`,\n )\n return []\n }\n\n const entries: CollectionSharpEntry[] = []\n\n for (const el of arrayLiteral.getElements()) {\n const collectionObj = resolveCollectionObject({ expression: el })\n\n if (!collectionObj) {\n notes.push(\n `${filePath}: a collection in \\`collections\\` (\\`${el.getText()}\\`) is defined externally — check it for Sharp-specific \\`upload\\` fields and move them into \\`sharpTransformer({ collections })\\` manually.`,\n )\n continue\n }\n\n const entry = extractCollectionSharpEntry({ collectionObj, configFile, notes })\n if (entry) {\n entries.push(entry)\n }\n }\n\n return entries\n}\n\n/** `sharpTransformer` authors image sizes as `variants`; the collection's `imageSizes` is renamed on the way in. */\nfunction printAsVariants(prop: PropertyAssignment | ShorthandPropertyAssignment): string {\n return Node.isShorthandPropertyAssignment(prop)\n ? `${VARIANTS_KEY}: ${prop.getName()}`\n : `${VARIANTS_KEY}: ${prop.getInitializerOrThrow().print()}`\n}\n\n/**\n * Renames `imageSizes` to `variants` inside every inline `sharpTransformer({ collections })`\n * entry in the file — configs migrated before `variants` existed. Returns whether it changed\n * anything.\n */\nfunction renameImageSizesInSharpTransformerCalls({\n notes,\n sourceFile,\n transformerLocalName,\n}: {\n notes: string[]\n sourceFile: SourceFile\n transformerLocalName: string\n}): boolean {\n let hasChanged = false\n\n const sharpTransformerCalls = sourceFile\n .getDescendantsOfKind(SyntaxKind.CallExpression)\n .filter((call) => {\n const callee = call.getExpression()\n return Node.isIdentifier(callee) && callee.getText() === transformerLocalName\n })\n\n for (const call of sharpTransformerCalls) {\n const collectionsObj = call\n .getArguments()[0]\n ?.asKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('collections')\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n\n for (const entry of collectionsObj?.getProperties() ?? []) {\n const entryObj = Node.isPropertyAssignment(entry)\n ? entry.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n : undefined\n\n if (!entryObj) {\n notes.push(\n `${sourceFile.getFilePath()}: a \\`${TRANSFORMER_NAME}({ collections })\\` entry isn't an inline object — rename any \\`imageSizes\\` in it to \\`${VARIANTS_KEY}\\` manually.`,\n )\n continue\n }\n\n const imageSizesProp = entryObj.getProperty('imageSizes')\n\n if (imageSizesProp && Node.isPropertyAssignment(imageSizesProp)) {\n imageSizesProp.getNameNode().replaceWithText(VARIANTS_KEY)\n hasChanged = true\n } else if (imageSizesProp && Node.isShorthandPropertyAssignment(imageSizesProp)) {\n imageSizesProp.replaceWithText(printAsVariants(imageSizesProp))\n hasChanged = true\n }\n }\n }\n\n return hasChanged\n}\n\nfunction findSharpTransformerCall({\n transformerLocalName,\n transformersArray,\n}: {\n transformerLocalName: string\n transformersArray: ArrayLiteralExpression\n}) {\n return transformersArray.getElements().find((el) => {\n if (!Node.isCallExpression(el)) {\n return false\n }\n const callee = el.getExpression()\n return Node.isIdentifier(callee) && callee.getText() === transformerLocalName\n })\n}\n\nexport const migrateSharpToTransformer: Transform = {\n name: 'migrate-sharp-to-transformer',\n apply: ({ project }) => {\n const filesChanged = new Set<string>()\n const notes: string[] = []\n\n for (const sourceFile of project.getSourceFiles()) {\n const { isImported, localName: transformerLocalName } =\n resolveSharpTransformerBinding(sourceFile)\n\n if (\n isImported &&\n renameImageSizesInSharpTransformerCalls({ notes, sourceFile, transformerLocalName })\n ) {\n filesChanged.add(sourceFile.getFilePath())\n }\n\n const buildConfigLocalNames = findBuildConfigLocalNames(sourceFile)\n if (buildConfigLocalNames.size === 0) {\n continue\n }\n\n const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => {\n const expr = call.getExpression()\n return Node.isIdentifier(expr) && buildConfigLocalNames.has(expr.getText())\n })\n\n for (const call of calls) {\n const [arg] = call.getArguments()\n const configObj = arg?.asKind(SyntaxKind.ObjectLiteralExpression)\n if (!configObj) {\n notes.push(\n `${sourceFile.getFilePath()}: \\`buildConfig\\` argument is not an inline object literal — check it manually for a top-level \\`sharp\\` dependency and per-collection Sharp-specific \\`upload\\` options.`,\n )\n continue\n }\n\n const uploadProp = configObj.getProperty('upload')\n const uploadObj = uploadProp\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression)\n const existingTransformersProp = uploadObj?.getProperty('transformers')\n const existingTransformersArray = existingTransformersProp\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression)\n\n if (\n existingTransformersArray &&\n findSharpTransformerCall({\n transformerLocalName,\n transformersArray: existingTransformersArray,\n })\n ) {\n // Already migrated, but a leftover `sharp` property would fail a later\n // type-check with no signal from this codemod — flag it here.\n if (configObj.getProperty('sharp')) {\n notes.push(\n `${sourceFile.getFilePath()}: a top-level \\`sharp\\` property remains even though \\`sharpTransformer\\` is already registered — move any value you still need into the existing \\`sharpTransformer\\` call, then remove \\`sharp\\` manually.`,\n )\n }\n continue\n }\n\n const sharpProp = configObj.getProperty('sharp')\n let sharpExpressionText: string | undefined\n if (sharpProp && Node.isPropertyAssignment(sharpProp)) {\n sharpExpressionText = sharpProp.getInitializer()?.getText()\n } else if (sharpProp && Node.isShorthandPropertyAssignment(sharpProp)) {\n sharpExpressionText = sharpProp.getName()\n }\n\n const collectionEntries = extractSharpCollectionEntries({ configObj, notes })\n\n if (!sharpExpressionText && collectionEntries.length === 0) {\n continue\n }\n\n const transformerArgs: string[] = []\n if (sharpExpressionText) {\n transformerArgs.push(\n sharpExpressionText === 'sharp' ? 'sharp' : `sharp: ${sharpExpressionText}`,\n )\n }\n if (collectionEntries.length > 0) {\n transformerArgs.push(\n `collections: { ${collectionEntries.map((entry) => entry.entryText).join(', ')} }`,\n )\n }\n\n const transformerCallText = `${transformerLocalName}({ ${transformerArgs.join(', ')} })`\n\n // Adding a `transformers` property next to a non-array one, or after a spread\n // that may already set it, would create a duplicate key whose last value wins\n // at runtime — silently dropping the existing transformers.\n const uploadHasSpread = uploadObj\n ?.getProperties()\n .some((prop) => Node.isSpreadAssignment(prop))\n\n // The old settings are only removed once the replacement call is registered —\n // otherwise the migrated config would silently lose its image processing.\n let isRegistered = true\n\n if (existingTransformersArray) {\n existingTransformersArray.addElement(transformerCallText)\n } else if (existingTransformersProp) {\n isRegistered = false\n notes.push(\n `${sourceFile.getFilePath()}: \\`upload.transformers\\` isn't an inline array — add \\`${transformerCallText}\\` to it manually, then remove the migrated Sharp settings.`,\n )\n } else if (uploadHasSpread) {\n isRegistered = false\n notes.push(\n `${sourceFile.getFilePath()}: \\`upload\\` contains a spread that may already set \\`transformers\\` — add \\`${transformerCallText}\\` to its transformers manually, then remove the migrated Sharp settings.`,\n )\n } else if (uploadObj) {\n uploadObj.addPropertyAssignment({\n name: 'transformers',\n initializer: `[${transformerCallText}]`,\n })\n } else if (uploadProp) {\n isRegistered = false\n notes.push(\n `${sourceFile.getFilePath()}: \\`upload\\` isn't an inline object — add \\`transformers: [${transformerCallText}]\\` to it manually, then remove the migrated Sharp settings.`,\n )\n } else {\n configObj.addPropertyAssignment({\n name: 'upload',\n initializer: `{ transformers: [${transformerCallText}] }`,\n })\n }\n\n if (!isRegistered) {\n continue\n }\n\n sharpProp?.remove()\n for (const entry of collectionEntries) {\n removeMovedCollectionProps(entry)\n filesChanged.add(entry.uploadObj.getSourceFile().getFilePath())\n }\n\n ensureSharpTransformerImport({ localName: transformerLocalName, sourceFile })\n filesChanged.add(sourceFile.getFilePath())\n }\n }\n\n if (filesChanged.size > 0) {\n notes.push(\n `Install the new dependency this migration relies on: pnpm add @payloadcms/transformer-sharp`,\n )\n }\n\n return { filesChanged: Array.from(filesChanged), notes: notes.length ? notes : undefined }\n },\n description:\n 'Move a top-level `sharp` dependency and per-collection Sharp-specific `upload` options (resizeOptions, imageSizes, formatOptions, trimOptions, constructorOptions, withMetadata, crop, focalPoint) into `sharpTransformer({ collections })`, registered under `upload.transformers`, with `imageSizes` renamed to `variants`. Also renames `imageSizes` to `variants` in existing `sharpTransformer({ collections })` entries.',\n}\n"],"names":["Node","SyntaxKind","TRANSFORMER_MODULE","TRANSFORMER_NAME","VARIANTS_KEY","IDENTIFIER_PATTERN","isSafePlainObjectKey","value","test","MOVED_UPLOAD_FIELDS","findBuildConfigLocalNames","file","localNames","Set","importDecl","getImportDeclarations","getModuleSpecifierValue","spec","getNamedImports","getName","add","getAliasNode","getText","resolveSharpTransformerBinding","sourceFile","namedImports","filter","decl","isTypeOnly","flatMap","named","unaliasedImport","find","aliasedImport","isImported","localName","usedIdentifiers","getDescendantsOfKind","Identifier","map","identifier","suffix","has","ensureSharpTransformerImport","namedImport","name","alias","existing","otherImports","fileOmitsSemicolonsOnImports","length","every","endsWith","insertedImport","addImportDeclaration","moduleSpecifier","insertedImportText","replaceWithText","slice","alreadyImported","some","addNamedImport","extractCollectionSharpEntry","collectionObj","configFile","notes","filePath","getSourceFile","getFilePath","isExternal","slugProp","getProperty","slugAssignment","asKind","PropertyAssignment","slugInitializer","getInitializer","undefined","uploadProp","isPropertyAssignment","uploadObj","getInitializerIfKind","ObjectLiteralExpression","getKind","TrueKeyword","push","uploadHasSpread","getProperties","prop","isSpreadAssignment","movedTexts","movedProps","isShorthandPropertyAssignment","localReference","findLocalReference","node","printAsVariants","print","slugLiteralValue","getSlugLiteralValue","keyText","isStringLiteralNode","replace","entryText","join","isStringLiteral","isNoSubstitutionTemplateLiteral","getLiteralValue","slugType","getType","getSymbol","getDeclarations","declaration","declarationFile","isDeclarationFile","isFromExternalLibrary","getPos","getEnd","resolveCollectionObject","expression","current","depth","isSatisfiesExpression","isAsExpression","isParenthesizedExpression","getExpression","isObjectLiteralExpression","isIdentifier","symbol","isAlias","getAliasedSymbol","isVariableDeclaration","isExportAssignment","removeMovedCollectionProps","remove","extractSharpCollectionEntries","configObj","collectionsProp","arrayLiteral","ArrayLiteralExpression","entries","el","getElements","entry","getInitializerOrThrow","renameImageSizesInSharpTransformerCalls","transformerLocalName","hasChanged","sharpTransformerCalls","CallExpression","call","callee","collectionsObj","getArguments","entryObj","imageSizesProp","getNameNode","findSharpTransformerCall","transformersArray","isCallExpression","migrateSharpToTransformer","apply","project","filesChanged","getSourceFiles","buildConfigLocalNames","size","calls","expr","arg","existingTransformersProp","existingTransformersArray","sharpProp","sharpExpressionText","collectionEntries","transformerArgs","transformerCallText","isRegistered","addElement","addPropertyAssignment","initializer","Array","from","description"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transforms/remove-storage-always-insert-fields/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAW/C,eAAO,MAAM,+BAA+B,EAAE,SA2D7C,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/transforms/remove-storage-always-insert-fields/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAW/C,eAAO,MAAM,+BAA+B,EAAE,SAgE7C,CAAA"}
@@ -40,6 +40,10 @@ export const removeStorageAlwaysInsertFields = {
40
40
  continue;
41
41
  }
42
42
  const localStorageFactoryName = storageFactoryImport.getAliasNode() ?? storageFactoryImport.getNameNode();
43
+ // Always an Identifier in valid code: a string-literal import name requires an alias.
44
+ if (!Node.isIdentifier(localStorageFactoryName)) {
45
+ continue;
46
+ }
43
47
  for (const reference of localStorageFactoryName.findReferencesAsNodes()){
44
48
  const call = reference.getParentIfKind(SyntaxKind.CallExpression);
45
49
  if (!call || call.getExpression() !== reference) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/transforms/remove-storage-always-insert-fields/index.ts"],"sourcesContent":["import { Node, SyntaxKind } from 'ts-morph'\n\nimport type { Transform } from '../../types.js'\n\nconst storageFactoryByPackage = new Map([\n ['@payloadcms/plugin-cloud-storage', 'cloudStoragePlugin'],\n ['@payloadcms/storage-azure', 'azureStorage'],\n ['@payloadcms/storage-gcs', 'gcsStorage'],\n ['@payloadcms/storage-r2', 'r2Storage'],\n ['@payloadcms/storage-s3', 's3Storage'],\n ['@payloadcms/storage-vercel-blob', 'vercelBlobStorage'],\n])\n\nexport const removeStorageAlwaysInsertFields: Transform = {\n name: 'remove-storage-always-insert-fields',\n apply: ({ project }) => {\n const filesChanged = new Set<string>()\n\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n const storageFactoryName = storageFactoryByPackage.get(\n importDeclaration.getModuleSpecifierValue(),\n )\n\n if (!storageFactoryName) {\n continue\n }\n\n const storageFactoryImport = importDeclaration\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === storageFactoryName)\n\n if (!storageFactoryImport) {\n continue\n }\n\n const localStorageFactoryName =\n storageFactoryImport.getAliasNode() ?? storageFactoryImport.getNameNode()\n\n for (const reference of localStorageFactoryName.findReferencesAsNodes()) {\n const call = reference.getParentIfKind(SyntaxKind.CallExpression)\n\n if (!call || call.getExpression() !== reference) {\n continue\n }\n\n const [options] = call.getArguments()\n\n if (!options || !Node.isObjectLiteralExpression(options)) {\n continue\n }\n\n if (options.getProperties().some((property) => Node.isSpreadAssignment(property))) {\n continue\n }\n\n const alwaysInsertFieldsProperty = options.getProperty('alwaysInsertFields')\n\n if (!alwaysInsertFieldsProperty) {\n continue\n }\n\n alwaysInsertFieldsProperty.remove()\n filesChanged.add(sourceFile.getFilePath())\n }\n }\n }\n\n return { filesChanged: Array.from(filesChanged) }\n },\n description:\n 'Remove the obsolete `alwaysInsertFields` option from cloud storage plugin and storage adapter configs. The prefix field is now always inserted.',\n}\n"],"names":["Node","SyntaxKind","storageFactoryByPackage","Map","removeStorageAlwaysInsertFields","name","apply","project","filesChanged","Set","sourceFile","getSourceFiles","importDeclaration","getImportDeclarations","storageFactoryName","get","getModuleSpecifierValue","storageFactoryImport","getNamedImports","find","namedImport","getName","localStorageFactoryName","getAliasNode","getNameNode","reference","findReferencesAsNodes","call","getParentIfKind","CallExpression","getExpression","options","getArguments","isObjectLiteralExpression","getProperties","some","property","isSpreadAssignment","alwaysInsertFieldsProperty","getProperty","remove","add","getFilePath","Array","from","description"],"mappings":"AAAA,SAASA,IAAI,EAAEC,UAAU,QAAQ,WAAU;AAI3C,MAAMC,0BAA0B,IAAIC,IAAI;IACtC;QAAC;QAAoC;KAAqB;IAC1D;QAAC;QAA6B;KAAe;IAC7C;QAAC;QAA2B;KAAa;IACzC;QAAC;QAA0B;KAAY;IACvC;QAAC;QAA0B;KAAY;IACvC;QAAC;QAAmC;KAAoB;CACzD;AAED,OAAO,MAAMC,kCAA6C;IACxDC,MAAM;IACNC,OAAO,CAAC,EAAEC,OAAO,EAAE;QACjB,MAAMC,eAAe,IAAIC;QAEzB,KAAK,MAAMC,cAAcH,QAAQI,cAAc,GAAI;YACjD,KAAK,MAAMC,qBAAqBF,WAAWG,qBAAqB,GAAI;gBAClE,MAAMC,qBAAqBZ,wBAAwBa,GAAG,CACpDH,kBAAkBI,uBAAuB;gBAG3C,IAAI,CAACF,oBAAoB;oBACvB;gBACF;gBAEA,MAAMG,uBAAuBL,kBAC1BM,eAAe,GACfC,IAAI,CAAC,CAACC,cAAgBA,YAAYC,OAAO,OAAOP;gBAEnD,IAAI,CAACG,sBAAsB;oBACzB;gBACF;gBAEA,MAAMK,0BACJL,qBAAqBM,YAAY,MAAMN,qBAAqBO,WAAW;gBAEzE,KAAK,MAAMC,aAAaH,wBAAwBI,qBAAqB,GAAI;oBACvE,MAAMC,OAAOF,UAAUG,eAAe,CAAC3B,WAAW4B,cAAc;oBAEhE,IAAI,CAACF,QAAQA,KAAKG,aAAa,OAAOL,WAAW;wBAC/C;oBACF;oBAEA,MAAM,CAACM,QAAQ,GAAGJ,KAAKK,YAAY;oBAEnC,IAAI,CAACD,WAAW,CAAC/B,KAAKiC,yBAAyB,CAACF,UAAU;wBACxD;oBACF;oBAEA,IAAIA,QAAQG,aAAa,GAAGC,IAAI,CAAC,CAACC,WAAapC,KAAKqC,kBAAkB,CAACD,YAAY;wBACjF;oBACF;oBAEA,MAAME,6BAA6BP,QAAQQ,WAAW,CAAC;oBAEvD,IAAI,CAACD,4BAA4B;wBAC/B;oBACF;oBAEAA,2BAA2BE,MAAM;oBACjChC,aAAaiC,GAAG,CAAC/B,WAAWgC,WAAW;gBACzC;YACF;QACF;QAEA,OAAO;YAAElC,cAAcmC,MAAMC,IAAI,CAACpC;QAAc;IAClD;IACAqC,aACE;AACJ,EAAC"}
1
+ {"version":3,"sources":["../../../src/transforms/remove-storage-always-insert-fields/index.ts"],"sourcesContent":["import { Node, SyntaxKind } from 'ts-morph'\n\nimport type { Transform } from '../../types.js'\n\nconst storageFactoryByPackage = new Map([\n ['@payloadcms/plugin-cloud-storage', 'cloudStoragePlugin'],\n ['@payloadcms/storage-azure', 'azureStorage'],\n ['@payloadcms/storage-gcs', 'gcsStorage'],\n ['@payloadcms/storage-r2', 'r2Storage'],\n ['@payloadcms/storage-s3', 's3Storage'],\n ['@payloadcms/storage-vercel-blob', 'vercelBlobStorage'],\n])\n\nexport const removeStorageAlwaysInsertFields: Transform = {\n name: 'remove-storage-always-insert-fields',\n apply: ({ project }) => {\n const filesChanged = new Set<string>()\n\n for (const sourceFile of project.getSourceFiles()) {\n for (const importDeclaration of sourceFile.getImportDeclarations()) {\n const storageFactoryName = storageFactoryByPackage.get(\n importDeclaration.getModuleSpecifierValue(),\n )\n\n if (!storageFactoryName) {\n continue\n }\n\n const storageFactoryImport = importDeclaration\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === storageFactoryName)\n\n if (!storageFactoryImport) {\n continue\n }\n\n const localStorageFactoryName =\n storageFactoryImport.getAliasNode() ?? storageFactoryImport.getNameNode()\n\n // Always an Identifier in valid code: a string-literal import name requires an alias.\n if (!Node.isIdentifier(localStorageFactoryName)) {\n continue\n }\n\n for (const reference of localStorageFactoryName.findReferencesAsNodes()) {\n const call = reference.getParentIfKind(SyntaxKind.CallExpression)\n\n if (!call || call.getExpression() !== reference) {\n continue\n }\n\n const [options] = call.getArguments()\n\n if (!options || !Node.isObjectLiteralExpression(options)) {\n continue\n }\n\n if (options.getProperties().some((property) => Node.isSpreadAssignment(property))) {\n continue\n }\n\n const alwaysInsertFieldsProperty = options.getProperty('alwaysInsertFields')\n\n if (!alwaysInsertFieldsProperty) {\n continue\n }\n\n alwaysInsertFieldsProperty.remove()\n filesChanged.add(sourceFile.getFilePath())\n }\n }\n }\n\n return { filesChanged: Array.from(filesChanged) }\n },\n description:\n 'Remove the obsolete `alwaysInsertFields` option from cloud storage plugin and storage adapter configs. The prefix field is now always inserted.',\n}\n"],"names":["Node","SyntaxKind","storageFactoryByPackage","Map","removeStorageAlwaysInsertFields","name","apply","project","filesChanged","Set","sourceFile","getSourceFiles","importDeclaration","getImportDeclarations","storageFactoryName","get","getModuleSpecifierValue","storageFactoryImport","getNamedImports","find","namedImport","getName","localStorageFactoryName","getAliasNode","getNameNode","isIdentifier","reference","findReferencesAsNodes","call","getParentIfKind","CallExpression","getExpression","options","getArguments","isObjectLiteralExpression","getProperties","some","property","isSpreadAssignment","alwaysInsertFieldsProperty","getProperty","remove","add","getFilePath","Array","from","description"],"mappings":"AAAA,SAASA,IAAI,EAAEC,UAAU,QAAQ,WAAU;AAI3C,MAAMC,0BAA0B,IAAIC,IAAI;IACtC;QAAC;QAAoC;KAAqB;IAC1D;QAAC;QAA6B;KAAe;IAC7C;QAAC;QAA2B;KAAa;IACzC;QAAC;QAA0B;KAAY;IACvC;QAAC;QAA0B;KAAY;IACvC;QAAC;QAAmC;KAAoB;CACzD;AAED,OAAO,MAAMC,kCAA6C;IACxDC,MAAM;IACNC,OAAO,CAAC,EAAEC,OAAO,EAAE;QACjB,MAAMC,eAAe,IAAIC;QAEzB,KAAK,MAAMC,cAAcH,QAAQI,cAAc,GAAI;YACjD,KAAK,MAAMC,qBAAqBF,WAAWG,qBAAqB,GAAI;gBAClE,MAAMC,qBAAqBZ,wBAAwBa,GAAG,CACpDH,kBAAkBI,uBAAuB;gBAG3C,IAAI,CAACF,oBAAoB;oBACvB;gBACF;gBAEA,MAAMG,uBAAuBL,kBAC1BM,eAAe,GACfC,IAAI,CAAC,CAACC,cAAgBA,YAAYC,OAAO,OAAOP;gBAEnD,IAAI,CAACG,sBAAsB;oBACzB;gBACF;gBAEA,MAAMK,0BACJL,qBAAqBM,YAAY,MAAMN,qBAAqBO,WAAW;gBAEzE,sFAAsF;gBACtF,IAAI,CAACxB,KAAKyB,YAAY,CAACH,0BAA0B;oBAC/C;gBACF;gBAEA,KAAK,MAAMI,aAAaJ,wBAAwBK,qBAAqB,GAAI;oBACvE,MAAMC,OAAOF,UAAUG,eAAe,CAAC5B,WAAW6B,cAAc;oBAEhE,IAAI,CAACF,QAAQA,KAAKG,aAAa,OAAOL,WAAW;wBAC/C;oBACF;oBAEA,MAAM,CAACM,QAAQ,GAAGJ,KAAKK,YAAY;oBAEnC,IAAI,CAACD,WAAW,CAAChC,KAAKkC,yBAAyB,CAACF,UAAU;wBACxD;oBACF;oBAEA,IAAIA,QAAQG,aAAa,GAAGC,IAAI,CAAC,CAACC,WAAarC,KAAKsC,kBAAkB,CAACD,YAAY;wBACjF;oBACF;oBAEA,MAAME,6BAA6BP,QAAQQ,WAAW,CAAC;oBAEvD,IAAI,CAACD,4BAA4B;wBAC/B;oBACF;oBAEAA,2BAA2BE,MAAM;oBACjCjC,aAAakC,GAAG,CAAChC,WAAWiC,WAAW;gBACzC;YACF;QACF;QAEA,OAAO;YAAEnC,cAAcoC,MAAMC,IAAI,CAACrC;QAAc;IAClD;IACAsC,aACE;AACJ,EAAC"}