@payloadcms/storage-vercel-blob 3.83.0 → 3.84.0-canary.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/storage-vercel-blob",
3
- "version": "3.83.0",
3
+ "version": "3.84.0-canary.0",
4
4
  "description": "Payload storage adapter for Vercel Blob Storage",
5
5
  "homepage": "https://payloadcms.com",
6
6
  "repository": {
@@ -38,13 +38,13 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@vercel/blob": "2.3.1",
41
- "@payloadcms/plugin-cloud-storage": "3.83.0"
41
+ "@payloadcms/plugin-cloud-storage": "3.84.0-canary.0"
42
42
  },
43
43
  "devDependencies": {
44
- "payload": "3.83.0"
44
+ "payload": "3.84.0-canary.0"
45
45
  },
46
46
  "peerDependencies": {
47
- "payload": "3.83.0"
47
+ "payload": "3.84.0-canary.0"
48
48
  },
49
49
  "engines": {
50
50
  "node": "^18.20.2 || >=20.9.0"
@@ -1,9 +0,0 @@
1
- import type { HandleDelete } from '@payloadcms/plugin-cloud-storage/types';
2
- type HandleDeleteArgs = {
3
- baseUrl: string;
4
- prefix?: string;
5
- token: string;
6
- };
7
- export declare const getHandleDelete: ({ baseUrl, token }: HandleDeleteArgs) => HandleDelete;
8
- export {};
9
- //# sourceMappingURL=handleDelete.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handleDelete.d.ts","sourceRoot":"","sources":["../src/handleDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAK1E,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,eAAe,uBAAwB,gBAAgB,KAAG,YAOtE,CAAA"}
@@ -1,13 +0,0 @@
1
- import { del } from '@vercel/blob';
2
- import path from 'path';
3
- export const getHandleDelete = ({ baseUrl, token })=>{
4
- return async ({ doc: { prefix = '' }, filename })=>{
5
- const fileUrl = `${baseUrl}/${path.posix.join(prefix, filename)}`;
6
- const deletedBlob = await del(fileUrl, {
7
- token
8
- });
9
- return deletedBlob;
10
- };
11
- };
12
-
13
- //# sourceMappingURL=handleDelete.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/handleDelete.ts"],"sourcesContent":["import type { HandleDelete } from '@payloadcms/plugin-cloud-storage/types'\n\nimport { del } from '@vercel/blob'\nimport path from 'path'\n\ntype HandleDeleteArgs = {\n baseUrl: string\n prefix?: string\n token: string\n}\n\nexport const getHandleDelete = ({ baseUrl, token }: HandleDeleteArgs): HandleDelete => {\n return async ({ doc: { prefix = '' }, filename }) => {\n const fileUrl = `${baseUrl}/${path.posix.join(prefix, filename)}`\n const deletedBlob = await del(fileUrl, { token })\n\n return deletedBlob\n }\n}\n"],"names":["del","path","getHandleDelete","baseUrl","token","doc","prefix","filename","fileUrl","posix","join","deletedBlob"],"mappings":"AAEA,SAASA,GAAG,QAAQ,eAAc;AAClC,OAAOC,UAAU,OAAM;AAQvB,OAAO,MAAMC,kBAAkB,CAAC,EAAEC,OAAO,EAAEC,KAAK,EAAoB;IAClE,OAAO,OAAO,EAAEC,KAAK,EAAEC,SAAS,EAAE,EAAE,EAAEC,QAAQ,EAAE;QAC9C,MAAMC,UAAU,GAAGL,QAAQ,CAAC,EAAEF,KAAKQ,KAAK,CAACC,IAAI,CAACJ,QAAQC,WAAW;QACjE,MAAMI,cAAc,MAAMX,IAAIQ,SAAS;YAAEJ;QAAM;QAE/C,OAAOO;IACT;AACF,EAAC"}
@@ -1,9 +0,0 @@
1
- import type { HandleUpload } from '@payloadcms/plugin-cloud-storage/types';
2
- import type { VercelBlobStorageOptions } from './index.js';
3
- type HandleUploadArgs = {
4
- baseUrl: string;
5
- prefix?: string;
6
- } & Omit<VercelBlobStorageOptions, 'collections'>;
7
- export declare const getHandleUpload: ({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, prefix, token, }: HandleUploadArgs) => HandleUpload;
8
- export {};
9
- //# sourceMappingURL=handleUpload.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"handleUpload.d.ts","sourceRoot":"","sources":["../src/handleUpload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAK1E,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAE1D,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,IAAI,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAA;AAEjD,eAAO,MAAM,eAAe,6EAOzB,gBAAgB,KAAG,YAmBrB,CAAA"}
@@ -1,21 +0,0 @@
1
- import { put } from '@vercel/blob';
2
- import path from 'path';
3
- export const getHandleUpload = ({ access = 'public', addRandomSuffix, baseUrl, cacheControlMaxAge, prefix = '', token })=>{
4
- return async ({ data, file: { buffer, filename, mimeType } })=>{
5
- const fileKey = path.posix.join(data.prefix || prefix, filename);
6
- const result = await put(fileKey, buffer, {
7
- access,
8
- addRandomSuffix,
9
- cacheControlMaxAge,
10
- contentType: mimeType,
11
- token
12
- });
13
- // Get filename with suffix from returned url
14
- if (addRandomSuffix) {
15
- data.filename = decodeURIComponent(result.url.replace(`${baseUrl}/`, ''));
16
- }
17
- return data;
18
- };
19
- };
20
-
21
- //# sourceMappingURL=handleUpload.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/handleUpload.ts"],"sourcesContent":["import type { HandleUpload } from '@payloadcms/plugin-cloud-storage/types'\n\nimport { put } from '@vercel/blob'\nimport path from 'path'\n\nimport type { VercelBlobStorageOptions } from './index.js'\n\ntype HandleUploadArgs = {\n baseUrl: string\n prefix?: string\n} & Omit<VercelBlobStorageOptions, 'collections'>\n\nexport const getHandleUpload = ({\n access = 'public',\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n prefix = '',\n token,\n}: HandleUploadArgs): HandleUpload => {\n return async ({ data, file: { buffer, filename, mimeType } }) => {\n const fileKey = path.posix.join(data.prefix || prefix, filename)\n\n const result = await put(fileKey, buffer, {\n access,\n addRandomSuffix,\n cacheControlMaxAge,\n contentType: mimeType,\n token,\n })\n\n // Get filename with suffix from returned url\n if (addRandomSuffix) {\n data.filename = decodeURIComponent(result.url.replace(`${baseUrl}/`, ''))\n }\n\n return data\n }\n}\n"],"names":["put","path","getHandleUpload","access","addRandomSuffix","baseUrl","cacheControlMaxAge","prefix","token","data","file","buffer","filename","mimeType","fileKey","posix","join","result","contentType","decodeURIComponent","url","replace"],"mappings":"AAEA,SAASA,GAAG,QAAQ,eAAc;AAClC,OAAOC,UAAU,OAAM;AASvB,OAAO,MAAMC,kBAAkB,CAAC,EAC9BC,SAAS,QAAQ,EACjBC,eAAe,EACfC,OAAO,EACPC,kBAAkB,EAClBC,SAAS,EAAE,EACXC,KAAK,EACY;IACjB,OAAO,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,EAAE;QAC1D,MAAMC,UAAUb,KAAKc,KAAK,CAACC,IAAI,CAACP,KAAKF,MAAM,IAAIA,QAAQK;QAEvD,MAAMK,SAAS,MAAMjB,IAAIc,SAASH,QAAQ;YACxCR;YACAC;YACAE;YACAY,aAAaL;YACbL;QACF;QAEA,6CAA6C;QAC7C,IAAIJ,iBAAiB;YACnBK,KAAKG,QAAQ,GAAGO,mBAAmBF,OAAOG,GAAG,CAACC,OAAO,CAAC,GAAGhB,QAAQ,CAAC,CAAC,EAAE;QACvE;QAEA,OAAOI;IACT;AACF,EAAC"}
@@ -1,10 +0,0 @@
1
- import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types';
2
- import type { CollectionConfig } from 'payload';
3
- type StaticHandlerArgs = {
4
- baseUrl: string;
5
- cacheControlMaxAge?: number;
6
- token: string;
7
- };
8
- export declare const getStaticHandler: ({ baseUrl, cacheControlMaxAge, token }: StaticHandlerArgs, collection: CollectionConfig) => StaticHandler;
9
- export {};
10
- //# sourceMappingURL=staticHandler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"staticHandler.d.ts","sourceRoot":"","sources":["../src/staticHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAQ/C,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,gBAAgB,2CACiB,iBAAiB,cACjD,gBAAgB,KAC3B,aAmFF,CAAA"}
@@ -1,98 +0,0 @@
1
- import { getFilePrefix } from '@payloadcms/plugin-cloud-storage/utilities';
2
- import { BlobNotFoundError, head } from '@vercel/blob';
3
- import path from 'path';
4
- import { getRangeRequestInfo } from 'payload/internal';
5
- import { sanitizeFilename } from 'payload/shared';
6
- export const getStaticHandler = ({ baseUrl, cacheControlMaxAge = 0, token }, collection)=>{
7
- return async (req, { headers: incomingHeaders, params: { clientUploadContext, filename } })=>{
8
- try {
9
- const prefix = await getFilePrefix({
10
- clientUploadContext,
11
- collection,
12
- filename,
13
- req
14
- });
15
- const fileKey = path.posix.join(prefix, encodeURIComponent(sanitizeFilename(filename)));
16
- const fileUrl = `${baseUrl}/${fileKey}`;
17
- const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match');
18
- const blobMetadata = await head(fileUrl, {
19
- token
20
- });
21
- const { contentDisposition, contentType, size, uploadedAt } = blobMetadata;
22
- const uploadedAtString = uploadedAt.toISOString();
23
- const ETag = `"${fileKey}-${uploadedAtString}"`;
24
- // Handle range request
25
- const rangeHeader = req.headers.get('range');
26
- const rangeResult = getRangeRequestInfo({
27
- fileSize: size,
28
- rangeHeader
29
- });
30
- if (rangeResult.type === 'invalid') {
31
- return new Response(null, {
32
- headers: new Headers(rangeResult.headers),
33
- status: rangeResult.status
34
- });
35
- }
36
- let headers = new Headers(incomingHeaders);
37
- // Add range-related headers from the result
38
- for (const [key, value] of Object.entries(rangeResult.headers)){
39
- headers.append(key, value);
40
- }
41
- headers.append('Cache-Control', `public, max-age=${cacheControlMaxAge}`);
42
- headers.append('Content-Disposition', contentDisposition);
43
- headers.append('Content-Type', contentType);
44
- headers.append('ETag', ETag);
45
- // Add Content-Security-Policy header for SVG files to prevent executable code
46
- if (contentType === 'image/svg+xml') {
47
- headers.append('Content-Security-Policy', "script-src 'none'");
48
- }
49
- if (collection.upload && typeof collection.upload === 'object' && typeof collection.upload.modifyResponseHeaders === 'function') {
50
- headers = collection.upload.modifyResponseHeaders({
51
- headers
52
- }) || headers;
53
- }
54
- if (etagFromHeaders && etagFromHeaders === ETag) {
55
- return new Response(null, {
56
- headers,
57
- status: 304
58
- });
59
- }
60
- const response = await fetch(`${fileUrl}?${uploadedAtString}`, {
61
- headers: {
62
- 'Cache-Control': 'no-store, no-cache, must-revalidate',
63
- Pragma: 'no-cache',
64
- ...rangeResult.type === 'partial' && {
65
- Range: `bytes=${rangeResult.rangeStart}-${rangeResult.rangeEnd}`
66
- }
67
- }
68
- });
69
- if (!response.ok || !response.body) {
70
- return new Response(null, {
71
- status: 204,
72
- statusText: 'No Content'
73
- });
74
- }
75
- headers.append('Last-Modified', uploadedAtString);
76
- return new Response(response.body, {
77
- headers,
78
- status: rangeResult.status
79
- });
80
- } catch (err) {
81
- if (err instanceof BlobNotFoundError) {
82
- return new Response(null, {
83
- status: 404,
84
- statusText: 'Not Found'
85
- });
86
- }
87
- req.payload.logger.error({
88
- err,
89
- msg: 'Unexpected error in staticHandler'
90
- });
91
- return new Response('Internal Server Error', {
92
- status: 500
93
- });
94
- }
95
- };
96
- };
97
-
98
- //# sourceMappingURL=staticHandler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/staticHandler.ts"],"sourcesContent":["import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types'\nimport type { CollectionConfig } from 'payload'\n\nimport { getFilePrefix } from '@payloadcms/plugin-cloud-storage/utilities'\nimport { BlobNotFoundError, head } from '@vercel/blob'\nimport path from 'path'\nimport { getRangeRequestInfo } from 'payload/internal'\nimport { sanitizeFilename } from 'payload/shared'\n\ntype StaticHandlerArgs = {\n baseUrl: string\n cacheControlMaxAge?: number\n token: string\n}\n\nexport const getStaticHandler = (\n { baseUrl, cacheControlMaxAge = 0, token }: StaticHandlerArgs,\n collection: CollectionConfig,\n): StaticHandler => {\n return async (req, { headers: incomingHeaders, params: { clientUploadContext, filename } }) => {\n try {\n const prefix = await getFilePrefix({ clientUploadContext, collection, filename, req })\n const fileKey = path.posix.join(prefix, encodeURIComponent(sanitizeFilename(filename)))\n const fileUrl = `${baseUrl}/${fileKey}`\n const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match')\n const blobMetadata = await head(fileUrl, { token })\n const { contentDisposition, contentType, size, uploadedAt } = blobMetadata\n const uploadedAtString = uploadedAt.toISOString()\n const ETag = `\"${fileKey}-${uploadedAtString}\"`\n\n // Handle range request\n const rangeHeader = req.headers.get('range')\n const rangeResult = getRangeRequestInfo({ fileSize: size, rangeHeader })\n\n if (rangeResult.type === 'invalid') {\n return new Response(null, {\n headers: new Headers(rangeResult.headers),\n status: rangeResult.status,\n })\n }\n\n let headers = new Headers(incomingHeaders)\n\n // Add range-related headers from the result\n for (const [key, value] of Object.entries(rangeResult.headers)) {\n headers.append(key, value)\n }\n\n headers.append('Cache-Control', `public, max-age=${cacheControlMaxAge}`)\n headers.append('Content-Disposition', contentDisposition)\n headers.append('Content-Type', contentType)\n headers.append('ETag', ETag)\n\n // Add Content-Security-Policy header for SVG files to prevent executable code\n if (contentType === 'image/svg+xml') {\n headers.append('Content-Security-Policy', \"script-src 'none'\")\n }\n\n if (\n collection.upload &&\n typeof collection.upload === 'object' &&\n typeof collection.upload.modifyResponseHeaders === 'function'\n ) {\n headers = collection.upload.modifyResponseHeaders({ headers }) || headers\n }\n\n if (etagFromHeaders && etagFromHeaders === ETag) {\n return new Response(null, {\n headers,\n status: 304,\n })\n }\n\n const response = await fetch(`${fileUrl}?${uploadedAtString}`, {\n headers: {\n 'Cache-Control': 'no-store, no-cache, must-revalidate',\n Pragma: 'no-cache',\n ...(rangeResult.type === 'partial' && {\n Range: `bytes=${rangeResult.rangeStart}-${rangeResult.rangeEnd}`,\n }),\n },\n })\n\n if (!response.ok || !response.body) {\n return new Response(null, { status: 204, statusText: 'No Content' })\n }\n\n headers.append('Last-Modified', uploadedAtString)\n\n return new Response(response.body, {\n headers,\n status: rangeResult.status,\n })\n } catch (err: unknown) {\n if (err instanceof BlobNotFoundError) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n req.payload.logger.error({ err, msg: 'Unexpected error in staticHandler' })\n return new Response('Internal Server Error', { status: 500 })\n }\n }\n}\n"],"names":["getFilePrefix","BlobNotFoundError","head","path","getRangeRequestInfo","sanitizeFilename","getStaticHandler","baseUrl","cacheControlMaxAge","token","collection","req","headers","incomingHeaders","params","clientUploadContext","filename","prefix","fileKey","posix","join","encodeURIComponent","fileUrl","etagFromHeaders","get","blobMetadata","contentDisposition","contentType","size","uploadedAt","uploadedAtString","toISOString","ETag","rangeHeader","rangeResult","fileSize","type","Response","Headers","status","key","value","Object","entries","append","upload","modifyResponseHeaders","response","fetch","Pragma","Range","rangeStart","rangeEnd","ok","body","statusText","err","payload","logger","error","msg"],"mappings":"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"}