@inoo-ch/payload-image-optimizer 1.3.3 → 1.3.5
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 +26 -0
- package/package.json +1 -1
- package/dist/components/ImageBox.d.ts +0 -8
- package/dist/components/OptimizationStatus.d.ts +0 -4
- package/dist/components/RegenerationButton.d.ts +0 -2
- package/dist/defaults.d.ts +0 -3
- package/dist/endpoints/regenerate.d.ts +0 -4
- package/dist/exports/client.d.ts +0 -6
- package/dist/exports/rsc.d.ts +0 -1
- package/dist/fields/imageOptimizerField.d.ts +0 -4
- package/dist/hooks/afterChange.d.ts +0 -3
- package/dist/hooks/beforeChange.d.ts +0 -3
- package/dist/index.d.ts +0 -6
- package/dist/processing/index.d.ts +0 -17
- package/dist/tasks/convertFormats.d.ts +0 -12
- package/dist/tasks/regenerateDocument.d.ts +0 -18
- package/dist/translations/index.d.ts +0 -1
- package/dist/types.d.ts +0 -57
- package/dist/utilities/getImageOptimizerProps.d.ts +0 -24
- package/dist/utilities/resolveStaticDir.d.ts +0 -3
- package/dist/utilities/storage.d.ts +0 -18
- package/dist/utilities/thumbhash.d.ts +0 -2
package/README.md
CHANGED
|
@@ -128,6 +128,32 @@ collections: {
|
|
|
128
128
|
|
|
129
129
|
All format conversion runs as async background jobs, so uploads return immediately.
|
|
130
130
|
|
|
131
|
+
## How It Differs from Payload's Default Image Handling
|
|
132
|
+
|
|
133
|
+
Payload CMS ships with [sharp](https://sharp.pixelplumbing.com/) built-in and can resize images and generate sizes on upload. This plugin **does not double-process your images** — it intercepts the raw upload in a `beforeChange` hook *before* Payload's own sharp pipeline runs, and writes the optimized buffer back to `req.file.data`. When Payload's built-in `uploadFiles` step kicks in to generate your configured sizes, it works from the already-optimized file, not the raw original.
|
|
134
|
+
|
|
135
|
+
### Comparison
|
|
136
|
+
|
|
137
|
+
| Capability | Payload Default | With This Plugin |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| Resize to max dimensions | Manual via `imageSizes` config | Automatic — configure once globally or per-collection |
|
|
140
|
+
| WebP/AVIF conversion | Requires custom hooks | Built-in, zero-config |
|
|
141
|
+
| EXIF metadata stripping | Not built-in | Automatic (configurable) |
|
|
142
|
+
| Blur hash placeholders | Requires custom hooks | ThumbHash generated automatically |
|
|
143
|
+
| Optimization status & savings | Not available | Admin sidebar panel per image |
|
|
144
|
+
| Bulk re-process existing images | Not available | One-click regeneration with progress tracking |
|
|
145
|
+
| Next.js `<Image>` with blur placeholder | Manual wiring | Drop-in `<ImageBox>` component |
|
|
146
|
+
| Per-collection format/quality overrides | N/A | Supported |
|
|
147
|
+
|
|
148
|
+
### CPU & Resource Impact
|
|
149
|
+
|
|
150
|
+
- **Single-format mode** (e.g. WebP only with `replaceOriginal: true`) adds virtually zero overhead compared to Payload's default sharp processing — the plugin replaces the sharp pass rather than adding a second one.
|
|
151
|
+
- **Additional format variants** (e.g. both WebP and AVIF) run as background jobs after upload — this is the one area where you'll see extra CPU usage vs vanilla Payload.
|
|
152
|
+
- **ThumbHash generation** processes a 100×100px thumbnail — negligible impact.
|
|
153
|
+
- **Bulk regeneration** processes images sequentially, not all at once, so it won't spike your server.
|
|
154
|
+
|
|
155
|
+
If you're on a resource-constrained server, use single-format mode and you'll be at roughly the same CPU cost as stock Payload.
|
|
156
|
+
|
|
131
157
|
## Admin UI
|
|
132
158
|
|
|
133
159
|
The plugin adds an **Optimization Status** panel to the document sidebar showing:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inoo-ch/payload-image-optimizer",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"description": "Payload CMS plugin for automatic image optimization — WebP/AVIF conversion, resize, EXIF strip, ThumbHash placeholders, and bulk regeneration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { type ImageProps } from 'next/image';
|
|
3
|
-
import type { MediaResource } from '../types.js';
|
|
4
|
-
export interface ImageBoxProps extends Omit<ImageProps, 'src' | 'alt'> {
|
|
5
|
-
media: MediaResource | string;
|
|
6
|
-
alt?: string;
|
|
7
|
-
}
|
|
8
|
-
export declare const ImageBox: React.FC<ImageBoxProps>;
|
package/dist/defaults.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { ImageOptimizerConfig, ResolvedCollectionOptimizerConfig, ResolvedImageOptimizerConfig } from './types.js';
|
|
2
|
-
export declare const resolveConfig: (config: ImageOptimizerConfig) => ResolvedImageOptimizerConfig;
|
|
3
|
-
export declare const resolveCollectionConfig: (resolvedConfig: ResolvedImageOptimizerConfig, collectionSlug: string) => ResolvedCollectionOptimizerConfig;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { PayloadHandler } from 'payload';
|
|
2
|
-
import type { ResolvedImageOptimizerConfig } from '../types.js';
|
|
3
|
-
export declare const createRegenerateHandler: (resolvedConfig: ResolvedImageOptimizerConfig) => PayloadHandler;
|
|
4
|
-
export declare const createRegenerateStatusHandler: (resolvedConfig: ResolvedImageOptimizerConfig) => PayloadHandler;
|
package/dist/exports/client.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { OptimizationStatus } from '../components/OptimizationStatus.js';
|
|
2
|
-
export { ImageBox } from '../components/ImageBox.js';
|
|
3
|
-
export type { ImageBoxProps } from '../components/ImageBox.js';
|
|
4
|
-
export { getImageOptimizerProps } from '../utilities/getImageOptimizerProps.js';
|
|
5
|
-
export type { ImageOptimizerProps } from '../utilities/getImageOptimizerProps.js';
|
|
6
|
-
export { RegenerationButton } from '../components/RegenerationButton.js';
|
package/dist/exports/rsc.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'payload';
|
|
2
|
-
import type { ImageOptimizerConfig } from './types.js';
|
|
3
|
-
export type { ImageOptimizerConfig, ImageFormat, FormatQuality, CollectionOptimizerConfig, ImageOptimizerData, MediaResource, FieldsOverride } from './types.js';
|
|
4
|
-
export { defaultImageOptimizerFields } from './fields/imageOptimizerField.js';
|
|
5
|
-
export { encodeImageToThumbHash, decodeThumbHashToDataURL } from './utilities/thumbhash.js';
|
|
6
|
-
export declare const imageOptimizer: (pluginOptions: ImageOptimizerConfig) => (config: Config) => Config;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare function stripAndResize(buffer: Buffer, maxDimensions: {
|
|
2
|
-
width: number;
|
|
3
|
-
height: number;
|
|
4
|
-
}, stripMetadata: boolean): Promise<{
|
|
5
|
-
buffer: Buffer;
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
size: number;
|
|
9
|
-
}>;
|
|
10
|
-
export declare function generateThumbHash(buffer: Buffer): Promise<string>;
|
|
11
|
-
export declare function convertFormat(buffer: Buffer, format: 'webp' | 'avif', quality: number): Promise<{
|
|
12
|
-
buffer: Buffer;
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
size: number;
|
|
16
|
-
mimeType: string;
|
|
17
|
-
}>;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ResolvedImageOptimizerConfig } from '../types.js';
|
|
2
|
-
export declare const createConvertFormatsHandler: (resolvedConfig: ResolvedImageOptimizerConfig) => ({ input, req }: {
|
|
3
|
-
input: {
|
|
4
|
-
collectionSlug: string;
|
|
5
|
-
docId: string;
|
|
6
|
-
};
|
|
7
|
-
req: any;
|
|
8
|
-
}) => Promise<{
|
|
9
|
-
output: {
|
|
10
|
-
variantsGenerated: number;
|
|
11
|
-
};
|
|
12
|
-
}>;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ResolvedImageOptimizerConfig } from '../types.js';
|
|
2
|
-
export declare const createRegenerateDocumentHandler: (resolvedConfig: ResolvedImageOptimizerConfig) => ({ input, req }: {
|
|
3
|
-
input: {
|
|
4
|
-
collectionSlug: string;
|
|
5
|
-
docId: string;
|
|
6
|
-
};
|
|
7
|
-
req: any;
|
|
8
|
-
}) => Promise<{
|
|
9
|
-
output: {
|
|
10
|
-
status: string;
|
|
11
|
-
reason: string;
|
|
12
|
-
};
|
|
13
|
-
} | {
|
|
14
|
-
output: {
|
|
15
|
-
status: string;
|
|
16
|
-
reason?: undefined;
|
|
17
|
-
};
|
|
18
|
-
}>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const translations: Record<string, Record<string, Record<string, string>>>;
|
package/dist/types.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { CollectionSlug, Field } from 'payload';
|
|
2
|
-
export type ImageFormat = 'webp' | 'avif';
|
|
3
|
-
export type FormatQuality = {
|
|
4
|
-
format: ImageFormat;
|
|
5
|
-
quality: number;
|
|
6
|
-
};
|
|
7
|
-
export type CollectionOptimizerConfig = {
|
|
8
|
-
formats?: FormatQuality[];
|
|
9
|
-
maxDimensions?: {
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
};
|
|
13
|
-
replaceOriginal?: boolean;
|
|
14
|
-
};
|
|
15
|
-
export type FieldsOverride = (args: {
|
|
16
|
-
defaultFields: Field[];
|
|
17
|
-
}) => Field[];
|
|
18
|
-
export type ImageOptimizerConfig = {
|
|
19
|
-
collections: Partial<Record<CollectionSlug, true | CollectionOptimizerConfig>>;
|
|
20
|
-
disabled?: boolean;
|
|
21
|
-
fieldsOverride?: FieldsOverride;
|
|
22
|
-
formats?: FormatQuality[];
|
|
23
|
-
generateThumbHash?: boolean;
|
|
24
|
-
maxDimensions?: {
|
|
25
|
-
width: number;
|
|
26
|
-
height: number;
|
|
27
|
-
};
|
|
28
|
-
replaceOriginal?: boolean;
|
|
29
|
-
stripMetadata?: boolean;
|
|
30
|
-
};
|
|
31
|
-
export type ResolvedCollectionOptimizerConfig = {
|
|
32
|
-
formats: FormatQuality[];
|
|
33
|
-
maxDimensions: {
|
|
34
|
-
width: number;
|
|
35
|
-
height: number;
|
|
36
|
-
};
|
|
37
|
-
replaceOriginal: boolean;
|
|
38
|
-
};
|
|
39
|
-
export type ResolvedImageOptimizerConfig = Required<Pick<ImageOptimizerConfig, 'formats' | 'generateThumbHash' | 'maxDimensions' | 'stripMetadata'>> & {
|
|
40
|
-
collections: ImageOptimizerConfig['collections'];
|
|
41
|
-
disabled: boolean;
|
|
42
|
-
replaceOriginal: boolean;
|
|
43
|
-
};
|
|
44
|
-
export type ImageOptimizerData = {
|
|
45
|
-
thumbHash?: string | null;
|
|
46
|
-
};
|
|
47
|
-
export type MediaResource = {
|
|
48
|
-
url?: string | null;
|
|
49
|
-
alt?: string | null;
|
|
50
|
-
width?: number | null;
|
|
51
|
-
height?: number | null;
|
|
52
|
-
filename?: string | null;
|
|
53
|
-
focalX?: number | null;
|
|
54
|
-
focalY?: number | null;
|
|
55
|
-
imageOptimizer?: ImageOptimizerData | null;
|
|
56
|
-
updatedAt?: string;
|
|
57
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { MediaResource } from '../types.js';
|
|
2
|
-
export type ImageOptimizerProps = {
|
|
3
|
-
placeholder: 'blur' | 'empty';
|
|
4
|
-
blurDataURL?: string;
|
|
5
|
-
style: {
|
|
6
|
-
objectPosition: string;
|
|
7
|
-
};
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Extracts image optimization props from a Payload media resource.
|
|
11
|
-
*
|
|
12
|
-
* Returns props that can be spread onto a Next.js `<Image>` component to add
|
|
13
|
-
* ThumbHash blur placeholders and focal-point-based object positioning.
|
|
14
|
-
*
|
|
15
|
-
* Works with any component — including the Payload website template's `ImageMedia`:
|
|
16
|
-
*
|
|
17
|
-
* ```tsx
|
|
18
|
-
* import { getImageOptimizerProps } from '@inoo-ch/payload-image-optimizer/client'
|
|
19
|
-
*
|
|
20
|
-
* const optimizerProps = getImageOptimizerProps(resource)
|
|
21
|
-
* <NextImage {...existingProps} {...optimizerProps} />
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export declare function getImageOptimizerProps(resource: MediaResource | null | undefined): ImageOptimizerProps;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns true when the collection uses cloud/external storage (disableLocalStorage: true).
|
|
3
|
-
* When true, files are uploaded by external adapter hooks — no local FS writes should happen.
|
|
4
|
-
*/
|
|
5
|
-
export declare function isCloudStorage(collectionConfig: {
|
|
6
|
-
upload?: boolean | Record<string, any>;
|
|
7
|
-
}): boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Reads a file buffer from local disk or fetches it from URL.
|
|
10
|
-
* Tries local disk first (when available), falls back to URL fetch.
|
|
11
|
-
* This makes the plugin storage-agnostic — works with local FS and cloud storage alike.
|
|
12
|
-
*/
|
|
13
|
-
export declare function fetchFileBuffer(doc: {
|
|
14
|
-
filename?: string;
|
|
15
|
-
url?: string;
|
|
16
|
-
}, collectionConfig: {
|
|
17
|
-
upload?: boolean | Record<string, any>;
|
|
18
|
-
}): Promise<Buffer>;
|