@payloadcms/plugin-cloud-storage 3.0.0-alpha.61 → 3.0.0-alpha.62
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/README.md +15 -0
- package/dist/adapters/azure/staticHandler.js +3 -2
- package/dist/adapters/azure/staticHandler.js.map +1 -1
- package/dist/adapters/gcs/staticHandler.js +3 -2
- package/dist/adapters/gcs/staticHandler.js.map +1 -1
- package/dist/adapters/s3/staticHandler.js +3 -2
- package/dist/adapters/s3/staticHandler.js.map +1 -1
- package/dist/adapters/vercelBlob/generateURL.d.ts +8 -0
- package/dist/adapters/vercelBlob/generateURL.d.ts.map +1 -0
- package/dist/adapters/vercelBlob/generateURL.js +8 -0
- package/dist/adapters/vercelBlob/generateURL.js.map +1 -0
- package/dist/adapters/vercelBlob/handleDelete.d.ts +9 -0
- package/dist/adapters/vercelBlob/handleDelete.d.ts.map +1 -0
- package/dist/adapters/vercelBlob/handleDelete.js +13 -0
- package/dist/adapters/vercelBlob/handleDelete.js.map +1 -0
- package/dist/adapters/vercelBlob/handleUpload.d.ts +10 -0
- package/dist/adapters/vercelBlob/handleUpload.d.ts.map +1 -0
- package/dist/adapters/vercelBlob/handleUpload.js +21 -0
- package/dist/adapters/vercelBlob/handleUpload.js.map +1 -0
- package/dist/adapters/vercelBlob/index.d.ts +32 -0
- package/dist/adapters/vercelBlob/index.d.ts.map +1 -0
- package/dist/adapters/vercelBlob/index.js +49 -0
- package/dist/adapters/vercelBlob/index.js.map +1 -0
- package/dist/adapters/vercelBlob/staticHandler.d.ts +9 -0
- package/dist/adapters/vercelBlob/staticHandler.d.ts.map +1 -0
- package/dist/adapters/vercelBlob/staticHandler.js +52 -0
- package/dist/adapters/vercelBlob/staticHandler.js.map +1 -0
- package/dist/exports/utilities.d.ts +2 -0
- package/dist/exports/utilities.d.ts.map +1 -0
- package/dist/exports/utilities.js +3 -0
- package/dist/exports/utilities.js.map +1 -0
- package/dist/exports/vercelBlob.d.ts +2 -0
- package/dist/exports/vercelBlob.d.ts.map +1 -0
- package/dist/exports/vercelBlob.js +3 -0
- package/dist/exports/vercelBlob.js.map +1 -0
- package/dist/utilities/getFilePrefix.d.ts +2 -1
- package/dist/utilities/getFilePrefix.d.ts.map +1 -1
- package/dist/utilities/getFilePrefix.js +1 -3
- package/dist/utilities/getFilePrefix.js.map +1 -1
- package/package.json +9 -4
- package/azure.d.ts +0 -2
- package/azure.js +0 -3
- package/gcs.d.ts +0 -2
- package/gcs.js +0 -3
- package/s3.d.ts +0 -2
- package/s3.js +0 -3
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ This plugin supports the following adapters:
|
|
|
63
63
|
- [Azure Blob Storage](#azure-blob-storage-adapter)
|
|
64
64
|
- [AWS S3-style Storage](#s3-adapter)
|
|
65
65
|
- [Google Cloud Storage](#gcs-adapter)
|
|
66
|
+
- [Vercel Blob Storage](#vercel-blob-adapter)
|
|
66
67
|
|
|
67
68
|
However, you can create your own adapter for any third-party service you would like to use.
|
|
68
69
|
|
|
@@ -176,6 +177,20 @@ const adapter = gcsAdapter({
|
|
|
176
177
|
// Now you can pass this adapter to the plugin
|
|
177
178
|
```
|
|
178
179
|
|
|
180
|
+
### Vercel Blob Adapter
|
|
181
|
+
|
|
182
|
+
To use the Vercel Blob adapter, you need to have `@vercel/blob` installed in your project dependencies.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { vercelBlobAdapter } from '@payloadcms/plugin-cloud-storage/vercelBlob'
|
|
186
|
+
|
|
187
|
+
const adapter = vercelBlobAdapter({
|
|
188
|
+
token: process.env.BLOB_READ_WRITE_TOKEN || '',
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Credit to @JarvisPrestidge for the original implementation of this plugin.
|
|
193
|
+
|
|
179
194
|
### Payload Access Control
|
|
180
195
|
|
|
181
196
|
Payload ships with access control that runs _even on statically served files_. The same `read` access control property on your `upload`-enabled collections is used, and it allows you to restrict who can request your uploaded files.
|
|
@@ -2,13 +2,14 @@ import path from 'path';
|
|
|
2
2
|
import { getFilePrefix } from '../../utilities/getFilePrefix.js';
|
|
3
3
|
import getRangeFromHeader from '../../utilities/getRangeFromHeader.js';
|
|
4
4
|
export const getHandler = ({ collection, getStorageClient })=>{
|
|
5
|
-
return async (req, { params })=>{
|
|
5
|
+
return async (req, { params: { filename } })=>{
|
|
6
6
|
try {
|
|
7
7
|
const prefix = await getFilePrefix({
|
|
8
8
|
collection,
|
|
9
|
+
filename,
|
|
9
10
|
req
|
|
10
11
|
});
|
|
11
|
-
const blockBlobClient = getStorageClient().getBlockBlobClient(path.posix.join(prefix,
|
|
12
|
+
const blockBlobClient = getStorageClient().getBlockBlobClient(path.posix.join(prefix, filename));
|
|
12
13
|
const { end, start } = await getRangeFromHeader(blockBlobClient, req.headers.get('range'));
|
|
13
14
|
const blob = await blockBlobClient.download(start, end);
|
|
14
15
|
// eslint-disable-next-line no-underscore-dangle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/azure/staticHandler.ts"],"sourcesContent":["import type { ContainerClient } from '@azure/storage-blob'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\nimport getRangeFromHeader from '../../utilities/getRangeFromHeader.js'\n\ninterface Args {\n collection: CollectionConfig\n getStorageClient: () => ContainerClient\n}\n\nexport const getHandler = ({ collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params }) => {\n try {\n const prefix = await getFilePrefix({ collection, req })\n const blockBlobClient = getStorageClient().getBlockBlobClient(\n path.posix.join(prefix,
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/azure/staticHandler.ts"],"sourcesContent":["import type { ContainerClient } from '@azure/storage-blob'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\nimport getRangeFromHeader from '../../utilities/getRangeFromHeader.js'\n\ninterface Args {\n collection: CollectionConfig\n getStorageClient: () => ContainerClient\n}\n\nexport const getHandler = ({ collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params: { filename } }) => {\n try {\n const prefix = await getFilePrefix({ collection, filename, req })\n const blockBlobClient = getStorageClient().getBlockBlobClient(\n path.posix.join(prefix, filename),\n )\n\n const { end, start } = await getRangeFromHeader(blockBlobClient, req.headers.get('range'))\n\n const blob = await blockBlobClient.download(start, end)\n // eslint-disable-next-line no-underscore-dangle\n const response = blob._response\n\n // Manually create a ReadableStream for the web from a Node.js stream.\n const readableStream = new ReadableStream({\n start(controller) {\n const nodeStream = blob.readableStreamBody\n nodeStream.on('data', (chunk) => {\n controller.enqueue(new Uint8Array(chunk))\n })\n nodeStream.on('end', () => {\n controller.close()\n })\n nodeStream.on('error', (err) => {\n controller.error(err)\n })\n },\n })\n\n return new Response(readableStream, {\n headers: response.headers.rawHeaders(),\n status: response.status,\n })\n } catch (err: unknown) {\n req.payload.logger.error(err)\n return new Response('Internal Server Error', { status: 500 })\n }\n }\n}\n"],"names":["path","getFilePrefix","getRangeFromHeader","getHandler","collection","getStorageClient","req","params","filename","prefix","blockBlobClient","getBlockBlobClient","posix","join","end","start","headers","get","blob","download","response","_response","readableStream","ReadableStream","controller","nodeStream","readableStreamBody","on","chunk","enqueue","Uint8Array","close","err","error","Response","rawHeaders","status","payload","logger"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAGA,OAAOA,UAAU,OAAM;AAIvB,SAASC,aAAa,QAAQ,mCAAkC;AAChE,OAAOC,wBAAwB,wCAAuC;AAOtE,OAAO,MAAMC,aAAa,CAAC,EAAEC,UAAU,EAAEC,gBAAgB,EAAQ;IAC/D,OAAO,OAAOC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,EAAE;QACzC,IAAI;YACF,MAAMC,SAAS,MAAMR,cAAc;gBAAEG;gBAAYI;gBAAUF;YAAI;YAC/D,MAAMI,kBAAkBL,mBAAmBM,kBAAkB,CAC3DX,KAAKY,KAAK,CAACC,IAAI,CAACJ,QAAQD;YAG1B,MAAM,EAAEM,GAAG,EAAEC,KAAK,EAAE,GAAG,MAAMb,mBAAmBQ,iBAAiBJ,IAAIU,OAAO,CAACC,GAAG,CAAC;YAEjF,MAAMC,OAAO,MAAMR,gBAAgBS,QAAQ,CAACJ,OAAOD;YACnD,gDAAgD;YAChD,MAAMM,WAAWF,KAAKG,SAAS;YAE/B,sEAAsE;YACtE,MAAMC,iBAAiB,IAAIC,eAAe;gBACxCR,OAAMS,UAAU;oBACd,MAAMC,aAAaP,KAAKQ,kBAAkB;oBAC1CD,WAAWE,EAAE,CAAC,QAAQ,CAACC;wBACrBJ,WAAWK,OAAO,CAAC,IAAIC,WAAWF;oBACpC;oBACAH,WAAWE,EAAE,CAAC,OAAO;wBACnBH,WAAWO,KAAK;oBAClB;oBACAN,WAAWE,EAAE,CAAC,SAAS,CAACK;wBACtBR,WAAWS,KAAK,CAACD;oBACnB;gBACF;YACF;YAEA,OAAO,IAAIE,SAASZ,gBAAgB;gBAClCN,SAASI,SAASJ,OAAO,CAACmB,UAAU;gBACpCC,QAAQhB,SAASgB,MAAM;YACzB;QACF,EAAE,OAAOJ,KAAc;YACrB1B,IAAI+B,OAAO,CAACC,MAAM,CAACL,KAAK,CAACD;YACzB,OAAO,IAAIE,SAAS,yBAAyB;gBAAEE,QAAQ;YAAI;QAC7D;IACF;AACF,EAAC"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { getFilePrefix } from '../../utilities/getFilePrefix.js';
|
|
3
3
|
export const getHandler = ({ bucket, collection, getStorageClient })=>{
|
|
4
|
-
return async (req, { params })=>{
|
|
4
|
+
return async (req, { params: { filename } })=>{
|
|
5
5
|
try {
|
|
6
6
|
const prefix = await getFilePrefix({
|
|
7
7
|
collection,
|
|
8
|
+
filename,
|
|
8
9
|
req
|
|
9
10
|
});
|
|
10
|
-
const file = getStorageClient().bucket(bucket).file(path.posix.join(prefix,
|
|
11
|
+
const file = getStorageClient().bucket(bucket).file(path.posix.join(prefix, filename));
|
|
11
12
|
const [metadata] = await file.getMetadata();
|
|
12
13
|
// Manually create a ReadableStream for the web from a Node.js stream.
|
|
13
14
|
const readableStream = new ReadableStream({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/gcs/staticHandler.ts"],"sourcesContent":["import type { Storage } from '@google-cloud/storage'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\n\ninterface Args {\n bucket: string\n collection: CollectionConfig\n getStorageClient: () => Storage\n}\n\nexport const getHandler = ({ bucket, collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params }) => {\n try {\n const prefix = await getFilePrefix({ collection, req })\n const file = getStorageClient().bucket(bucket).file(path.posix.join(prefix,
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/gcs/staticHandler.ts"],"sourcesContent":["import type { Storage } from '@google-cloud/storage'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\n\ninterface Args {\n bucket: string\n collection: CollectionConfig\n getStorageClient: () => Storage\n}\n\nexport const getHandler = ({ bucket, collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params: { filename } }) => {\n try {\n const prefix = await getFilePrefix({ collection, filename, req })\n const file = getStorageClient().bucket(bucket).file(path.posix.join(prefix, filename))\n\n const [metadata] = await file.getMetadata()\n\n // Manually create a ReadableStream for the web from a Node.js stream.\n const readableStream = new ReadableStream({\n start(controller) {\n const nodeStream = file.createReadStream()\n nodeStream.on('data', (chunk) => {\n controller.enqueue(new Uint8Array(chunk))\n })\n nodeStream.on('end', () => {\n controller.close()\n })\n nodeStream.on('error', (err) => {\n controller.error(err)\n })\n },\n })\n\n return new Response(readableStream, {\n headers: new Headers({\n 'Content-Length': String(metadata.size),\n 'Content-Type': metadata.contentType,\n ETag: metadata.etag,\n }),\n status: 200,\n })\n } catch (err: unknown) {\n req.payload.logger.error(err)\n return new Response('Internal Server Error', { status: 500 })\n }\n }\n}\n"],"names":["path","getFilePrefix","getHandler","bucket","collection","getStorageClient","req","params","filename","prefix","file","posix","join","metadata","getMetadata","readableStream","ReadableStream","start","controller","nodeStream","createReadStream","on","chunk","enqueue","Uint8Array","close","err","error","Response","headers","Headers","String","size","contentType","ETag","etag","status","payload","logger"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAGA,OAAOA,UAAU,OAAM;AAIvB,SAASC,aAAa,QAAQ,mCAAkC;AAQhE,OAAO,MAAMC,aAAa,CAAC,EAAEC,MAAM,EAAEC,UAAU,EAAEC,gBAAgB,EAAQ;IACvE,OAAO,OAAOC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,EAAE;QACzC,IAAI;YACF,MAAMC,SAAS,MAAMR,cAAc;gBAAEG;gBAAYI;gBAAUF;YAAI;YAC/D,MAAMI,OAAOL,mBAAmBF,MAAM,CAACA,QAAQO,IAAI,CAACV,KAAKW,KAAK,CAACC,IAAI,CAACH,QAAQD;YAE5E,MAAM,CAACK,SAAS,GAAG,MAAMH,KAAKI,WAAW;YAEzC,sEAAsE;YACtE,MAAMC,iBAAiB,IAAIC,eAAe;gBACxCC,OAAMC,UAAU;oBACd,MAAMC,aAAaT,KAAKU,gBAAgB;oBACxCD,WAAWE,EAAE,CAAC,QAAQ,CAACC;wBACrBJ,WAAWK,OAAO,CAAC,IAAIC,WAAWF;oBACpC;oBACAH,WAAWE,EAAE,CAAC,OAAO;wBACnBH,WAAWO,KAAK;oBAClB;oBACAN,WAAWE,EAAE,CAAC,SAAS,CAACK;wBACtBR,WAAWS,KAAK,CAACD;oBACnB;gBACF;YACF;YAEA,OAAO,IAAIE,SAASb,gBAAgB;gBAClCc,SAAS,IAAIC,QAAQ;oBACnB,kBAAkBC,OAAOlB,SAASmB,IAAI;oBACtC,gBAAgBnB,SAASoB,WAAW;oBACpCC,MAAMrB,SAASsB,IAAI;gBACrB;gBACAC,QAAQ;YACV;QACF,EAAE,OAAOV,KAAc;YACrBpB,IAAI+B,OAAO,CAACC,MAAM,CAACX,KAAK,CAACD;YACzB,OAAO,IAAIE,SAAS,yBAAyB;gBAAEQ,QAAQ;YAAI;QAC7D;IACF;AACF,EAAC"}
|
|
@@ -9,15 +9,16 @@ const streamToBuffer = async (readableStream)=>{
|
|
|
9
9
|
return Buffer.concat(chunks);
|
|
10
10
|
};
|
|
11
11
|
export const getHandler = ({ bucket, collection, getStorageClient })=>{
|
|
12
|
-
return async (req, { params })=>{
|
|
12
|
+
return async (req, { params: { filename } })=>{
|
|
13
13
|
try {
|
|
14
14
|
const prefix = await getFilePrefix({
|
|
15
15
|
collection,
|
|
16
|
+
filename,
|
|
16
17
|
req
|
|
17
18
|
});
|
|
18
19
|
const object = await getStorageClient().getObject({
|
|
19
20
|
Bucket: bucket,
|
|
20
|
-
Key: path.posix.join(prefix,
|
|
21
|
+
Key: path.posix.join(prefix, filename)
|
|
21
22
|
});
|
|
22
23
|
if (!object.Body) {
|
|
23
24
|
return new Response(null, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/adapters/s3/staticHandler.ts"],"sourcesContent":["import type * as AWS from '@aws-sdk/client-s3'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\n\ninterface Args {\n bucket: string\n collection: CollectionConfig\n getStorageClient: () => AWS.S3\n}\n\n// Convert a stream into a promise that resolves with a Buffer\nconst streamToBuffer = async (readableStream) => {\n const chunks = []\n for await (const chunk of readableStream) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)\n }\n return Buffer.concat(chunks)\n}\n\nexport const getHandler = ({ bucket, collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params }) => {\n try {\n const prefix = await getFilePrefix({ collection, req })\n\n const object = await getStorageClient().getObject({\n Bucket: bucket,\n Key: path.posix.join(prefix,
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/s3/staticHandler.ts"],"sourcesContent":["import type * as AWS from '@aws-sdk/client-s3'\nimport type { CollectionConfig } from 'payload/types'\n\nimport path from 'path'\n\nimport type { StaticHandler } from '../../types.js'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\n\ninterface Args {\n bucket: string\n collection: CollectionConfig\n getStorageClient: () => AWS.S3\n}\n\n// Convert a stream into a promise that resolves with a Buffer\nconst streamToBuffer = async (readableStream) => {\n const chunks = []\n for await (const chunk of readableStream) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk)\n }\n return Buffer.concat(chunks)\n}\n\nexport const getHandler = ({ bucket, collection, getStorageClient }: Args): StaticHandler => {\n return async (req, { params: { filename } }) => {\n try {\n const prefix = await getFilePrefix({ collection, filename, req })\n\n const object = await getStorageClient().getObject({\n Bucket: bucket,\n Key: path.posix.join(prefix, filename),\n })\n\n if (!object.Body) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const bodyBuffer = await streamToBuffer(object.Body)\n\n return new Response(bodyBuffer, {\n headers: new Headers({\n 'Accept-Ranges': object.AcceptRanges,\n 'Content-Length': String(object.ContentLength),\n 'Content-Type': object.ContentType,\n ETag: object.ETag,\n }),\n status: 200,\n })\n } catch (err) {\n req.payload.logger.error(err)\n return new Response('Internal Server Error', { status: 500 })\n }\n }\n}\n"],"names":["path","getFilePrefix","streamToBuffer","readableStream","chunks","chunk","push","Buffer","from","concat","getHandler","bucket","collection","getStorageClient","req","params","filename","prefix","object","getObject","Bucket","Key","posix","join","Body","Response","status","statusText","bodyBuffer","headers","Headers","AcceptRanges","String","ContentLength","ContentType","ETag","err","payload","logger","error"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAGA,OAAOA,UAAU,OAAM;AAIvB,SAASC,aAAa,QAAQ,mCAAkC;AAQhE,8DAA8D;AAC9D,MAAMC,iBAAiB,OAAOC;IAC5B,MAAMC,SAAS,EAAE;IACjB,WAAW,MAAMC,SAASF,eAAgB;QACxCC,OAAOE,IAAI,CAAC,OAAOD,UAAU,WAAWE,OAAOC,IAAI,CAACH,SAASA;IAC/D;IACA,OAAOE,OAAOE,MAAM,CAACL;AACvB;AAEA,OAAO,MAAMM,aAAa,CAAC,EAAEC,MAAM,EAAEC,UAAU,EAAEC,gBAAgB,EAAQ;IACvE,OAAO,OAAOC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,EAAE;QACzC,IAAI;YACF,MAAMC,SAAS,MAAMhB,cAAc;gBAAEW;gBAAYI;gBAAUF;YAAI;YAE/D,MAAMI,SAAS,MAAML,mBAAmBM,SAAS,CAAC;gBAChDC,QAAQT;gBACRU,KAAKrB,KAAKsB,KAAK,CAACC,IAAI,CAACN,QAAQD;YAC/B;YAEA,IAAI,CAACE,OAAOM,IAAI,EAAE;gBAChB,OAAO,IAAIC,SAAS,MAAM;oBAAEC,QAAQ;oBAAKC,YAAY;gBAAY;YACnE;YAEA,MAAMC,aAAa,MAAM1B,eAAegB,OAAOM,IAAI;YAEnD,OAAO,IAAIC,SAASG,YAAY;gBAC9BC,SAAS,IAAIC,QAAQ;oBACnB,iBAAiBZ,OAAOa,YAAY;oBACpC,kBAAkBC,OAAOd,OAAOe,aAAa;oBAC7C,gBAAgBf,OAAOgB,WAAW;oBAClCC,MAAMjB,OAAOiB,IAAI;gBACnB;gBACAT,QAAQ;YACV;QACF,EAAE,OAAOU,KAAK;YACZtB,IAAIuB,OAAO,CAACC,MAAM,CAACC,KAAK,CAACH;YACzB,OAAO,IAAIX,SAAS,yBAAyB;gBAAEC,QAAQ;YAAI;QAC7D;IACF;AACF,EAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GenerateURL } from '@payloadcms/plugin-cloud-storage/types';
|
|
2
|
+
type GenerateUrlArgs = {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
prefix?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const getGenerateUrl: ({ baseUrl }: GenerateUrlArgs) => GenerateURL;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=generateURL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateURL.d.ts","sourceRoot":"","sources":["../../../src/adapters/vercelBlob/generateURL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAIzE,KAAK,eAAe,GAAG;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,cAAc,gBAAiB,eAAe,KAAG,WAI7D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercelBlob/generateURL.ts"],"sourcesContent":["import type { GenerateURL } from '@payloadcms/plugin-cloud-storage/types'\n\nimport path from 'path'\n\ntype GenerateUrlArgs = {\n baseUrl: string\n prefix?: string\n}\n\nexport const getGenerateUrl = ({ baseUrl }: GenerateUrlArgs): GenerateURL => {\n return ({ filename, prefix = '' }) => {\n return `${baseUrl}/${path.posix.join(prefix, filename)}`\n }\n}\n"],"names":["path","getGenerateUrl","baseUrl","filename","prefix","posix","join"],"rangeMappings":";;;;;","mappings":"AAEA,OAAOA,UAAU,OAAM;AAOvB,OAAO,MAAMC,iBAAiB,CAAC,EAAEC,OAAO,EAAmB;IACzD,OAAO,CAAC,EAAEC,QAAQ,EAAEC,SAAS,EAAE,EAAE;QAC/B,OAAO,CAAC,EAAEF,QAAQ,CAAC,EAAEF,KAAKK,KAAK,CAACC,IAAI,CAACF,QAAQD,UAAU,CAAC;IAC1D;AACF,EAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handleDelete.d.ts","sourceRoot":"","sources":["../../../src/adapters/vercelBlob/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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercelBlob/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"],"rangeMappings":";;;;;;;;;;","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,CAAC,EAAEL,QAAQ,CAAC,EAAEF,KAAKQ,KAAK,CAACC,IAAI,CAACJ,QAAQC,UAAU,CAAC;QACjE,MAAMI,cAAc,MAAMX,IAAIQ,SAAS;YAAEJ;QAAM;QAE/C,OAAOO;IACT;AACF,EAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HandleUpload } from '@payloadcms/plugin-cloud-storage/types';
|
|
2
|
+
import type { VercelBlobAdapterUploadOptions } from './index.js';
|
|
3
|
+
type HandleUploadArgs = VercelBlobAdapterUploadOptions & {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
token: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const getHandleUpload: ({ access, addRandomSuffix, baseUrl, cacheControlMaxAge, prefix, token, }: HandleUploadArgs) => HandleUpload;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=handleUpload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handleUpload.d.ts","sourceRoot":"","sources":["../../../src/adapters/vercelBlob/handleUpload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAK1E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAA;AAEhE,KAAK,gBAAgB,GAAG,8BAA8B,GAAG;IACvD,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,eAAe,6EAOzB,gBAAgB,KAAG,YAmBrB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
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 = result.url.replace(`${baseUrl}/`, '');
|
|
16
|
+
}
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=handleUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercelBlob/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 { VercelBlobAdapterUploadOptions } from './index.js'\n\ntype HandleUploadArgs = VercelBlobAdapterUploadOptions & {\n baseUrl: string\n prefix?: string\n token: string\n}\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 = 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","url","replace"],"rangeMappings":";;;;;;;;;;;;;;;;;;","mappings":"AAEA,SAASA,GAAG,QAAQ,eAAc;AAClC,OAAOC,UAAU,OAAM;AAUvB,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,GAAGK,OAAOE,GAAG,CAACC,OAAO,CAAC,CAAC,EAAEf,QAAQ,CAAC,CAAC,EAAE;QACpD;QAEA,OAAOI;IACT;AACF,EAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Adapter } from '@payloadcms/plugin-cloud-storage/types';
|
|
2
|
+
export interface VercelBlobAdapterArgs {
|
|
3
|
+
options?: VercelBlobAdapterUploadOptions;
|
|
4
|
+
/**
|
|
5
|
+
* Vercel Blob storage read/write token
|
|
6
|
+
*
|
|
7
|
+
* Usually process.env.BLOB_READ_WRITE_TOKEN set by Vercel
|
|
8
|
+
*/
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export interface VercelBlobAdapterUploadOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Access control level
|
|
14
|
+
*
|
|
15
|
+
* @default 'public'
|
|
16
|
+
*/
|
|
17
|
+
access?: 'public';
|
|
18
|
+
/**
|
|
19
|
+
* Add a random suffix to the uploaded file name
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
addRandomSuffix?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Cache-Control max-age in seconds
|
|
26
|
+
*
|
|
27
|
+
* @default 31536000 (1 year)
|
|
28
|
+
*/
|
|
29
|
+
cacheControlMaxAge?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare const vercelBlobAdapter: ({ options, token }: VercelBlobAdapterArgs) => Adapter;
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/vercelBlob/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAoB,MAAM,wCAAwC,CAAA;AAOvF,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,8BAA8B,CAAA;IAExC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAQD,eAAO,MAAM,iBAAiB,uBACF,qBAAqB,KAAG,OAmCjD,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getGenerateUrl } from './generateURL.js';
|
|
2
|
+
import { getHandleDelete } from './handleDelete.js';
|
|
3
|
+
import { getHandleUpload } from './handleUpload.js';
|
|
4
|
+
import { getStaticHandler } from './staticHandler.js';
|
|
5
|
+
const defaultUploadOptions = {
|
|
6
|
+
access: 'public',
|
|
7
|
+
addRandomSuffix: false,
|
|
8
|
+
cacheControlMaxAge: 60 * 60 * 24 * 365
|
|
9
|
+
};
|
|
10
|
+
export const vercelBlobAdapter = ({ options = {}, token })=>({ collection, prefix })=>{
|
|
11
|
+
if (!token) {
|
|
12
|
+
throw new Error('The token argument is required for the Vercel Blob adapter.');
|
|
13
|
+
}
|
|
14
|
+
// Parse storeId from token
|
|
15
|
+
const storeId = token.match(/^vercel_blob_rw_([a-z\d]+)_[a-z\d]+$/i)?.[1].toLowerCase();
|
|
16
|
+
if (!storeId) {
|
|
17
|
+
throw new Error('Invalid token format for Vercel Blob adapter. Should be vercel_blob_rw_<store_id>_<random_string>.');
|
|
18
|
+
}
|
|
19
|
+
const { access, addRandomSuffix, cacheControlMaxAge } = {
|
|
20
|
+
...defaultUploadOptions,
|
|
21
|
+
...options
|
|
22
|
+
};
|
|
23
|
+
const baseUrl = `https://${storeId}.${access}.blob.vercel-storage.com`;
|
|
24
|
+
return {
|
|
25
|
+
generateURL: getGenerateUrl({
|
|
26
|
+
baseUrl,
|
|
27
|
+
prefix
|
|
28
|
+
}),
|
|
29
|
+
handleDelete: getHandleDelete({
|
|
30
|
+
baseUrl,
|
|
31
|
+
prefix,
|
|
32
|
+
token
|
|
33
|
+
}),
|
|
34
|
+
handleUpload: getHandleUpload({
|
|
35
|
+
access,
|
|
36
|
+
addRandomSuffix,
|
|
37
|
+
baseUrl,
|
|
38
|
+
cacheControlMaxAge,
|
|
39
|
+
prefix,
|
|
40
|
+
token
|
|
41
|
+
}),
|
|
42
|
+
staticHandler: getStaticHandler({
|
|
43
|
+
baseUrl,
|
|
44
|
+
token
|
|
45
|
+
}, collection)
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercelBlob/index.ts"],"sourcesContent":["import type { Adapter, GeneratedAdapter } from '@payloadcms/plugin-cloud-storage/types'\n\nimport { getGenerateUrl } from './generateURL.js'\nimport { getHandleDelete } from './handleDelete.js'\nimport { getHandleUpload } from './handleUpload.js'\nimport { getStaticHandler } from './staticHandler.js'\n\nexport interface VercelBlobAdapterArgs {\n options?: VercelBlobAdapterUploadOptions\n\n /**\n * Vercel Blob storage read/write token\n *\n * Usually process.env.BLOB_READ_WRITE_TOKEN set by Vercel\n */\n token: string\n}\n\nexport interface VercelBlobAdapterUploadOptions {\n /**\n * Access control level\n *\n * @default 'public'\n */\n access?: 'public'\n /**\n * Add a random suffix to the uploaded file name\n *\n * @default false\n */\n addRandomSuffix?: boolean\n /**\n * Cache-Control max-age in seconds\n *\n * @default 31536000 (1 year)\n */\n cacheControlMaxAge?: number\n}\n\nconst defaultUploadOptions: VercelBlobAdapterUploadOptions = {\n access: 'public',\n addRandomSuffix: false,\n cacheControlMaxAge: 60 * 60 * 24 * 365, // 1 year\n}\n\nexport const vercelBlobAdapter =\n ({ options = {}, token }: VercelBlobAdapterArgs): Adapter =>\n ({ collection, prefix }): GeneratedAdapter => {\n if (!token) {\n throw new Error('The token argument is required for the Vercel Blob adapter.')\n }\n\n // Parse storeId from token\n const storeId = token.match(/^vercel_blob_rw_([a-z\\d]+)_[a-z\\d]+$/i)?.[1].toLowerCase()\n\n if (!storeId) {\n throw new Error(\n 'Invalid token format for Vercel Blob adapter. Should be vercel_blob_rw_<store_id>_<random_string>.',\n )\n }\n\n const { access, addRandomSuffix, cacheControlMaxAge } = {\n ...defaultUploadOptions,\n ...options,\n }\n\n const baseUrl = `https://${storeId}.${access}.blob.vercel-storage.com`\n\n return {\n generateURL: getGenerateUrl({ baseUrl, prefix }),\n handleDelete: getHandleDelete({ baseUrl, prefix, token }),\n handleUpload: getHandleUpload({\n access,\n addRandomSuffix,\n baseUrl,\n cacheControlMaxAge,\n prefix,\n token,\n }),\n staticHandler: getStaticHandler({ baseUrl, token }, collection),\n }\n }\n"],"names":["getGenerateUrl","getHandleDelete","getHandleUpload","getStaticHandler","defaultUploadOptions","access","addRandomSuffix","cacheControlMaxAge","vercelBlobAdapter","options","token","collection","prefix","Error","storeId","match","toLowerCase","baseUrl","generateURL","handleDelete","handleUpload","staticHandler"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,SAASA,cAAc,QAAQ,mBAAkB;AACjD,SAASC,eAAe,QAAQ,oBAAmB;AACnD,SAASC,eAAe,QAAQ,oBAAmB;AACnD,SAASC,gBAAgB,QAAQ,qBAAoB;AAkCrD,MAAMC,uBAAuD;IAC3DC,QAAQ;IACRC,iBAAiB;IACjBC,oBAAoB,KAAK,KAAK,KAAK;AACrC;AAEA,OAAO,MAAMC,oBACX,CAAC,EAAEC,UAAU,CAAC,CAAC,EAAEC,KAAK,EAAyB,GAC/C,CAAC,EAAEC,UAAU,EAAEC,MAAM,EAAE;QACrB,IAAI,CAACF,OAAO;YACV,MAAM,IAAIG,MAAM;QAClB;QAEA,2BAA2B;QAC3B,MAAMC,UAAUJ,MAAMK,KAAK,CAAC,0CAA0C,CAAC,EAAE,CAACC;QAE1E,IAAI,CAACF,SAAS;YACZ,MAAM,IAAID,MACR;QAEJ;QAEA,MAAM,EAAER,MAAM,EAAEC,eAAe,EAAEC,kBAAkB,EAAE,GAAG;YACtD,GAAGH,oBAAoB;YACvB,GAAGK,OAAO;QACZ;QAEA,MAAMQ,UAAU,CAAC,QAAQ,EAAEH,QAAQ,CAAC,EAAET,OAAO,wBAAwB,CAAC;QAEtE,OAAO;YACLa,aAAalB,eAAe;gBAAEiB;gBAASL;YAAO;YAC9CO,cAAclB,gBAAgB;gBAAEgB;gBAASL;gBAAQF;YAAM;YACvDU,cAAclB,gBAAgB;gBAC5BG;gBACAC;gBACAW;gBACAV;gBACAK;gBACAF;YACF;YACAW,eAAelB,iBAAiB;gBAAEc;gBAASP;YAAM,GAAGC;QACtD;IACF,EAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types';
|
|
2
|
+
import type { CollectionConfig } from 'payload/types';
|
|
3
|
+
type StaticHandlerArgs = {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
token: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const getStaticHandler: ({ baseUrl, token }: StaticHandlerArgs, collection: CollectionConfig) => StaticHandler;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=staticHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staticHandler.d.ts","sourceRoot":"","sources":["../../../src/adapters/vercelBlob/staticHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,EAAE,gBAAgB,EAAgC,MAAM,eAAe,CAAA;AAOnF,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,eAAO,MAAM,gBAAgB,uBACP,iBAAiB,cACzB,gBAAgB,KAC3B,aAmCF,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { head } from '@vercel/blob';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { getFilePrefix } from '../../utilities/getFilePrefix.js';
|
|
4
|
+
export const getStaticHandler = ({ baseUrl, token }, collection)=>{
|
|
5
|
+
return async (req, { params: { filename } })=>{
|
|
6
|
+
try {
|
|
7
|
+
const prefix = await getFilePrefix({
|
|
8
|
+
collection,
|
|
9
|
+
req,
|
|
10
|
+
filename
|
|
11
|
+
});
|
|
12
|
+
const fileUrl = `${baseUrl}/${path.posix.join(prefix, filename)}`;
|
|
13
|
+
const blobMetadata = await head(fileUrl, {
|
|
14
|
+
token
|
|
15
|
+
});
|
|
16
|
+
if (!blobMetadata) {
|
|
17
|
+
return new Response(null, {
|
|
18
|
+
status: 404,
|
|
19
|
+
statusText: 'Not Found'
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const { contentDisposition, contentType, size } = blobMetadata;
|
|
23
|
+
const response = await fetch(fileUrl);
|
|
24
|
+
const blob = await response.blob();
|
|
25
|
+
if (!blob) {
|
|
26
|
+
return new Response(null, {
|
|
27
|
+
status: 204,
|
|
28
|
+
statusText: 'No Content'
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const bodyBuffer = await blob.arrayBuffer();
|
|
32
|
+
return new Response(bodyBuffer, {
|
|
33
|
+
headers: new Headers({
|
|
34
|
+
'Content-Disposition': contentDisposition,
|
|
35
|
+
'Content-Length': String(size),
|
|
36
|
+
'Content-Type': contentType
|
|
37
|
+
}),
|
|
38
|
+
status: 200
|
|
39
|
+
});
|
|
40
|
+
} catch (err) {
|
|
41
|
+
req.payload.logger.error({
|
|
42
|
+
err,
|
|
43
|
+
msg: 'Unexpected error in staticHandler'
|
|
44
|
+
});
|
|
45
|
+
return new Response('Internal Server Error', {
|
|
46
|
+
status: 500
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=staticHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/adapters/vercelBlob/staticHandler.ts"],"sourcesContent":["import type { StaticHandler } from '@payloadcms/plugin-cloud-storage/types'\nimport type { CollectionConfig, PayloadRequest, UploadConfig } from 'payload/types'\n\nimport { head } from '@vercel/blob'\nimport path from 'path'\n\nimport { getFilePrefix } from '../../utilities/getFilePrefix.js'\n\ntype StaticHandlerArgs = {\n baseUrl: string\n token: string\n}\n\nexport const getStaticHandler = (\n { baseUrl, token }: StaticHandlerArgs,\n collection: CollectionConfig,\n): StaticHandler => {\n return async (req, { params: { filename } }) => {\n try {\n const prefix = await getFilePrefix({ collection, req, filename })\n\n const fileUrl = `${baseUrl}/${path.posix.join(prefix, filename)}`\n\n const blobMetadata = await head(fileUrl, { token })\n if (!blobMetadata) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const { contentDisposition, contentType, size } = blobMetadata\n const response = await fetch(fileUrl)\n const blob = await response.blob()\n\n if (!blob) {\n return new Response(null, { status: 204, statusText: 'No Content' })\n }\n\n const bodyBuffer = await blob.arrayBuffer()\n\n return new Response(bodyBuffer, {\n headers: new Headers({\n 'Content-Disposition': contentDisposition,\n 'Content-Length': String(size),\n 'Content-Type': contentType,\n }),\n status: 200,\n })\n } catch (err: unknown) {\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":["head","path","getFilePrefix","getStaticHandler","baseUrl","token","collection","req","params","filename","prefix","fileUrl","posix","join","blobMetadata","Response","status","statusText","contentDisposition","contentType","size","response","fetch","blob","bodyBuffer","arrayBuffer","headers","Headers","String","err","payload","logger","error","msg"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAGA,SAASA,IAAI,QAAQ,eAAc;AACnC,OAAOC,UAAU,OAAM;AAEvB,SAASC,aAAa,QAAQ,mCAAkC;AAOhE,OAAO,MAAMC,mBAAmB,CAC9B,EAAEC,OAAO,EAAEC,KAAK,EAAqB,EACrCC;IAEA,OAAO,OAAOC,KAAK,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,EAAE;QACzC,IAAI;YACF,MAAMC,SAAS,MAAMR,cAAc;gBAAEI;gBAAYC;gBAAKE;YAAS;YAE/D,MAAME,UAAU,CAAC,EAAEP,QAAQ,CAAC,EAAEH,KAAKW,KAAK,CAACC,IAAI,CAACH,QAAQD,UAAU,CAAC;YAEjE,MAAMK,eAAe,MAAMd,KAAKW,SAAS;gBAAEN;YAAM;YACjD,IAAI,CAACS,cAAc;gBACjB,OAAO,IAAIC,SAAS,MAAM;oBAAEC,QAAQ;oBAAKC,YAAY;gBAAY;YACnE;YAEA,MAAM,EAAEC,kBAAkB,EAAEC,WAAW,EAAEC,IAAI,EAAE,GAAGN;YAClD,MAAMO,WAAW,MAAMC,MAAMX;YAC7B,MAAMY,OAAO,MAAMF,SAASE,IAAI;YAEhC,IAAI,CAACA,MAAM;gBACT,OAAO,IAAIR,SAAS,MAAM;oBAAEC,QAAQ;oBAAKC,YAAY;gBAAa;YACpE;YAEA,MAAMO,aAAa,MAAMD,KAAKE,WAAW;YAEzC,OAAO,IAAIV,SAASS,YAAY;gBAC9BE,SAAS,IAAIC,QAAQ;oBACnB,uBAAuBT;oBACvB,kBAAkBU,OAAOR;oBACzB,gBAAgBD;gBAClB;gBACAH,QAAQ;YACV;QACF,EAAE,OAAOa,KAAc;YACrBtB,IAAIuB,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;gBAAEH;gBAAKI,KAAK;YAAoC;YACzE,OAAO,IAAIlB,SAAS,yBAAyB;gBAAEC,QAAQ;YAAI;QAC7D;IACF;AACF,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../../src/exports/utilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/utilities.ts"],"sourcesContent":["export { getFilePrefix } from '../utilities/getFilePrefix.js'\n"],"names":["getFilePrefix"],"rangeMappings":"","mappings":"AAAA,SAASA,aAAa,QAAQ,gCAA+B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vercelBlob.d.ts","sourceRoot":"","sources":["../../src/exports/vercelBlob.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/exports/vercelBlob.ts"],"sourcesContent":["export { vercelBlobAdapter } from '../adapters/vercelBlob/index.js'\n"],"names":["vercelBlobAdapter"],"rangeMappings":"","mappings":"AAAA,SAASA,iBAAiB,QAAQ,kCAAiC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CollectionConfig, PayloadRequest } from 'payload/types';
|
|
2
|
-
export declare function getFilePrefix({ collection, req, }: {
|
|
2
|
+
export declare function getFilePrefix({ collection, req, filename, }: {
|
|
3
3
|
collection: CollectionConfig;
|
|
4
4
|
req: PayloadRequest;
|
|
5
|
+
filename: string;
|
|
5
6
|
}): Promise<string>;
|
|
6
7
|
//# sourceMappingURL=getFilePrefix.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFilePrefix.d.ts","sourceRoot":"","sources":["../../src/utilities/getFilePrefix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAgB,MAAM,eAAe,CAAA;AAEnF,wBAAsB,aAAa,CAAC,EAClC,UAAU,EACV,GAAG,
|
|
1
|
+
{"version":3,"file":"getFilePrefix.d.ts","sourceRoot":"","sources":["../../src/utilities/getFilePrefix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAgB,MAAM,eAAe,CAAA;AAEnF,wBAAsB,aAAa,CAAC,EAClC,UAAU,EACV,GAAG,EACH,QAAQ,GACT,EAAE;IACD,UAAU,EAAE,gBAAgB,CAAA;IAC5B,GAAG,EAAE,cAAc,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBlB"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export async function getFilePrefix({ collection, req }) {
|
|
1
|
+
export async function getFilePrefix({ collection, req, filename }) {
|
|
2
2
|
const imageSizes = collection?.upload?.imageSizes || [];
|
|
3
|
-
const { routeParams } = req;
|
|
4
|
-
const filename = routeParams['filename'];
|
|
5
3
|
const files = await req.payload.find({
|
|
6
4
|
collection: collection.slug,
|
|
7
5
|
depth: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/getFilePrefix.ts"],"sourcesContent":["import type { CollectionConfig, PayloadRequest, UploadConfig } from 'payload/types'\n\nexport async function getFilePrefix({\n collection,\n req,\n}: {\n collection: CollectionConfig\n req: PayloadRequest\n}): Promise<string> {\n const imageSizes = (collection?.upload as UploadConfig)?.imageSizes || []\n
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getFilePrefix.ts"],"sourcesContent":["import type { CollectionConfig, PayloadRequest, UploadConfig } from 'payload/types'\n\nexport async function getFilePrefix({\n collection,\n req,\n filename,\n}: {\n collection: CollectionConfig\n req: PayloadRequest\n filename: string\n}): Promise<string> {\n const imageSizes = (collection?.upload as UploadConfig)?.imageSizes || []\n\n const files = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 1,\n pagination: false,\n where: {\n or: [\n {\n filename: { equals: filename },\n },\n ...imageSizes.map((imageSize) => ({\n [`sizes.${imageSize.name}.filename`]: { equals: filename },\n })),\n ],\n },\n })\n const prefix = files?.docs?.[0]?.prefix\n return prefix ? (prefix as string) : ''\n}\n"],"names":["getFilePrefix","collection","req","filename","imageSizes","upload","files","payload","find","slug","depth","limit","pagination","where","or","equals","map","imageSize","name","prefix","docs"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAEA,OAAO,eAAeA,cAAc,EAClCC,UAAU,EACVC,GAAG,EACHC,QAAQ,EAKT;IACC,MAAMC,aAAa,AAACH,YAAYI,QAAyBD,cAAc,EAAE;IAEzE,MAAME,QAAQ,MAAMJ,IAAIK,OAAO,CAACC,IAAI,CAAC;QACnCP,YAAYA,WAAWQ,IAAI;QAC3BC,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,OAAO;YACLC,IAAI;gBACF;oBACEX,UAAU;wBAAEY,QAAQZ;oBAAS;gBAC/B;mBACGC,WAAWY,GAAG,CAAC,CAACC,YAAe,CAAA;wBAChC,CAAC,CAAC,MAAM,EAAEA,UAAUC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE;4BAAEH,QAAQZ;wBAAS;oBAC3D,CAAA;aACD;QACH;IACF;IACA,MAAMgB,SAASb,OAAOc,MAAM,CAAC,EAAE,EAAED;IACjC,OAAOA,SAAUA,SAAoB;AACvC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-cloud-storage",
|
|
3
3
|
"description": "The official cloud storage plugin for Payload CMS",
|
|
4
|
-
"version": "3.0.0-alpha.
|
|
4
|
+
"version": "3.0.0-alpha.62",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"@azure/abort-controller": "^1.0.0",
|
|
19
19
|
"@azure/storage-blob": "^12.11.0",
|
|
20
20
|
"@google-cloud/storage": "^7.7.0",
|
|
21
|
-
"
|
|
21
|
+
"@vercel/blob": "^0.22.3",
|
|
22
|
+
"payload": "3.0.0-alpha.62"
|
|
22
23
|
},
|
|
23
24
|
"peerDependenciesMeta": {
|
|
24
25
|
"@aws-sdk/client-s3": {
|
|
@@ -35,6 +36,9 @@
|
|
|
35
36
|
},
|
|
36
37
|
"@google-cloud/storage": {
|
|
37
38
|
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"@vercel/blob": {
|
|
41
|
+
"optional": true
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
"files": [
|
|
@@ -48,7 +52,8 @@
|
|
|
48
52
|
"@azure/storage-blob": "^12.11.0",
|
|
49
53
|
"@google-cloud/storage": "^7.7.0",
|
|
50
54
|
"@types/find-node-modules": "^2.1.2",
|
|
51
|
-
"
|
|
55
|
+
"@vercel/blob": "^0.22.3",
|
|
56
|
+
"payload": "3.0.0-alpha.62"
|
|
52
57
|
},
|
|
53
58
|
"dependencies": {
|
|
54
59
|
"find-node-modules": "^2.1.3",
|
|
@@ -75,7 +80,7 @@
|
|
|
75
80
|
"registry": "https://registry.npmjs.org/"
|
|
76
81
|
},
|
|
77
82
|
"scripts": {
|
|
78
|
-
"build": "pnpm build:swc && pnpm build:types
|
|
83
|
+
"build": "pnpm build:swc && pnpm build:types",
|
|
79
84
|
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
|
|
80
85
|
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
|
81
86
|
"clean": "rimraf {dist,*.tsbuildinfo}",
|
package/azure.d.ts
DELETED
package/azure.js
DELETED
package/gcs.d.ts
DELETED
package/gcs.js
DELETED
package/s3.d.ts
DELETED
package/s3.js
DELETED