fix(storage-*): ensure client handler is always added to the import map, even if the plugin is disabled (#11438)

Ensures that even if you pass `enabled: false` to the storage adapter
options, e.g:
```ts
s3Storage({
  enabled: false,
  collections: {
    [mediaSlug]: true,
  },
  bucket: process.env.S3_BUCKET,
  config: {
    credentials: {
      accessKeyId: process.env.S3_ACCESS_KEY_ID,
      secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
    },
  },
})
```
the client handler component is added to the import map. This prevents
errors when you use the adapter only on production, but you don't
regenerate the import map before running the build
This commit is contained in:
Sasha
2025-02-28 16:34:00 +02:00
committed by GitHub
parent e055565ca8
commit dfddee2125
5 changed files with 61 additions and 72 deletions

View File

@@ -64,21 +64,19 @@ type AzureStoragePlugin = (azureStorageArgs: AzureStorageOptions) => Plugin
export const azureStorage: AzureStoragePlugin =
(azureStorageOptions: AzureStorageOptions) =>
(incomingConfig: Config): Config => {
if (azureStorageOptions.enabled === false) {
return incomingConfig
}
const getStorageClient = () =>
getStorageClientFunc({
connectionString: azureStorageOptions.connectionString,
containerName: azureStorageOptions.containerName,
})
const isPluginDisabled = azureStorageOptions.enabled === false
initClientUploads({
clientHandler: '@payloadcms/storage-azure/client#AzureClientUploadHandler',
collections: azureStorageOptions.collections,
config: incomingConfig,
enabled: !!azureStorageOptions.clientUploads,
enabled: !isPluginDisabled && Boolean(azureStorageOptions.clientUploads),
serverHandler: getGenerateSignedURLHandler({
access:
typeof azureStorageOptions.clientUploads === 'object'
@@ -91,6 +89,10 @@ export const azureStorage: AzureStoragePlugin =
serverHandlerPath: '/storage-azure-generate-signed-url',
})
if (isPluginDisabled) {
return incomingConfig
}
const adapter = azureStorageInternal(getStorageClient, azureStorageOptions)
// Add adapter to each collection option object

View File

@@ -10,6 +10,7 @@ import type { Config, Plugin, UploadCollectionSlug } from 'payload'
import { Storage } from '@google-cloud/storage'
import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'
import { initClientUploads } from '@payloadcms/plugin-cloud-storage/utilities'
import { getGenerateSignedURLHandler } from './generateSignedURL.js'
import { getGenerateURL } from './generateURL.js'
@@ -52,10 +53,6 @@ type GcsStoragePlugin = (gcsStorageArgs: GcsStorageOptions) => Plugin
export const gcsStorage: GcsStoragePlugin =
(gcsStorageOptions: GcsStorageOptions) =>
(incomingConfig: Config): Config => {
if (gcsStorageOptions.enabled === false) {
return incomingConfig
}
let storageClient: null | Storage = null
const getStorageClient = (): Storage => {
@@ -69,46 +66,27 @@ export const gcsStorage: GcsStoragePlugin =
const adapter = gcsStorageInternal(getStorageClient, gcsStorageOptions)
if (gcsStorageOptions.clientUploads) {
if (!incomingConfig.endpoints) {
incomingConfig.endpoints = []
}
const isPluginDisabled = gcsStorageOptions.enabled === false
incomingConfig.endpoints.push({
handler: getGenerateSignedURLHandler({
access:
typeof gcsStorageOptions.clientUploads === 'object'
? gcsStorageOptions.clientUploads.access
: undefined,
bucket: gcsStorageOptions.bucket,
collections: gcsStorageOptions.collections,
getStorageClient,
}),
method: 'post',
path: '/storage-gcs-generate-signed-url',
})
}
initClientUploads({
clientHandler: '@payloadcms/storage-gcs/client#GcsClientUploadHandler',
collections: gcsStorageOptions.collections,
config: incomingConfig,
enabled: !isPluginDisabled && Boolean(gcsStorageOptions.enabled),
serverHandler: getGenerateSignedURLHandler({
access:
typeof gcsStorageOptions.clientUploads === 'object'
? gcsStorageOptions.clientUploads.access
: undefined,
bucket: gcsStorageOptions.bucket,
collections: gcsStorageOptions.collections,
getStorageClient,
}),
serverHandlerPath: '/storage-gcs-generate-signed-url',
})
if (!incomingConfig.admin) {
incomingConfig.admin = {}
}
if (!incomingConfig.admin.components) {
incomingConfig.admin.components = {}
}
if (!incomingConfig.admin.components.providers) {
incomingConfig.admin.components.providers = []
}
for (const collectionSlug in gcsStorageOptions.collections) {
incomingConfig.admin.components.providers.push({
clientProps: {
collectionSlug,
enabled: !!gcsStorageOptions.clientUploads,
},
path: '@payloadcms/storage-gcs/client#GcsClientUploadHandler',
})
if (isPluginDisabled) {
return incomingConfig
}
// Add adapter to each collection option object

View File

@@ -67,10 +67,6 @@ type S3StoragePlugin = (storageS3Args: S3StorageOptions) => Plugin
export const s3Storage: S3StoragePlugin =
(s3StorageOptions: S3StorageOptions) =>
(incomingConfig: Config): Config => {
if (s3StorageOptions.enabled === false) {
return incomingConfig
}
let storageClient: AWS.S3 | null = null
const getStorageClient: () => AWS.S3 = () => {
@@ -81,11 +77,13 @@ export const s3Storage: S3StoragePlugin =
return storageClient
}
const isPluginDisabled = s3StorageOptions.enabled === false
initClientUploads({
clientHandler: '@payloadcms/storage-s3/client#S3ClientUploadHandler',
collections: s3StorageOptions.collections,
config: incomingConfig,
enabled: !!s3StorageOptions.clientUploads,
enabled: !isPluginDisabled && Boolean(s3StorageOptions.clientUploads),
serverHandler: getGenerateSignedURLHandler({
access:
typeof s3StorageOptions.clientUploads === 'object'
@@ -99,6 +97,10 @@ export const s3Storage: S3StoragePlugin =
serverHandlerPath: '/storage-s3-generate-signed-url',
})
if (isPluginDisabled) {
return incomingConfig
}
const adapter = s3StorageInternal(getStorageClient, s3StorageOptions)
// Add adapter to each collection option object

View File

@@ -56,22 +56,13 @@ export type ACL = 'private' | 'public-read'
export const uploadthingStorage: UploadthingPlugin =
(uploadthingStorageOptions: UploadthingStorageOptions) =>
(incomingConfig: Config): Config => {
if (uploadthingStorageOptions.enabled === false) {
return incomingConfig
}
// Default ACL to public-read
if (!uploadthingStorageOptions.options.acl) {
uploadthingStorageOptions.options.acl = 'public-read'
}
const adapter = uploadthingInternal(uploadthingStorageOptions)
const isPluginDisabled = uploadthingStorageOptions.enabled === false
initClientUploads({
clientHandler: '@payloadcms/storage-uploadthing/client#UploadthingClientUploadHandler',
collections: uploadthingStorageOptions.collections,
config: incomingConfig,
enabled: !!uploadthingStorageOptions.clientUploads,
enabled: !isPluginDisabled && Boolean(uploadthingStorageOptions.clientUploads),
serverHandler: getClientUploadRoute({
access:
typeof uploadthingStorageOptions.clientUploads === 'object'
@@ -83,6 +74,17 @@ export const uploadthingStorage: UploadthingPlugin =
serverHandlerPath: '/storage-uploadthing-client-upload-route',
})
if (isPluginDisabled) {
return incomingConfig
}
// Default ACL to public-read
if (!uploadthingStorageOptions.options.acl) {
uploadthingStorageOptions.options.acl = 'public-read'
}
const adapter = uploadthingInternal(uploadthingStorageOptions)
// Add adapter to each collection option object
const collectionsWithAdapter: CloudStoragePluginOptions['collections'] = Object.entries(
uploadthingStorageOptions.collections,

View File

@@ -80,15 +80,15 @@ type VercelBlobStoragePlugin = (vercelBlobStorageOpts: VercelBlobStorageOptions)
export const vercelBlobStorage: VercelBlobStoragePlugin =
(options: VercelBlobStorageOptions) =>
(incomingConfig: Config): Config => {
// If the plugin is disabled or no token is provided, do not enable the plugin
if (options.enabled === false || !options.token) {
return incomingConfig
}
// Parse storeId from token
const storeId = options.token.match(/^vercel_blob_rw_([a-z\d]+)_[a-z\d]+$/i)?.[1]?.toLowerCase()
const storeId = options.token
?.match(/^vercel_blob_rw_([a-z\d]+)_[a-z\d]+$/i)?.[1]
?.toLowerCase()
if (!storeId) {
const isPluginDisabled = options.enabled === false || !options.token
// Don't throw if the plugin is disabled
if (!storeId && !isPluginDisabled) {
throw new Error(
'Invalid token format for Vercel Blob adapter. Should be vercel_blob_rw_<store_id>_<random_string>.',
)
@@ -108,7 +108,7 @@ export const vercelBlobStorage: VercelBlobStoragePlugin =
clientHandler: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',
collections: options.collections,
config: incomingConfig,
enabled: !!options.clientUploads,
enabled: !isPluginDisabled && Boolean(options.clientUploads),
extraClientHandlerProps: (collection) => ({
addRandomSuffix: !!optionsWithDefaults.addRandomSuffix,
baseURL: baseUrl,
@@ -119,11 +119,16 @@ export const vercelBlobStorage: VercelBlobStoragePlugin =
typeof options.clientUploads === 'object' ? options.clientUploads.access : undefined,
addRandomSuffix: optionsWithDefaults.addRandomSuffix,
cacheControlMaxAge: options.cacheControlMaxAge,
token: options.token,
token: options.token ?? '',
}),
serverHandlerPath: '/vercel-blob-client-upload-route',
})
// If the plugin is disabled or no token is provided, do not enable the plugin
if (isPluginDisabled) {
return incomingConfig
}
const adapter = vercelBlobStorageInternal({ ...optionsWithDefaults, baseUrl })
// Add adapter to each collection option object