@payloadcms/storage-vercel-blob 4.0.0-internal.b8e7c89 → 4.0.0-internal.bf4bcce

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.
Files changed (41) hide show
  1. package/README.md +10 -8
  2. package/dist/adapter.d.ts +3 -1
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +68 -26
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/authorizeFileOverwrite.d.ts +16 -0
  7. package/dist/authorizeFileOverwrite.d.ts.map +1 -0
  8. package/dist/authorizeFileOverwrite.js +117 -0
  9. package/dist/authorizeFileOverwrite.js.map +1 -0
  10. package/dist/client/VercelBlobClientUploadHandler.d.ts.map +1 -1
  11. package/dist/client/VercelBlobClientUploadHandler.js +3 -9
  12. package/dist/client/VercelBlobClientUploadHandler.js.map +1 -1
  13. package/dist/copyFile.d.ts +12 -0
  14. package/dist/copyFile.d.ts.map +1 -0
  15. package/dist/copyFile.js +86 -0
  16. package/dist/copyFile.js.map +1 -0
  17. package/dist/deleteFile.d.ts +2 -5
  18. package/dist/deleteFile.d.ts.map +1 -1
  19. package/dist/deleteFile.js +3 -10
  20. package/dist/deleteFile.js.map +1 -1
  21. package/dist/generateURL.d.ts +1 -0
  22. package/dist/generateURL.d.ts.map +1 -1
  23. package/dist/generateURL.js +13 -9
  24. package/dist/generateURL.js.map +1 -1
  25. package/dist/getCollectionSources.d.ts +20 -0
  26. package/dist/getCollectionSources.d.ts.map +1 -0
  27. package/dist/getCollectionSources.js +27 -0
  28. package/dist/getCollectionSources.js.map +1 -0
  29. package/dist/getFile.d.ts +4 -3
  30. package/dist/getFile.d.ts.map +1 -1
  31. package/dist/getFile.js +20 -12
  32. package/dist/getFile.js.map +1 -1
  33. package/dist/index.d.ts +10 -18
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +33 -22
  36. package/dist/index.js.map +1 -1
  37. package/dist/uploadFile.d.ts +2 -5
  38. package/dist/uploadFile.d.ts.map +1 -1
  39. package/dist/uploadFile.js +2 -9
  40. package/dist/uploadFile.js.map +1 -1
  41. package/package.json +4 -4
package/README.md CHANGED
@@ -41,11 +41,13 @@ export default buildConfig({
41
41
  })
42
42
  ```
43
43
 
44
- | Option | Description | Default |
45
- | -------------------- | -------------------------------------------------------------------- | ----------------------------- |
46
- | `enabled` | Whether or not to enable the plugin | `true` |
47
- | `collections` | Collections to apply the Vercel Blob adapter to | |
48
- | `addRandomSuffix` | Add a random suffix to the uploaded file name in Vercel Blob storage | `false` |
49
- | `cacheControlMaxAge` | Cache-Control max-age in seconds | `365 * 24 * 60 * 60` (1 Year) |
50
- | `token` | Vercel Blob storage read/write token | `''` |
51
- | `clientUploads` | Upload directly to Vercel Blob instead of through Payload. | |
44
+ | Option | Description | Default |
45
+ | -------------------- | --------------------------------------------------------------------------------------- | ----------------------------- |
46
+ | `enabled` | Whether or not to enable the plugin | `true` |
47
+ | `collections` | Collections to apply the Vercel Blob adapter to | |
48
+ | `addRandomSuffix` | Must be `false` or omitted; enabled adapters with configured collections reject `true`. | `false` |
49
+ | `cacheControlMaxAge` | Cache-Control max-age in seconds | `365 * 24 * 60 * 60` (1 Year) |
50
+ | `token` | Vercel Blob storage read/write token | `''` |
51
+ | `clientUploads` | Upload directly to Vercel Blob instead of through Payload. | |
52
+
53
+ Set `addRandomSuffix` to `false` or omit it. Payload requires exact storage paths for reads, rollback, and deletion, and already allocates unique `_objectKey` folders for managed uploads. Enabled adapters with configured collections reject `true` during initialization. Disabled adapters retain their existing behavior. Changing this option does not rename existing blobs; migrate any mismatched stored paths and saved metadata together.
package/dist/adapter.d.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  import type { Adapter, ClientUploadsConfig } from '@payloadcms/plugin-cloud-storage/types';
2
+ import type { VercelBlobCollectionSource } from './authorizeFileOverwrite.js';
2
3
  interface CreateVercelBlobAdapterArgs {
3
4
  access: 'public';
4
5
  addRandomSuffix?: boolean;
5
6
  baseUrl: string;
6
7
  cacheControlMaxAge: number;
7
8
  clientUploads?: ClientUploadsConfig;
9
+ collectionSources: VercelBlobCollectionSource[];
8
10
  token: string;
9
11
  useCompositePrefixes?: boolean;
10
12
  }
11
- export declare function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, token, useCompositePrefixes, }: CreateVercelBlobAdapterArgs): Adapter;
13
+ export declare function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, collectionSources, token, useCompositePrefixes, }: CreateVercelBlobAdapterArgs): Adapter;
12
14
  export {};
13
15
  //# sourceMappingURL=adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,mBAAmB,EAEpB,MAAM,wCAAwC,CAAA;AAW/C,UAAU,2BAA2B;IACnC,MAAM,EAAE,QAAQ,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,eAAe,EACf,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,KAAK,EACL,oBAA4B,GAC7B,EAAE,2BAA2B,GAAG,OAAO,CAwHvC"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,mBAAmB,EAGpB,MAAM,wCAAwC,CAAA;AAU/C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAS7E,UAAU,2BAA2B;IACnC,MAAM,EAAE,QAAQ,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,iBAAiB,EAAE,0BAA0B,EAAE,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,MAAM,EACN,eAAe,EACf,OAAO,EACP,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,KAAK,EACL,oBAA4B,GAC7B,EAAE,2BAA2B,GAAG,OAAO,CAoJvC"}
package/dist/adapter.js CHANGED
@@ -1,14 +1,31 @@
1
- import { resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities';
1
+ import { buildUploadStoragePathData, resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities';
2
2
  import { generateClientTokenFromReadWriteToken } from '@vercel/blob/client';
3
3
  import { Forbidden } from 'payload';
4
+ import { assertClientUploadAllowed, createClientUploadReceipt } from 'payload/internal';
5
+ import { authorizeClientOverwrite } from './authorizeFileOverwrite.js';
6
+ import { copyVercelBlobFile } from './copyFile.js';
4
7
  import { deleteFile } from './deleteFile.js';
5
8
  import { generateURL } from './generateURL.js';
6
9
  import { getFile } from './getFile.js';
7
10
  import { uploadFile } from './uploadFile.js';
8
- export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, token, useCompositePrefixes = false }) {
11
+ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, clientUploads, collectionSources, token, useCompositePrefixes = false }) {
9
12
  const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined;
13
+ const deleteStoredFile = ({ storageFilePath })=>deleteFile({
14
+ baseUrl,
15
+ storageFilePath,
16
+ token
17
+ });
10
18
  return ({ collection, prefix = '' })=>({
11
19
  name: 'vercel-blob',
20
+ copyFile: ({ from, req, to })=>copyVercelBlobFile({
21
+ access,
22
+ cacheControlMaxAge,
23
+ from,
24
+ req,
25
+ to,
26
+ token
27
+ }),
28
+ deleteFile: deleteStoredFile,
12
29
  uploadInstructions: {
13
30
  adminHandler: {
14
31
  path: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler'
@@ -21,7 +38,40 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
21
38
  }) : !req.user)) {
22
39
  throw new Forbidden(req.t);
23
40
  }
24
- const resolved = await resolveSignedURLKey({
41
+ assertClientUploadAllowed({
42
+ collection,
43
+ filename,
44
+ mimeType
45
+ });
46
+ const requested = buildUploadStoragePathData({
47
+ collectionPrefix: prefix,
48
+ docPrefix,
49
+ filename,
50
+ useCompositePrefixes
51
+ });
52
+ const allowOverwrite = collection.versions ? false : await authorizeClientOverwrite({
53
+ collectionPrefix: prefix,
54
+ collectionSources,
55
+ overrideAccess,
56
+ req,
57
+ requestedCollectionSlug: collectionSlug,
58
+ requestedFilename: requested.sanitizedFilename,
59
+ requestedStorageFilePath: requested.storageFilePath
60
+ });
61
+ const resolved = allowOverwrite ? {
62
+ ...requested,
63
+ uploadReference: {
64
+ prefix: requested.sanitizedDocPrefix,
65
+ signedReceipt: createClientUploadReceipt({
66
+ allowOverwrite: true,
67
+ collectionSlug,
68
+ filename: requested.sanitizedFilename,
69
+ filePrefix: requested.sanitizedDocPrefix,
70
+ req,
71
+ storageFilePath: requested.storageFilePath
72
+ })
73
+ }
74
+ } : await resolveSignedURLKey({
25
75
  collectionPrefix: prefix,
26
76
  collectionSlug,
27
77
  docPrefix,
@@ -33,16 +83,18 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
33
83
  name: 'uploadToVercelBlob',
34
84
  type: 'dispatch',
35
85
  data: {
36
- pathname: resolved.fileKey,
86
+ pathname: resolved.storageFilePath,
37
87
  token: await generateClientTokenFromReadWriteToken({
38
- addRandomSuffix,
88
+ addRandomSuffix: false,
39
89
  allowedContentTypes: mimeType ? [
40
90
  mimeType
41
91
  ] : undefined,
42
- allowOverwrite: true,
92
+ ...allowOverwrite && {
93
+ allowOverwrite: true
94
+ },
43
95
  cacheControlMaxAge,
44
96
  maximumSizeInBytes: filesize,
45
- pathname: resolved.fileKey,
97
+ pathname: resolved.storageFilePath,
46
98
  token
47
99
  })
48
100
  },
@@ -50,12 +102,11 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
50
102
  filename: resolved.sanitizedFilename,
51
103
  mimeType,
52
104
  size: filesize,
53
- uploadReference: {
54
- prefix: resolved.sanitizedDocPrefix
55
- }
105
+ uploadReference: resolved.uploadReference
56
106
  }
57
107
  };
58
108
  },
109
+ requiresUploadReceipt: true,
59
110
  useInAdmin: true
60
111
  },
61
112
  generateURL: ({ filename, prefix: urlPrefix = '' })=>generateURL({
@@ -65,40 +116,31 @@ export function createVercelBlobAdapter({ access, addRandomSuffix, baseUrl, cach
65
116
  prefix: urlPrefix,
66
117
  useCompositePrefixes
67
118
  }),
68
- handleDelete: ({ doc: { prefix: docPrefix = '' }, filename })=>deleteFile({
69
- baseUrl,
70
- collectionPrefix: prefix,
71
- docPrefix,
72
- filename,
73
- token,
74
- useCompositePrefixes
75
- }),
76
- handleUpload: async ({ data, file: { buffer, filename, mimeType } })=>{
119
+ handleDelete: deleteStoredFile,
120
+ handleUpload: async ({ data, file: { buffer, mimeType }, storageFilePath })=>{
77
121
  const result = await uploadFile({
78
122
  access,
79
123
  addRandomSuffix,
80
124
  buffer,
81
125
  cacheControlMaxAge,
82
- collectionPrefix: prefix,
83
- docPrefix: data.prefix,
84
- filename,
85
126
  mimeType,
86
- token,
87
- useCompositePrefixes
127
+ storageFilePath,
128
+ token
88
129
  });
89
130
  if (result.filename) {
90
131
  data.filename = result.filename;
91
132
  }
92
133
  return data;
93
134
  },
94
- staticHandler: (req, { headers, params: { filename, prefix: prefixQueryParam, uploadReference } })=>getFile({
135
+ staticHandler: (req, { doc, headers, params: { filename, operation, uploadReference } })=>getFile({
95
136
  baseUrl,
96
137
  cacheControlMaxAge,
97
138
  collection,
98
139
  collectionPrefix: prefix,
140
+ doc,
99
141
  filename,
100
142
  incomingHeaders: headers,
101
- prefixQueryParam,
143
+ operation,
102
144
  req,
103
145
  token,
104
146
  uploadReference,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import type {\n Adapter,\n ClientUploadsConfig,\n GeneratedAdapter,\n} from '@payloadcms/plugin-cloud-storage/types'\n\nimport { resolveSignedURLKey } from '@payloadcms/plugin-cloud-storage/utilities'\nimport { generateClientTokenFromReadWriteToken } from '@vercel/blob/client'\nimport { Forbidden } from 'payload'\n\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateVercelBlobAdapterArgs {\n access: 'public'\n addRandomSuffix?: boolean\n baseUrl: string\n cacheControlMaxAge: number\n clientUploads?: ClientUploadsConfig\n token: string\n useCompositePrefixes?: boolean\n}\n\nexport function createVercelBlobAdapter({\n access,\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n clientUploads,\n token,\n useCompositePrefixes = false,\n}: CreateVercelBlobAdapterArgs): Adapter {\n const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'vercel-blob',\n\n uploadInstructions: {\n adminHandler: {\n path: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n generate: async ({\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n overrideAccess,\n req,\n }) => {\n if (\n !overrideAccess &&\n (clientUploadsAccess ? !(await clientUploadsAccess({ collectionSlug, req })) : !req.user)\n ) {\n throw new Forbidden(req.t)\n }\n\n const resolved = await resolveSignedURLKey({\n collectionPrefix: prefix,\n collectionSlug,\n docPrefix,\n filename,\n req,\n useCompositePrefixes,\n })\n\n return {\n name: 'uploadToVercelBlob',\n type: 'dispatch',\n data: {\n pathname: resolved.fileKey,\n token: await generateClientTokenFromReadWriteToken({\n addRandomSuffix,\n allowedContentTypes: mimeType ? [mimeType] : undefined,\n allowOverwrite: true,\n cacheControlMaxAge,\n maximumSizeInBytes: filesize,\n pathname: resolved.fileKey,\n token,\n }),\n },\n file: {\n filename: resolved.sanitizedFilename,\n mimeType,\n size: filesize,\n uploadReference: { prefix: resolved.sanitizedDocPrefix },\n },\n }\n },\n useInAdmin: true,\n },\n\n generateURL: ({ filename, prefix: urlPrefix = '' }) =>\n generateURL({\n baseUrl,\n collectionPrefix: prefix,\n filename,\n prefix: urlPrefix,\n useCompositePrefixes,\n }),\n\n handleDelete: ({ doc: { prefix: docPrefix = '' }, filename }) =>\n deleteFile({\n baseUrl,\n collectionPrefix: prefix,\n docPrefix,\n filename,\n token,\n useCompositePrefixes,\n }),\n\n handleUpload: async ({ data, file: { buffer, filename, mimeType } }) => {\n const result = await uploadFile({\n access,\n addRandomSuffix,\n buffer,\n cacheControlMaxAge,\n collectionPrefix: prefix,\n docPrefix: data.prefix,\n filename,\n mimeType,\n token,\n useCompositePrefixes,\n })\n\n if (result.filename) {\n data.filename = result.filename\n }\n\n return data\n },\n\n staticHandler: (\n req,\n { headers, params: { filename, prefix: prefixQueryParam, uploadReference } },\n ) =>\n getFile({\n baseUrl,\n cacheControlMaxAge,\n collection,\n collectionPrefix: prefix,\n filename,\n incomingHeaders: headers,\n prefixQueryParam,\n req,\n token,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["resolveSignedURLKey","generateClientTokenFromReadWriteToken","Forbidden","deleteFile","generateURL","getFile","uploadFile","createVercelBlobAdapter","access","addRandomSuffix","baseUrl","cacheControlMaxAge","clientUploads","token","useCompositePrefixes","clientUploadsAccess","undefined","collection","prefix","name","uploadInstructions","adminHandler","path","enabled","Boolean","generate","collectionSlug","docPrefix","filename","filesize","mimeType","overrideAccess","req","user","t","resolved","collectionPrefix","type","data","pathname","fileKey","allowedContentTypes","allowOverwrite","maximumSizeInBytes","file","sanitizedFilename","size","uploadReference","sanitizedDocPrefix","useInAdmin","urlPrefix","handleDelete","doc","handleUpload","buffer","result","staticHandler","headers","params","prefixQueryParam","incomingHeaders"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import type {\n Adapter,\n ClientUploadsConfig,\n DeleteFile,\n GeneratedAdapter,\n} from '@payloadcms/plugin-cloud-storage/types'\n\nimport {\n buildUploadStoragePathData,\n resolveSignedURLKey,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { generateClientTokenFromReadWriteToken } from '@vercel/blob/client'\nimport { Forbidden } from 'payload'\nimport { assertClientUploadAllowed, createClientUploadReceipt } from 'payload/internal'\n\nimport type { VercelBlobCollectionSource } from './authorizeFileOverwrite.js'\n\nimport { authorizeClientOverwrite } from './authorizeFileOverwrite.js'\nimport { copyVercelBlobFile } from './copyFile.js'\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateVercelBlobAdapterArgs {\n access: 'public'\n addRandomSuffix?: boolean\n baseUrl: string\n cacheControlMaxAge: number\n clientUploads?: ClientUploadsConfig\n collectionSources: VercelBlobCollectionSource[]\n token: string\n useCompositePrefixes?: boolean\n}\n\nexport function createVercelBlobAdapter({\n access,\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n clientUploads,\n collectionSources,\n token,\n useCompositePrefixes = false,\n}: CreateVercelBlobAdapterArgs): Adapter {\n const clientUploadsAccess = typeof clientUploads === 'object' ? clientUploads.access : undefined\n const deleteStoredFile: DeleteFile = ({ storageFilePath }) =>\n deleteFile({ baseUrl, storageFilePath, token })\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'vercel-blob',\n\n copyFile: ({ from, req, to }) =>\n copyVercelBlobFile({ access, cacheControlMaxAge, from, req, to, token }),\n deleteFile: deleteStoredFile,\n\n uploadInstructions: {\n adminHandler: {\n path: '@payloadcms/storage-vercel-blob/client#VercelBlobClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n generate: async ({\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n overrideAccess,\n req,\n }) => {\n if (\n !overrideAccess &&\n (clientUploadsAccess ? !(await clientUploadsAccess({ collectionSlug, req })) : !req.user)\n ) {\n throw new Forbidden(req.t)\n }\n\n assertClientUploadAllowed({ collection, filename, mimeType })\n\n const requested = buildUploadStoragePathData({\n collectionPrefix: prefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n const allowOverwrite = collection.versions\n ? false\n : await authorizeClientOverwrite({\n collectionPrefix: prefix,\n collectionSources,\n overrideAccess,\n req,\n requestedCollectionSlug: collectionSlug,\n requestedFilename: requested.sanitizedFilename,\n requestedStorageFilePath: requested.storageFilePath,\n })\n const resolved = allowOverwrite\n ? {\n ...requested,\n uploadReference: {\n prefix: requested.sanitizedDocPrefix,\n signedReceipt: createClientUploadReceipt({\n allowOverwrite: true,\n collectionSlug,\n filename: requested.sanitizedFilename,\n filePrefix: requested.sanitizedDocPrefix,\n req,\n storageFilePath: requested.storageFilePath,\n }),\n },\n }\n : await resolveSignedURLKey({\n collectionPrefix: prefix,\n collectionSlug,\n docPrefix,\n filename,\n req,\n useCompositePrefixes,\n })\n\n return {\n name: 'uploadToVercelBlob',\n type: 'dispatch',\n data: {\n pathname: resolved.storageFilePath,\n token: await generateClientTokenFromReadWriteToken({\n addRandomSuffix: false,\n allowedContentTypes: mimeType ? [mimeType] : undefined,\n ...(allowOverwrite && { allowOverwrite: true }),\n cacheControlMaxAge,\n maximumSizeInBytes: filesize,\n pathname: resolved.storageFilePath,\n token,\n }),\n },\n file: {\n filename: resolved.sanitizedFilename,\n mimeType,\n size: filesize,\n uploadReference: resolved.uploadReference,\n },\n }\n },\n requiresUploadReceipt: true,\n useInAdmin: true,\n },\n\n generateURL: ({ filename, prefix: urlPrefix = '' }) =>\n generateURL({\n baseUrl,\n collectionPrefix: prefix,\n filename,\n prefix: urlPrefix,\n useCompositePrefixes,\n }),\n\n handleDelete: deleteStoredFile,\n\n handleUpload: async ({ data, file: { buffer, mimeType }, storageFilePath }) => {\n const result = await uploadFile({\n access,\n addRandomSuffix,\n buffer,\n cacheControlMaxAge,\n mimeType,\n storageFilePath,\n token,\n })\n\n if (result.filename) {\n data.filename = result.filename\n }\n\n return data\n },\n\n staticHandler: (req, { doc, headers, params: { filename, operation, uploadReference } }) =>\n getFile({\n baseUrl,\n cacheControlMaxAge,\n collection,\n collectionPrefix: prefix,\n doc,\n filename,\n incomingHeaders: headers,\n operation,\n req,\n token,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["buildUploadStoragePathData","resolveSignedURLKey","generateClientTokenFromReadWriteToken","Forbidden","assertClientUploadAllowed","createClientUploadReceipt","authorizeClientOverwrite","copyVercelBlobFile","deleteFile","generateURL","getFile","uploadFile","createVercelBlobAdapter","access","addRandomSuffix","baseUrl","cacheControlMaxAge","clientUploads","collectionSources","token","useCompositePrefixes","clientUploadsAccess","undefined","deleteStoredFile","storageFilePath","collection","prefix","name","copyFile","from","req","to","uploadInstructions","adminHandler","path","enabled","Boolean","generate","collectionSlug","docPrefix","filename","filesize","mimeType","overrideAccess","user","t","requested","collectionPrefix","allowOverwrite","versions","requestedCollectionSlug","requestedFilename","sanitizedFilename","requestedStorageFilePath","resolved","uploadReference","sanitizedDocPrefix","signedReceipt","filePrefix","type","data","pathname","allowedContentTypes","maximumSizeInBytes","file","size","requiresUploadReceipt","useInAdmin","urlPrefix","handleDelete","handleUpload","buffer","result","staticHandler","doc","headers","params","operation","incomingHeaders"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ export type VercelBlobCollectionSource = {
3
+ collectionPrefix: string;
4
+ collectionSlug: string;
5
+ useCompositePrefixes: boolean;
6
+ };
7
+ export declare function authorizeClientOverwrite({ collectionPrefix: collectionPrefixArg, collectionSources, overrideAccess, req, requestedCollectionSlug, requestedFilename, requestedStorageFilePath, }: {
8
+ collectionPrefix: string;
9
+ collectionSources: VercelBlobCollectionSource[];
10
+ overrideAccess?: boolean;
11
+ req: PayloadRequest;
12
+ requestedCollectionSlug: string;
13
+ requestedFilename: string;
14
+ requestedStorageFilePath: string;
15
+ }): Promise<boolean>;
16
+ //# sourceMappingURL=authorizeFileOverwrite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorizeFileOverwrite.d.ts","sourceRoot":"","sources":["../src/authorizeFileOverwrite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,cAAc,EAAqB,MAAM,SAAS,CAAA;AAU1E,MAAM,MAAM,0BAA0B,GAAG;IACvC,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,oBAAoB,EAAE,OAAO,CAAA;CAC9B,CAAA;AAmHD,wBAAsB,wBAAwB,CAAC,EAC7C,gBAAgB,EAAE,mBAAmB,EACrC,iBAAiB,EACjB,cAAsB,EACtB,GAAG,EACH,uBAAuB,EACvB,iBAAiB,EACjB,wBAAwB,GACzB,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,iBAAiB,EAAE,0BAA0B,EAAE,CAAA;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;IACnB,uBAAuB,EAAE,MAAM,CAAA;IAC/B,iBAAiB,EAAE,MAAM,CAAA;IACzB,wBAAwB,EAAE,MAAM,CAAA;CACjC,GAAG,OAAO,CAAC,OAAO,CAAC,CA8CnB"}
@@ -0,0 +1,117 @@
1
+ import { buildStoragePathData, isStoragePathWithinCollectionPrefix } from '@payloadcms/plugin-cloud-storage/utilities';
2
+ import { combineQueries, executeAccess, Forbidden } from 'payload';
3
+ function getDocumentFileKeys({ collectionPrefix, doc, useCompositePrefixes }) {
4
+ return [
5
+ doc.filename,
6
+ ...Object.values(doc.variants || {}).map((size)=>size?.filename)
7
+ ].filter((filename)=>typeof filename === 'string').map((filename)=>buildStoragePathData({
8
+ collectionPrefix,
9
+ docPrefix: doc.prefix,
10
+ filename,
11
+ useCompositePrefixes
12
+ }).storageFilePath);
13
+ }
14
+ async function findMatchingDocs({ collectionPrefix, collectionSlug, req, requestedFilename, requestedStorageFilePath, useCompositePrefixes }) {
15
+ const collection = req.payload.collections[collectionSlug];
16
+ if (!collection) {
17
+ return [];
18
+ }
19
+ const variants = collection.config.upload && typeof collection.config.upload === 'object' ? collection.config.upload.variants || [] : [];
20
+ const filenameQueries = [
21
+ {
22
+ filename: {
23
+ equals: requestedFilename
24
+ }
25
+ },
26
+ ...variants.map(({ name })=>({
27
+ [`variants.${name}.filename`]: {
28
+ equals: requestedFilename
29
+ }
30
+ }))
31
+ ];
32
+ const result = await req.payload.find({
33
+ collection: collectionSlug,
34
+ depth: 0,
35
+ draft: true,
36
+ overrideAccess: true,
37
+ pagination: false,
38
+ req,
39
+ where: {
40
+ or: filenameQueries
41
+ }
42
+ });
43
+ return result.docs.filter((doc)=>getDocumentFileKeys({
44
+ collectionPrefix,
45
+ doc,
46
+ useCompositePrefixes
47
+ }).includes(requestedStorageFilePath));
48
+ }
49
+ async function canUpdateDoc({ collectionSlug, doc, req }) {
50
+ const collection = req.payload.collections[collectionSlug];
51
+ if (!collection) {
52
+ return false;
53
+ }
54
+ const accessResult = await executeAccess({
55
+ id: doc.id,
56
+ slug: collectionSlug,
57
+ disableErrors: true,
58
+ req
59
+ }, collection.config.access.update);
60
+ if (typeof accessResult === 'boolean') {
61
+ return accessResult;
62
+ }
63
+ const result = await req.payload.find({
64
+ collection: collectionSlug,
65
+ depth: 0,
66
+ draft: true,
67
+ limit: 1,
68
+ overrideAccess: true,
69
+ pagination: false,
70
+ req,
71
+ where: combineQueries({
72
+ id: {
73
+ equals: doc.id
74
+ }
75
+ }, accessResult)
76
+ });
77
+ return result.docs.length === 1;
78
+ }
79
+ export async function authorizeClientOverwrite({ collectionPrefix: collectionPrefixArg, collectionSources, overrideAccess = false, req, requestedCollectionSlug, requestedFilename, requestedStorageFilePath }) {
80
+ if (!isStoragePathWithinCollectionPrefix({
81
+ collectionPrefix: collectionPrefixArg,
82
+ docPrefix: requestedStorageFilePath
83
+ })) {
84
+ throw new Forbidden(req.t);
85
+ }
86
+ const matchedDocs = (await Promise.all(collectionSources.map(async ({ collectionPrefix, collectionSlug, useCompositePrefixes })=>{
87
+ const docs = await findMatchingDocs({
88
+ collectionPrefix,
89
+ collectionSlug,
90
+ req,
91
+ requestedFilename,
92
+ requestedStorageFilePath,
93
+ useCompositePrefixes
94
+ });
95
+ return docs.map((doc)=>({
96
+ collectionSlug,
97
+ doc
98
+ }));
99
+ }))).flat();
100
+ if (matchedDocs.length === 0) {
101
+ return false;
102
+ }
103
+ const matchedDoc = matchedDocs[0];
104
+ if (matchedDocs.length !== 1 || matchedDoc.collectionSlug !== requestedCollectionSlug) {
105
+ throw new Forbidden(req.t);
106
+ }
107
+ if (!overrideAccess && !await canUpdateDoc({
108
+ collectionSlug: matchedDoc.collectionSlug,
109
+ doc: matchedDoc.doc,
110
+ req
111
+ })) {
112
+ throw new Forbidden(req.t);
113
+ }
114
+ return true;
115
+ }
116
+
117
+ //# sourceMappingURL=authorizeFileOverwrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/authorizeFileOverwrite.ts"],"sourcesContent":["import type { FileData, PayloadRequest, TypeWithID, Where } from 'payload'\n\nimport {\n buildStoragePathData,\n isStoragePathWithinCollectionPrefix,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { combineQueries, executeAccess, Forbidden } from 'payload'\n\ntype OwnerDocument = { prefix?: string } & FileData & TypeWithID\n\nexport type VercelBlobCollectionSource = {\n collectionPrefix: string\n collectionSlug: string\n useCompositePrefixes: boolean\n}\n\ntype Owner = {\n collectionSlug: string\n doc: OwnerDocument\n}\n\nfunction getDocumentFileKeys({\n collectionPrefix,\n doc,\n useCompositePrefixes,\n}: {\n collectionPrefix: string\n doc: OwnerDocument\n useCompositePrefixes: boolean\n}): string[] {\n return [doc.filename, ...Object.values(doc.variants || {}).map((size) => size?.filename)]\n .filter((filename): filename is string => typeof filename === 'string')\n .map(\n (filename) =>\n buildStoragePathData({\n collectionPrefix,\n docPrefix: doc.prefix,\n filename,\n useCompositePrefixes,\n }).storageFilePath,\n )\n}\n\nasync function findMatchingDocs({\n collectionPrefix,\n collectionSlug,\n req,\n requestedFilename,\n requestedStorageFilePath,\n useCompositePrefixes,\n}: {\n collectionPrefix: string\n collectionSlug: string\n req: PayloadRequest\n requestedFilename: string\n requestedStorageFilePath: string\n useCompositePrefixes: boolean\n}): Promise<OwnerDocument[]> {\n const collection = req.payload.collections[collectionSlug]\n\n if (!collection) {\n return []\n }\n\n const variants =\n collection.config.upload && typeof collection.config.upload === 'object'\n ? collection.config.upload.variants || []\n : []\n const filenameQueries: Where[] = [\n { filename: { equals: requestedFilename } },\n ...variants.map(({ name }) => ({\n [`variants.${name}.filename`]: { equals: requestedFilename },\n })),\n ]\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 0,\n draft: true,\n overrideAccess: true,\n pagination: false,\n req,\n where: { or: filenameQueries },\n })\n\n return (result.docs as OwnerDocument[]).filter((doc) =>\n getDocumentFileKeys({ collectionPrefix, doc, useCompositePrefixes }).includes(\n requestedStorageFilePath,\n ),\n )\n}\n\nasync function canUpdateDoc({\n collectionSlug,\n doc,\n req,\n}: {\n collectionSlug: string\n doc: OwnerDocument\n req: PayloadRequest\n}): Promise<boolean> {\n const collection = req.payload.collections[collectionSlug]\n\n if (!collection) {\n return false\n }\n\n const accessResult = await executeAccess(\n { id: doc.id, slug: collectionSlug, disableErrors: true, req },\n collection.config.access.update,\n )\n\n if (typeof accessResult === 'boolean') {\n return accessResult\n }\n\n const result = await req.payload.find({\n collection: collectionSlug,\n depth: 0,\n draft: true,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where: combineQueries({ id: { equals: doc.id } }, accessResult),\n })\n\n return result.docs.length === 1\n}\n\nexport async function authorizeClientOverwrite({\n collectionPrefix: collectionPrefixArg,\n collectionSources,\n overrideAccess = false,\n req,\n requestedCollectionSlug,\n requestedFilename,\n requestedStorageFilePath,\n}: {\n collectionPrefix: string\n collectionSources: VercelBlobCollectionSource[]\n overrideAccess?: boolean\n req: PayloadRequest\n requestedCollectionSlug: string\n requestedFilename: string\n requestedStorageFilePath: string\n}): Promise<boolean> {\n if (\n !isStoragePathWithinCollectionPrefix({\n collectionPrefix: collectionPrefixArg,\n docPrefix: requestedStorageFilePath,\n })\n ) {\n throw new Forbidden(req.t)\n }\n\n const matchedDocs = (\n await Promise.all(\n collectionSources.map(\n async ({ collectionPrefix, collectionSlug, useCompositePrefixes }): Promise<Owner[]> => {\n const docs = await findMatchingDocs({\n collectionPrefix,\n collectionSlug,\n req,\n requestedFilename,\n requestedStorageFilePath,\n useCompositePrefixes,\n })\n\n return docs.map((doc) => ({ collectionSlug, doc }))\n },\n ),\n )\n ).flat()\n\n if (matchedDocs.length === 0) {\n return false\n }\n\n const matchedDoc = matchedDocs[0]!\n if (matchedDocs.length !== 1 || matchedDoc.collectionSlug !== requestedCollectionSlug) {\n throw new Forbidden(req.t)\n }\n\n if (\n !overrideAccess &&\n !(await canUpdateDoc({ collectionSlug: matchedDoc.collectionSlug, doc: matchedDoc.doc, req }))\n ) {\n throw new Forbidden(req.t)\n }\n\n return true\n}\n"],"names":["buildStoragePathData","isStoragePathWithinCollectionPrefix","combineQueries","executeAccess","Forbidden","getDocumentFileKeys","collectionPrefix","doc","useCompositePrefixes","filename","Object","values","variants","map","size","filter","docPrefix","prefix","storageFilePath","findMatchingDocs","collectionSlug","req","requestedFilename","requestedStorageFilePath","collection","payload","collections","config","upload","filenameQueries","equals","name","result","find","depth","draft","overrideAccess","pagination","where","or","docs","includes","canUpdateDoc","accessResult","id","slug","disableErrors","access","update","limit","length","authorizeClientOverwrite","collectionPrefixArg","collectionSources","requestedCollectionSlug","t","matchedDocs","Promise","all","flat","matchedDoc"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"VercelBlobClientUploadHandler.d.ts","sourceRoot":"","sources":["../../src/client/VercelBlobClientUploadHandler.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,6BAA6B;;;;;;iCAgBxC,CAAA"}
1
+ {"version":3,"file":"VercelBlobClientUploadHandler.d.ts","sourceRoot":"","sources":["../../src/client/VercelBlobClientUploadHandler.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,6BAA6B;;;;;;iCAexC,CAAA"}
@@ -1,23 +1,17 @@
1
1
  'use client';
2
2
  import { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client';
3
3
  import { put } from '@vercel/blob/client';
4
- /** Last path segment only (POSIX), for keys like `folder/sub/file.png`. */ function posixBasename(key) {
5
- const normalized = key.replace(/^\/+/, '');
6
- const lastSlash = normalized.lastIndexOf('/');
7
- return lastSlash === -1 ? normalized : normalized.slice(lastSlash + 1);
8
- }
9
4
  export const VercelBlobClientUploadHandler = createClientUploadHandler({
10
5
  name: 'uploadToVercelBlob',
11
- handler: async ({ data, file, updateFilename })=>{
6
+ handler: async ({ data, file })=>{
12
7
  const { pathname, token } = data;
13
8
  const result = await put(pathname, file, {
14
9
  access: 'public',
15
10
  contentType: file.type,
16
11
  token
17
12
  });
18
- const filename = decodeURIComponent(posixBasename(result.pathname.replace(/^\/+/, '')));
19
- if (filename !== file.name) {
20
- updateFilename(filename);
13
+ if (decodeURIComponent(result.pathname) !== decodeURIComponent(pathname)) {
14
+ throw new Error('The uploaded file was stored at an unexpected location');
21
15
  }
22
16
  }
23
17
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/VercelBlobClientUploadHandler.ts"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\nimport { put } from '@vercel/blob/client'\n\n/** Last path segment only (POSIX), for keys like `folder/sub/file.png`. */\nfunction posixBasename(key: string): string {\n const normalized = key.replace(/^\\/+/, '')\n const lastSlash = normalized.lastIndexOf('/')\n return lastSlash === -1 ? normalized : normalized.slice(lastSlash + 1)\n}\n\nexport const VercelBlobClientUploadHandler = createClientUploadHandler({\n name: 'uploadToVercelBlob',\n handler: async ({ data, file, updateFilename }) => {\n const { pathname, token } = data as { pathname: string; token: string }\n\n const result = await put(pathname, file, {\n access: 'public',\n contentType: file.type,\n token,\n })\n\n const filename = decodeURIComponent(posixBasename(result.pathname.replace(/^\\/+/, '')))\n if (filename !== file.name) {\n updateFilename(filename)\n }\n },\n})\n"],"names":["createClientUploadHandler","put","posixBasename","key","normalized","replace","lastSlash","lastIndexOf","slice","VercelBlobClientUploadHandler","name","handler","data","file","updateFilename","pathname","token","result","access","contentType","type","filename","decodeURIComponent"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AACnF,SAASC,GAAG,QAAQ,sBAAqB;AAEzC,yEAAyE,GACzE,SAASC,cAAcC,GAAW;IAChC,MAAMC,aAAaD,IAAIE,OAAO,CAAC,QAAQ;IACvC,MAAMC,YAAYF,WAAWG,WAAW,CAAC;IACzC,OAAOD,cAAc,CAAC,IAAIF,aAAaA,WAAWI,KAAK,CAACF,YAAY;AACtE;AAEA,OAAO,MAAMG,gCAAgCT,0BAA0B;IACrEU,MAAM;IACNC,SAAS,OAAO,EAAEC,IAAI,EAAEC,IAAI,EAAEC,cAAc,EAAE;QAC5C,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAE,GAAGJ;QAE5B,MAAMK,SAAS,MAAMhB,IAAIc,UAAUF,MAAM;YACvCK,QAAQ;YACRC,aAAaN,KAAKO,IAAI;YACtBJ;QACF;QAEA,MAAMK,WAAWC,mBAAmBpB,cAAce,OAAOF,QAAQ,CAACV,OAAO,CAAC,QAAQ;QAClF,IAAIgB,aAAaR,KAAKH,IAAI,EAAE;YAC1BI,eAAeO;QACjB;IACF;AACF,GAAE"}
1
+ {"version":3,"sources":["../../src/client/VercelBlobClientUploadHandler.ts"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\nimport { put } from '@vercel/blob/client'\n\nexport const VercelBlobClientUploadHandler = createClientUploadHandler({\n name: 'uploadToVercelBlob',\n handler: async ({ data, file }) => {\n const { pathname, token } = data as { pathname: string; token: string }\n\n const result = await put(pathname, file, {\n access: 'public',\n contentType: file.type,\n token,\n })\n\n if (decodeURIComponent(result.pathname) !== decodeURIComponent(pathname)) {\n throw new Error('The uploaded file was stored at an unexpected location')\n }\n },\n})\n"],"names":["createClientUploadHandler","put","VercelBlobClientUploadHandler","name","handler","data","file","pathname","token","result","access","contentType","type","decodeURIComponent","Error"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AACnF,SAASC,GAAG,QAAQ,sBAAqB;AAEzC,OAAO,MAAMC,gCAAgCF,0BAA0B;IACrEG,MAAM;IACNC,SAAS,OAAO,EAAEC,IAAI,EAAEC,IAAI,EAAE;QAC5B,MAAM,EAAEC,QAAQ,EAAEC,KAAK,EAAE,GAAGH;QAE5B,MAAMI,SAAS,MAAMR,IAAIM,UAAUD,MAAM;YACvCI,QAAQ;YACRC,aAAaL,KAAKM,IAAI;YACtBJ;QACF;QAEA,IAAIK,mBAAmBJ,OAAOF,QAAQ,MAAMM,mBAAmBN,WAAW;YACxE,MAAM,IAAIO,MAAM;QAClB;IACF;AACF,GAAE"}
@@ -0,0 +1,12 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ type Args = {
3
+ access: 'public';
4
+ cacheControlMaxAge: number;
5
+ from: string;
6
+ req?: PayloadRequest;
7
+ to: string;
8
+ token: string;
9
+ };
10
+ export declare const copyVercelBlobFile: ({ access, cacheControlMaxAge, from, req, to, token, }: Args) => Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=copyFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copyFile.d.ts","sourceRoot":"","sources":["../src/copyFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAI7C,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,QAAQ,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,kBAAkB,0DAO5B,IAAI,KAAG,OAAO,CAAC,IAAI,CA+ErB,CAAA"}
@@ -0,0 +1,86 @@
1
+ import { BlobNotFoundError, copy, del, head, put } from '@vercel/blob';
2
+ export const copyVercelBlobFile = async ({ access, cacheControlMaxAge, from, req, to, token })=>{
3
+ if (from === to) {
4
+ throw new Error('Storage copy requires different source and destination keys');
5
+ }
6
+ const source = await head(from, {
7
+ token
8
+ });
9
+ try {
10
+ await head(to, {
11
+ token
12
+ });
13
+ throw new Error(`Storage destination already exists: ${to}`);
14
+ } catch (err) {
15
+ if (!isBlobNotFound(err)) {
16
+ throw err;
17
+ }
18
+ }
19
+ const sourceMaxAge = /(?:^|,)\s*max-age=(\d+)/.exec(source.cacheControl);
20
+ let copied = await copy(from, to, {
21
+ access,
22
+ addRandomSuffix: false,
23
+ allowOverwrite: false,
24
+ cacheControlMaxAge: sourceMaxAge ? Number(sourceMaxAge[1]) : cacheControlMaxAge,
25
+ contentType: source.contentType,
26
+ token
27
+ });
28
+ try {
29
+ if (copied.pathname !== to) {
30
+ throw new Error(`Vercel Blob assigned an unexpected destination key: ${copied.pathname}`);
31
+ }
32
+ let destination = await head(to, {
33
+ token
34
+ });
35
+ if (destination.size !== source.size) {
36
+ await del(to, {
37
+ ifMatch: copied.etag,
38
+ token
39
+ });
40
+ // The first copy is gone; a rejected fallback must not delete another upload's object.
41
+ copied = undefined;
42
+ const sourceResponse = await fetch(source.url);
43
+ if (!sourceResponse.ok || !sourceResponse.body) {
44
+ throw new Error(`Vercel Blob source is not readable: ${from}`);
45
+ }
46
+ copied = await put(to, sourceResponse.body, {
47
+ access,
48
+ addRandomSuffix: false,
49
+ allowOverwrite: false,
50
+ cacheControlMaxAge: sourceMaxAge ? Number(sourceMaxAge[1]) : cacheControlMaxAge,
51
+ contentType: source.contentType,
52
+ token
53
+ });
54
+ if (copied.pathname !== to) {
55
+ throw new Error(`Vercel Blob assigned an unexpected destination key: ${copied.pathname}`);
56
+ }
57
+ destination = await head(to, {
58
+ token
59
+ });
60
+ if (destination.size !== source.size) {
61
+ throw new Error(`Copied Vercel Blob object is not readable at its expected length: ${to}`);
62
+ }
63
+ }
64
+ } catch (err) {
65
+ if (copied) {
66
+ try {
67
+ if (copied.pathname === from || !copied.etag) {
68
+ throw new Error('Vercel Blob copy did not return a safe destination for cleanup');
69
+ }
70
+ await del(copied.pathname, {
71
+ ifMatch: copied.etag,
72
+ token
73
+ });
74
+ } catch (cleanupError) {
75
+ req?.payload.logger.error({
76
+ err: cleanupError,
77
+ msg: `Failed to remove unsuccessful Vercel Blob copy at ${copied.pathname}`
78
+ });
79
+ }
80
+ }
81
+ throw err;
82
+ }
83
+ };
84
+ const isBlobNotFound = (err)=>err instanceof BlobNotFoundError || err !== null && typeof err === 'object' && 'name' in err && err.name === 'BlobNotFoundError';
85
+
86
+ //# sourceMappingURL=copyFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/copyFile.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport { BlobNotFoundError, copy, del, head, put } from '@vercel/blob'\n\ntype Args = {\n access: 'public'\n cacheControlMaxAge: number\n from: string\n req?: PayloadRequest\n to: string\n token: string\n}\n\nexport const copyVercelBlobFile = async ({\n access,\n cacheControlMaxAge,\n from,\n req,\n to,\n token,\n}: Args): Promise<void> => {\n if (from === to) {\n throw new Error('Storage copy requires different source and destination keys')\n }\n\n const source = await head(from, { token })\n\n try {\n await head(to, { token })\n throw new Error(`Storage destination already exists: ${to}`)\n } catch (err) {\n if (!isBlobNotFound(err)) {\n throw err\n }\n }\n\n const sourceMaxAge = /(?:^|,)\\s*max-age=(\\d+)/.exec(source.cacheControl)\n let copied: { etag: string; pathname: string } | undefined = await copy(from, to, {\n access,\n addRandomSuffix: false,\n allowOverwrite: false,\n cacheControlMaxAge: sourceMaxAge ? Number(sourceMaxAge[1]) : cacheControlMaxAge,\n contentType: source.contentType,\n token,\n })\n\n try {\n if (copied.pathname !== to) {\n throw new Error(`Vercel Blob assigned an unexpected destination key: ${copied.pathname}`)\n }\n\n let destination = await head(to, { token })\n\n if (destination.size !== source.size) {\n await del(to, { ifMatch: copied.etag, token })\n // The first copy is gone; a rejected fallback must not delete another upload's object.\n copied = undefined\n\n const sourceResponse = await fetch(source.url)\n\n if (!sourceResponse.ok || !sourceResponse.body) {\n throw new Error(`Vercel Blob source is not readable: ${from}`)\n }\n\n copied = await put(to, sourceResponse.body, {\n access,\n addRandomSuffix: false,\n allowOverwrite: false,\n cacheControlMaxAge: sourceMaxAge ? Number(sourceMaxAge[1]) : cacheControlMaxAge,\n contentType: source.contentType,\n token,\n })\n\n if (copied.pathname !== to) {\n throw new Error(`Vercel Blob assigned an unexpected destination key: ${copied.pathname}`)\n }\n\n destination = await head(to, { token })\n\n if (destination.size !== source.size) {\n throw new Error(`Copied Vercel Blob object is not readable at its expected length: ${to}`)\n }\n }\n } catch (err) {\n if (copied) {\n try {\n if (copied.pathname === from || !copied.etag) {\n throw new Error('Vercel Blob copy did not return a safe destination for cleanup')\n }\n await del(copied.pathname, { ifMatch: copied.etag, token })\n } catch (cleanupError) {\n req?.payload.logger.error({\n err: cleanupError,\n msg: `Failed to remove unsuccessful Vercel Blob copy at ${copied.pathname}`,\n })\n }\n }\n throw err\n }\n}\n\nconst isBlobNotFound = (err: unknown): boolean =>\n err instanceof BlobNotFoundError ||\n (err !== null && typeof err === 'object' && 'name' in err && err.name === 'BlobNotFoundError')\n"],"names":["BlobNotFoundError","copy","del","head","put","copyVercelBlobFile","access","cacheControlMaxAge","from","req","to","token","Error","source","err","isBlobNotFound","sourceMaxAge","exec","cacheControl","copied","addRandomSuffix","allowOverwrite","Number","contentType","pathname","destination","size","ifMatch","etag","undefined","sourceResponse","fetch","url","ok","body","cleanupError","payload","logger","error","msg","name"],"mappings":"AAEA,SAASA,iBAAiB,EAAEC,IAAI,EAAEC,GAAG,EAAEC,IAAI,EAAEC,GAAG,QAAQ,eAAc;AAWtE,OAAO,MAAMC,qBAAqB,OAAO,EACvCC,MAAM,EACNC,kBAAkB,EAClBC,IAAI,EACJC,GAAG,EACHC,EAAE,EACFC,KAAK,EACA;IACL,IAAIH,SAASE,IAAI;QACf,MAAM,IAAIE,MAAM;IAClB;IAEA,MAAMC,SAAS,MAAMV,KAAKK,MAAM;QAAEG;IAAM;IAExC,IAAI;QACF,MAAMR,KAAKO,IAAI;YAAEC;QAAM;QACvB,MAAM,IAAIC,MAAM,CAAC,oCAAoC,EAAEF,IAAI;IAC7D,EAAE,OAAOI,KAAK;QACZ,IAAI,CAACC,eAAeD,MAAM;YACxB,MAAMA;QACR;IACF;IAEA,MAAME,eAAe,0BAA0BC,IAAI,CAACJ,OAAOK,YAAY;IACvE,IAAIC,SAAyD,MAAMlB,KAAKO,MAAME,IAAI;QAChFJ;QACAc,iBAAiB;QACjBC,gBAAgB;QAChBd,oBAAoBS,eAAeM,OAAON,YAAY,CAAC,EAAE,IAAIT;QAC7DgB,aAAaV,OAAOU,WAAW;QAC/BZ;IACF;IAEA,IAAI;QACF,IAAIQ,OAAOK,QAAQ,KAAKd,IAAI;YAC1B,MAAM,IAAIE,MAAM,CAAC,oDAAoD,EAAEO,OAAOK,QAAQ,EAAE;QAC1F;QAEA,IAAIC,cAAc,MAAMtB,KAAKO,IAAI;YAAEC;QAAM;QAEzC,IAAIc,YAAYC,IAAI,KAAKb,OAAOa,IAAI,EAAE;YACpC,MAAMxB,IAAIQ,IAAI;gBAAEiB,SAASR,OAAOS,IAAI;gBAAEjB;YAAM;YAC5C,uFAAuF;YACvFQ,SAASU;YAET,MAAMC,iBAAiB,MAAMC,MAAMlB,OAAOmB,GAAG;YAE7C,IAAI,CAACF,eAAeG,EAAE,IAAI,CAACH,eAAeI,IAAI,EAAE;gBAC9C,MAAM,IAAItB,MAAM,CAAC,oCAAoC,EAAEJ,MAAM;YAC/D;YAEAW,SAAS,MAAMf,IAAIM,IAAIoB,eAAeI,IAAI,EAAE;gBAC1C5B;gBACAc,iBAAiB;gBACjBC,gBAAgB;gBAChBd,oBAAoBS,eAAeM,OAAON,YAAY,CAAC,EAAE,IAAIT;gBAC7DgB,aAAaV,OAAOU,WAAW;gBAC/BZ;YACF;YAEA,IAAIQ,OAAOK,QAAQ,KAAKd,IAAI;gBAC1B,MAAM,IAAIE,MAAM,CAAC,oDAAoD,EAAEO,OAAOK,QAAQ,EAAE;YAC1F;YAEAC,cAAc,MAAMtB,KAAKO,IAAI;gBAAEC;YAAM;YAErC,IAAIc,YAAYC,IAAI,KAAKb,OAAOa,IAAI,EAAE;gBACpC,MAAM,IAAId,MAAM,CAAC,kEAAkE,EAAEF,IAAI;YAC3F;QACF;IACF,EAAE,OAAOI,KAAK;QACZ,IAAIK,QAAQ;YACV,IAAI;gBACF,IAAIA,OAAOK,QAAQ,KAAKhB,QAAQ,CAACW,OAAOS,IAAI,EAAE;oBAC5C,MAAM,IAAIhB,MAAM;gBAClB;gBACA,MAAMV,IAAIiB,OAAOK,QAAQ,EAAE;oBAAEG,SAASR,OAAOS,IAAI;oBAAEjB;gBAAM;YAC3D,EAAE,OAAOwB,cAAc;gBACrB1B,KAAK2B,QAAQC,OAAOC,MAAM;oBACxBxB,KAAKqB;oBACLI,KAAK,CAAC,kDAAkD,EAAEpB,OAAOK,QAAQ,EAAE;gBAC7E;YACF;QACF;QACA,MAAMV;IACR;AACF,EAAC;AAED,MAAMC,iBAAiB,CAACD,MACtBA,eAAed,qBACdc,QAAQ,QAAQ,OAAOA,QAAQ,YAAY,UAAUA,OAAOA,IAAI0B,IAAI,KAAK"}
@@ -1,11 +1,8 @@
1
1
  interface DeleteFileArgs {
2
2
  baseUrl: string;
3
- collectionPrefix?: string;
4
- docPrefix: string;
5
- filename: string;
3
+ storageFilePath: string;
6
4
  token: string;
7
- useCompositePrefixes?: boolean;
8
5
  }
9
- export declare function deleteFile({ baseUrl, collectionPrefix, docPrefix, filename, token, useCompositePrefixes, }: DeleteFileArgs): Promise<void>;
6
+ export declare function deleteFile({ baseUrl, storageFilePath, token, }: DeleteFileArgs): Promise<void>;
10
7
  export {};
11
8
  //# sourceMappingURL=deleteFile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAsB,UAAU,CAAC,EAC/B,OAAO,EACP,gBAAqB,EACrB,SAAS,EACT,QAAQ,EACR,KAAK,EACL,oBAA4B,GAC7B,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhC"}
1
+ {"version":3,"file":"deleteFile.d.ts","sourceRoot":"","sources":["../src/deleteFile.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAsB,UAAU,CAAC,EAC/B,OAAO,EACP,eAAe,EACf,KAAK,GACN,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhC"}
@@ -1,14 +1,7 @@
1
1
  import { del } from '@vercel/blob';
2
- import { generateURL } from './generateURL.js';
3
- export async function deleteFile({ baseUrl, collectionPrefix = '', docPrefix, filename, token, useCompositePrefixes = false }) {
4
- const fileUrl = generateURL({
5
- baseUrl,
6
- collectionPrefix,
7
- filename,
8
- prefix: docPrefix,
9
- useCompositePrefixes
10
- });
11
- await del(fileUrl, {
2
+ import { buildBlobUrl } from './generateURL.js';
3
+ export async function deleteFile({ baseUrl, storageFilePath, token }) {
4
+ await del(buildBlobUrl(baseUrl, storageFilePath), {
12
5
  token
13
6
  });
14
7
  }