Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { formatAdminURL } from 'payload/shared'

export type VercelBlobClientUploadHandlerExtra = {
addRandomSuffix: boolean
allowOverwrite: boolean
baseURL: string
prefix: string
}
Expand All @@ -14,7 +15,7 @@ export const VercelBlobClientUploadHandler =
handler: async ({
apiRoute,
collectionSlug,
extra: { addRandomSuffix, baseURL, prefix = '' },
extra: { addRandomSuffix, allowOverwrite, baseURL, prefix = '' },
file,
serverHandlerPath,
serverURL,
Expand Down
4 changes: 3 additions & 1 deletion packages/storage-vercel-blob/src/getClientUploadRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ type Args = {
req: PayloadRequest
}) => boolean | Promise<boolean>
addRandomSuffix?: boolean
allowOverwrite?: boolean
cacheControlMaxAge?: number
token: string
}

const defaultAccess: Args['access'] = ({ req }) => !!req.user

export const getClientUploadRoute =
({ access = defaultAccess, addRandomSuffix, cacheControlMaxAge, token }: Args): PayloadHandler =>
({ access = defaultAccess, addRandomSuffix, allowOverwrite, cacheControlMaxAge, token }: Args): PayloadHandler =>
async (req) => {
const body = (await req.json!()) as HandleUploadBody

Expand All @@ -34,6 +35,7 @@ export const getClientUploadRoute =

return Promise.resolve({
addRandomSuffix,
allowOverwrite,
cacheControlMaxAge,
})
},
Expand Down
2 changes: 2 additions & 0 deletions packages/storage-vercel-blob/src/handleUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type HandleUploadArgs = {
export const getHandleUpload = ({
access = 'public',
addRandomSuffix,
allowOverwrite,
baseUrl,
cacheControlMaxAge,
prefix = '',
Expand All @@ -24,6 +25,7 @@ export const getHandleUpload = ({
const result = await put(fileKey, buffer, {
access,
addRandomSuffix,
allowOverwrite,
cacheControlMaxAge,
contentType: mimeType,
token,
Expand Down
21 changes: 20 additions & 1 deletion packages/storage-vercel-blob/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ export type VercelBlobStorageOptions = {
*/
addRandomSuffix?: boolean

/**
* Allow overwriting existing blobs with the same pathname.
*
* When `false` (the default), uploading a file with the same name as an
* existing blob will throw an error. This commonly happens when a previous
* upload fails partway through (the blob is created but the Payload record
* is not), leaving an orphan blob that blocks subsequent uploads of the
* same file.
*
* Set to `true` to silently overwrite the existing blob instead of erroring.
*
* @default false
*/
allowOverwrite?: boolean

/**
* When enabled, fields (like the prefix field) will always be inserted into
* the collection schema regardless of whether the plugin is enabled. This
Expand Down Expand Up @@ -82,6 +97,7 @@ export type VercelBlobStorageOptions = {
const defaultUploadOptions: Partial<VercelBlobStorageOptions> = {
access: 'public',
addRandomSuffix: false,
allowOverwrite: false,
cacheControlMaxAge: 60 * 60 * 24 * 365, // 1 year
enabled: true,
}
Expand Down Expand Up @@ -122,6 +138,7 @@ export const vercelBlobStorage: VercelBlobStoragePlugin =
enabled: !isPluginDisabled && Boolean(options.clientUploads),
extraClientHandlerProps: (collection) => ({
addRandomSuffix: !!optionsWithDefaults.addRandomSuffix,
allowOverwrite: !!optionsWithDefaults.allowOverwrite,
baseURL: baseUrl,
prefix:
(typeof collection === 'object' && collection.prefix && `${collection.prefix}/`) || '',
Expand All @@ -130,6 +147,7 @@ export const vercelBlobStorage: VercelBlobStoragePlugin =
access:
typeof options.clientUploads === 'object' ? options.clientUploads.access : undefined,
addRandomSuffix: optionsWithDefaults.addRandomSuffix,
allowOverwrite: optionsWithDefaults.allowOverwrite,
cacheControlMaxAge: options.cacheControlMaxAge,
token: options.token ?? '',
}),
Expand Down Expand Up @@ -185,7 +203,7 @@ function vercelBlobStorageInternal(
options: { baseUrl: string } & VercelBlobStorageOptions,
): Adapter {
return ({ collection, prefix }): GeneratedAdapter => {
const { access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, token } = options
const { access, addRandomSuffix, allowOverwrite, baseUrl, cacheControlMaxAge, clientUploads, token } = options

if (!token) {
throw new Error('Vercel Blob storage token is required')
Expand All @@ -199,6 +217,7 @@ function vercelBlobStorageInternal(
handleUpload: getHandleUpload({
access,
addRandomSuffix,
allowOverwrite,
baseUrl,
cacheControlMaxAge,
prefix,
Expand Down