payload 3.71.1 → 3.72.0-canary.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload",
3
- "version": "3.71.1",
3
+ "version": "3.72.0-canary.1",
4
4
  "description": "Node, React, Headless CMS and Application Framework built on Next.js",
5
5
  "keywords": [
6
6
  "admin panel",
@@ -111,7 +111,7 @@
111
111
  "undici": "7.10.0",
112
112
  "uuid": "10.0.0",
113
113
  "ws": "^8.16.0",
114
- "@payloadcms/translations": "3.71.1"
114
+ "@payloadcms/translations": "3.72.0-canary.1"
115
115
  },
116
116
  "devDependencies": {
117
117
  "@hyrious/esbuild-plugin-commonjs": "0.2.6",
@@ -1,40 +0,0 @@
1
- import type { SanitizedCollectionConfig } from '../collections/config/types.js';
2
- import type { SharpDependency } from '../config/types.js';
3
- import type { PayloadRequest } from '../types/index.js';
4
- import type { WithMetadata } from './optionallyAppendMetadata.js';
5
- import type { FileSizes, FileToSave, ProbedImageSize, UploadEdits } from './types.js';
6
- type ResizeArgs = {
7
- config: SanitizedCollectionConfig;
8
- dimensions: ProbedImageSize;
9
- file: PayloadRequest['file'];
10
- mimeType: string;
11
- req: PayloadRequest;
12
- savedFilename: string;
13
- sharp?: SharpDependency;
14
- staticPath: string;
15
- uploadEdits?: UploadEdits;
16
- withMetadata?: WithMetadata;
17
- };
18
- /** Result from resizing and transforming the requested image sizes */
19
- type ImageSizesResult = {
20
- focalPoint?: UploadEdits['focalPoint'];
21
- sizeData: FileSizes;
22
- sizesToSave: FileToSave[];
23
- };
24
- /**
25
- * For the provided image sizes, handle the resizing and the transforms
26
- * (format, trim, etc.) of each requested image size and return the result object.
27
- * This only handles the image sizes. The transforms of the original image
28
- * are handled in {@link ./generateFileData.ts}.
29
- *
30
- * The image will be resized according to the provided
31
- * resize config. If no image sizes are requested, the resolved data will be empty.
32
- * For every image that does not need to be resized, a result object with `null`
33
- * parameters will be returned.
34
- *
35
- * @param resizeConfig - the resize config
36
- * @returns the result of the resize operation(s)
37
- */
38
- export declare function resizeAndTransformImageSizes({ config, dimensions, file, mimeType, req, savedFilename, sharp, staticPath, uploadEdits, withMetadata, }: ResizeArgs): Promise<ImageSizesResult>;
39
- export {};
40
- //# sourceMappingURL=imageResizer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageResizer.d.ts","sourceRoot":"","sources":["../../src/uploads/imageResizer.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAA;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,KAAK,EAEV,SAAS,EACT,UAAU,EAEV,eAAe,EACf,WAAW,EACZ,MAAM,YAAY,CAAA;AAMnB,KAAK,UAAU,GAAG;IAChB,MAAM,EAAE,yBAAyB,CAAA;IACjC,UAAU,EAAE,eAAe,CAAA;IAC3B,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAA;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,cAAc,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B,CAAA;AAED,sEAAsE;AACtE,KAAK,gBAAgB,GAAG;IACtB,UAAU,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAA;IACtC,QAAQ,EAAE,SAAS,CAAA;IACnB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B,CAAA;AAwMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,4BAA4B,CAAC,EACjD,MAAM,EACN,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,aAAa,EACb,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,GACb,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgPxC"}
@@ -1,356 +0,0 @@
1
- import { fileTypeFromBuffer } from 'file-type';
2
- import fs from 'fs/promises';
3
- import sanitize from 'sanitize-filename';
4
- import { isNumber } from '../utilities/isNumber.js';
5
- import { fileExists } from './fileExists.js';
6
- import { optionallyAppendMetadata } from './optionallyAppendMetadata.js';
7
- /**
8
- * Sanitize the image name and extract the extension from the source image
9
- *
10
- * @param sourceImage - the source image
11
- * @returns the sanitized name and extension
12
- */ const getSanitizedImageData = (sourceImage)=>{
13
- const extension = sourceImage.split('.').pop();
14
- const name = sanitize(sourceImage.substring(0, sourceImage.lastIndexOf('.')) || sourceImage);
15
- return {
16
- name,
17
- ext: extension
18
- };
19
- };
20
- const createImageName = ({ extension, height, outputImageName, width })=>{
21
- return `${outputImageName}-${width}x${height}.${extension}`;
22
- };
23
- /**
24
- * Create the result object for the image resize operation based on the
25
- * provided parameters. If the name is not provided, an empty result object
26
- * is returned.
27
- *
28
- * @param name - the name of the image
29
- * @param filename - the filename of the image
30
- * @param width - the width of the image
31
- * @param height - the height of the image
32
- * @param filesize - the filesize of the image
33
- * @param mimeType - the mime type of the image
34
- * @param sizesToSave - the sizes to save
35
- * @returns the result object
36
- */ const createResult = ({ name, filename = null, filesize = null, height = null, mimeType = null, sizesToSave = [], width = null })=>{
37
- return {
38
- sizeData: {
39
- [name]: {
40
- filename,
41
- filesize,
42
- height,
43
- mimeType,
44
- width
45
- }
46
- },
47
- sizesToSave
48
- };
49
- };
50
- /**
51
- * Determine whether or not to resize the image.
52
- * - resize using image config
53
- * - resize using image config with focal adjustments
54
- * - do not resize at all
55
- *
56
- * `imageResizeConfig.withoutEnlargement`:
57
- * - undefined [default]: uploading images with smaller width AND height than the image size will return null
58
- * - false: always enlarge images to the image size
59
- * - true: if the image is smaller than the image size, return the original image
60
- *
61
- * `imageResizeConfig.withoutReduction`:
62
- * - false [default]: always enlarge images to the image size
63
- * - true: if the image is smaller than the image size, return the original image
64
- *
65
- * @return 'omit' | 'resize' | 'resizeWithFocalPoint'
66
- */ const getImageResizeAction = ({ dimensions: originalImage, hasFocalPoint, imageResizeConfig })=>{
67
- const { fit, withoutEnlargement, withoutReduction } = imageResizeConfig;
68
- const targetWidth = imageResizeConfig.width;
69
- const targetHeight = imageResizeConfig.height;
70
- // prevent upscaling by default when x and y are both smaller than target image size
71
- if (targetHeight && targetWidth) {
72
- const originalImageIsSmallerXAndY = originalImage.width < targetWidth && originalImage.height < targetHeight;
73
- if (withoutEnlargement === undefined && originalImageIsSmallerXAndY) {
74
- return 'omit' // prevent image size from being enlarged
75
- ;
76
- }
77
- }
78
- if (withoutEnlargement === undefined && (!targetWidth || !targetHeight)) {
79
- if (targetWidth && originalImage.width < targetWidth || targetHeight && originalImage.height < targetHeight) {
80
- return 'omit';
81
- }
82
- }
83
- const originalImageIsSmallerXOrY = originalImage.width < targetWidth || originalImage.height < targetHeight;
84
- if (fit === 'contain' || fit === 'inside') {
85
- return 'resize';
86
- }
87
- if (!isNumber(targetHeight) && !isNumber(targetWidth)) {
88
- return 'resize';
89
- }
90
- const targetAspectRatio = targetWidth / targetHeight;
91
- const originalAspectRatio = originalImage.width / originalImage.height;
92
- if (originalAspectRatio === targetAspectRatio) {
93
- return 'resize';
94
- }
95
- if (withoutEnlargement && originalImageIsSmallerXOrY) {
96
- return 'resize';
97
- }
98
- if (withoutReduction && !originalImageIsSmallerXOrY) {
99
- return 'resize';
100
- }
101
- return hasFocalPoint ? 'resizeWithFocalPoint' : 'resize';
102
- };
103
- /**
104
- * Sanitize the resize config. If the resize config has the `withoutReduction`
105
- * property set to true, the `fit` and `position` properties will be set to `contain`
106
- * and `top left` respectively.
107
- *
108
- * @param resizeConfig - the resize config
109
- * @returns a sanitized resize config
110
- */ const sanitizeResizeConfig = (resizeConfig)=>{
111
- if (resizeConfig.withoutReduction) {
112
- return {
113
- ...resizeConfig,
114
- // Why fit `contain` should also be set to https://github.com/lovell/sharp/issues/3595
115
- fit: resizeConfig?.fit || 'contain',
116
- position: resizeConfig?.position || 'left top'
117
- };
118
- }
119
- return resizeConfig;
120
- };
121
- /**
122
- * Used to extract height from images, animated or not.
123
- *
124
- * @param sharpMetadata - the sharp metadata
125
- * @returns the height of the image
126
- */ function extractHeightFromImage(sharpMetadata) {
127
- if (sharpMetadata?.pages) {
128
- return sharpMetadata.height / sharpMetadata.pages;
129
- }
130
- return sharpMetadata.height;
131
- }
132
- /**
133
- * For the provided image sizes, handle the resizing and the transforms
134
- * (format, trim, etc.) of each requested image size and return the result object.
135
- * This only handles the image sizes. The transforms of the original image
136
- * are handled in {@link ./generateFileData.ts}.
137
- *
138
- * The image will be resized according to the provided
139
- * resize config. If no image sizes are requested, the resolved data will be empty.
140
- * For every image that does not need to be resized, a result object with `null`
141
- * parameters will be returned.
142
- *
143
- * @param resizeConfig - the resize config
144
- * @returns the result of the resize operation(s)
145
- */ export async function resizeAndTransformImageSizes({ config, dimensions, file, mimeType, req, savedFilename, sharp, staticPath, uploadEdits, withMetadata }) {
146
- const { focalPoint: focalPointEnabled = true, imageSizes } = config.upload;
147
- // Focal point adjustments
148
- const incomingFocalPoint = uploadEdits?.focalPoint ? {
149
- x: isNumber(uploadEdits.focalPoint.x) ? Math.round(uploadEdits.focalPoint.x) : 50,
150
- y: isNumber(uploadEdits.focalPoint.y) ? Math.round(uploadEdits.focalPoint.y) : 50
151
- } : undefined;
152
- const defaultResult = {
153
- ...focalPointEnabled && incomingFocalPoint && {
154
- focalPoint: incomingFocalPoint
155
- },
156
- sizeData: {},
157
- sizesToSave: []
158
- };
159
- if (!imageSizes || !sharp) {
160
- return defaultResult;
161
- }
162
- // Determine if the file is animated
163
- const fileIsAnimatedType = [
164
- 'image/avif',
165
- 'image/gif',
166
- 'image/webp'
167
- ].includes(file.mimetype);
168
- const sharpOptions = {};
169
- if (fileIsAnimatedType) {
170
- sharpOptions.animated = true;
171
- }
172
- const sharpBase = sharp(file.tempFilePath || file.data, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
173
- ;
174
- const originalImageMeta = await sharpBase.metadata();
175
- let adjustedDimensions = {
176
- ...dimensions
177
- };
178
- // Images with an exif orientation of 5, 6, 7, or 8 are auto-rotated by sharp
179
- // Need to adjust the dimensions to match the original image
180
- if ([
181
- 5,
182
- 6,
183
- 7,
184
- 8
185
- ].includes(originalImageMeta.orientation)) {
186
- adjustedDimensions = {
187
- ...dimensions,
188
- height: dimensions.width,
189
- width: dimensions.height
190
- };
191
- }
192
- const resizeImageMeta = {
193
- height: extractHeightFromImage(originalImageMeta),
194
- width: originalImageMeta.width
195
- };
196
- const results = await Promise.all(imageSizes.map(async (imageResizeConfig)=>{
197
- imageResizeConfig = sanitizeResizeConfig(imageResizeConfig);
198
- const resizeAction = getImageResizeAction({
199
- dimensions,
200
- hasFocalPoint: Boolean(incomingFocalPoint),
201
- imageResizeConfig
202
- });
203
- if (resizeAction === 'omit') {
204
- return createResult({
205
- name: imageResizeConfig.name
206
- });
207
- }
208
- const imageToResize = sharpBase.clone();
209
- let resized = imageToResize;
210
- if (resizeAction === 'resizeWithFocalPoint') {
211
- let { height: resizeHeight, width: resizeWidth } = imageResizeConfig;
212
- const originalAspectRatio = adjustedDimensions.width / adjustedDimensions.height;
213
- // Calculate resizeWidth based on original aspect ratio if it's undefined
214
- if (resizeHeight && !resizeWidth) {
215
- resizeWidth = Math.round(resizeHeight * originalAspectRatio);
216
- }
217
- // Calculate resizeHeight based on original aspect ratio if it's undefined
218
- if (resizeWidth && !resizeHeight) {
219
- resizeHeight = Math.round(resizeWidth / originalAspectRatio);
220
- }
221
- if (!resizeHeight) {
222
- resizeHeight = resizeImageMeta.height;
223
- }
224
- if (!resizeWidth) {
225
- resizeWidth = resizeImageMeta.width;
226
- }
227
- const resizeAspectRatio = resizeWidth / resizeHeight;
228
- const prioritizeHeight = resizeAspectRatio < originalAspectRatio;
229
- // Scales the image before extracting from it
230
- resized = imageToResize.resize({
231
- fastShrinkOnLoad: false,
232
- height: prioritizeHeight ? resizeHeight : undefined,
233
- width: prioritizeHeight ? undefined : resizeWidth
234
- });
235
- const metadataAppendedFile = await optionallyAppendMetadata({
236
- req,
237
- sharpFile: resized,
238
- withMetadata: withMetadata
239
- });
240
- // Must read from buffer, resized.metadata will return the original image metadata
241
- const { info } = await metadataAppendedFile.toBuffer({
242
- resolveWithObject: true
243
- });
244
- resizeImageMeta.height = extractHeightFromImage({
245
- ...originalImageMeta,
246
- height: info.height
247
- });
248
- resizeImageMeta.width = info.width;
249
- const halfResizeX = resizeWidth / 2;
250
- const xFocalCenter = resizeImageMeta.width * (incomingFocalPoint.x / 100);
251
- const calculatedRightPixelBound = xFocalCenter + halfResizeX;
252
- let leftBound = xFocalCenter - halfResizeX;
253
- // if the right bound is greater than the image width, adjust the left bound
254
- // keeping focus on the right
255
- if (calculatedRightPixelBound > resizeImageMeta.width) {
256
- leftBound = resizeImageMeta.width - resizeWidth;
257
- }
258
- // if the left bound is less than 0, adjust the left bound to 0
259
- // keeping the focus on the left
260
- if (leftBound < 0) {
261
- leftBound = 0;
262
- }
263
- const halfResizeY = resizeHeight / 2;
264
- const yFocalCenter = resizeImageMeta.height * (incomingFocalPoint.y / 100);
265
- const calculatedBottomPixelBound = yFocalCenter + halfResizeY;
266
- let topBound = yFocalCenter - halfResizeY;
267
- // if the bottom bound is greater than the image height, adjust the top bound
268
- // keeping the image as far right as possible
269
- if (calculatedBottomPixelBound > resizeImageMeta.height) {
270
- topBound = resizeImageMeta.height - resizeHeight;
271
- }
272
- // if the top bound is less than 0, adjust the top bound to 0
273
- // keeping the image focus near the top
274
- if (topBound < 0) {
275
- topBound = 0;
276
- }
277
- resized = resized.extract({
278
- height: resizeHeight,
279
- left: Math.floor(leftBound),
280
- top: Math.floor(topBound),
281
- width: resizeWidth
282
- });
283
- } else {
284
- resized = imageToResize.resize(imageResizeConfig);
285
- }
286
- if (imageResizeConfig.formatOptions) {
287
- resized = resized.toFormat(imageResizeConfig.formatOptions.format, imageResizeConfig.formatOptions.options);
288
- }
289
- if (imageResizeConfig.trimOptions) {
290
- resized = resized.trim(imageResizeConfig.trimOptions);
291
- }
292
- const metadataAppendedFile = await optionallyAppendMetadata({
293
- req,
294
- sharpFile: resized,
295
- withMetadata: withMetadata
296
- });
297
- const { data: bufferData, info: bufferInfo } = await metadataAppendedFile.toBuffer({
298
- resolveWithObject: true
299
- });
300
- const sanitizedImage = getSanitizedImageData(savedFilename);
301
- if (req.payloadUploadSizes) {
302
- req.payloadUploadSizes[imageResizeConfig.name] = bufferData;
303
- }
304
- const mimeInfo = await fileTypeFromBuffer(bufferData);
305
- const imageNameWithDimensions = imageResizeConfig.generateImageName ? imageResizeConfig.generateImageName({
306
- extension: mimeInfo?.ext || sanitizedImage.ext,
307
- height: extractHeightFromImage({
308
- ...originalImageMeta,
309
- height: bufferInfo.height
310
- }),
311
- originalName: sanitizedImage.name,
312
- sizeName: imageResizeConfig.name,
313
- width: bufferInfo.width
314
- }) : createImageName({
315
- extension: mimeInfo?.ext || sanitizedImage.ext,
316
- height: extractHeightFromImage({
317
- ...originalImageMeta,
318
- height: bufferInfo.height
319
- }),
320
- outputImageName: sanitizedImage.name,
321
- width: bufferInfo.width
322
- });
323
- const imagePath = `${staticPath}/${imageNameWithDimensions}`;
324
- if (await fileExists(imagePath)) {
325
- try {
326
- await fs.unlink(imagePath);
327
- } catch {
328
- // Ignore unlink errors
329
- }
330
- }
331
- const { height, size, width } = bufferInfo;
332
- return createResult({
333
- name: imageResizeConfig.name,
334
- filename: imageNameWithDimensions,
335
- filesize: size,
336
- height: fileIsAnimatedType && originalImageMeta.pages ? height / originalImageMeta.pages : height,
337
- mimeType: mimeInfo?.mime || mimeType,
338
- sizesToSave: [
339
- {
340
- buffer: bufferData,
341
- path: imagePath
342
- }
343
- ],
344
- width
345
- });
346
- }));
347
- return results.reduce((acc, result)=>{
348
- Object.assign(acc.sizeData, result.sizeData);
349
- acc.sizesToSave.push(...result.sizesToSave);
350
- return acc;
351
- }, {
352
- ...defaultResult
353
- });
354
- }
355
-
356
- //# sourceMappingURL=imageResizer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/uploads/imageResizer.ts"],"sourcesContent":["import type { Sharp, Metadata as SharpMetadata, SharpOptions } from 'sharp'\n\nimport { fileTypeFromBuffer } from 'file-type'\nimport fs from 'fs/promises'\nimport sanitize from 'sanitize-filename'\n\nimport type { SanitizedCollectionConfig } from '../collections/config/types.js'\nimport type { SharpDependency } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { WithMetadata } from './optionallyAppendMetadata.js'\nimport type {\n FileSize,\n FileSizes,\n FileToSave,\n ImageSize,\n ProbedImageSize,\n UploadEdits,\n} from './types.js'\n\nimport { isNumber } from '../utilities/isNumber.js'\nimport { fileExists } from './fileExists.js'\nimport { optionallyAppendMetadata } from './optionallyAppendMetadata.js'\n\ntype ResizeArgs = {\n config: SanitizedCollectionConfig\n dimensions: ProbedImageSize\n file: PayloadRequest['file']\n mimeType: string\n req: PayloadRequest\n savedFilename: string\n sharp?: SharpDependency\n staticPath: string\n uploadEdits?: UploadEdits\n withMetadata?: WithMetadata\n}\n\n/** Result from resizing and transforming the requested image sizes */\ntype ImageSizesResult = {\n focalPoint?: UploadEdits['focalPoint']\n sizeData: FileSizes\n sizesToSave: FileToSave[]\n}\n\ntype SanitizedImageData = {\n ext: string\n name: string\n}\n\n/**\n * Sanitize the image name and extract the extension from the source image\n *\n * @param sourceImage - the source image\n * @returns the sanitized name and extension\n */\nconst getSanitizedImageData = (sourceImage: string): SanitizedImageData => {\n const extension = sourceImage.split('.').pop()\n const name = sanitize(sourceImage.substring(0, sourceImage.lastIndexOf('.')) || sourceImage)\n return { name, ext: extension! }\n}\n\n/**\n * Create a new image name based on the output image name, the dimensions and\n * the extension.\n *\n * Ignore the fact that duplicate names could happen if the there is one\n * size with `width AND height` and one with only `height OR width`. Because\n * space is expensive, we will reuse the same image for both sizes.\n *\n * @param outputImageName - the sanitized image name\n * @param bufferInfo - the buffer info\n * @param extension - the extension to use\n * @returns the new image name that is not taken\n */\ntype CreateImageNameArgs = {\n extension: string\n height: number\n outputImageName: string\n width: number\n}\nconst createImageName = ({\n extension,\n height,\n outputImageName,\n width,\n}: CreateImageNameArgs): string => {\n return `${outputImageName}-${width}x${height}.${extension}`\n}\n\ntype CreateResultArgs = {\n filename?: FileSize['filename']\n filesize?: FileSize['filesize']\n height?: FileSize['height']\n mimeType?: FileSize['mimeType']\n name: string\n sizesToSave?: FileToSave[]\n width?: FileSize['width']\n}\n\n/**\n * Create the result object for the image resize operation based on the\n * provided parameters. If the name is not provided, an empty result object\n * is returned.\n *\n * @param name - the name of the image\n * @param filename - the filename of the image\n * @param width - the width of the image\n * @param height - the height of the image\n * @param filesize - the filesize of the image\n * @param mimeType - the mime type of the image\n * @param sizesToSave - the sizes to save\n * @returns the result object\n */\nconst createResult = ({\n name,\n filename = null,\n filesize = null,\n height = null,\n mimeType = null,\n sizesToSave = [],\n width = null,\n}: CreateResultArgs): ImageSizesResult => {\n return {\n sizeData: {\n [name]: {\n filename,\n filesize,\n height,\n mimeType,\n width,\n },\n },\n sizesToSave,\n }\n}\n\n/**\n * Determine whether or not to resize the image.\n * - resize using image config\n * - resize using image config with focal adjustments\n * - do not resize at all\n *\n * `imageResizeConfig.withoutEnlargement`:\n * - undefined [default]: uploading images with smaller width AND height than the image size will return null\n * - false: always enlarge images to the image size\n * - true: if the image is smaller than the image size, return the original image\n *\n * `imageResizeConfig.withoutReduction`:\n * - false [default]: always enlarge images to the image size\n * - true: if the image is smaller than the image size, return the original image\n *\n * @return 'omit' | 'resize' | 'resizeWithFocalPoint'\n */\nconst getImageResizeAction = ({\n dimensions: originalImage,\n hasFocalPoint,\n imageResizeConfig,\n}: {\n dimensions: ProbedImageSize\n hasFocalPoint?: boolean\n imageResizeConfig: ImageSize\n}): 'omit' | 'resize' | 'resizeWithFocalPoint' => {\n const { fit, withoutEnlargement, withoutReduction } = imageResizeConfig\n const targetWidth = imageResizeConfig.width!\n const targetHeight = imageResizeConfig.height!\n\n // prevent upscaling by default when x and y are both smaller than target image size\n if (targetHeight && targetWidth) {\n const originalImageIsSmallerXAndY =\n originalImage.width < targetWidth && originalImage.height < targetHeight\n if (withoutEnlargement === undefined && originalImageIsSmallerXAndY) {\n return 'omit' // prevent image size from being enlarged\n }\n }\n\n if (withoutEnlargement === undefined && (!targetWidth || !targetHeight)) {\n if (\n (targetWidth && originalImage.width < targetWidth) ||\n (targetHeight && originalImage.height < targetHeight)\n ) {\n return 'omit'\n }\n }\n\n const originalImageIsSmallerXOrY =\n originalImage.width < targetWidth || originalImage.height < targetHeight\n if (fit === 'contain' || fit === 'inside') {\n return 'resize'\n }\n if (!isNumber(targetHeight) && !isNumber(targetWidth)) {\n return 'resize'\n }\n\n const targetAspectRatio = targetWidth / targetHeight\n const originalAspectRatio = originalImage.width / originalImage.height\n if (originalAspectRatio === targetAspectRatio) {\n return 'resize'\n }\n\n if (withoutEnlargement && originalImageIsSmallerXOrY) {\n return 'resize'\n }\n if (withoutReduction && !originalImageIsSmallerXOrY) {\n return 'resize'\n }\n\n return hasFocalPoint ? 'resizeWithFocalPoint' : 'resize'\n}\n\n/**\n * Sanitize the resize config. If the resize config has the `withoutReduction`\n * property set to true, the `fit` and `position` properties will be set to `contain`\n * and `top left` respectively.\n *\n * @param resizeConfig - the resize config\n * @returns a sanitized resize config\n */\nconst sanitizeResizeConfig = (resizeConfig: ImageSize): ImageSize => {\n if (resizeConfig.withoutReduction) {\n return {\n ...resizeConfig,\n // Why fit `contain` should also be set to https://github.com/lovell/sharp/issues/3595\n fit: resizeConfig?.fit || 'contain',\n position: resizeConfig?.position || 'left top',\n }\n }\n return resizeConfig\n}\n\n/**\n * Used to extract height from images, animated or not.\n *\n * @param sharpMetadata - the sharp metadata\n * @returns the height of the image\n */\nfunction extractHeightFromImage(sharpMetadata: SharpMetadata): number {\n if (sharpMetadata?.pages) {\n return sharpMetadata.height! / sharpMetadata.pages\n }\n return sharpMetadata.height!\n}\n\n/**\n * For the provided image sizes, handle the resizing and the transforms\n * (format, trim, etc.) of each requested image size and return the result object.\n * This only handles the image sizes. The transforms of the original image\n * are handled in {@link ./generateFileData.ts}.\n *\n * The image will be resized according to the provided\n * resize config. If no image sizes are requested, the resolved data will be empty.\n * For every image that does not need to be resized, a result object with `null`\n * parameters will be returned.\n *\n * @param resizeConfig - the resize config\n * @returns the result of the resize operation(s)\n */\nexport async function resizeAndTransformImageSizes({\n config,\n dimensions,\n file,\n mimeType,\n req,\n savedFilename,\n sharp,\n staticPath,\n uploadEdits,\n withMetadata,\n}: ResizeArgs): Promise<ImageSizesResult> {\n const { focalPoint: focalPointEnabled = true, imageSizes } = config.upload\n\n // Focal point adjustments\n const incomingFocalPoint = uploadEdits?.focalPoint\n ? {\n x: isNumber(uploadEdits.focalPoint.x) ? Math.round(uploadEdits.focalPoint.x) : 50,\n y: isNumber(uploadEdits.focalPoint.y) ? Math.round(uploadEdits.focalPoint.y) : 50,\n }\n : undefined\n\n const defaultResult: ImageSizesResult = {\n ...(focalPointEnabled && incomingFocalPoint && { focalPoint: incomingFocalPoint }),\n sizeData: {},\n sizesToSave: [],\n }\n\n if (!imageSizes || !sharp) {\n return defaultResult\n }\n\n // Determine if the file is animated\n const fileIsAnimatedType = ['image/avif', 'image/gif', 'image/webp'].includes(file!.mimetype)\n const sharpOptions: SharpOptions = {}\n\n if (fileIsAnimatedType) {\n sharpOptions.animated = true\n }\n\n const sharpBase: Sharp | undefined = sharp(\n file!.tempFilePath || file!.data,\n sharpOptions,\n ).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081\n const originalImageMeta = await sharpBase.metadata()\n\n let adjustedDimensions = { ...dimensions }\n\n // Images with an exif orientation of 5, 6, 7, or 8 are auto-rotated by sharp\n // Need to adjust the dimensions to match the original image\n if ([5, 6, 7, 8].includes(originalImageMeta.orientation!)) {\n adjustedDimensions = {\n ...dimensions,\n height: dimensions.width,\n width: dimensions.height,\n }\n }\n\n const resizeImageMeta = {\n height: extractHeightFromImage(originalImageMeta),\n width: originalImageMeta.width,\n }\n\n const results: ImageSizesResult[] = await Promise.all(\n imageSizes.map(async (imageResizeConfig): Promise<ImageSizesResult> => {\n imageResizeConfig = sanitizeResizeConfig(imageResizeConfig)\n\n const resizeAction = getImageResizeAction({\n dimensions,\n hasFocalPoint: Boolean(incomingFocalPoint),\n imageResizeConfig,\n })\n if (resizeAction === 'omit') {\n return createResult({ name: imageResizeConfig.name })\n }\n\n const imageToResize = sharpBase.clone()\n let resized = imageToResize\n\n if (resizeAction === 'resizeWithFocalPoint') {\n let { height: resizeHeight, width: resizeWidth } = imageResizeConfig\n\n const originalAspectRatio = adjustedDimensions.width / adjustedDimensions.height\n\n // Calculate resizeWidth based on original aspect ratio if it's undefined\n if (resizeHeight && !resizeWidth) {\n resizeWidth = Math.round(resizeHeight * originalAspectRatio)\n }\n\n // Calculate resizeHeight based on original aspect ratio if it's undefined\n if (resizeWidth && !resizeHeight) {\n resizeHeight = Math.round(resizeWidth / originalAspectRatio)\n }\n\n if (!resizeHeight) {\n resizeHeight = resizeImageMeta.height\n }\n if (!resizeWidth) {\n resizeWidth = resizeImageMeta.width\n }\n\n const resizeAspectRatio = resizeWidth! / resizeHeight\n const prioritizeHeight = resizeAspectRatio < originalAspectRatio\n // Scales the image before extracting from it\n resized = imageToResize.resize({\n fastShrinkOnLoad: false,\n height: prioritizeHeight ? resizeHeight : undefined,\n width: prioritizeHeight ? undefined : resizeWidth,\n })\n\n const metadataAppendedFile = await optionallyAppendMetadata({\n req,\n sharpFile: resized,\n withMetadata: withMetadata!,\n })\n\n // Must read from buffer, resized.metadata will return the original image metadata\n const { info } = await metadataAppendedFile.toBuffer({ resolveWithObject: true })\n\n resizeImageMeta.height = extractHeightFromImage({\n ...originalImageMeta,\n height: info.height,\n })\n resizeImageMeta.width = info.width\n\n const halfResizeX = resizeWidth! / 2\n const xFocalCenter = resizeImageMeta.width * (incomingFocalPoint!.x / 100)\n const calculatedRightPixelBound = xFocalCenter + halfResizeX\n let leftBound = xFocalCenter - halfResizeX\n\n // if the right bound is greater than the image width, adjust the left bound\n // keeping focus on the right\n if (calculatedRightPixelBound > resizeImageMeta.width) {\n leftBound = resizeImageMeta.width - resizeWidth!\n }\n\n // if the left bound is less than 0, adjust the left bound to 0\n // keeping the focus on the left\n if (leftBound < 0) {\n leftBound = 0\n }\n\n const halfResizeY = resizeHeight / 2\n const yFocalCenter = resizeImageMeta.height * (incomingFocalPoint!.y / 100)\n const calculatedBottomPixelBound = yFocalCenter + halfResizeY\n let topBound = yFocalCenter - halfResizeY\n\n // if the bottom bound is greater than the image height, adjust the top bound\n // keeping the image as far right as possible\n if (calculatedBottomPixelBound > resizeImageMeta.height) {\n topBound = resizeImageMeta.height - resizeHeight\n }\n\n // if the top bound is less than 0, adjust the top bound to 0\n // keeping the image focus near the top\n if (topBound < 0) {\n topBound = 0\n }\n\n resized = resized.extract({\n height: resizeHeight,\n left: Math.floor(leftBound),\n top: Math.floor(topBound),\n width: resizeWidth!,\n })\n } else {\n resized = imageToResize.resize(imageResizeConfig)\n }\n\n if (imageResizeConfig.formatOptions) {\n resized = resized.toFormat(\n imageResizeConfig.formatOptions.format,\n imageResizeConfig.formatOptions.options,\n )\n }\n\n if (imageResizeConfig.trimOptions) {\n resized = resized.trim(imageResizeConfig.trimOptions)\n }\n\n const metadataAppendedFile = await optionallyAppendMetadata({\n req,\n sharpFile: resized,\n withMetadata: withMetadata!,\n })\n\n const { data: bufferData, info: bufferInfo } = await metadataAppendedFile.toBuffer({\n resolveWithObject: true,\n })\n\n const sanitizedImage = getSanitizedImageData(savedFilename)\n\n if (req.payloadUploadSizes) {\n req.payloadUploadSizes[imageResizeConfig.name] = bufferData\n }\n\n const mimeInfo = await fileTypeFromBuffer(bufferData)\n\n const imageNameWithDimensions = imageResizeConfig.generateImageName\n ? imageResizeConfig.generateImageName({\n extension: mimeInfo?.ext || sanitizedImage.ext,\n height: extractHeightFromImage({\n ...originalImageMeta,\n height: bufferInfo.height,\n }),\n originalName: sanitizedImage.name,\n sizeName: imageResizeConfig.name,\n width: bufferInfo.width,\n })\n : createImageName({\n extension: mimeInfo?.ext || sanitizedImage.ext,\n height: extractHeightFromImage({\n ...originalImageMeta,\n height: bufferInfo.height,\n }),\n outputImageName: sanitizedImage.name,\n width: bufferInfo.width,\n })\n\n const imagePath = `${staticPath}/${imageNameWithDimensions}`\n\n if (await fileExists(imagePath)) {\n try {\n await fs.unlink(imagePath)\n } catch {\n // Ignore unlink errors\n }\n }\n\n const { height, size, width } = bufferInfo\n return createResult({\n name: imageResizeConfig.name,\n filename: imageNameWithDimensions,\n filesize: size,\n height:\n fileIsAnimatedType && originalImageMeta.pages ? height / originalImageMeta.pages : height,\n mimeType: mimeInfo?.mime || mimeType,\n sizesToSave: [{ buffer: bufferData, path: imagePath }],\n width,\n })\n }),\n )\n\n return results.reduce(\n (acc, result) => {\n Object.assign(acc.sizeData, result.sizeData)\n acc.sizesToSave.push(...result.sizesToSave)\n return acc\n },\n { ...defaultResult },\n )\n}\n"],"names":["fileTypeFromBuffer","fs","sanitize","isNumber","fileExists","optionallyAppendMetadata","getSanitizedImageData","sourceImage","extension","split","pop","name","substring","lastIndexOf","ext","createImageName","height","outputImageName","width","createResult","filename","filesize","mimeType","sizesToSave","sizeData","getImageResizeAction","dimensions","originalImage","hasFocalPoint","imageResizeConfig","fit","withoutEnlargement","withoutReduction","targetWidth","targetHeight","originalImageIsSmallerXAndY","undefined","originalImageIsSmallerXOrY","targetAspectRatio","originalAspectRatio","sanitizeResizeConfig","resizeConfig","position","extractHeightFromImage","sharpMetadata","pages","resizeAndTransformImageSizes","config","file","req","savedFilename","sharp","staticPath","uploadEdits","withMetadata","focalPoint","focalPointEnabled","imageSizes","upload","incomingFocalPoint","x","Math","round","y","defaultResult","fileIsAnimatedType","includes","mimetype","sharpOptions","animated","sharpBase","tempFilePath","data","rotate","originalImageMeta","metadata","adjustedDimensions","orientation","resizeImageMeta","results","Promise","all","map","resizeAction","Boolean","imageToResize","clone","resized","resizeHeight","resizeWidth","resizeAspectRatio","prioritizeHeight","resize","fastShrinkOnLoad","metadataAppendedFile","sharpFile","info","toBuffer","resolveWithObject","halfResizeX","xFocalCenter","calculatedRightPixelBound","leftBound","halfResizeY","yFocalCenter","calculatedBottomPixelBound","topBound","extract","left","floor","top","formatOptions","toFormat","format","options","trimOptions","trim","bufferData","bufferInfo","sanitizedImage","payloadUploadSizes","mimeInfo","imageNameWithDimensions","generateImageName","originalName","sizeName","imagePath","unlink","size","mime","buffer","path","reduce","acc","result","Object","assign","push"],"mappings":"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"}