@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.
- package/README.md +6 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.help.d.ts +4 -0
- package/dist/cli.help.d.ts.map +1 -0
- package/dist/cli.help.js +29 -0
- package/dist/cli.help.js.map +1 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/cli.parseFlags.d.ts +1 -0
- package/dist/cli.parseFlags.d.ts.map +1 -1
- package/dist/cli.parseFlags.js +6 -0
- package/dist/cli.parseFlags.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +6 -0
- package/dist/registry.js.map +1 -1
- package/dist/runbook/payload-v4-upgrade.md +2 -2
- package/dist/runbook/v4.mdx +370 -80
- package/dist/transforms/migrate-admin-context-properties/basic.input.js +32 -0
- package/dist/transforms/migrate-admin-context-properties/basic.input.js.map +1 -0
- package/dist/transforms/migrate-admin-context-properties/basic.output.js +30 -0
- package/dist/transforms/migrate-admin-context-properties/basic.output.js.map +1 -0
- package/dist/transforms/migrate-admin-context-properties/index.d.ts +3 -0
- package/dist/transforms/migrate-admin-context-properties/index.d.ts.map +1 -0
- package/dist/transforms/migrate-admin-context-properties/index.js +302 -0
- package/dist/transforms/migrate-admin-context-properties/index.js.map +1 -0
- package/dist/transforms/migrate-admin-context-properties/no-match.input.js +30 -0
- package/dist/transforms/migrate-admin-context-properties/no-match.input.js.map +1 -0
- package/dist/transforms/migrate-admin-context-properties/no-match.output.js +30 -0
- package/dist/transforms/migrate-admin-context-properties/no-match.output.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/basic.input.js +4 -0
- package/dist/transforms/migrate-displayed-field-value-args/basic.input.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/basic.output.js +8 -0
- package/dist/transforms/migrate-displayed-field-value-args/basic.output.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/index.d.ts +3 -0
- package/dist/transforms/migrate-displayed-field-value-args/index.d.ts.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/index.js +84 -0
- package/dist/transforms/migrate-displayed-field-value-args/index.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/namespace.input.js +4 -0
- package/dist/transforms/migrate-displayed-field-value-args/namespace.input.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/namespace.output.js +8 -0
- package/dist/transforms/migrate-displayed-field-value-args/namespace.output.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/no-match.input.js +4 -0
- package/dist/transforms/migrate-displayed-field-value-args/no-match.input.js.map +1 -0
- package/dist/transforms/migrate-displayed-field-value-args/no-match.output.js +4 -0
- package/dist/transforms/migrate-displayed-field-value-args/no-match.output.js.map +1 -0
- package/dist/transforms/migrate-field-component-types/index.d.ts.map +1 -1
- package/dist/transforms/migrate-field-component-types/index.js +4 -0
- package/dist/transforms/migrate-field-component-types/index.js.map +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/basic.output.js +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/basic.output.js.map +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/existing-transformers.output.js +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/existing-transformers.output.js.map +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/index.d.ts.map +1 -1
- package/dist/transforms/migrate-sharp-to-transformer/index.js +232 -82
- package/dist/transforms/migrate-sharp-to-transformer/index.js.map +1 -1
- package/dist/transforms/remove-storage-always-insert-fields/index.d.ts.map +1 -1
- package/dist/transforms/remove-storage-always-insert-fields/index.js +4 -0
- package/dist/transforms/remove-storage-always-insert-fields/index.js.map +1 -1
- package/dist/transforms/rename-diff-value-props/basic.input.js +38 -0
- package/dist/transforms/rename-diff-value-props/basic.input.js.map +1 -0
- package/dist/transforms/rename-diff-value-props/basic.output.js +38 -0
- package/dist/transforms/rename-diff-value-props/basic.output.js.map +1 -0
- package/dist/transforms/rename-diff-value-props/index.d.ts +3 -0
- package/dist/transforms/rename-diff-value-props/index.d.ts.map +1 -0
- package/dist/transforms/rename-diff-value-props/index.js +328 -0
- package/dist/transforms/rename-diff-value-props/index.js.map +1 -0
- package/dist/transforms/rename-diff-value-props/no-match.input.js +8 -0
- package/dist/transforms/rename-diff-value-props/no-match.input.js.map +1 -0
- package/dist/transforms/rename-experimental-table-feature/index.d.ts.map +1 -1
- package/dist/transforms/rename-experimental-table-feature/index.js +7 -1
- package/dist/transforms/rename-experimental-table-feature/index.js.map +1 -1
- package/dist/upgrade/defaultTag.d.ts +1 -1
- package/dist/upgrade/defaultTag.js +2 -2
- package/dist/upgrade/defaultTag.js.map +1 -1
- package/dist/upgrade/prompt.js +2 -2
- package/dist/upgrade/prompt.js.map +1 -1
- package/dist/upgrade/rewritePackageJson.d.ts.map +1 -1
- package/dist/upgrade/rewritePackageJson.js +52 -11
- package/dist/upgrade/rewritePackageJson.js.map +1 -1
- package/dist/utils/project.d.ts +7 -1
- package/dist/utils/project.d.ts.map +1 -1
- package/dist/utils/project.js +20 -7
- package/dist/utils/project.js.map +1 -1
- 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)
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
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(
|
|
89
|
+
existing.addNamedImport(namedImport);
|
|
103
90
|
}
|
|
104
91
|
}
|
|
105
92
|
/**
|
|
106
|
-
*
|
|
107
|
-
* a `<slug>: { ... }` entry text for the `sharpTransformer({ collections })` map
|
|
108
|
-
* Returns `undefined` when the collection has nothing to migrate.
|
|
109
|
-
*/ function extractCollectionSharpEntry({ collectionObj,
|
|
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
|
|
135
|
-
|
|
136
|
-
|
|
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,
|
|
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
|
-
|
|
167
|
-
|
|
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
|
|
172
|
-
|
|
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
|
|
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() ===
|
|
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(
|
|
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 = `${
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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"}
|