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:
@@ -64,21 +64,19 @@ type AzureStoragePlugin = (azureStorageArgs: AzureStorageOptions) => Plugin
|
|||||||
export const azureStorage: AzureStoragePlugin =
|
export const azureStorage: AzureStoragePlugin =
|
||||||
(azureStorageOptions: AzureStorageOptions) =>
|
(azureStorageOptions: AzureStorageOptions) =>
|
||||||
(incomingConfig: Config): Config => {
|
(incomingConfig: Config): Config => {
|
||||||
if (azureStorageOptions.enabled === false) {
|
|
||||||
return incomingConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStorageClient = () =>
|
const getStorageClient = () =>
|
||||||
getStorageClientFunc({
|
getStorageClientFunc({
|
||||||
connectionString: azureStorageOptions.connectionString,
|
connectionString: azureStorageOptions.connectionString,
|
||||||
containerName: azureStorageOptions.containerName,
|
containerName: azureStorageOptions.containerName,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isPluginDisabled = azureStorageOptions.enabled === false
|
||||||
|
|
||||||
initClientUploads({
|
initClientUploads({
|
||||||
clientHandler: '@payloadcms/storage-azure/client#AzureClientUploadHandler',
|
clientHandler: '@payloadcms/storage-azure/client#AzureClientUploadHandler',
|
||||||
collections: azureStorageOptions.collections,
|
collections: azureStorageOptions.collections,
|
||||||
config: incomingConfig,
|
config: incomingConfig,
|
||||||
enabled: !!azureStorageOptions.clientUploads,
|
enabled: !isPluginDisabled && Boolean(azureStorageOptions.clientUploads),
|
||||||
serverHandler: getGenerateSignedURLHandler({
|
serverHandler: getGenerateSignedURLHandler({
|
||||||
access:
|
access:
|
||||||
typeof azureStorageOptions.clientUploads === 'object'
|
typeof azureStorageOptions.clientUploads === 'object'
|
||||||
@@ -91,6 +89,10 @@ export const azureStorage: AzureStoragePlugin =
|
|||||||
serverHandlerPath: '/storage-azure-generate-signed-url',
|
serverHandlerPath: '/storage-azure-generate-signed-url',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (isPluginDisabled) {
|
||||||
|
return incomingConfig
|
||||||
|
}
|
||||||
|
|
||||||
const adapter = azureStorageInternal(getStorageClient, azureStorageOptions)
|
const adapter = azureStorageInternal(getStorageClient, azureStorageOptions)
|
||||||
|
|
||||||
// Add adapter to each collection option object
|
// Add adapter to each collection option object
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import type { Config, Plugin, UploadCollectionSlug } from 'payload'
|
|||||||
|
|
||||||
import { Storage } from '@google-cloud/storage'
|
import { Storage } from '@google-cloud/storage'
|
||||||
import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'
|
import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage'
|
||||||
|
import { initClientUploads } from '@payloadcms/plugin-cloud-storage/utilities'
|
||||||
|
|
||||||
import { getGenerateSignedURLHandler } from './generateSignedURL.js'
|
import { getGenerateSignedURLHandler } from './generateSignedURL.js'
|
||||||
import { getGenerateURL } from './generateURL.js'
|
import { getGenerateURL } from './generateURL.js'
|
||||||
@@ -52,10 +53,6 @@ type GcsStoragePlugin = (gcsStorageArgs: GcsStorageOptions) => Plugin
|
|||||||
export const gcsStorage: GcsStoragePlugin =
|
export const gcsStorage: GcsStoragePlugin =
|
||||||
(gcsStorageOptions: GcsStorageOptions) =>
|
(gcsStorageOptions: GcsStorageOptions) =>
|
||||||
(incomingConfig: Config): Config => {
|
(incomingConfig: Config): Config => {
|
||||||
if (gcsStorageOptions.enabled === false) {
|
|
||||||
return incomingConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
let storageClient: null | Storage = null
|
let storageClient: null | Storage = null
|
||||||
|
|
||||||
const getStorageClient = (): Storage => {
|
const getStorageClient = (): Storage => {
|
||||||
@@ -69,46 +66,27 @@ export const gcsStorage: GcsStoragePlugin =
|
|||||||
|
|
||||||
const adapter = gcsStorageInternal(getStorageClient, gcsStorageOptions)
|
const adapter = gcsStorageInternal(getStorageClient, gcsStorageOptions)
|
||||||
|
|
||||||
if (gcsStorageOptions.clientUploads) {
|
const isPluginDisabled = gcsStorageOptions.enabled === false
|
||||||
if (!incomingConfig.endpoints) {
|
|
||||||
incomingConfig.endpoints = []
|
|
||||||
}
|
|
||||||
|
|
||||||
incomingConfig.endpoints.push({
|
initClientUploads({
|
||||||
handler: getGenerateSignedURLHandler({
|
clientHandler: '@payloadcms/storage-gcs/client#GcsClientUploadHandler',
|
||||||
access:
|
collections: gcsStorageOptions.collections,
|
||||||
typeof gcsStorageOptions.clientUploads === 'object'
|
config: incomingConfig,
|
||||||
? gcsStorageOptions.clientUploads.access
|
enabled: !isPluginDisabled && Boolean(gcsStorageOptions.enabled),
|
||||||
: undefined,
|
serverHandler: getGenerateSignedURLHandler({
|
||||||
bucket: gcsStorageOptions.bucket,
|
access:
|
||||||
collections: gcsStorageOptions.collections,
|
typeof gcsStorageOptions.clientUploads === 'object'
|
||||||
getStorageClient,
|
? gcsStorageOptions.clientUploads.access
|
||||||
}),
|
: undefined,
|
||||||
method: 'post',
|
bucket: gcsStorageOptions.bucket,
|
||||||
path: '/storage-gcs-generate-signed-url',
|
collections: gcsStorageOptions.collections,
|
||||||
})
|
getStorageClient,
|
||||||
}
|
}),
|
||||||
|
serverHandlerPath: '/storage-gcs-generate-signed-url',
|
||||||
|
})
|
||||||
|
|
||||||
if (!incomingConfig.admin) {
|
if (isPluginDisabled) {
|
||||||
incomingConfig.admin = {}
|
return incomingConfig
|
||||||
}
|
|
||||||
|
|
||||||
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',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adapter to each collection option object
|
// Add adapter to each collection option object
|
||||||
|
|||||||
@@ -67,10 +67,6 @@ type S3StoragePlugin = (storageS3Args: S3StorageOptions) => Plugin
|
|||||||
export const s3Storage: S3StoragePlugin =
|
export const s3Storage: S3StoragePlugin =
|
||||||
(s3StorageOptions: S3StorageOptions) =>
|
(s3StorageOptions: S3StorageOptions) =>
|
||||||
(incomingConfig: Config): Config => {
|
(incomingConfig: Config): Config => {
|
||||||
if (s3StorageOptions.enabled === false) {
|
|
||||||
return incomingConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
let storageClient: AWS.S3 | null = null
|
let storageClient: AWS.S3 | null = null
|
||||||
|
|
||||||
const getStorageClient: () => AWS.S3 = () => {
|
const getStorageClient: () => AWS.S3 = () => {
|
||||||
@@ -81,11 +77,13 @@ export const s3Storage: S3StoragePlugin =
|
|||||||
return storageClient
|
return storageClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isPluginDisabled = s3StorageOptions.enabled === false
|
||||||
|
|
||||||
initClientUploads({
|
initClientUploads({
|
||||||
clientHandler: '@payloadcms/storage-s3/client#S3ClientUploadHandler',
|
clientHandler: '@payloadcms/storage-s3/client#S3ClientUploadHandler',
|
||||||
collections: s3StorageOptions.collections,
|
collections: s3StorageOptions.collections,
|
||||||
config: incomingConfig,
|
config: incomingConfig,
|
||||||
enabled: !!s3StorageOptions.clientUploads,
|
enabled: !isPluginDisabled && Boolean(s3StorageOptions.clientUploads),
|
||||||
serverHandler: getGenerateSignedURLHandler({
|
serverHandler: getGenerateSignedURLHandler({
|
||||||
access:
|
access:
|
||||||
typeof s3StorageOptions.clientUploads === 'object'
|
typeof s3StorageOptions.clientUploads === 'object'
|
||||||
@@ -99,6 +97,10 @@ export const s3Storage: S3StoragePlugin =
|
|||||||
serverHandlerPath: '/storage-s3-generate-signed-url',
|
serverHandlerPath: '/storage-s3-generate-signed-url',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (isPluginDisabled) {
|
||||||
|
return incomingConfig
|
||||||
|
}
|
||||||
|
|
||||||
const adapter = s3StorageInternal(getStorageClient, s3StorageOptions)
|
const adapter = s3StorageInternal(getStorageClient, s3StorageOptions)
|
||||||
|
|
||||||
// Add adapter to each collection option object
|
// Add adapter to each collection option object
|
||||||
|
|||||||
@@ -56,22 +56,13 @@ export type ACL = 'private' | 'public-read'
|
|||||||
export const uploadthingStorage: UploadthingPlugin =
|
export const uploadthingStorage: UploadthingPlugin =
|
||||||
(uploadthingStorageOptions: UploadthingStorageOptions) =>
|
(uploadthingStorageOptions: UploadthingStorageOptions) =>
|
||||||
(incomingConfig: Config): Config => {
|
(incomingConfig: Config): Config => {
|
||||||
if (uploadthingStorageOptions.enabled === false) {
|
const isPluginDisabled = uploadthingStorageOptions.enabled === false
|
||||||
return incomingConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default ACL to public-read
|
|
||||||
if (!uploadthingStorageOptions.options.acl) {
|
|
||||||
uploadthingStorageOptions.options.acl = 'public-read'
|
|
||||||
}
|
|
||||||
|
|
||||||
const adapter = uploadthingInternal(uploadthingStorageOptions)
|
|
||||||
|
|
||||||
initClientUploads({
|
initClientUploads({
|
||||||
clientHandler: '@payloadcms/storage-uploadthing/client#UploadthingClientUploadHandler',
|
clientHandler: '@payloadcms/storage-uploadthing/client#UploadthingClientUploadHandler',
|
||||||
collections: uploadthingStorageOptions.collections,
|
collections: uploadthingStorageOptions.collections,
|
||||||
config: incomingConfig,
|
config: incomingConfig,
|
||||||
enabled: !!uploadthingStorageOptions.clientUploads,
|
enabled: !isPluginDisabled && Boolean(uploadthingStorageOptions.clientUploads),
|
||||||
serverHandler: getClientUploadRoute({
|
serverHandler: getClientUploadRoute({
|
||||||
access:
|
access:
|
||||||
typeof uploadthingStorageOptions.clientUploads === 'object'
|
typeof uploadthingStorageOptions.clientUploads === 'object'
|
||||||
@@ -83,6 +74,17 @@ export const uploadthingStorage: UploadthingPlugin =
|
|||||||
serverHandlerPath: '/storage-uploadthing-client-upload-route',
|
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
|
// Add adapter to each collection option object
|
||||||
const collectionsWithAdapter: CloudStoragePluginOptions['collections'] = Object.entries(
|
const collectionsWithAdapter: CloudStoragePluginOptions['collections'] = Object.entries(
|
||||||
uploadthingStorageOptions.collections,
|
uploadthingStorageOptions.collections,
|
||||||
|
|||||||
@@ -80,15 +80,15 @@ type VercelBlobStoragePlugin = (vercelBlobStorageOpts: VercelBlobStorageOptions)
|
|||||||
export const vercelBlobStorage: VercelBlobStoragePlugin =
|
export const vercelBlobStorage: VercelBlobStoragePlugin =
|
||||||
(options: VercelBlobStorageOptions) =>
|
(options: VercelBlobStorageOptions) =>
|
||||||
(incomingConfig: Config): Config => {
|
(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
|
// 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(
|
throw new Error(
|
||||||
'Invalid token format for Vercel Blob adapter. Should be vercel_blob_rw_<store_id>_<random_string>.',
|
'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',
|
clientHandler: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',
|
||||||
collections: options.collections,
|
collections: options.collections,
|
||||||
config: incomingConfig,
|
config: incomingConfig,
|
||||||
enabled: !!options.clientUploads,
|
enabled: !isPluginDisabled && Boolean(options.clientUploads),
|
||||||
extraClientHandlerProps: (collection) => ({
|
extraClientHandlerProps: (collection) => ({
|
||||||
addRandomSuffix: !!optionsWithDefaults.addRandomSuffix,
|
addRandomSuffix: !!optionsWithDefaults.addRandomSuffix,
|
||||||
baseURL: baseUrl,
|
baseURL: baseUrl,
|
||||||
@@ -119,11 +119,16 @@ export const vercelBlobStorage: VercelBlobStoragePlugin =
|
|||||||
typeof options.clientUploads === 'object' ? options.clientUploads.access : undefined,
|
typeof options.clientUploads === 'object' ? options.clientUploads.access : undefined,
|
||||||
addRandomSuffix: optionsWithDefaults.addRandomSuffix,
|
addRandomSuffix: optionsWithDefaults.addRandomSuffix,
|
||||||
cacheControlMaxAge: options.cacheControlMaxAge,
|
cacheControlMaxAge: options.cacheControlMaxAge,
|
||||||
token: options.token,
|
token: options.token ?? '',
|
||||||
}),
|
}),
|
||||||
serverHandlerPath: '/vercel-blob-client-upload-route',
|
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 })
|
const adapter = vercelBlobStorageInternal({ ...optionsWithDefaults, baseUrl })
|
||||||
|
|
||||||
// Add adapter to each collection option object
|
// Add adapter to each collection option object
|
||||||
|
|||||||
Reference in New Issue
Block a user