@payloadcms/storage-r2 4.0.0-internal.cd47d20 → 4.0.0-internal.ce66a41
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/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +2 -1
- package/dist/adapter.js.map +1 -1
- package/dist/getFile.d.ts +3 -2
- package/dist/getFile.d.ts.map +1 -1
- package/dist/getFile.js +9 -12
- package/dist/getFile.js.map +1 -1
- package/package.json +4 -4
package/dist/adapter.d.ts.map
CHANGED
|
@@ -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;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAO1C,UAAU,mBAAmB;IAC3B,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IAC5C,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,aAAa,EACb,WAAW,EACX,oBAA4B,GAC7B,EAAE,mBAAmB,GAAG,OAAO,
|
|
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;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAO1C,UAAU,mBAAmB;IAC3B,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,WAAW,EAAE,gBAAgB,CAAC,aAAa,CAAC,CAAA;IAC5C,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,aAAa,EACb,WAAW,EACX,oBAA4B,GAC7B,EAAE,mBAAmB,GAAG,OAAO,CA8D/B"}
|
package/dist/adapter.js
CHANGED
|
@@ -44,12 +44,13 @@ export function createR2Adapter({ bucket, clientUploads, collections, useComposi
|
|
|
44
44
|
mimeType: file.mimeType,
|
|
45
45
|
storageFilePath
|
|
46
46
|
}),
|
|
47
|
-
staticHandler: (req, { doc, headers, params: { filename, uploadReference } })=>getFile({
|
|
47
|
+
staticHandler: (req, { doc, headers, params: { filename, operation, uploadReference } })=>getFile({
|
|
48
48
|
bucket,
|
|
49
49
|
collection,
|
|
50
50
|
doc,
|
|
51
51
|
filename,
|
|
52
52
|
incomingHeaders: headers,
|
|
53
|
+
operation,
|
|
53
54
|
prefix,
|
|
54
55
|
req,
|
|
55
56
|
uploadReference,
|
package/dist/adapter.js.map
CHANGED
|
@@ -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 type { R2StorageOptions } from './index.js'\nimport type { R2Bucket } from './types.js'\n\nimport { deleteFile } from './deleteFile.js'\nimport { getFile } from './getFile.js'\nimport { getHandleMultiPartUpload } from './handleMultiPartUpload.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateR2AdapterArgs {\n bucket: R2Bucket\n clientUploads?: ClientUploadsConfig\n collections: R2StorageOptions['collections']\n useCompositePrefixes?: boolean\n}\n\nexport function createR2Adapter({\n bucket,\n clientUploads,\n collections,\n useCompositePrefixes = false,\n}: CreateR2AdapterArgs): Adapter {\n const access = typeof clientUploads === 'object' ? clientUploads.access : undefined\n const uploadInstructions: GeneratedAdapter['uploadInstructions'] = {\n adminHandler: {\n path: '@payloadcms/storage-r2/client#R2ClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n endpoint: {\n handler: getHandleMultiPartUpload({\n access,\n bucket,\n collections,\n useCompositePrefixes,\n }),\n path: '/storage-r2-multi-part-upload',\n },\n generate: ({ filename, filesize, mimeType }) => ({\n name: 'uploadToR2',\n type: 'dispatch',\n file: {\n filename,\n mimeType,\n size: filesize,\n uploadReference: {},\n },\n }),\n requiresUploadReceipt: true,\n useInAdmin: true,\n }\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'r2',\n uploadInstructions,\n\n handleDelete: ({ storageFilePath }) =>\n deleteFile({\n bucket,\n storageFilePath,\n }),\n\n handleUpload: ({ file, storageFilePath }) =>\n uploadFile({\n bucket,\n buffer: file.buffer,\n mimeType: file.mimeType,\n storageFilePath,\n }),\n\n staticHandler: (req, { doc, headers, params: { filename, uploadReference } }) =>\n getFile({\n bucket,\n collection,\n doc,\n filename,\n incomingHeaders: headers,\n prefix,\n req,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["deleteFile","getFile","getHandleMultiPartUpload","uploadFile","createR2Adapter","bucket","clientUploads","collections","useCompositePrefixes","access","undefined","uploadInstructions","adminHandler","path","enabled","Boolean","endpoint","handler","generate","filename","filesize","mimeType","name","type","file","size","uploadReference","requiresUploadReceipt","useInAdmin","collection","prefix","handleDelete","storageFilePath","handleUpload","buffer","staticHandler","req","doc","headers","params","incomingHeaders"],"mappings":"AASA,SAASA,UAAU,QAAQ,kBAAiB;AAC5C,SAASC,OAAO,QAAQ,eAAc;AACtC,SAASC,wBAAwB,QAAQ,6BAA4B;AACrE,SAASC,UAAU,QAAQ,kBAAiB;AAS5C,OAAO,SAASC,gBAAgB,EAC9BC,MAAM,EACNC,aAAa,EACbC,WAAW,EACXC,uBAAuB,KAAK,EACR;IACpB,MAAMC,SAAS,OAAOH,kBAAkB,WAAWA,cAAcG,MAAM,GAAGC;IAC1E,MAAMC,qBAA6D;QACjEC,cAAc;YACZC,MAAM;QACR;QACAC,SAASC,QAAQT;QACjBU,UAAU;YACRC,SAASf,yBAAyB;gBAChCO;gBACAJ;gBACAE;gBACAC;YACF;YACAK,MAAM;QACR;QACAK,UAAU,CAAC,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAM,CAAA;gBAC/CC,MAAM;gBACNC,MAAM;gBACNC,MAAM;oBACJL;oBACAE;oBACAI,MAAML;oBACNM,iBAAiB,CAAC;gBACpB;YACF,CAAA;QACAC,uBAAuB;QACvBC,YAAY;IACd;IAEA,OAAO,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAE,EAAE,GAAwB,CAAA;YACzDR,MAAM;YACNX;YAEAoB,cAAc,CAAC,EAAEC,eAAe,EAAE,GAChChC,WAAW;oBACTK;oBACA2B;gBACF;YAEFC,cAAc,CAAC,EAAET,IAAI,EAAEQ,eAAe,EAAE,GACtC7B,WAAW;oBACTE;oBACA6B,QAAQV,KAAKU,MAAM;oBACnBb,UAAUG,KAAKH,QAAQ;oBACvBW;gBACF;YAEFG,eAAe,CAACC,KAAK,EAAEC,GAAG,EAAEC,OAAO,EAAEC,QAAQ,EAAEpB,QAAQ,
|
|
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 type { R2StorageOptions } from './index.js'\nimport type { R2Bucket } from './types.js'\n\nimport { deleteFile } from './deleteFile.js'\nimport { getFile } from './getFile.js'\nimport { getHandleMultiPartUpload } from './handleMultiPartUpload.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateR2AdapterArgs {\n bucket: R2Bucket\n clientUploads?: ClientUploadsConfig\n collections: R2StorageOptions['collections']\n useCompositePrefixes?: boolean\n}\n\nexport function createR2Adapter({\n bucket,\n clientUploads,\n collections,\n useCompositePrefixes = false,\n}: CreateR2AdapterArgs): Adapter {\n const access = typeof clientUploads === 'object' ? clientUploads.access : undefined\n const uploadInstructions: GeneratedAdapter['uploadInstructions'] = {\n adminHandler: {\n path: '@payloadcms/storage-r2/client#R2ClientUploadHandler',\n },\n enabled: Boolean(clientUploads),\n endpoint: {\n handler: getHandleMultiPartUpload({\n access,\n bucket,\n collections,\n useCompositePrefixes,\n }),\n path: '/storage-r2-multi-part-upload',\n },\n generate: ({ filename, filesize, mimeType }) => ({\n name: 'uploadToR2',\n type: 'dispatch',\n file: {\n filename,\n mimeType,\n size: filesize,\n uploadReference: {},\n },\n }),\n requiresUploadReceipt: true,\n useInAdmin: true,\n }\n\n return ({ collection, prefix = '' }): GeneratedAdapter => ({\n name: 'r2',\n uploadInstructions,\n\n handleDelete: ({ storageFilePath }) =>\n deleteFile({\n bucket,\n storageFilePath,\n }),\n\n handleUpload: ({ file, storageFilePath }) =>\n uploadFile({\n bucket,\n buffer: file.buffer,\n mimeType: file.mimeType,\n storageFilePath,\n }),\n\n staticHandler: (req, { doc, headers, params: { filename, operation, uploadReference } }) =>\n getFile({\n bucket,\n collection,\n doc,\n filename,\n incomingHeaders: headers,\n operation,\n prefix,\n req,\n uploadReference,\n useCompositePrefixes,\n }),\n })\n}\n"],"names":["deleteFile","getFile","getHandleMultiPartUpload","uploadFile","createR2Adapter","bucket","clientUploads","collections","useCompositePrefixes","access","undefined","uploadInstructions","adminHandler","path","enabled","Boolean","endpoint","handler","generate","filename","filesize","mimeType","name","type","file","size","uploadReference","requiresUploadReceipt","useInAdmin","collection","prefix","handleDelete","storageFilePath","handleUpload","buffer","staticHandler","req","doc","headers","params","operation","incomingHeaders"],"mappings":"AASA,SAASA,UAAU,QAAQ,kBAAiB;AAC5C,SAASC,OAAO,QAAQ,eAAc;AACtC,SAASC,wBAAwB,QAAQ,6BAA4B;AACrE,SAASC,UAAU,QAAQ,kBAAiB;AAS5C,OAAO,SAASC,gBAAgB,EAC9BC,MAAM,EACNC,aAAa,EACbC,WAAW,EACXC,uBAAuB,KAAK,EACR;IACpB,MAAMC,SAAS,OAAOH,kBAAkB,WAAWA,cAAcG,MAAM,GAAGC;IAC1E,MAAMC,qBAA6D;QACjEC,cAAc;YACZC,MAAM;QACR;QACAC,SAASC,QAAQT;QACjBU,UAAU;YACRC,SAASf,yBAAyB;gBAChCO;gBACAJ;gBACAE;gBACAC;YACF;YACAK,MAAM;QACR;QACAK,UAAU,CAAC,EAAEC,QAAQ,EAAEC,QAAQ,EAAEC,QAAQ,EAAE,GAAM,CAAA;gBAC/CC,MAAM;gBACNC,MAAM;gBACNC,MAAM;oBACJL;oBACAE;oBACAI,MAAML;oBACNM,iBAAiB,CAAC;gBACpB;YACF,CAAA;QACAC,uBAAuB;QACvBC,YAAY;IACd;IAEA,OAAO,CAAC,EAAEC,UAAU,EAAEC,SAAS,EAAE,EAAE,GAAwB,CAAA;YACzDR,MAAM;YACNX;YAEAoB,cAAc,CAAC,EAAEC,eAAe,EAAE,GAChChC,WAAW;oBACTK;oBACA2B;gBACF;YAEFC,cAAc,CAAC,EAAET,IAAI,EAAEQ,eAAe,EAAE,GACtC7B,WAAW;oBACTE;oBACA6B,QAAQV,KAAKU,MAAM;oBACnBb,UAAUG,KAAKH,QAAQ;oBACvBW;gBACF;YAEFG,eAAe,CAACC,KAAK,EAAEC,GAAG,EAAEC,OAAO,EAAEC,QAAQ,EAAEpB,QAAQ,EAAEqB,SAAS,EAAEd,eAAe,EAAE,EAAE,GACrFzB,QAAQ;oBACNI;oBACAwB;oBACAQ;oBACAlB;oBACAsB,iBAAiBH;oBACjBE;oBACAV;oBACAM;oBACAV;oBACAlB;gBACF;QACJ,CAAA;AACF"}
|
package/dist/getFile.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CollectionConfig, PayloadRequest, TypeWithID } from 'payload';
|
|
1
|
+
import type { CollectionConfig, FileHandlerOperation, PayloadRequest, TypeWithID } from 'payload';
|
|
2
2
|
import type { R2Bucket } from './types.js';
|
|
3
3
|
interface GetFileArgs {
|
|
4
4
|
bucket: R2Bucket;
|
|
@@ -6,11 +6,12 @@ interface GetFileArgs {
|
|
|
6
6
|
doc?: TypeWithID;
|
|
7
7
|
filename: string;
|
|
8
8
|
incomingHeaders?: Headers;
|
|
9
|
+
operation?: FileHandlerOperation;
|
|
9
10
|
prefix: string;
|
|
10
11
|
req: PayloadRequest;
|
|
11
12
|
uploadReference?: unknown;
|
|
12
13
|
useCompositePrefixes?: boolean;
|
|
13
14
|
}
|
|
14
|
-
export declare function getFile({ bucket, collection, doc, filename, incomingHeaders, prefix, req, uploadReference, useCompositePrefixes, }: GetFileArgs): Promise<Response>;
|
|
15
|
+
export declare function getFile({ bucket, collection, doc, filename, incomingHeaders, operation, prefix, req, uploadReference, useCompositePrefixes, }: GetFileArgs): Promise<Response>;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=getFile.d.ts.map
|
package/dist/getFile.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../src/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../src/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAQjG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,UAAU,WAAW;IACnB,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,GAAG,CAAC,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,SAAS,CAAC,EAAE,oBAAoB,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,cAAc,CAAA;IACnB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAID,wBAAsB,OAAO,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,GAAG,EACH,QAAQ,EACR,eAAe,EACf,SAAkB,EAClB,MAAW,EACX,GAAG,EACH,eAAe,EACf,oBAA4B,GAC7B,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwHjC"}
|
package/dist/getFile.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { buildStoragePathData, getFilePrefix as getDocPrefix } from '@payloadcms/plugin-cloud-storage/utilities';
|
|
2
2
|
import { getRangeRequestInfo, isXmlMimeType, uploadContentSecurityPolicy } from 'payload/internal';
|
|
3
3
|
const isMiniflare = process.env.NODE_ENV === 'development';
|
|
4
|
-
export async function getFile({ bucket, collection, doc, filename, incomingHeaders, prefix = '', req, uploadReference, useCompositePrefixes = false }) {
|
|
4
|
+
export async function getFile({ bucket, collection, doc, filename, incomingHeaders, operation = 'read', prefix = '', req, uploadReference, useCompositePrefixes = false }) {
|
|
5
|
+
const isTransformSource = operation === 'transform';
|
|
5
6
|
try {
|
|
6
7
|
const docPrefix = await getDocPrefix({
|
|
7
8
|
collection,
|
|
@@ -27,14 +28,14 @@ export async function getFile({ bucket, collection, doc, filename, incomingHeade
|
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
const fileSize = headObj.size;
|
|
30
|
-
// Don't return large file uploads back to the client, or the Worker will run out of memory
|
|
31
|
-
|
|
31
|
+
// Don't return large file uploads back to the client, or the Worker will run out of memory.
|
|
32
|
+
// Skipped for `transform`, which needs the real bytes and would otherwise silently corrupt.
|
|
33
|
+
if (fileSize > 50 * 1024 * 1024 && uploadReference && !isTransformSource) {
|
|
32
34
|
return new Response(null, {
|
|
33
35
|
status: 200
|
|
34
36
|
});
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
const rangeHeader = req.headers.get('range');
|
|
38
|
+
const rangeHeader = isTransformSource ? null : req.headers.get('range');
|
|
38
39
|
const rangeResult = getRangeRequestInfo({
|
|
39
40
|
fileSize,
|
|
40
41
|
rangeHeader
|
|
@@ -45,7 +46,6 @@ export async function getFile({ bucket, collection, doc, filename, incomingHeade
|
|
|
45
46
|
status: rangeResult.status
|
|
46
47
|
});
|
|
47
48
|
}
|
|
48
|
-
// Get object with range if needed
|
|
49
49
|
// Due to https://github.com/cloudflare/workers-sdk/issues/6047
|
|
50
50
|
// We cannot send a Headers instance to Miniflare
|
|
51
51
|
const obj = rangeResult.type === 'partial' && !isMiniflare ? await bucket?.get(storageFilePath, {
|
|
@@ -61,13 +61,10 @@ export async function getFile({ bucket, collection, doc, filename, incomingHeade
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
let headers = new Headers(incomingHeaders);
|
|
64
|
-
// Add range-related headers from the result
|
|
65
64
|
for (const [headerKey, value] of Object.entries(rangeResult.headers)){
|
|
66
65
|
headers.append(headerKey, value);
|
|
67
66
|
}
|
|
68
|
-
// Add R2-specific headers
|
|
69
67
|
if (isMiniflare) {
|
|
70
|
-
// In development with Miniflare, manually set headers from httpMetadata
|
|
71
68
|
const metadata = obj.httpMetadata;
|
|
72
69
|
if (metadata?.cacheControl) {
|
|
73
70
|
headers.set('Cache-Control', metadata.cacheControl);
|
|
@@ -87,18 +84,18 @@ export async function getFile({ bucket, collection, doc, filename, incomingHeade
|
|
|
87
84
|
} else {
|
|
88
85
|
obj.writeHttpMetadata(headers);
|
|
89
86
|
}
|
|
90
|
-
// Apply a restrictive policy to XML-family responses served through Payload.
|
|
91
87
|
const contentType = headers.get('Content-Type');
|
|
88
|
+
// Apply a restrictive policy to XML-family responses served through Payload.
|
|
92
89
|
if (isXmlMimeType(contentType)) {
|
|
93
90
|
headers.set('Content-Security-Policy', uploadContentSecurityPolicy);
|
|
94
91
|
}
|
|
95
92
|
const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match');
|
|
96
|
-
if (collection.upload && typeof collection.upload === 'object' && typeof collection.upload.modifyResponseHeaders === 'function') {
|
|
93
|
+
if (!isTransformSource && collection.upload && typeof collection.upload === 'object' && typeof collection.upload.modifyResponseHeaders === 'function') {
|
|
97
94
|
headers = collection.upload.modifyResponseHeaders({
|
|
98
95
|
headers
|
|
99
96
|
}) || headers;
|
|
100
97
|
}
|
|
101
|
-
if (etagFromHeaders && etagFromHeaders === obj.etag) {
|
|
98
|
+
if (!isTransformSource && etagFromHeaders && etagFromHeaders === obj.etag) {
|
|
102
99
|
return new Response(null, {
|
|
103
100
|
headers,
|
|
104
101
|
status: 304
|
package/dist/getFile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/getFile.ts"],"sourcesContent":["import type { CollectionConfig, PayloadRequest, TypeWithID } from 'payload'\n\nimport {\n buildStoragePathData,\n getFilePrefix as getDocPrefix,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { getRangeRequestInfo, isXmlMimeType, uploadContentSecurityPolicy } from 'payload/internal'\n\nimport type { R2Bucket } from './types.js'\n\ninterface GetFileArgs {\n bucket: R2Bucket\n collection: CollectionConfig\n doc?: TypeWithID\n filename: string\n incomingHeaders?: Headers\n prefix: string\n req: PayloadRequest\n uploadReference?: unknown\n useCompositePrefixes?: boolean\n}\n\nconst isMiniflare = process.env.NODE_ENV === 'development'\n\nexport async function getFile({\n bucket,\n collection,\n doc,\n filename,\n incomingHeaders,\n prefix = '',\n req,\n uploadReference,\n useCompositePrefixes = false,\n}: GetFileArgs): Promise<Response> {\n try {\n const docPrefix = await getDocPrefix({\n collection,\n collectionPrefix: prefix,\n doc,\n filename,\n req,\n uploadReference,\n useCompositePrefixes,\n })\n\n const { storageFilePath } = buildStoragePathData({\n collectionPrefix: prefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n\n // Get file size for range validation\n const headObj = await bucket?.head(storageFilePath)\n if (!headObj) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const fileSize = headObj.size\n\n // Don't return large file uploads back to the client, or the Worker will run out of memory
|
|
1
|
+
{"version":3,"sources":["../src/getFile.ts"],"sourcesContent":["import type { CollectionConfig, FileHandlerOperation, PayloadRequest, TypeWithID } from 'payload'\n\nimport {\n buildStoragePathData,\n getFilePrefix as getDocPrefix,\n} from '@payloadcms/plugin-cloud-storage/utilities'\nimport { getRangeRequestInfo, isXmlMimeType, uploadContentSecurityPolicy } from 'payload/internal'\n\nimport type { R2Bucket } from './types.js'\n\ninterface GetFileArgs {\n bucket: R2Bucket\n collection: CollectionConfig\n doc?: TypeWithID\n filename: string\n incomingHeaders?: Headers\n operation?: FileHandlerOperation\n prefix: string\n req: PayloadRequest\n uploadReference?: unknown\n useCompositePrefixes?: boolean\n}\n\nconst isMiniflare = process.env.NODE_ENV === 'development'\n\nexport async function getFile({\n bucket,\n collection,\n doc,\n filename,\n incomingHeaders,\n operation = 'read',\n prefix = '',\n req,\n uploadReference,\n useCompositePrefixes = false,\n}: GetFileArgs): Promise<Response> {\n const isTransformSource = operation === 'transform'\n\n try {\n const docPrefix = await getDocPrefix({\n collection,\n collectionPrefix: prefix,\n doc,\n filename,\n req,\n uploadReference,\n useCompositePrefixes,\n })\n\n const { storageFilePath } = buildStoragePathData({\n collectionPrefix: prefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n\n // Get file size for range validation\n const headObj = await bucket?.head(storageFilePath)\n if (!headObj) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const fileSize = headObj.size\n\n // Don't return large file uploads back to the client, or the Worker will run out of memory.\n // Skipped for `transform`, which needs the real bytes and would otherwise silently corrupt.\n if (fileSize > 50 * 1024 * 1024 && uploadReference && !isTransformSource) {\n return new Response(null, { status: 200 })\n }\n\n const rangeHeader = isTransformSource ? null : req.headers.get('range')\n const rangeResult = getRangeRequestInfo({ fileSize, 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 // Due to https://github.com/cloudflare/workers-sdk/issues/6047\n // We cannot send a Headers instance to Miniflare\n const obj =\n rangeResult.type === 'partial' && !isMiniflare\n ? await bucket?.get(storageFilePath, {\n range: {\n length: rangeResult.rangeEnd - rangeResult.rangeStart + 1,\n offset: rangeResult.rangeStart,\n },\n })\n : await bucket?.get(storageFilePath)\n\n if (!obj || obj.body == undefined) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n let headers = new Headers(incomingHeaders)\n\n for (const [headerKey, value] of Object.entries(rangeResult.headers)) {\n headers.append(headerKey, value)\n }\n\n if (isMiniflare) {\n const metadata = obj.httpMetadata\n if (metadata?.cacheControl) {\n headers.set('Cache-Control', metadata.cacheControl)\n }\n if (metadata?.contentDisposition) {\n headers.set('Content-Disposition', metadata.contentDisposition)\n }\n if (metadata?.contentEncoding) {\n headers.set('Content-Encoding', metadata.contentEncoding)\n }\n if (metadata?.contentLanguage) {\n headers.set('Content-Language', metadata.contentLanguage)\n }\n if (metadata?.contentType) {\n headers.set('Content-Type', metadata.contentType)\n }\n } else {\n obj.writeHttpMetadata(headers)\n }\n\n const contentType = headers.get('Content-Type')\n\n // Apply a restrictive policy to XML-family responses served through Payload.\n if (isXmlMimeType(contentType)) {\n headers.set('Content-Security-Policy', uploadContentSecurityPolicy)\n }\n\n const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match')\n\n if (\n !isTransformSource &&\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 (!isTransformSource && etagFromHeaders && etagFromHeaders === obj.etag) {\n return new Response(null, {\n headers,\n status: 304,\n })\n }\n\n return new Response(obj.body, {\n headers,\n status: rangeResult.status,\n })\n } catch (_err: unknown) {\n return new Response('Internal Server Error', { status: 500 })\n }\n}\n"],"names":["buildStoragePathData","getFilePrefix","getDocPrefix","getRangeRequestInfo","isXmlMimeType","uploadContentSecurityPolicy","isMiniflare","process","env","NODE_ENV","getFile","bucket","collection","doc","filename","incomingHeaders","operation","prefix","req","uploadReference","useCompositePrefixes","isTransformSource","docPrefix","collectionPrefix","storageFilePath","headObj","head","Response","status","statusText","fileSize","size","rangeHeader","headers","get","rangeResult","type","Headers","obj","range","length","rangeEnd","rangeStart","offset","body","undefined","headerKey","value","Object","entries","append","metadata","httpMetadata","cacheControl","set","contentDisposition","contentEncoding","contentLanguage","contentType","writeHttpMetadata","etagFromHeaders","upload","modifyResponseHeaders","etag","_err"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/storage-r2",
|
|
3
|
-
"version": "4.0.0-internal.
|
|
3
|
+
"version": "4.0.0-internal.ce66a41",
|
|
4
4
|
"description": "Payload storage adapter for Cloudflare R2",
|
|
5
5
|
"homepage": "https://payloadcms.com",
|
|
6
6
|
"repository": {
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@payloadcms/plugin-cloud-storage": "4.0.0-internal.
|
|
40
|
+
"@payloadcms/plugin-cloud-storage": "4.0.0-internal.ce66a41"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@cloudflare/workers-types": "4.20260218.0",
|
|
44
|
-
"payload": "4.0.0-internal.
|
|
44
|
+
"payload": "4.0.0-internal.ce66a41"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"payload": "4.0.0-internal.
|
|
47
|
+
"payload": "4.0.0-internal.ce66a41"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=24.15.0"
|