@payloadcms/storage-uploadthing 3.89.0 → 3.90.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.
@@ -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,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE/C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AAOrC,UAAU,4BAA4B;IACpC,GAAG,EAAE,GAAG,CAAA;IACR,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,wBAAwB,CAAC,EACvC,GAAG,EACH,aAAa,EACb,KAAK,GACN,EAAE,4BAA4B,GAAG,OAAO,CAiDxC"}
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,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAE/C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAA;AAOrC,UAAU,4BAA4B;IACpC,GAAG,EAAE,GAAG,CAAA;IACR,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,wBAAwB,CAAC,EACvC,GAAG,EACH,aAAa,EACb,KAAK,GACN,EAAE,4BAA4B,GAAG,OAAO,CAkDxC"}
package/dist/adapter.js CHANGED
@@ -19,6 +19,7 @@ export function createUploadthingAdapter({ acl, clientUploads, utApi }) {
19
19
  name: 'uploadthing',
20
20
  clientUploads,
21
21
  fields,
22
+ requiresClientUploadReceipt: true,
22
23
  generateURL,
23
24
  handleDelete: ({ doc, filename, req })=>deleteFile({
24
25
  doc: doc,
@@ -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'\nimport type { Field } from 'payload'\nimport type { UTApi } from 'uploadthing/server'\n\nimport type { ACL } from './index.js'\n\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateUploadthingAdapterArgs {\n acl: ACL\n clientUploads?: ClientUploadsConfig\n utApi: UTApi\n}\n\nexport function createUploadthingAdapter({\n acl,\n clientUploads,\n utApi,\n}: CreateUploadthingAdapterArgs): Adapter {\n const fields: Field[] = [\n {\n name: '_key',\n type: 'text',\n admin: {\n disableBulkEdit: true,\n disableListColumn: true,\n disableListFilter: true,\n hidden: true,\n },\n },\n ]\n\n return (): GeneratedAdapter => ({\n name: 'uploadthing',\n clientUploads,\n fields,\n\n generateURL,\n\n handleDelete: ({ doc, filename, req }) =>\n deleteFile({ doc: doc as unknown as Record<string, unknown>, filename, req, utApi }),\n\n handleUpload: async ({ clientUploadContext, data, file }) => {\n const result = await uploadFile({\n acl,\n buffer: file.buffer,\n clientUploadContext,\n data,\n filename: file.filename,\n mimeType: file.mimeType,\n utApi,\n })\n\n return result\n },\n\n staticHandler: (req, { doc, headers, params: { clientUploadContext, collection, filename } }) =>\n getFile({\n clientUploadContext,\n collection,\n doc: doc as unknown as Record<string, unknown> | undefined,\n filename,\n incomingHeaders: headers || new Headers(),\n req,\n utApi,\n }),\n })\n}\n"],"names":["deleteFile","generateURL","getFile","uploadFile","createUploadthingAdapter","acl","clientUploads","utApi","fields","name","type","admin","disableBulkEdit","disableListColumn","disableListFilter","hidden","handleDelete","doc","filename","req","handleUpload","clientUploadContext","data","file","result","buffer","mimeType","staticHandler","headers","params","collection","incomingHeaders","Headers"],"mappings":"AAUA,SAASA,UAAU,QAAQ,kBAAiB;AAC5C,SAASC,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,OAAO,QAAQ,eAAc;AACtC,SAASC,UAAU,QAAQ,kBAAiB;AAQ5C,OAAO,SAASC,yBAAyB,EACvCC,GAAG,EACHC,aAAa,EACbC,KAAK,EACwB;IAC7B,MAAMC,SAAkB;QACtB;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,iBAAiB;gBACjBC,mBAAmB;gBACnBC,mBAAmB;gBACnBC,QAAQ;YACV;QACF;KACD;IAED,OAAO,IAAyB,CAAA;YAC9BN,MAAM;YACNH;YACAE;YAEAP;YAEAe,cAAc,CAAC,EAAEC,GAAG,EAAEC,QAAQ,EAAEC,GAAG,EAAE,GACnCnB,WAAW;oBAAEiB,KAAKA;oBAA2CC;oBAAUC;oBAAKZ;gBAAM;YAEpFa,cAAc,OAAO,EAAEC,mBAAmB,EAAEC,IAAI,EAAEC,IAAI,EAAE;gBACtD,MAAMC,SAAS,MAAMrB,WAAW;oBAC9BE;oBACAoB,QAAQF,KAAKE,MAAM;oBACnBJ;oBACAC;oBACAJ,UAAUK,KAAKL,QAAQ;oBACvBQ,UAAUH,KAAKG,QAAQ;oBACvBnB;gBACF;gBAEA,OAAOiB;YACT;YAEAG,eAAe,CAACR,KAAK,EAAEF,GAAG,EAAEW,OAAO,EAAEC,QAAQ,EAAER,mBAAmB,EAAES,UAAU,EAAEZ,QAAQ,EAAE,EAAE,GAC1FhB,QAAQ;oBACNmB;oBACAS;oBACAb,KAAKA;oBACLC;oBACAa,iBAAiBH,WAAW,IAAII;oBAChCb;oBACAZ;gBACF;QACJ,CAAA;AACF"}
1
+ {"version":3,"sources":["../src/adapter.ts"],"sourcesContent":["import type {\n Adapter,\n ClientUploadsConfig,\n GeneratedAdapter,\n} from '@payloadcms/plugin-cloud-storage/types'\nimport type { Field } from 'payload'\nimport type { UTApi } from 'uploadthing/server'\n\nimport type { ACL } from './index.js'\n\nimport { deleteFile } from './deleteFile.js'\nimport { generateURL } from './generateURL.js'\nimport { getFile } from './getFile.js'\nimport { uploadFile } from './uploadFile.js'\n\ninterface CreateUploadthingAdapterArgs {\n acl: ACL\n clientUploads?: ClientUploadsConfig\n utApi: UTApi\n}\n\nexport function createUploadthingAdapter({\n acl,\n clientUploads,\n utApi,\n}: CreateUploadthingAdapterArgs): Adapter {\n const fields: Field[] = [\n {\n name: '_key',\n type: 'text',\n admin: {\n disableBulkEdit: true,\n disableListColumn: true,\n disableListFilter: true,\n hidden: true,\n },\n },\n ]\n\n return (): GeneratedAdapter => ({\n name: 'uploadthing',\n clientUploads,\n fields,\n requiresClientUploadReceipt: true,\n\n generateURL,\n\n handleDelete: ({ doc, filename, req }) =>\n deleteFile({ doc: doc as unknown as Record<string, unknown>, filename, req, utApi }),\n\n handleUpload: async ({ clientUploadContext, data, file }) => {\n const result = await uploadFile({\n acl,\n buffer: file.buffer,\n clientUploadContext,\n data,\n filename: file.filename,\n mimeType: file.mimeType,\n utApi,\n })\n\n return result\n },\n\n staticHandler: (req, { doc, headers, params: { clientUploadContext, collection, filename } }) =>\n getFile({\n clientUploadContext,\n collection,\n doc: doc as unknown as Record<string, unknown> | undefined,\n filename,\n incomingHeaders: headers || new Headers(),\n req,\n utApi,\n }),\n })\n}\n"],"names":["deleteFile","generateURL","getFile","uploadFile","createUploadthingAdapter","acl","clientUploads","utApi","fields","name","type","admin","disableBulkEdit","disableListColumn","disableListFilter","hidden","requiresClientUploadReceipt","handleDelete","doc","filename","req","handleUpload","clientUploadContext","data","file","result","buffer","mimeType","staticHandler","headers","params","collection","incomingHeaders","Headers"],"mappings":"AAUA,SAASA,UAAU,QAAQ,kBAAiB;AAC5C,SAASC,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,OAAO,QAAQ,eAAc;AACtC,SAASC,UAAU,QAAQ,kBAAiB;AAQ5C,OAAO,SAASC,yBAAyB,EACvCC,GAAG,EACHC,aAAa,EACbC,KAAK,EACwB;IAC7B,MAAMC,SAAkB;QACtB;YACEC,MAAM;YACNC,MAAM;YACNC,OAAO;gBACLC,iBAAiB;gBACjBC,mBAAmB;gBACnBC,mBAAmB;gBACnBC,QAAQ;YACV;QACF;KACD;IAED,OAAO,IAAyB,CAAA;YAC9BN,MAAM;YACNH;YACAE;YACAQ,6BAA6B;YAE7Bf;YAEAgB,cAAc,CAAC,EAAEC,GAAG,EAAEC,QAAQ,EAAEC,GAAG,EAAE,GACnCpB,WAAW;oBAAEkB,KAAKA;oBAA2CC;oBAAUC;oBAAKb;gBAAM;YAEpFc,cAAc,OAAO,EAAEC,mBAAmB,EAAEC,IAAI,EAAEC,IAAI,EAAE;gBACtD,MAAMC,SAAS,MAAMtB,WAAW;oBAC9BE;oBACAqB,QAAQF,KAAKE,MAAM;oBACnBJ;oBACAC;oBACAJ,UAAUK,KAAKL,QAAQ;oBACvBQ,UAAUH,KAAKG,QAAQ;oBACvBpB;gBACF;gBAEA,OAAOkB;YACT;YAEAG,eAAe,CAACR,KAAK,EAAEF,GAAG,EAAEW,OAAO,EAAEC,QAAQ,EAAER,mBAAmB,EAAES,UAAU,EAAEZ,QAAQ,EAAE,EAAE,GAC1FjB,QAAQ;oBACNoB;oBACAS;oBACAb,KAAKA;oBACLC;oBACAa,iBAAiBH,WAAW,IAAII;oBAChCb;oBACAb;gBACF;QACJ,CAAA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"UploadthingClientUploadHandler.d.ts","sourceRoot":"","sources":["../../src/client/UploadthingClientUploadHandler.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,8BAA8B;;;;;;;aAmB6F,OAAO,aAD7I,CAAA"}
1
+ {"version":3,"file":"UploadthingClientUploadHandler.d.ts","sourceRoot":"","sources":["../../src/client/UploadthingClientUploadHandler.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,8BAA8B;;;;;;;aAwBf,OAAO,aAKjC,CAAA"}
@@ -18,8 +18,13 @@ export const UploadthingClientUploadHandler = createClientUploadHandler({
18
18
  file
19
19
  ]
20
20
  });
21
+ const uploaded = res[0];
22
+ if (!uploaded?.serverData?.signedReceipt) {
23
+ throw new Error('Uploadthing did not return a client upload receipt');
24
+ }
21
25
  return {
22
- key: res[0]?.key
26
+ key: uploaded.key,
27
+ signedReceipt: uploaded.serverData.signedReceipt
23
28
  };
24
29
  }
25
30
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/UploadthingClientUploadHandler.ts"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\nimport { formatAdminURL } from 'payload/shared'\nimport { genUploader } from 'uploadthing/client'\n\nexport const UploadthingClientUploadHandler = createClientUploadHandler({\n handler: async ({ apiRoute, collectionSlug, file, serverHandlerPath, serverURL }) => {\n const endpointRoute = formatAdminURL({\n apiRoute,\n path: `${serverHandlerPath}?collectionSlug=${collectionSlug}`,\n serverURL,\n })\n const { uploadFiles } = genUploader({\n package: 'storage-uploadthing',\n url: endpointRoute,\n })\n\n const res = await uploadFiles('uploader', {\n files: [file],\n })\n\n return { key: res[0]?.key }\n },\n})\n"],"names":["createClientUploadHandler","formatAdminURL","genUploader","UploadthingClientUploadHandler","handler","apiRoute","collectionSlug","file","serverHandlerPath","serverURL","endpointRoute","path","uploadFiles","package","url","res","files","key"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AACnF,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,WAAW,QAAQ,qBAAoB;AAEhD,OAAO,MAAMC,iCAAiCH,0BAA0B;IACtEI,SAAS,OAAO,EAAEC,QAAQ,EAAEC,cAAc,EAAEC,IAAI,EAAEC,iBAAiB,EAAEC,SAAS,EAAE;QAC9E,MAAMC,gBAAgBT,eAAe;YACnCI;YACAM,MAAM,GAAGH,kBAAkB,gBAAgB,EAAEF,gBAAgB;YAC7DG;QACF;QACA,MAAM,EAAEG,WAAW,EAAE,GAAGV,YAAY;YAClCW,SAAS;YACTC,KAAKJ;QACP;QAEA,MAAMK,MAAM,MAAMH,YAAY,YAAY;YACxCI,OAAO;gBAACT;aAAK;QACf;QAEA,OAAO;YAAEU,KAAKF,GAAG,CAAC,EAAE,EAAEE;QAAI;IAC5B;AACF,GAAE"}
1
+ {"version":3,"sources":["../../src/client/UploadthingClientUploadHandler.ts"],"sourcesContent":["'use client'\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\nimport { formatAdminURL } from 'payload/shared'\nimport { genUploader } from 'uploadthing/client'\n\nexport const UploadthingClientUploadHandler = createClientUploadHandler({\n handler: async ({\n apiRoute,\n collectionSlug,\n file,\n serverHandlerPath,\n serverURL,\n }): Promise<{ key: string; signedReceipt: string }> => {\n const endpointRoute = formatAdminURL({\n apiRoute,\n path: `${serverHandlerPath}?collectionSlug=${collectionSlug}`,\n serverURL,\n })\n const { uploadFiles } = genUploader({\n package: 'storage-uploadthing',\n url: endpointRoute,\n })\n\n const res = await uploadFiles('uploader', {\n files: [file],\n })\n\n const uploaded = res[0]\n if (!uploaded?.serverData?.signedReceipt) {\n throw new Error('Uploadthing did not return a client upload receipt')\n }\n\n return { key: uploaded.key, signedReceipt: uploaded.serverData.signedReceipt }\n },\n})\n"],"names":["createClientUploadHandler","formatAdminURL","genUploader","UploadthingClientUploadHandler","handler","apiRoute","collectionSlug","file","serverHandlerPath","serverURL","endpointRoute","path","uploadFiles","package","url","res","files","uploaded","serverData","signedReceipt","Error","key"],"mappings":"AAAA;AACA,SAASA,yBAAyB,QAAQ,0CAAyC;AACnF,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,WAAW,QAAQ,qBAAoB;AAEhD,OAAO,MAAMC,iCAAiCH,0BAA0B;IACtEI,SAAS,OAAO,EACdC,QAAQ,EACRC,cAAc,EACdC,IAAI,EACJC,iBAAiB,EACjBC,SAAS,EACV;QACC,MAAMC,gBAAgBT,eAAe;YACnCI;YACAM,MAAM,GAAGH,kBAAkB,gBAAgB,EAAEF,gBAAgB;YAC7DG;QACF;QACA,MAAM,EAAEG,WAAW,EAAE,GAAGV,YAAY;YAClCW,SAAS;YACTC,KAAKJ;QACP;QAEA,MAAMK,MAAM,MAAMH,YAAY,YAAY;YACxCI,OAAO;gBAACT;aAAK;QACf;QAEA,MAAMU,WAAWF,GAAG,CAAC,EAAE;QACvB,IAAI,CAACE,UAAUC,YAAYC,eAAe;YACxC,MAAM,IAAIC,MAAM;QAClB;QAEA,OAAO;YAAEC,KAAKJ,SAASI,GAAG;YAAEF,eAAeF,SAASC,UAAU,CAACC,aAAa;QAAC;IAC/E;AACF,GAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"getClientUploadRoute.d.ts","sourceRoot":"","sources":["../src/getClientUploadRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAA;AAEhB,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,cAAc,EAAE,oBAAoB,CAAA;QACpC,GAAG,EAAE,cAAc,CAAA;KACpB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChC,GAAG,EAAE,SAAS,GAAG,aAAa,CAAA;IAC9B,iBAAiB,CAAC,EAAE,qBAAqB,CAAA;IACzC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AASD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,eAAO,MAAM,oBAAoB,+CAK9B,IAAI,KAAG,cAoCT,CAAA"}
1
+ {"version":3,"file":"getClientUploadRoute.d.ts","sourceRoot":"","sources":["../src/getClientUploadRoute.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAA;AAOhB,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,cAAc,EAAE,oBAAoB,CAAA;QACpC,GAAG,EAAE,cAAc,CAAA;KACpB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChC,GAAG,EAAE,SAAS,GAAG,aAAa,CAAA;IAC9B,iBAAiB,CAAC,EAAE,qBAAqB,CAAA;IACzC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AASD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEvD,eAAO,MAAM,oBAAoB,+CAK9B,IAAI,KAAG,cA2DT,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { APIError, Forbidden } from 'payload';
2
+ import { assertClientUploadAccess, assertClientUploadAllowed, createClientUploadReceipt } from 'payload/internal';
2
3
  const defaultAccess = ({ req })=>!!req.user;
3
4
  import { createRouteHandler } from 'uploadthing/next';
4
5
  import { createUploadthing } from 'uploadthing/server';
@@ -13,20 +14,48 @@ export const getClientUploadRoute = ({ access = defaultAccess, acl, routerInputC
13
14
  maxFileSize: '512MB',
14
15
  ...'blob' in routerInputConfig ? routerInputConfig.blob : {}
15
16
  }
16
- }).middleware(async ({ req: rawReq })=>{
17
+ }).middleware(async ({ files, req: rawReq })=>{
17
18
  const req = rawReq;
18
19
  const collectionSlug = req.searchParams.get('collectionSlug');
19
20
  if (!collectionSlug) {
20
21
  throw new APIError('No payload was provided');
21
22
  }
23
+ await assertClientUploadAccess({
24
+ collectionSlug,
25
+ req
26
+ });
22
27
  if (!await access({
23
28
  collectionSlug,
24
29
  req
25
30
  })) {
26
31
  throw new Forbidden();
27
32
  }
28
- return {};
29
- }).onUploadComplete(()=>{})
33
+ for (const file of files){
34
+ assertClientUploadAllowed({
35
+ collection: req.payload.collections[collectionSlug]?.config,
36
+ filename: file.name,
37
+ mimeType: file.type
38
+ });
39
+ }
40
+ return {
41
+ collectionSlug,
42
+ filename: files[0].name,
43
+ user: {
44
+ userCollection: req.user?.collection ?? null,
45
+ userID: req.user?.id ?? null
46
+ }
47
+ };
48
+ }).onUploadComplete(({ file, metadata, req: rawReq })=>({
49
+ signedReceipt: createClientUploadReceipt({
50
+ collectionSlug: metadata.collectionSlug,
51
+ context: {
52
+ key: file.key
53
+ },
54
+ filename: metadata.filename,
55
+ req: rawReq,
56
+ user: metadata.user
57
+ })
58
+ }))
30
59
  };
31
60
  const { POST } = createRouteHandler({
32
61
  config: {
@@ -34,9 +63,7 @@ export const getClientUploadRoute = ({ access = defaultAccess, acl, routerInputC
34
63
  },
35
64
  router: uploadRouter
36
65
  });
37
- return async (req)=>{
38
- return POST(req);
39
- };
66
+ return (req)=>POST(req);
40
67
  };
41
68
 
42
69
  //# sourceMappingURL=getClientUploadRoute.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/getClientUploadRoute.ts"],"sourcesContent":["import {\n APIError,\n Forbidden,\n type PayloadHandler,\n type PayloadRequest,\n type UploadCollectionSlug,\n} from 'payload'\n\ntype Args = {\n access?: (args: {\n collectionSlug: UploadCollectionSlug\n req: PayloadRequest\n }) => boolean | Promise<boolean>\n acl: 'private' | 'public-read'\n routerInputConfig?: FileRouterInputConfig\n token?: string\n}\n\nconst defaultAccess: Args['access'] = ({ req }) => !!req.user\n\nimport type { FileRouter } from 'uploadthing/server'\n\nimport { createRouteHandler } from 'uploadthing/next'\nimport { createUploadthing } from 'uploadthing/server'\n\nimport type { FileRouterInputConfig } from './index.js'\n\nexport const getClientUploadRoute = ({\n access = defaultAccess,\n acl,\n routerInputConfig = {},\n token,\n}: Args): PayloadHandler => {\n const f = createUploadthing()\n\n const uploadRouter = {\n uploader: f({\n ...routerInputConfig,\n blob: {\n acl,\n maxFileCount: 1,\n maxFileSize: '512MB',\n ...('blob' in routerInputConfig ? routerInputConfig.blob : {}),\n },\n })\n .middleware(async ({ req: rawReq }) => {\n const req = rawReq as PayloadRequest\n\n const collectionSlug = req.searchParams.get('collectionSlug')\n\n if (!collectionSlug) {\n throw new APIError('No payload was provided')\n }\n\n if (!(await access({ collectionSlug, req }))) {\n throw new Forbidden()\n }\n\n return {}\n })\n .onUploadComplete(() => {}),\n } satisfies FileRouter\n\n const { POST } = createRouteHandler({ config: { token }, router: uploadRouter })\n\n return async (req) => {\n return POST(req)\n }\n}\n"],"names":["APIError","Forbidden","defaultAccess","req","user","createRouteHandler","createUploadthing","getClientUploadRoute","access","acl","routerInputConfig","token","f","uploadRouter","uploader","blob","maxFileCount","maxFileSize","middleware","rawReq","collectionSlug","searchParams","get","onUploadComplete","POST","config","router"],"mappings":"AAAA,SACEA,QAAQ,EACRC,SAAS,QAIJ,UAAS;AAYhB,MAAMC,gBAAgC,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;AAI7D,SAASC,kBAAkB,QAAQ,mBAAkB;AACrD,SAASC,iBAAiB,QAAQ,qBAAoB;AAItD,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,SAASN,aAAa,EACtBO,GAAG,EACHC,oBAAoB,CAAC,CAAC,EACtBC,KAAK,EACA;IACL,MAAMC,IAAIN;IAEV,MAAMO,eAAe;QACnBC,UAAUF,EAAE;YACV,GAAGF,iBAAiB;YACpBK,MAAM;gBACJN;gBACAO,cAAc;gBACdC,aAAa;gBACb,GAAI,UAAUP,oBAAoBA,kBAAkBK,IAAI,GAAG,CAAC,CAAC;YAC/D;QACF,GACGG,UAAU,CAAC,OAAO,EAAEf,KAAKgB,MAAM,EAAE;YAChC,MAAMhB,MAAMgB;YAEZ,MAAMC,iBAAiBjB,IAAIkB,YAAY,CAACC,GAAG,CAAC;YAE5C,IAAI,CAACF,gBAAgB;gBACnB,MAAM,IAAIpB,SAAS;YACrB;YAEA,IAAI,CAAE,MAAMQ,OAAO;gBAAEY;gBAAgBjB;YAAI,IAAK;gBAC5C,MAAM,IAAIF;YACZ;YAEA,OAAO,CAAC;QACV,GACCsB,gBAAgB,CAAC,KAAO;IAC7B;IAEA,MAAM,EAAEC,IAAI,EAAE,GAAGnB,mBAAmB;QAAEoB,QAAQ;YAAEd;QAAM;QAAGe,QAAQb;IAAa;IAE9E,OAAO,OAAOV;QACZ,OAAOqB,KAAKrB;IACd;AACF,EAAC"}
1
+ {"version":3,"sources":["../src/getClientUploadRoute.ts"],"sourcesContent":["import {\n APIError,\n Forbidden,\n type PayloadHandler,\n type PayloadRequest,\n type UploadCollectionSlug,\n} from 'payload'\nimport {\n assertClientUploadAccess,\n assertClientUploadAllowed,\n createClientUploadReceipt,\n} from 'payload/internal'\n\ntype Args = {\n access?: (args: {\n collectionSlug: UploadCollectionSlug\n req: PayloadRequest\n }) => boolean | Promise<boolean>\n acl: 'private' | 'public-read'\n routerInputConfig?: FileRouterInputConfig\n token?: string\n}\n\nconst defaultAccess: Args['access'] = ({ req }) => !!req.user\n\nimport type { FileRouter } from 'uploadthing/server'\n\nimport { createRouteHandler } from 'uploadthing/next'\nimport { createUploadthing } from 'uploadthing/server'\n\nimport type { FileRouterInputConfig } from './index.js'\n\nexport const getClientUploadRoute = ({\n access = defaultAccess,\n acl,\n routerInputConfig = {},\n token,\n}: Args): PayloadHandler => {\n const f = createUploadthing()\n\n const uploadRouter = {\n uploader: f({\n ...routerInputConfig,\n blob: {\n acl,\n maxFileCount: 1,\n maxFileSize: '512MB',\n ...('blob' in routerInputConfig ? routerInputConfig.blob : {}),\n },\n })\n .middleware(async ({ files, req: rawReq }) => {\n const req = rawReq as PayloadRequest\n\n const collectionSlug = req.searchParams.get('collectionSlug')\n\n if (!collectionSlug) {\n throw new APIError('No payload was provided')\n }\n\n await assertClientUploadAccess({ collectionSlug, req })\n\n if (!(await access({ collectionSlug, req }))) {\n throw new Forbidden()\n }\n\n for (const file of files) {\n assertClientUploadAllowed({\n collection: req.payload.collections[collectionSlug]?.config,\n filename: file.name,\n mimeType: file.type,\n })\n }\n\n return {\n collectionSlug,\n filename: files[0]!.name,\n user: {\n userCollection: req.user?.collection ?? null,\n userID: req.user?.id ?? null,\n },\n }\n })\n .onUploadComplete(({ file, metadata, req: rawReq }) => ({\n signedReceipt: createClientUploadReceipt({\n collectionSlug: metadata.collectionSlug,\n context: { key: file.key },\n filename: metadata.filename,\n req: rawReq as PayloadRequest,\n user: metadata.user,\n }),\n })),\n } satisfies FileRouter\n\n const { POST } = createRouteHandler({ config: { token }, router: uploadRouter })\n\n return (req) => POST(req)\n}\n"],"names":["APIError","Forbidden","assertClientUploadAccess","assertClientUploadAllowed","createClientUploadReceipt","defaultAccess","req","user","createRouteHandler","createUploadthing","getClientUploadRoute","access","acl","routerInputConfig","token","f","uploadRouter","uploader","blob","maxFileCount","maxFileSize","middleware","files","rawReq","collectionSlug","searchParams","get","file","collection","payload","collections","config","filename","name","mimeType","type","userCollection","userID","id","onUploadComplete","metadata","signedReceipt","context","key","POST","router"],"mappings":"AAAA,SACEA,QAAQ,EACRC,SAAS,QAIJ,UAAS;AAChB,SACEC,wBAAwB,EACxBC,yBAAyB,EACzBC,yBAAyB,QACpB,mBAAkB;AAYzB,MAAMC,gBAAgC,CAAC,EAAEC,GAAG,EAAE,GAAK,CAAC,CAACA,IAAIC,IAAI;AAI7D,SAASC,kBAAkB,QAAQ,mBAAkB;AACrD,SAASC,iBAAiB,QAAQ,qBAAoB;AAItD,OAAO,MAAMC,uBAAuB,CAAC,EACnCC,SAASN,aAAa,EACtBO,GAAG,EACHC,oBAAoB,CAAC,CAAC,EACtBC,KAAK,EACA;IACL,MAAMC,IAAIN;IAEV,MAAMO,eAAe;QACnBC,UAAUF,EAAE;YACV,GAAGF,iBAAiB;YACpBK,MAAM;gBACJN;gBACAO,cAAc;gBACdC,aAAa;gBACb,GAAI,UAAUP,oBAAoBA,kBAAkBK,IAAI,GAAG,CAAC,CAAC;YAC/D;QACF,GACGG,UAAU,CAAC,OAAO,EAAEC,KAAK,EAAEhB,KAAKiB,MAAM,EAAE;YACvC,MAAMjB,MAAMiB;YAEZ,MAAMC,iBAAiBlB,IAAImB,YAAY,CAACC,GAAG,CAAC;YAE5C,IAAI,CAACF,gBAAgB;gBACnB,MAAM,IAAIxB,SAAS;YACrB;YAEA,MAAME,yBAAyB;gBAAEsB;gBAAgBlB;YAAI;YAErD,IAAI,CAAE,MAAMK,OAAO;gBAAEa;gBAAgBlB;YAAI,IAAK;gBAC5C,MAAM,IAAIL;YACZ;YAEA,KAAK,MAAM0B,QAAQL,MAAO;gBACxBnB,0BAA0B;oBACxByB,YAAYtB,IAAIuB,OAAO,CAACC,WAAW,CAACN,eAAe,EAAEO;oBACrDC,UAAUL,KAAKM,IAAI;oBACnBC,UAAUP,KAAKQ,IAAI;gBACrB;YACF;YAEA,OAAO;gBACLX;gBACAQ,UAAUV,KAAK,CAAC,EAAE,CAAEW,IAAI;gBACxB1B,MAAM;oBACJ6B,gBAAgB9B,IAAIC,IAAI,EAAEqB,cAAc;oBACxCS,QAAQ/B,IAAIC,IAAI,EAAE+B,MAAM;gBAC1B;YACF;QACF,GACCC,gBAAgB,CAAC,CAAC,EAAEZ,IAAI,EAAEa,QAAQ,EAAElC,KAAKiB,MAAM,EAAE,GAAM,CAAA;gBACtDkB,eAAerC,0BAA0B;oBACvCoB,gBAAgBgB,SAAShB,cAAc;oBACvCkB,SAAS;wBAAEC,KAAKhB,KAAKgB,GAAG;oBAAC;oBACzBX,UAAUQ,SAASR,QAAQ;oBAC3B1B,KAAKiB;oBACLhB,MAAMiC,SAASjC,IAAI;gBACrB;YACF,CAAA;IACJ;IAEA,MAAM,EAAEqC,IAAI,EAAE,GAAGpC,mBAAmB;QAAEuB,QAAQ;YAAEjB;QAAM;QAAG+B,QAAQ7B;IAAa;IAE9E,OAAO,CAACV,MAAQsC,KAAKtC;AACvB,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../src/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAM/C,UAAU,WAAW;IACnB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAsB,OAAO,CAAC,EAC5B,mBAAmB,EACnB,UAAU,EACV,GAAG,EACH,QAAQ,EACR,eAAe,EACf,GAAG,EACH,KAAK,GACN,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuIjC"}
1
+ {"version":3,"file":"getFile.d.ts","sourceRoot":"","sources":["../src/getFile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAU/C,UAAU,WAAW;IACnB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,cAAc,CAAA;IACnB,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAsB,OAAO,CAAC,EAC5B,mBAAmB,EACnB,UAAU,EACV,GAAG,EACH,QAAQ,EACR,eAAe,EACf,GAAG,EACH,KAAK,GACN,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAuIjC"}
package/dist/getFile.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getRangeRequestInfo } from 'payload/internal';
1
+ import { getRangeRequestInfo, isXmlMimeType, UPLOAD_CONTENT_SECURITY_POLICY } from 'payload/internal';
2
2
  import { getKeyFromFilename } from './utilities.js';
3
3
  export async function getFile({ clientUploadContext, collection, doc, filename, incomingHeaders, req, utApi }) {
4
4
  try {
@@ -102,8 +102,8 @@ export async function getFile({ clientUploadContext, collection, doc, filename,
102
102
  if (objectEtag) {
103
103
  headers.append('ETag', objectEtag);
104
104
  }
105
- if (contentType === 'image/svg+xml') {
106
- headers.append('Content-Security-Policy', "script-src 'none'");
105
+ if (isXmlMimeType(contentType)) {
106
+ headers.append('Content-Security-Policy', UPLOAD_CONTENT_SECURITY_POLICY);
107
107
  }
108
108
  if (collectionConfig?.upload && typeof collectionConfig.upload === 'object' && typeof collectionConfig.upload.modifyResponseHeaders === 'function') {
109
109
  headers = collectionConfig.upload.modifyResponseHeaders({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/getFile.ts"],"sourcesContent":["import type { PayloadRequest, Where } from 'payload'\nimport type { UTApi } from 'uploadthing/server'\n\nimport { getRangeRequestInfo } from 'payload/internal'\n\nimport { getKeyFromFilename } from './utilities.js'\n\ninterface GetFileArgs {\n clientUploadContext?: unknown\n collection: string\n doc?: Record<string, unknown>\n filename: string\n incomingHeaders: Headers\n req: PayloadRequest\n utApi: UTApi\n}\n\nexport async function getFile({\n clientUploadContext,\n collection,\n doc,\n filename,\n incomingHeaders,\n req,\n utApi,\n}: GetFileArgs): Promise<Response> {\n try {\n let key: string\n const collectionConfig = req.payload.collections[collection]?.config\n\n if (\n clientUploadContext &&\n typeof clientUploadContext === 'object' &&\n 'key' in clientUploadContext &&\n typeof clientUploadContext.key === 'string'\n ) {\n key = clientUploadContext.key\n } else {\n let retrievedDoc = doc\n\n if (!retrievedDoc) {\n const or: Where[] = [\n {\n filename: {\n equals: filename,\n },\n },\n ]\n\n if (collectionConfig?.upload.imageSizes) {\n collectionConfig.upload.imageSizes.forEach(({ name }) => {\n or.push({\n [`sizes.${name}.filename`]: {\n equals: filename,\n },\n })\n })\n }\n\n const result = await req.payload.db.findOne({\n collection,\n req,\n where: { or },\n })\n\n if (result) {\n retrievedDoc = result as Record<string, unknown>\n }\n }\n\n if (!retrievedDoc) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n key = getKeyFromFilename(retrievedDoc, filename)!\n }\n\n if (!key) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const { url: signedURL } = await utApi.getSignedURL(key)\n\n if (!signedURL) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const headResponse = await fetch(signedURL, { method: 'HEAD' })\n if (!headResponse.ok) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const fileSize = Number(headResponse.headers.get('content-length'))\n\n const rangeHeader = 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 const response = await fetch(signedURL, {\n headers:\n rangeResult.type === 'partial'\n ? { Range: `bytes=${rangeResult.rangeStart}-${rangeResult.rangeEnd}` }\n : undefined,\n })\n\n if (!response.ok || !response.body) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match')\n const objectEtag = response.headers.get('etag')\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 const contentType = response.headers.get('content-type')\n if (contentType) {\n headers.append('Content-Type', contentType)\n }\n\n if (objectEtag) {\n headers.append('ETag', objectEtag)\n }\n\n if (contentType === 'image/svg+xml') {\n headers.append('Content-Security-Policy', \"script-src 'none'\")\n }\n\n if (\n collectionConfig?.upload &&\n typeof collectionConfig.upload === 'object' &&\n typeof collectionConfig.upload.modifyResponseHeaders === 'function'\n ) {\n headers = collectionConfig.upload.modifyResponseHeaders({ headers }) || headers\n }\n\n if (etagFromHeaders && etagFromHeaders === objectEtag) {\n return new Response(null, {\n headers,\n status: 304,\n })\n }\n\n return new Response(response.body, {\n headers,\n status: rangeResult.status,\n })\n } catch (err) {\n req.payload.logger.error({ err, msg: 'Unexpected error in staticHandler' })\n return new Response('Internal Server Error', { status: 500 })\n }\n}\n"],"names":["getRangeRequestInfo","getKeyFromFilename","getFile","clientUploadContext","collection","doc","filename","incomingHeaders","req","utApi","key","collectionConfig","payload","collections","config","retrievedDoc","or","equals","upload","imageSizes","forEach","name","push","result","db","findOne","where","Response","status","statusText","url","signedURL","getSignedURL","headResponse","fetch","method","ok","fileSize","Number","headers","get","rangeHeader","rangeResult","type","Headers","response","Range","rangeStart","rangeEnd","undefined","body","etagFromHeaders","objectEtag","headerKey","value","Object","entries","append","contentType","modifyResponseHeaders","err","logger","error","msg"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/getFile.ts"],"sourcesContent":["import type { PayloadRequest, Where } from 'payload'\nimport type { UTApi } from 'uploadthing/server'\n\nimport {\n getRangeRequestInfo,\n isXmlMimeType,\n UPLOAD_CONTENT_SECURITY_POLICY,\n} from 'payload/internal'\n\nimport { getKeyFromFilename } from './utilities.js'\n\ninterface GetFileArgs {\n clientUploadContext?: unknown\n collection: string\n doc?: Record<string, unknown>\n filename: string\n incomingHeaders: Headers\n req: PayloadRequest\n utApi: UTApi\n}\n\nexport async function getFile({\n clientUploadContext,\n collection,\n doc,\n filename,\n incomingHeaders,\n req,\n utApi,\n}: GetFileArgs): Promise<Response> {\n try {\n let key: string\n const collectionConfig = req.payload.collections[collection]?.config\n\n if (\n clientUploadContext &&\n typeof clientUploadContext === 'object' &&\n 'key' in clientUploadContext &&\n typeof clientUploadContext.key === 'string'\n ) {\n key = clientUploadContext.key\n } else {\n let retrievedDoc = doc\n\n if (!retrievedDoc) {\n const or: Where[] = [\n {\n filename: {\n equals: filename,\n },\n },\n ]\n\n if (collectionConfig?.upload.imageSizes) {\n collectionConfig.upload.imageSizes.forEach(({ name }) => {\n or.push({\n [`sizes.${name}.filename`]: {\n equals: filename,\n },\n })\n })\n }\n\n const result = await req.payload.db.findOne({\n collection,\n req,\n where: { or },\n })\n\n if (result) {\n retrievedDoc = result as Record<string, unknown>\n }\n }\n\n if (!retrievedDoc) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n key = getKeyFromFilename(retrievedDoc, filename)!\n }\n\n if (!key) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const { url: signedURL } = await utApi.getSignedURL(key)\n\n if (!signedURL) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const headResponse = await fetch(signedURL, { method: 'HEAD' })\n if (!headResponse.ok) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const fileSize = Number(headResponse.headers.get('content-length'))\n\n const rangeHeader = 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 const response = await fetch(signedURL, {\n headers:\n rangeResult.type === 'partial'\n ? { Range: `bytes=${rangeResult.rangeStart}-${rangeResult.rangeEnd}` }\n : undefined,\n })\n\n if (!response.ok || !response.body) {\n return new Response(null, { status: 404, statusText: 'Not Found' })\n }\n\n const etagFromHeaders = req.headers.get('etag') || req.headers.get('if-none-match')\n const objectEtag = response.headers.get('etag')\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 const contentType = response.headers.get('content-type')\n if (contentType) {\n headers.append('Content-Type', contentType)\n }\n\n if (objectEtag) {\n headers.append('ETag', objectEtag)\n }\n\n if (isXmlMimeType(contentType)) {\n headers.append('Content-Security-Policy', UPLOAD_CONTENT_SECURITY_POLICY)\n }\n\n if (\n collectionConfig?.upload &&\n typeof collectionConfig.upload === 'object' &&\n typeof collectionConfig.upload.modifyResponseHeaders === 'function'\n ) {\n headers = collectionConfig.upload.modifyResponseHeaders({ headers }) || headers\n }\n\n if (etagFromHeaders && etagFromHeaders === objectEtag) {\n return new Response(null, {\n headers,\n status: 304,\n })\n }\n\n return new Response(response.body, {\n headers,\n status: rangeResult.status,\n })\n } catch (err) {\n req.payload.logger.error({ err, msg: 'Unexpected error in staticHandler' })\n return new Response('Internal Server Error', { status: 500 })\n }\n}\n"],"names":["getRangeRequestInfo","isXmlMimeType","UPLOAD_CONTENT_SECURITY_POLICY","getKeyFromFilename","getFile","clientUploadContext","collection","doc","filename","incomingHeaders","req","utApi","key","collectionConfig","payload","collections","config","retrievedDoc","or","equals","upload","imageSizes","forEach","name","push","result","db","findOne","where","Response","status","statusText","url","signedURL","getSignedURL","headResponse","fetch","method","ok","fileSize","Number","headers","get","rangeHeader","rangeResult","type","Headers","response","Range","rangeStart","rangeEnd","undefined","body","etagFromHeaders","objectEtag","headerKey","value","Object","entries","append","contentType","modifyResponseHeaders","err","logger","error","msg"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/storage-uploadthing",
3
- "version": "3.89.0",
3
+ "version": "3.90.0",
4
4
  "description": "Payload storage adapter for uploadthing",
5
5
  "homepage": "https://payloadcms.com",
6
6
  "repository": {
@@ -38,13 +38,13 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "uploadthing": "7.3.0",
41
- "@payloadcms/plugin-cloud-storage": "3.89.0"
41
+ "@payloadcms/plugin-cloud-storage": "3.90.0"
42
42
  },
43
43
  "devDependencies": {
44
- "payload": "3.89.0"
44
+ "payload": "3.90.0"
45
45
  },
46
46
  "peerDependencies": {
47
- "payload": "3.89.0"
47
+ "payload": "3.90.0"
48
48
  },
49
49
  "engines": {
50
50
  "node": "^18.20.2 || >=20.9.0"