@payloadcms/payload-cloud 3.0.0-alpha.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.
Files changed (55) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +93 -0
  3. package/dist/email.d.ts +6 -0
  4. package/dist/email.d.ts.map +1 -0
  5. package/dist/email.js +48 -0
  6. package/dist/email.js.map +1 -0
  7. package/dist/email.spec.d.ts +2 -0
  8. package/dist/email.spec.d.ts.map +1 -0
  9. package/dist/hooks/afterDelete.d.ts +8 -0
  10. package/dist/hooks/afterDelete.d.ts.map +1 -0
  11. package/dist/hooks/afterDelete.js +30 -0
  12. package/dist/hooks/afterDelete.js.map +1 -0
  13. package/dist/hooks/beforeChange.d.ts +7 -0
  14. package/dist/hooks/beforeChange.d.ts.map +1 -0
  15. package/dist/hooks/beforeChange.js +73 -0
  16. package/dist/hooks/beforeChange.js.map +1 -0
  17. package/dist/hooks/uploadCache.d.ts +8 -0
  18. package/dist/hooks/uploadCache.d.ts.map +1 -0
  19. package/dist/hooks/uploadCache.js +87 -0
  20. package/dist/hooks/uploadCache.js.map +1 -0
  21. package/dist/index.d.ts +4 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +5 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/plugin.d.ts +4 -0
  26. package/dist/plugin.d.ts.map +1 -0
  27. package/dist/plugin.js +88 -0
  28. package/dist/plugin.js.map +1 -0
  29. package/dist/plugin.spec.d.ts +2 -0
  30. package/dist/plugin.spec.d.ts.map +1 -0
  31. package/dist/staticHandler.d.ts +9 -0
  32. package/dist/staticHandler.d.ts.map +1 -0
  33. package/dist/staticHandler.js +65 -0
  34. package/dist/staticHandler.js.map +1 -0
  35. package/dist/types.d.ts +103 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +3 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/utilities/authAsCognitoUser.d.ts +3 -0
  40. package/dist/utilities/authAsCognitoUser.d.ts.map +1 -0
  41. package/dist/utilities/authAsCognitoUser.js +34 -0
  42. package/dist/utilities/authAsCognitoUser.js.map +1 -0
  43. package/dist/utilities/createKey.d.ts +8 -0
  44. package/dist/utilities/createKey.d.ts.map +1 -0
  45. package/dist/utilities/createKey.js +3 -0
  46. package/dist/utilities/createKey.js.map +1 -0
  47. package/dist/utilities/getIncomingFiles.d.ts +7 -0
  48. package/dist/utilities/getIncomingFiles.d.ts.map +1 -0
  49. package/dist/utilities/getIncomingFiles.js +33 -0
  50. package/dist/utilities/getIncomingFiles.js.map +1 -0
  51. package/dist/utilities/getStorageClient.d.ts +7 -0
  52. package/dist/utilities/getStorageClient.d.ts.map +1 -0
  53. package/dist/utilities/getStorageClient.js +40 -0
  54. package/dist/utilities/getStorageClient.js.map +1 -0
  55. package/package.json +53 -0
package/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2018-2022 Payload CMS, LLC <info@payloadcms.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Payload Cloud Plugin
2
+
3
+ This is the official Payload Cloud plugin that connects your Payload instance to the resources that Payload Cloud provides.
4
+
5
+ ## File storage
6
+
7
+ Payload Cloud gives you S3 file storage backed by Cloudflare as a CDN, and this plugin extends Payload so that all of your media will be stored in S3 rather than locally.
8
+
9
+ ## Email delivery
10
+
11
+ Payload Cloud provides an email delivery service out-of-the-box for all Payload Cloud customers. Powered by [Resend](https://resend.com).
12
+
13
+ ## Upload caching
14
+
15
+ Payload Cloud provides a caching for all upload collections by default through Cloudflare's CDN.
16
+
17
+ ## How to use
18
+
19
+ Add the plugin to your Payload config
20
+
21
+ `yarn add @payloadcms/payload-cloud`
22
+
23
+ ```ts
24
+ import { payloadCloud } from '@payloadcms/payload-cloud'
25
+ import { buildConfig } from 'payload'
26
+
27
+ export default buildConfig({
28
+ plugins: [payloadCloud()],
29
+ // rest of config
30
+ })
31
+ ```
32
+
33
+ NOTE: If your Payload config already has an email with transport, this will take precedence over Payload Cloud's email service.
34
+
35
+ ### From Domain
36
+
37
+ After configuring, ensure that the `from` email address is from a domain you have access to. Payload Cloud will automatically give you permissions to use your deployed domain with the value available in `process.env.PAYLOAD_CLOUD_DEFAULT_DOMAIN`. If you have custom domains, your custom domains will also be whitelisted. Attempting to send from a domain you do not have access to will not succeed.
38
+
39
+ ### Optional configuration
40
+
41
+ If you wish to opt-out of any Payload cloud features, the plugin also accepts options to do so.
42
+
43
+ ```ts
44
+ payloadCloud({
45
+ storage: false, // Disable file storage
46
+ email: false, // Disable email delivery
47
+ uploadCaching: false, // Disable upload caching
48
+ })
49
+ ```
50
+
51
+ #### Upload Caching Configuration
52
+
53
+ If you wish to configure upload caching on a per-collection basis, you can do so by passing in a keyed object of collection names. By default, all collections will be cached for 24 hours (86400 seconds). The cache is invalidated when an item is updated or deleted.
54
+
55
+ ```ts
56
+ payloadCloud({
57
+ uploadCaching: {
58
+ maxAge: 604800, // Override default maxAge for all collections
59
+ collection1Slug: {
60
+ maxAge: 10, // Collection-specific maxAge, takes precedence over others
61
+ },
62
+ collection2Slug: {
63
+ enabled: false, // Disable caching for this collection
64
+ },
65
+ },
66
+ })
67
+ ```
68
+
69
+ ### Accessing File Storage from Local Environment
70
+
71
+ This plugin works off of a specific set of environment variables in order to access your file resources. The following values must be set in your local environment in order to access your file resources:
72
+
73
+ ```txt
74
+ PAYLOAD_CLOUD=true
75
+ PAYLOAD_CLOUD_ENVIRONMENT=prod
76
+ PAYLOAD_CLOUD_COGNITO_USER_POOL_CLIENT_ID=
77
+ PAYLOAD_CLOUD_COGNITO_USER_POOL_ID=
78
+ PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID=
79
+ PAYLOAD_CLOUD_PROJECT_ID=
80
+ PAYLOAD_CLOUD_BUCKET=
81
+ PAYLOAD_CLOUD_BUCKET_REGION=
82
+ PAYLOAD_CLOUD_COGNITO_PASSWORD=
83
+ ```
84
+
85
+ ## Future enhancements
86
+
87
+ ### API CDN
88
+
89
+ In the future, this plugin will also ship with a way to dynamically cache API requests as well as purge them whenever a resource is updated.
90
+
91
+ ## When it executes
92
+
93
+ This plugin will only execute if the required environment variables set by Payload Cloud are in place. If they are not, the plugin will not execute and your Payload instance will behave as normal.
@@ -0,0 +1,6 @@
1
+ import { nodemailerAdapter } from '@payloadcms/email-nodemailer';
2
+ import type { PayloadCloudEmailOptions } from './types.js';
3
+ type NodemailerAdapter = ReturnType<typeof nodemailerAdapter>;
4
+ export declare const payloadCloudEmail: (args: PayloadCloudEmailOptions) => Promise<NodemailerAdapter> | undefined;
5
+ export {};
6
+ //# sourceMappingURL=email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAGhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAA;AAE1D,KAAK,iBAAiB,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE7D,eAAO,MAAM,iBAAiB,SACtB,wBAAwB,KAC7B,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAyD/B,CAAA"}
package/dist/email.js ADDED
@@ -0,0 +1,48 @@
1
+ import { nodemailerAdapter } from '@payloadcms/email-nodemailer';
2
+ import nodemailer from 'nodemailer';
3
+ export const payloadCloudEmail = async (args)=>{
4
+ if (process.env.PAYLOAD_CLOUD !== 'true' || !args) {
5
+ return undefined;
6
+ }
7
+ if (!args.apiKey) {
8
+ throw new Error('apiKey must be provided to use Payload Cloud Email');
9
+ }
10
+ if (!args.defaultDomain) {
11
+ throw new Error('defaultDomain must be provided to use Payload Cloud Email');
12
+ }
13
+ // Check if already has email configuration
14
+ if (args.config.email) {
15
+ // eslint-disable-next-line no-console
16
+ console.log('Payload Cloud Email is enabled but email configuration is already provided in Payload config. If this is intentional, set `email: false` in the Payload Cloud plugin options.');
17
+ return args.config.email;
18
+ }
19
+ const { apiKey, defaultDomain, skipVerify } = args;
20
+ const customDomainEnvs = Object.keys(process.env).filter((e)=>e.startsWith('PAYLOAD_CLOUD_EMAIL_DOMAIN_') && !e.endsWith('API_KEY'));
21
+ const customDomains = customDomainEnvs.map((e)=>process.env[e]).filter(Boolean);
22
+ if (customDomains.length) {
23
+ // eslint-disable-next-line no-console
24
+ console.log(`Configuring Payload Cloud Email for ${[
25
+ defaultDomain,
26
+ ...customDomains || []
27
+ ].join(', ')}`);
28
+ }
29
+ const defaultFromName = args.defaultFromName || 'Payload CMS';
30
+ const defaultFromAddress = args.defaultFromAddress || `cms@${customDomains.length ? customDomains[0] : defaultDomain}`;
31
+ const emailAdapter = await nodemailerAdapter({
32
+ defaultFromAddress,
33
+ defaultFromName,
34
+ skipVerify,
35
+ transport: nodemailer.createTransport({
36
+ auth: {
37
+ pass: apiKey,
38
+ user: 'resend'
39
+ },
40
+ host: 'smtp.resend.com',
41
+ port: 465,
42
+ secure: true
43
+ })
44
+ });
45
+ return emailAdapter;
46
+ };
47
+
48
+ //# sourceMappingURL=email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/email.ts"],"sourcesContent":["import { nodemailerAdapter } from '@payloadcms/email-nodemailer'\nimport nodemailer from 'nodemailer'\n\nimport type { PayloadCloudEmailOptions } from './types.js'\n\ntype NodemailerAdapter = ReturnType<typeof nodemailerAdapter>\n\nexport const payloadCloudEmail = async (\n args: PayloadCloudEmailOptions,\n): Promise<NodemailerAdapter> | undefined => {\n if (process.env.PAYLOAD_CLOUD !== 'true' || !args) {\n return undefined\n }\n\n if (!args.apiKey) {\n throw new Error('apiKey must be provided to use Payload Cloud Email')\n }\n if (!args.defaultDomain) {\n throw new Error('defaultDomain must be provided to use Payload Cloud Email')\n }\n\n // Check if already has email configuration\n\n if (args.config.email) {\n // eslint-disable-next-line no-console\n console.log(\n 'Payload Cloud Email is enabled but email configuration is already provided in Payload config. If this is intentional, set `email: false` in the Payload Cloud plugin options.',\n )\n return args.config.email\n }\n\n const { apiKey, defaultDomain, skipVerify } = args\n\n const customDomainEnvs = Object.keys(process.env).filter(\n (e) => e.startsWith('PAYLOAD_CLOUD_EMAIL_DOMAIN_') && !e.endsWith('API_KEY'),\n )\n\n const customDomains = customDomainEnvs.map((e) => process.env[e]).filter(Boolean)\n\n if (customDomains.length) {\n // eslint-disable-next-line no-console\n console.log(\n `Configuring Payload Cloud Email for ${[defaultDomain, ...(customDomains || [])].join(', ')}`,\n )\n }\n\n const defaultFromName = args.defaultFromName || 'Payload CMS'\n const defaultFromAddress =\n args.defaultFromAddress || `cms@${customDomains.length ? customDomains[0] : defaultDomain}`\n\n const emailAdapter = await nodemailerAdapter({\n defaultFromAddress,\n defaultFromName,\n skipVerify,\n transport: nodemailer.createTransport({\n auth: {\n pass: apiKey,\n user: 'resend',\n },\n host: 'smtp.resend.com',\n port: 465,\n secure: true,\n }),\n })\n\n return emailAdapter\n}\n"],"names":["nodemailerAdapter","nodemailer","payloadCloudEmail","args","process","env","PAYLOAD_CLOUD","undefined","apiKey","Error","defaultDomain","config","email","console","log","skipVerify","customDomainEnvs","Object","keys","filter","e","startsWith","endsWith","customDomains","map","Boolean","length","join","defaultFromName","defaultFromAddress","emailAdapter","transport","createTransport","auth","pass","user","host","port","secure"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,+BAA8B;AAChE,OAAOC,gBAAgB,aAAY;AAMnC,OAAO,MAAMC,oBAAoB,OAC/BC;IAEA,IAAIC,QAAQC,GAAG,CAACC,aAAa,KAAK,UAAU,CAACH,MAAM;QACjD,OAAOI;IACT;IAEA,IAAI,CAACJ,KAAKK,MAAM,EAAE;QAChB,MAAM,IAAIC,MAAM;IAClB;IACA,IAAI,CAACN,KAAKO,aAAa,EAAE;QACvB,MAAM,IAAID,MAAM;IAClB;IAEA,2CAA2C;IAE3C,IAAIN,KAAKQ,MAAM,CAACC,KAAK,EAAE;QACrB,sCAAsC;QACtCC,QAAQC,GAAG,CACT;QAEF,OAAOX,KAAKQ,MAAM,CAACC,KAAK;IAC1B;IAEA,MAAM,EAAEJ,MAAM,EAAEE,aAAa,EAAEK,UAAU,EAAE,GAAGZ;IAE9C,MAAMa,mBAAmBC,OAAOC,IAAI,CAACd,QAAQC,GAAG,EAAEc,MAAM,CACtD,CAACC,IAAMA,EAAEC,UAAU,CAAC,kCAAkC,CAACD,EAAEE,QAAQ,CAAC;IAGpE,MAAMC,gBAAgBP,iBAAiBQ,GAAG,CAAC,CAACJ,IAAMhB,QAAQC,GAAG,CAACe,EAAE,EAAED,MAAM,CAACM;IAEzE,IAAIF,cAAcG,MAAM,EAAE;QACxB,sCAAsC;QACtCb,QAAQC,GAAG,CACT,CAAC,oCAAoC,EAAE;YAACJ;eAAmBa,iBAAiB,EAAE;SAAE,CAACI,IAAI,CAAC,MAAM,CAAC;IAEjG;IAEA,MAAMC,kBAAkBzB,KAAKyB,eAAe,IAAI;IAChD,MAAMC,qBACJ1B,KAAK0B,kBAAkB,IAAI,CAAC,IAAI,EAAEN,cAAcG,MAAM,GAAGH,aAAa,CAAC,EAAE,GAAGb,cAAc,CAAC;IAE7F,MAAMoB,eAAe,MAAM9B,kBAAkB;QAC3C6B;QACAD;QACAb;QACAgB,WAAW9B,WAAW+B,eAAe,CAAC;YACpCC,MAAM;gBACJC,MAAM1B;gBACN2B,MAAM;YACR;YACAC,MAAM;YACNC,MAAM;YACNC,QAAQ;QACV;IACF;IAEA,OAAOR;AACT,EAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=email.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.spec.d.ts","sourceRoot":"","sources":["../src/email.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { CollectionAfterDeleteHook, CollectionConfig, FileData, TypeWithID } from 'payload';
2
+ import type { TypeWithPrefix } from '../types.js';
3
+ interface Args {
4
+ collection: CollectionConfig;
5
+ }
6
+ export declare const getAfterDeleteHook: ({ collection, }: Args) => CollectionAfterDeleteHook<FileData & TypeWithID & TypeWithPrefix>;
7
+ export {};
8
+ //# sourceMappingURL=afterDelete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"afterDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEhG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAKjD,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAED,eAAO,MAAM,kBAAkB,oBAE5B,IAAI,KAAG,yBAAyB,CAAC,QAAQ,GAAG,UAAU,GAAG,cAAc,CA0BzE,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { createKey } from '../utilities/createKey.js';
2
+ import { getStorageClient } from '../utilities/getStorageClient.js';
3
+ export const getAfterDeleteHook = ({ collection })=>{
4
+ return async ({ doc, req })=>{
5
+ try {
6
+ const { identityID, storageClient } = await getStorageClient();
7
+ const filesToDelete = [
8
+ doc.filename,
9
+ ...Object.values(doc?.sizes || []).map((resizedFileData)=>resizedFileData?.filename)
10
+ ];
11
+ const promises = filesToDelete.map(async (filename)=>{
12
+ await storageClient.deleteObject({
13
+ Bucket: process.env.PAYLOAD_CLOUD_BUCKET,
14
+ Key: createKey({
15
+ collection: collection.slug,
16
+ filename,
17
+ identityID
18
+ })
19
+ });
20
+ });
21
+ await Promise.all(promises);
22
+ } catch (err) {
23
+ req.payload.logger.error(`There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}:`);
24
+ req.payload.logger.error(err);
25
+ }
26
+ return doc;
27
+ };
28
+ };
29
+
30
+ //# sourceMappingURL=afterDelete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/afterDelete.ts"],"sourcesContent":["import type { CollectionAfterDeleteHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport type { TypeWithPrefix } from '../types.js'\n\nimport { createKey } from '../utilities/createKey.js'\nimport { getStorageClient } from '../utilities/getStorageClient.js'\n\ninterface Args {\n collection: CollectionConfig\n}\n\nexport const getAfterDeleteHook = ({\n collection,\n}: Args): CollectionAfterDeleteHook<FileData & TypeWithID & TypeWithPrefix> => {\n return async ({ doc, req }) => {\n try {\n const { identityID, storageClient } = await getStorageClient()\n\n const filesToDelete: string[] = [\n doc.filename,\n ...Object.values(doc?.sizes || []).map((resizedFileData) => resizedFileData?.filename),\n ]\n\n const promises = filesToDelete.map(async (filename) => {\n await storageClient.deleteObject({\n Bucket: process.env.PAYLOAD_CLOUD_BUCKET,\n Key: createKey({ collection: collection.slug, filename, identityID }),\n })\n })\n\n await Promise.all(promises)\n } catch (err: unknown) {\n req.payload.logger.error(\n `There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}:`,\n )\n req.payload.logger.error(err)\n }\n return doc\n }\n}\n"],"names":["createKey","getStorageClient","getAfterDeleteHook","collection","doc","req","identityID","storageClient","filesToDelete","filename","Object","values","sizes","map","resizedFileData","promises","deleteObject","Bucket","process","env","PAYLOAD_CLOUD_BUCKET","Key","slug","Promise","all","err","payload","logger","error","labels","singular","id"],"mappings":"AAIA,SAASA,SAAS,QAAQ,4BAA2B;AACrD,SAASC,gBAAgB,QAAQ,mCAAkC;AAMnE,OAAO,MAAMC,qBAAqB,CAAC,EACjCC,UAAU,EACL;IACL,OAAO,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;QACxB,IAAI;YACF,MAAM,EAAEC,UAAU,EAAEC,aAAa,EAAE,GAAG,MAAMN;YAE5C,MAAMO,gBAA0B;gBAC9BJ,IAAIK,QAAQ;mBACTC,OAAOC,MAAM,CAACP,KAAKQ,SAAS,EAAE,EAAEC,GAAG,CAAC,CAACC,kBAAoBA,iBAAiBL;aAC9E;YAED,MAAMM,WAAWP,cAAcK,GAAG,CAAC,OAAOJ;gBACxC,MAAMF,cAAcS,YAAY,CAAC;oBAC/BC,QAAQC,QAAQC,GAAG,CAACC,oBAAoB;oBACxCC,KAAKrB,UAAU;wBAAEG,YAAYA,WAAWmB,IAAI;wBAAEb;wBAAUH;oBAAW;gBACrE;YACF;YAEA,MAAMiB,QAAQC,GAAG,CAACT;QACpB,EAAE,OAAOU,KAAc;YACrBpB,IAAIqB,OAAO,CAACC,MAAM,CAACC,KAAK,CACtB,CAAC,6DAA6D,EAAEzB,WAAW0B,MAAM,EAAEC,SAAS,SAAS,EAAE1B,IAAI2B,EAAE,CAAC,CAAC,CAAC;YAElH1B,IAAIqB,OAAO,CAACC,MAAM,CAACC,KAAK,CAACH;QAC3B;QACA,OAAOrB;IACT;AACF,EAAC"}
@@ -0,0 +1,7 @@
1
+ import type { CollectionBeforeChangeHook, CollectionConfig, FileData, TypeWithID } from 'payload';
2
+ interface Args {
3
+ collection: CollectionConfig;
4
+ }
5
+ export declare const getBeforeChangeHook: ({ collection }: Args) => CollectionBeforeChangeHook<FileData & TypeWithID>;
6
+ export {};
7
+ //# sourceMappingURL=beforeChange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../src/hooks/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAUjG,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAID,eAAO,MAAM,mBAAmB,mBACb,IAAI,KAAG,0BAA0B,CAAC,QAAQ,GAAG,UAAU,CAuEvE,CAAA"}
@@ -0,0 +1,73 @@
1
+ import { Upload } from '@aws-sdk/lib-storage';
2
+ import fs from 'fs';
3
+ import { createKey } from '../utilities/createKey.js';
4
+ import { getIncomingFiles } from '../utilities/getIncomingFiles.js';
5
+ import { getStorageClient } from '../utilities/getStorageClient.js';
6
+ const MB = 1024 * 1024;
7
+ export const getBeforeChangeHook = ({ collection })=>async ({ data, req })=>{
8
+ try {
9
+ const files = getIncomingFiles({
10
+ data,
11
+ req
12
+ });
13
+ req.payload.logger.debug({
14
+ msg: `Preparing to upload ${files.length} files`
15
+ });
16
+ const { identityID, storageClient } = await getStorageClient();
17
+ const promises = files.map(async (file)=>{
18
+ const fileKey = file.filename;
19
+ req.payload.logger.debug({
20
+ fileKey,
21
+ msg: `File buffer length: ${file.buffer.length / MB}MB`,
22
+ tempFilePath: file.tempFilePath ?? 'undefined'
23
+ });
24
+ const fileBufferOrStream = file.tempFilePath ? fs.createReadStream(file.tempFilePath) : file.buffer;
25
+ if (file.buffer.length > 0) {
26
+ req.payload.logger.debug({
27
+ fileKey,
28
+ msg: `Uploading ${fileKey} from buffer. Size: ${file.buffer.length / MB}MB`
29
+ });
30
+ await storageClient.putObject({
31
+ Body: fileBufferOrStream,
32
+ Bucket: process.env.PAYLOAD_CLOUD_BUCKET,
33
+ ContentType: file.mimeType,
34
+ Key: createKey({
35
+ collection: collection.slug,
36
+ filename: fileKey,
37
+ identityID
38
+ })
39
+ });
40
+ }
41
+ // This will buffer at max 4 * 5MB = 20MB. Default queueSize is 4 and default partSize is 5MB.
42
+ const parallelUploadS3 = new Upload({
43
+ client: storageClient,
44
+ params: {
45
+ Body: fileBufferOrStream,
46
+ Bucket: process.env.PAYLOAD_CLOUD_BUCKET,
47
+ ContentType: file.mimeType,
48
+ Key: createKey({
49
+ collection: collection.slug,
50
+ filename: fileKey,
51
+ identityID
52
+ })
53
+ }
54
+ });
55
+ parallelUploadS3.on('httpUploadProgress', (progress)=>{
56
+ if (progress.total) {
57
+ req.payload.logger.debug({
58
+ fileKey,
59
+ msg: `Uploaded part ${progress.part} - ${(progress.loaded || 0) / MB}MB out of ${(progress.total || 0) / MB}MB`
60
+ });
61
+ }
62
+ });
63
+ await parallelUploadS3.done();
64
+ });
65
+ await Promise.all(promises);
66
+ } catch (err) {
67
+ req.payload.logger.error(`There was an error while uploading files corresponding to the collection ${collection.slug} with filename ${data.filename}:`);
68
+ req.payload.logger.error(err);
69
+ }
70
+ return data;
71
+ };
72
+
73
+ //# sourceMappingURL=beforeChange.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/beforeChange.ts"],"sourcesContent":["import type { CollectionBeforeChangeHook, CollectionConfig, FileData, TypeWithID } from 'payload'\nimport type stream from 'stream'\n\nimport { Upload } from '@aws-sdk/lib-storage'\nimport fs from 'fs'\n\nimport { createKey } from '../utilities/createKey.js'\nimport { getIncomingFiles } from '../utilities/getIncomingFiles.js'\nimport { getStorageClient } from '../utilities/getStorageClient.js'\n\ninterface Args {\n collection: CollectionConfig\n}\n\nconst MB = 1024 * 1024\n\nexport const getBeforeChangeHook =\n ({ collection }: Args): CollectionBeforeChangeHook<FileData & TypeWithID> =>\n async ({ data, req }) => {\n try {\n const files = getIncomingFiles({ data, req })\n\n req.payload.logger.debug({\n msg: `Preparing to upload ${files.length} files`,\n })\n\n const { identityID, storageClient } = await getStorageClient()\n\n const promises = files.map(async (file) => {\n const fileKey = file.filename\n\n req.payload.logger.debug({\n fileKey,\n msg: `File buffer length: ${file.buffer.length / MB}MB`,\n tempFilePath: file.tempFilePath ?? 'undefined',\n })\n\n const fileBufferOrStream: Buffer | stream.Readable = file.tempFilePath\n ? fs.createReadStream(file.tempFilePath)\n : file.buffer\n\n if (file.buffer.length > 0) {\n req.payload.logger.debug({\n fileKey,\n msg: `Uploading ${fileKey} from buffer. Size: ${file.buffer.length / MB}MB`,\n })\n\n await storageClient.putObject({\n Body: fileBufferOrStream,\n Bucket: process.env.PAYLOAD_CLOUD_BUCKET,\n ContentType: file.mimeType,\n Key: createKey({ collection: collection.slug, filename: fileKey, identityID }),\n })\n }\n\n // This will buffer at max 4 * 5MB = 20MB. Default queueSize is 4 and default partSize is 5MB.\n const parallelUploadS3 = new Upload({\n client: storageClient,\n params: {\n Body: fileBufferOrStream,\n Bucket: process.env.PAYLOAD_CLOUD_BUCKET,\n ContentType: file.mimeType,\n Key: createKey({ collection: collection.slug, filename: fileKey, identityID }),\n },\n })\n\n parallelUploadS3.on('httpUploadProgress', (progress) => {\n if (progress.total) {\n req.payload.logger.debug({\n fileKey,\n msg: `Uploaded part ${progress.part} - ${(progress.loaded || 0) / MB}MB out of ${\n (progress.total || 0) / MB\n }MB`,\n })\n }\n })\n\n await parallelUploadS3.done()\n })\n\n await Promise.all(promises)\n } catch (err: unknown) {\n req.payload.logger.error(\n `There was an error while uploading files corresponding to the collection ${collection.slug} with filename ${data.filename}:`,\n )\n req.payload.logger.error(err)\n }\n return data\n }\n"],"names":["Upload","fs","createKey","getIncomingFiles","getStorageClient","MB","getBeforeChangeHook","collection","data","req","files","payload","logger","debug","msg","length","identityID","storageClient","promises","map","file","fileKey","filename","buffer","tempFilePath","fileBufferOrStream","createReadStream","putObject","Body","Bucket","process","env","PAYLOAD_CLOUD_BUCKET","ContentType","mimeType","Key","slug","parallelUploadS3","client","params","on","progress","total","part","loaded","done","Promise","all","err","error"],"mappings":"AAGA,SAASA,MAAM,QAAQ,uBAAsB;AAC7C,OAAOC,QAAQ,KAAI;AAEnB,SAASC,SAAS,QAAQ,4BAA2B;AACrD,SAASC,gBAAgB,QAAQ,mCAAkC;AACnE,SAASC,gBAAgB,QAAQ,mCAAkC;AAMnE,MAAMC,KAAK,OAAO;AAElB,OAAO,MAAMC,sBACX,CAAC,EAAEC,UAAU,EAAQ,GACrB,OAAO,EAAEC,IAAI,EAAEC,GAAG,EAAE;QAClB,IAAI;YACF,MAAMC,QAAQP,iBAAiB;gBAAEK;gBAAMC;YAAI;YAE3CA,IAAIE,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;gBACvBC,KAAK,CAAC,oBAAoB,EAAEJ,MAAMK,MAAM,CAAC,MAAM,CAAC;YAClD;YAEA,MAAM,EAAEC,UAAU,EAAEC,aAAa,EAAE,GAAG,MAAMb;YAE5C,MAAMc,WAAWR,MAAMS,GAAG,CAAC,OAAOC;gBAChC,MAAMC,UAAUD,KAAKE,QAAQ;gBAE7Bb,IAAIE,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;oBACvBQ;oBACAP,KAAK,CAAC,oBAAoB,EAAEM,KAAKG,MAAM,CAACR,MAAM,GAAGV,GAAG,EAAE,CAAC;oBACvDmB,cAAcJ,KAAKI,YAAY,IAAI;gBACrC;gBAEA,MAAMC,qBAA+CL,KAAKI,YAAY,GAClEvB,GAAGyB,gBAAgB,CAACN,KAAKI,YAAY,IACrCJ,KAAKG,MAAM;gBAEf,IAAIH,KAAKG,MAAM,CAACR,MAAM,GAAG,GAAG;oBAC1BN,IAAIE,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;wBACvBQ;wBACAP,KAAK,CAAC,UAAU,EAAEO,QAAQ,oBAAoB,EAAED,KAAKG,MAAM,CAACR,MAAM,GAAGV,GAAG,EAAE,CAAC;oBAC7E;oBAEA,MAAMY,cAAcU,SAAS,CAAC;wBAC5BC,MAAMH;wBACNI,QAAQC,QAAQC,GAAG,CAACC,oBAAoB;wBACxCC,aAAab,KAAKc,QAAQ;wBAC1BC,KAAKjC,UAAU;4BAAEK,YAAYA,WAAW6B,IAAI;4BAAEd,UAAUD;4BAASL;wBAAW;oBAC9E;gBACF;gBAEA,8FAA8F;gBAC9F,MAAMqB,mBAAmB,IAAIrC,OAAO;oBAClCsC,QAAQrB;oBACRsB,QAAQ;wBACNX,MAAMH;wBACNI,QAAQC,QAAQC,GAAG,CAACC,oBAAoB;wBACxCC,aAAab,KAAKc,QAAQ;wBAC1BC,KAAKjC,UAAU;4BAAEK,YAAYA,WAAW6B,IAAI;4BAAEd,UAAUD;4BAASL;wBAAW;oBAC9E;gBACF;gBAEAqB,iBAAiBG,EAAE,CAAC,sBAAsB,CAACC;oBACzC,IAAIA,SAASC,KAAK,EAAE;wBAClBjC,IAAIE,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;4BACvBQ;4BACAP,KAAK,CAAC,cAAc,EAAE2B,SAASE,IAAI,CAAC,GAAG,EAAE,AAACF,CAAAA,SAASG,MAAM,IAAI,CAAA,IAAKvC,GAAG,UAAU,EAC7E,AAACoC,CAAAA,SAASC,KAAK,IAAI,CAAA,IAAKrC,GACzB,EAAE,CAAC;wBACN;oBACF;gBACF;gBAEA,MAAMgC,iBAAiBQ,IAAI;YAC7B;YAEA,MAAMC,QAAQC,GAAG,CAAC7B;QACpB,EAAE,OAAO8B,KAAc;YACrBvC,IAAIE,OAAO,CAACC,MAAM,CAACqC,KAAK,CACtB,CAAC,yEAAyE,EAAE1C,WAAW6B,IAAI,CAAC,eAAe,EAAE5B,KAAKc,QAAQ,CAAC,CAAC,CAAC;YAE/Hb,IAAIE,OAAO,CAACC,MAAM,CAACqC,KAAK,CAACD;QAC3B;QACA,OAAOxC;IACT,EAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload';
2
+ interface Args {
3
+ endpoint: string;
4
+ }
5
+ export declare const getCacheUploadsAfterChangeHook: ({ endpoint }: Args) => CollectionAfterChangeHook;
6
+ export declare const getCacheUploadsAfterDeleteHook: ({ endpoint }: Args) => CollectionAfterDeleteHook;
7
+ export {};
8
+ //# sourceMappingURL=uploadCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadCache.d.ts","sourceRoot":"","sources":["../../src/hooks/uploadCache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,yBAAyB,EAAkB,MAAM,SAAS,CAAA;AAEnG,UAAU,IAAI;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,8BAA8B,iBAC1B,IAAI,KAAG,yBAgBrB,CAAA;AAEH,eAAO,MAAM,8BAA8B,iBAC1B,IAAI,KAAG,yBAerB,CAAA"}
@@ -0,0 +1,87 @@
1
+ export const getCacheUploadsAfterChangeHook = ({ endpoint })=>({ doc, operation, req })=>{
2
+ if (!req || !process.env.PAYLOAD_CLOUD_CACHE_KEY) {
3
+ return doc;
4
+ }
5
+ // WARNING:
6
+ // TODO: Test this for 3.0
7
+ const { payloadAPI } = req;
8
+ if (payloadAPI !== 'local') {
9
+ if (operation === 'update') {
10
+ // Unawaited promise
11
+ void purge({
12
+ doc,
13
+ endpoint,
14
+ operation,
15
+ req
16
+ });
17
+ }
18
+ }
19
+ return doc;
20
+ };
21
+ export const getCacheUploadsAfterDeleteHook = ({ endpoint })=>({ doc, req })=>{
22
+ if (!req || !process.env.PAYLOAD_CLOUD_CACHE_KEY) {
23
+ return doc;
24
+ }
25
+ const { payloadAPI } = req;
26
+ // WARNING:
27
+ // TODO: Test this for 3.0
28
+ if (payloadAPI !== 'local') {
29
+ // Unawaited promise
30
+ void purge({
31
+ doc,
32
+ endpoint,
33
+ operation: 'delete',
34
+ req
35
+ });
36
+ }
37
+ return doc;
38
+ };
39
+ async function purge({ doc, endpoint, operation, req }) {
40
+ const filePath = doc.url;
41
+ if (!filePath) {
42
+ req.payload.logger.error({
43
+ msg: 'No url found on doc',
44
+ project: {
45
+ id: process.env.PAYLOAD_CLOUD_PROJECT_ID
46
+ }
47
+ });
48
+ return;
49
+ }
50
+ const body = {
51
+ cacheKey: process.env.PAYLOAD_CLOUD_CACHE_KEY,
52
+ filepath: doc.url,
53
+ projectID: process.env.PAYLOAD_CLOUD_PROJECT_ID
54
+ };
55
+ req.payload.logger.debug({
56
+ filepath: doc.url,
57
+ msg: 'Attempting to purge cache',
58
+ operation,
59
+ project: {
60
+ id: process.env.PAYLOAD_CLOUD_PROJECT_ID
61
+ }
62
+ });
63
+ try {
64
+ const purgeRes = await fetch(`${endpoint}/api/purge-cache`, {
65
+ body: JSON.stringify({
66
+ ...body
67
+ }),
68
+ headers: {
69
+ 'Content-Type': 'application/json'
70
+ },
71
+ method: 'POST'
72
+ });
73
+ req.payload.logger.debug({
74
+ msg: 'Purge cache result',
75
+ operation,
76
+ statusCode: purgeRes.status
77
+ });
78
+ } catch (err) {
79
+ req.payload.logger.error({
80
+ body,
81
+ err,
82
+ msg: '/purge-cache call failed'
83
+ });
84
+ }
85
+ }
86
+
87
+ //# sourceMappingURL=uploadCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/uploadCache.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, PayloadRequest } from 'payload'\n\ninterface Args {\n endpoint: string\n}\n\nexport const getCacheUploadsAfterChangeHook =\n ({ endpoint }: Args): CollectionAfterChangeHook =>\n ({ doc, operation, req }) => {\n if (!req || !process.env.PAYLOAD_CLOUD_CACHE_KEY) {\n return doc\n }\n\n // WARNING:\n // TODO: Test this for 3.0\n const { payloadAPI } = req\n if (payloadAPI !== 'local') {\n if (operation === 'update') {\n // Unawaited promise\n void purge({ doc, endpoint, operation, req })\n }\n }\n return doc\n }\n\nexport const getCacheUploadsAfterDeleteHook =\n ({ endpoint }: Args): CollectionAfterDeleteHook =>\n ({ doc, req }) => {\n if (!req || !process.env.PAYLOAD_CLOUD_CACHE_KEY) {\n return doc\n }\n\n const { payloadAPI } = req\n\n // WARNING:\n // TODO: Test this for 3.0\n if (payloadAPI !== 'local') {\n // Unawaited promise\n void purge({ doc, endpoint, operation: 'delete', req })\n }\n return doc\n }\n\ntype PurgeRequest = {\n doc: any\n endpoint: string\n operation: string\n req: PayloadRequest\n}\n\nasync function purge({ doc, endpoint, operation, req }: PurgeRequest) {\n const filePath = doc.url\n\n if (!filePath) {\n req.payload.logger.error({\n msg: 'No url found on doc',\n project: {\n id: process.env.PAYLOAD_CLOUD_PROJECT_ID,\n },\n })\n return\n }\n\n const body = {\n cacheKey: process.env.PAYLOAD_CLOUD_CACHE_KEY,\n filepath: doc.url,\n projectID: process.env.PAYLOAD_CLOUD_PROJECT_ID,\n }\n req.payload.logger.debug({\n filepath: doc.url,\n msg: 'Attempting to purge cache',\n operation,\n project: {\n id: process.env.PAYLOAD_CLOUD_PROJECT_ID,\n },\n })\n\n try {\n const purgeRes = await fetch(`${endpoint}/api/purge-cache`, {\n body: JSON.stringify({\n ...body,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n })\n\n req.payload.logger.debug({\n msg: 'Purge cache result',\n operation,\n statusCode: purgeRes.status,\n })\n } catch (err: unknown) {\n req.payload.logger.error({ body, err, msg: '/purge-cache call failed' })\n }\n}\n"],"names":["getCacheUploadsAfterChangeHook","endpoint","doc","operation","req","process","env","PAYLOAD_CLOUD_CACHE_KEY","payloadAPI","purge","getCacheUploadsAfterDeleteHook","filePath","url","payload","logger","error","msg","project","id","PAYLOAD_CLOUD_PROJECT_ID","body","cacheKey","filepath","projectID","debug","purgeRes","fetch","JSON","stringify","headers","method","statusCode","status","err"],"mappings":"AAMA,OAAO,MAAMA,iCACX,CAAC,EAAEC,QAAQ,EAAQ,GACnB,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAEC,GAAG,EAAE;QACtB,IAAI,CAACA,OAAO,CAACC,QAAQC,GAAG,CAACC,uBAAuB,EAAE;YAChD,OAAOL;QACT;QAEA,WAAW;QACX,0BAA0B;QAC1B,MAAM,EAAEM,UAAU,EAAE,GAAGJ;QACvB,IAAII,eAAe,SAAS;YAC1B,IAAIL,cAAc,UAAU;gBAC1B,oBAAoB;gBACpB,KAAKM,MAAM;oBAAEP;oBAAKD;oBAAUE;oBAAWC;gBAAI;YAC7C;QACF;QACA,OAAOF;IACT,EAAC;AAEH,OAAO,MAAMQ,iCACX,CAAC,EAAET,QAAQ,EAAQ,GACnB,CAAC,EAAEC,GAAG,EAAEE,GAAG,EAAE;QACX,IAAI,CAACA,OAAO,CAACC,QAAQC,GAAG,CAACC,uBAAuB,EAAE;YAChD,OAAOL;QACT;QAEA,MAAM,EAAEM,UAAU,EAAE,GAAGJ;QAEvB,WAAW;QACX,0BAA0B;QAC1B,IAAII,eAAe,SAAS;YAC1B,oBAAoB;YACpB,KAAKC,MAAM;gBAAEP;gBAAKD;gBAAUE,WAAW;gBAAUC;YAAI;QACvD;QACA,OAAOF;IACT,EAAC;AASH,eAAeO,MAAM,EAAEP,GAAG,EAAED,QAAQ,EAAEE,SAAS,EAAEC,GAAG,EAAgB;IAClE,MAAMO,WAAWT,IAAIU,GAAG;IAExB,IAAI,CAACD,UAAU;QACbP,IAAIS,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;YACvBC,KAAK;YACLC,SAAS;gBACPC,IAAIb,QAAQC,GAAG,CAACa,wBAAwB;YAC1C;QACF;QACA;IACF;IAEA,MAAMC,OAAO;QACXC,UAAUhB,QAAQC,GAAG,CAACC,uBAAuB;QAC7Ce,UAAUpB,IAAIU,GAAG;QACjBW,WAAWlB,QAAQC,GAAG,CAACa,wBAAwB;IACjD;IACAf,IAAIS,OAAO,CAACC,MAAM,CAACU,KAAK,CAAC;QACvBF,UAAUpB,IAAIU,GAAG;QACjBI,KAAK;QACLb;QACAc,SAAS;YACPC,IAAIb,QAAQC,GAAG,CAACa,wBAAwB;QAC1C;IACF;IAEA,IAAI;QACF,MAAMM,WAAW,MAAMC,MAAM,CAAC,EAAEzB,SAAS,gBAAgB,CAAC,EAAE;YAC1DmB,MAAMO,KAAKC,SAAS,CAAC;gBACnB,GAAGR,IAAI;YACT;YACAS,SAAS;gBACP,gBAAgB;YAClB;YACAC,QAAQ;QACV;QAEA1B,IAAIS,OAAO,CAACC,MAAM,CAACU,KAAK,CAAC;YACvBR,KAAK;YACLb;YACA4B,YAAYN,SAASO,MAAM;QAC7B;IACF,EAAE,OAAOC,KAAc;QACrB7B,IAAIS,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;YAAEK;YAAMa;YAAKjB,KAAK;QAA2B;IACxE;AACF"}
@@ -0,0 +1,4 @@
1
+ export { payloadCloudPlugin } from './plugin.js';
2
+ export { createKey } from './utilities/createKey.js';
3
+ export { getStorageClient } from './utilities/getStorageClient.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { payloadCloudPlugin } from './plugin.js';
2
+ export { createKey } from './utilities/createKey.js';
3
+ export { getStorageClient } from './utilities/getStorageClient.js';
4
+
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { payloadCloudPlugin } from './plugin.js'\nexport { createKey } from './utilities/createKey.js'\nexport { getStorageClient } from './utilities/getStorageClient.js'\n"],"names":["payloadCloudPlugin","createKey","getStorageClient"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,cAAa;AAChD,SAASC,SAAS,QAAQ,2BAA0B;AACpD,SAASC,gBAAgB,QAAQ,kCAAiC"}
@@ -0,0 +1,4 @@
1
+ import type { Config } from 'payload';
2
+ import type { PluginOptions } from './types.js';
3
+ export declare const payloadCloudPlugin: (pluginOptions?: PluginOptions) => (incomingConfig: Config) => Promise<Config>;
4
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAW/C,eAAO,MAAM,kBAAkB,mBACZ,aAAa,sBACP,MAAM,KAAG,OAAO,CAAC,MAAM,CAiF7C,CAAA"}
package/dist/plugin.js ADDED
@@ -0,0 +1,88 @@
1
+ import { payloadCloudEmail } from './email.js';
2
+ import { getAfterDeleteHook } from './hooks/afterDelete.js';
3
+ import { getBeforeChangeHook } from './hooks/beforeChange.js';
4
+ import { getCacheUploadsAfterChangeHook, getCacheUploadsAfterDeleteHook } from './hooks/uploadCache.js';
5
+ import { getStaticHandler } from './staticHandler.js';
6
+ export const payloadCloudPlugin = (pluginOptions)=>async (incomingConfig)=>{
7
+ let config = {
8
+ ...incomingConfig
9
+ };
10
+ if (process.env.PAYLOAD_CLOUD !== 'true') {
11
+ return config;
12
+ }
13
+ const cachingEnabled = pluginOptions?.uploadCaching !== false && !!process.env.PAYLOAD_CLOUD_CACHE_KEY;
14
+ const apiEndpoint = pluginOptions?.endpoint || 'https://cloud-api.payloadcms.com';
15
+ // Configure cloud storage
16
+ if (pluginOptions?.storage !== false) {
17
+ config = {
18
+ ...config,
19
+ collections: (config.collections || []).map((collection)=>{
20
+ if (collection.upload) {
21
+ return {
22
+ ...collection,
23
+ hooks: {
24
+ ...collection.hooks || {},
25
+ afterChange: [
26
+ ...collection.hooks?.afterChange || [],
27
+ ...cachingEnabled ? [
28
+ getCacheUploadsAfterChangeHook({
29
+ endpoint: apiEndpoint
30
+ })
31
+ ] : []
32
+ ],
33
+ afterDelete: [
34
+ ...collection.hooks?.afterDelete || [],
35
+ getAfterDeleteHook({
36
+ collection
37
+ }),
38
+ ...cachingEnabled ? [
39
+ getCacheUploadsAfterDeleteHook({
40
+ endpoint: apiEndpoint
41
+ })
42
+ ] : []
43
+ ],
44
+ beforeChange: [
45
+ ...collection.hooks?.beforeChange || [],
46
+ getBeforeChangeHook({
47
+ collection
48
+ })
49
+ ]
50
+ },
51
+ upload: {
52
+ ...typeof collection.upload === 'object' ? collection.upload : {},
53
+ disableLocalStorage: true,
54
+ handlers: [
55
+ ...typeof collection.upload === 'object' && Array.isArray(collection.upload.handlers) ? collection.upload.handlers : [],
56
+ getStaticHandler({
57
+ cachingOptions: pluginOptions?.uploadCaching,
58
+ collection
59
+ })
60
+ ]
61
+ }
62
+ };
63
+ }
64
+ return collection;
65
+ }),
66
+ upload: {
67
+ ...config.upload || {},
68
+ useTempFiles: true
69
+ }
70
+ };
71
+ }
72
+ // Configure cloud email
73
+ const apiKey = process.env.PAYLOAD_CLOUD_EMAIL_API_KEY;
74
+ const defaultDomain = process.env.PAYLOAD_CLOUD_DEFAULT_DOMAIN;
75
+ if (pluginOptions?.email !== false && apiKey && defaultDomain) {
76
+ config.email = await payloadCloudEmail({
77
+ apiKey,
78
+ config,
79
+ defaultDomain,
80
+ defaultFromAddress: pluginOptions?.email?.defaultFromAddress,
81
+ defaultFromName: pluginOptions?.email?.defaultFromName,
82
+ skipVerify: pluginOptions?.email?.skipVerify
83
+ });
84
+ }
85
+ return config;
86
+ };
87
+
88
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { PluginOptions } from './types.js'\n\nimport { payloadCloudEmail } from './email.js'\nimport { getAfterDeleteHook } from './hooks/afterDelete.js'\nimport { getBeforeChangeHook } from './hooks/beforeChange.js'\nimport {\n getCacheUploadsAfterChangeHook,\n getCacheUploadsAfterDeleteHook,\n} from './hooks/uploadCache.js'\nimport { getStaticHandler } from './staticHandler.js'\n\nexport const payloadCloudPlugin =\n (pluginOptions?: PluginOptions) =>\n async (incomingConfig: Config): Promise<Config> => {\n let config = { ...incomingConfig }\n\n if (process.env.PAYLOAD_CLOUD !== 'true') {\n return config\n }\n\n const cachingEnabled =\n pluginOptions?.uploadCaching !== false && !!process.env.PAYLOAD_CLOUD_CACHE_KEY\n\n const apiEndpoint = pluginOptions?.endpoint || 'https://cloud-api.payloadcms.com'\n\n // Configure cloud storage\n if (pluginOptions?.storage !== false) {\n config = {\n ...config,\n collections: (config.collections || []).map((collection) => {\n if (collection.upload) {\n return {\n ...collection,\n hooks: {\n ...(collection.hooks || {}),\n afterChange: [\n ...(collection.hooks?.afterChange || []),\n ...(cachingEnabled\n ? [getCacheUploadsAfterChangeHook({ endpoint: apiEndpoint })]\n : []),\n ],\n afterDelete: [\n ...(collection.hooks?.afterDelete || []),\n getAfterDeleteHook({ collection }),\n ...(cachingEnabled\n ? [getCacheUploadsAfterDeleteHook({ endpoint: apiEndpoint })]\n : []),\n ],\n beforeChange: [\n ...(collection.hooks?.beforeChange || []),\n getBeforeChangeHook({ collection }),\n ],\n },\n upload: {\n ...(typeof collection.upload === 'object' ? collection.upload : {}),\n disableLocalStorage: true,\n handlers: [\n ...(typeof collection.upload === 'object' &&\n Array.isArray(collection.upload.handlers)\n ? collection.upload.handlers\n : []),\n getStaticHandler({\n cachingOptions: pluginOptions?.uploadCaching,\n collection,\n }),\n ],\n },\n }\n }\n\n return collection\n }),\n upload: {\n ...(config.upload || {}),\n useTempFiles: true,\n },\n }\n }\n\n // Configure cloud email\n const apiKey = process.env.PAYLOAD_CLOUD_EMAIL_API_KEY\n const defaultDomain = process.env.PAYLOAD_CLOUD_DEFAULT_DOMAIN\n if (pluginOptions?.email !== false && apiKey && defaultDomain) {\n config.email = await payloadCloudEmail({\n apiKey,\n config,\n defaultDomain,\n defaultFromAddress: pluginOptions?.email?.defaultFromAddress,\n defaultFromName: pluginOptions?.email?.defaultFromName,\n skipVerify: pluginOptions?.email?.skipVerify,\n })\n }\n\n return config\n }\n"],"names":["payloadCloudEmail","getAfterDeleteHook","getBeforeChangeHook","getCacheUploadsAfterChangeHook","getCacheUploadsAfterDeleteHook","getStaticHandler","payloadCloudPlugin","pluginOptions","incomingConfig","config","process","env","PAYLOAD_CLOUD","cachingEnabled","uploadCaching","PAYLOAD_CLOUD_CACHE_KEY","apiEndpoint","endpoint","storage","collections","map","collection","upload","hooks","afterChange","afterDelete","beforeChange","disableLocalStorage","handlers","Array","isArray","cachingOptions","useTempFiles","apiKey","PAYLOAD_CLOUD_EMAIL_API_KEY","defaultDomain","PAYLOAD_CLOUD_DEFAULT_DOMAIN","email","defaultFromAddress","defaultFromName","skipVerify"],"mappings":"AAIA,SAASA,iBAAiB,QAAQ,aAAY;AAC9C,SAASC,kBAAkB,QAAQ,yBAAwB;AAC3D,SAASC,mBAAmB,QAAQ,0BAAyB;AAC7D,SACEC,8BAA8B,EAC9BC,8BAA8B,QACzB,yBAAwB;AAC/B,SAASC,gBAAgB,QAAQ,qBAAoB;AAErD,OAAO,MAAMC,qBACX,CAACC,gBACD,OAAOC;QACL,IAAIC,SAAS;YAAE,GAAGD,cAAc;QAAC;QAEjC,IAAIE,QAAQC,GAAG,CAACC,aAAa,KAAK,QAAQ;YACxC,OAAOH;QACT;QAEA,MAAMI,iBACJN,eAAeO,kBAAkB,SAAS,CAAC,CAACJ,QAAQC,GAAG,CAACI,uBAAuB;QAEjF,MAAMC,cAAcT,eAAeU,YAAY;QAE/C,0BAA0B;QAC1B,IAAIV,eAAeW,YAAY,OAAO;YACpCT,SAAS;gBACP,GAAGA,MAAM;gBACTU,aAAa,AAACV,CAAAA,OAAOU,WAAW,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;oBAC3C,IAAIA,WAAWC,MAAM,EAAE;wBACrB,OAAO;4BACL,GAAGD,UAAU;4BACbE,OAAO;gCACL,GAAIF,WAAWE,KAAK,IAAI,CAAC,CAAC;gCAC1BC,aAAa;uCACPH,WAAWE,KAAK,EAAEC,eAAe,EAAE;uCACnCX,iBACA;wCAACV,+BAA+B;4CAAEc,UAAUD;wCAAY;qCAAG,GAC3D,EAAE;iCACP;gCACDS,aAAa;uCACPJ,WAAWE,KAAK,EAAEE,eAAe,EAAE;oCACvCxB,mBAAmB;wCAAEoB;oCAAW;uCAC5BR,iBACA;wCAACT,+BAA+B;4CAAEa,UAAUD;wCAAY;qCAAG,GAC3D,EAAE;iCACP;gCACDU,cAAc;uCACRL,WAAWE,KAAK,EAAEG,gBAAgB,EAAE;oCACxCxB,oBAAoB;wCAAEmB;oCAAW;iCAClC;4BACH;4BACAC,QAAQ;gCACN,GAAI,OAAOD,WAAWC,MAAM,KAAK,WAAWD,WAAWC,MAAM,GAAG,CAAC,CAAC;gCAClEK,qBAAqB;gCACrBC,UAAU;uCACJ,OAAOP,WAAWC,MAAM,KAAK,YACjCO,MAAMC,OAAO,CAACT,WAAWC,MAAM,CAACM,QAAQ,IACpCP,WAAWC,MAAM,CAACM,QAAQ,GAC1B,EAAE;oCACNvB,iBAAiB;wCACf0B,gBAAgBxB,eAAeO;wCAC/BO;oCACF;iCACD;4BACH;wBACF;oBACF;oBAEA,OAAOA;gBACT;gBACAC,QAAQ;oBACN,GAAIb,OAAOa,MAAM,IAAI,CAAC,CAAC;oBACvBU,cAAc;gBAChB;YACF;QACF;QAEA,wBAAwB;QACxB,MAAMC,SAASvB,QAAQC,GAAG,CAACuB,2BAA2B;QACtD,MAAMC,gBAAgBzB,QAAQC,GAAG,CAACyB,4BAA4B;QAC9D,IAAI7B,eAAe8B,UAAU,SAASJ,UAAUE,eAAe;YAC7D1B,OAAO4B,KAAK,GAAG,MAAMrC,kBAAkB;gBACrCiC;gBACAxB;gBACA0B;gBACAG,oBAAoB/B,eAAe8B,OAAOC;gBAC1CC,iBAAiBhC,eAAe8B,OAAOE;gBACvCC,YAAYjC,eAAe8B,OAAOG;YACpC;QACF;QAEA,OAAO/B;IACT,EAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plugin.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.spec.d.ts","sourceRoot":"","sources":["../src/plugin.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ import type { PluginOptions, StaticHandler } from './types.js';
3
+ interface Args {
4
+ cachingOptions?: PluginOptions['uploadCaching'];
5
+ collection: CollectionConfig;
6
+ }
7
+ export declare const getStaticHandler: ({ cachingOptions, collection }: Args) => StaticHandler;
8
+ export {};
9
+ //# sourceMappingURL=staticHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staticHandler.d.ts","sourceRoot":"","sources":["../src/staticHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE/C,OAAO,KAAK,EAA2B,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAKvF,UAAU,IAAI;IACZ,cAAc,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAA;IAC/C,UAAU,EAAE,gBAAgB,CAAA;CAC7B;AAWD,eAAO,MAAM,gBAAgB,mCAAoC,IAAI,KAAG,aAoDvE,CAAA"}
@@ -0,0 +1,65 @@
1
+ import { createKey } from './utilities/createKey.js';
2
+ import { getStorageClient } from './utilities/getStorageClient.js';
3
+ // Convert a stream into a promise that resolves with a Buffer
4
+ const streamToBuffer = async (readableStream)=>{
5
+ const chunks = [];
6
+ for await (const chunk of readableStream){
7
+ chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
8
+ }
9
+ return Buffer.concat(chunks);
10
+ };
11
+ export const getStaticHandler = ({ cachingOptions, collection })=>{
12
+ let maxAge = 86400 // 24 hours default
13
+ ;
14
+ let collCacheConfig;
15
+ if (cachingOptions !== false) {
16
+ // Set custom maxAge for all collections
17
+ maxAge = cachingOptions?.maxAge || maxAge;
18
+ collCacheConfig = cachingOptions?.collections?.[collection.slug] || {};
19
+ }
20
+ // Set maxAge using collection-specific override
21
+ maxAge = collCacheConfig?.maxAge || maxAge;
22
+ const cachingEnabled = cachingOptions !== false && !!process.env.PAYLOAD_CLOUD_CACHE_KEY && collCacheConfig?.enabled !== false;
23
+ return async (req, { params })=>{
24
+ try {
25
+ const { identityID, storageClient } = await getStorageClient();
26
+ const Key = createKey({
27
+ collection: collection.slug,
28
+ filename: params.filename,
29
+ identityID
30
+ });
31
+ const object = await storageClient.getObject({
32
+ Bucket: process.env.PAYLOAD_CLOUD_BUCKET,
33
+ Key
34
+ });
35
+ if (!object.Body) {
36
+ return new Response(null, {
37
+ status: 404,
38
+ statusText: 'Not Found'
39
+ });
40
+ }
41
+ const bodyBuffer = await streamToBuffer(object.Body);
42
+ return new Response(bodyBuffer, {
43
+ headers: new Headers({
44
+ 'Content-Length': String(object.ContentLength),
45
+ 'Content-Type': object.ContentType,
46
+ ...cachingEnabled && {
47
+ 'Cache-Control': `public, max-age=${maxAge}`
48
+ },
49
+ ETag: object.ETag
50
+ }),
51
+ status: 200
52
+ });
53
+ } catch (err) {
54
+ req.payload.logger.error({
55
+ err,
56
+ msg: 'Error getting file from cloud storage'
57
+ });
58
+ return new Response('Internal Server Error', {
59
+ status: 500
60
+ });
61
+ }
62
+ };
63
+ };
64
+
65
+ //# sourceMappingURL=staticHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/staticHandler.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\n\nimport type { CollectionCachingConfig, PluginOptions, StaticHandler } from './types.js'\n\nimport { createKey } from './utilities/createKey.js'\nimport { getStorageClient } from './utilities/getStorageClient.js'\n\ninterface Args {\n cachingOptions?: PluginOptions['uploadCaching']\n collection: CollectionConfig\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 getStaticHandler = ({ cachingOptions, collection }: Args): StaticHandler => {\n let maxAge = 86400 // 24 hours default\n let collCacheConfig: CollectionCachingConfig | undefined\n if (cachingOptions !== false) {\n // Set custom maxAge for all collections\n maxAge = cachingOptions?.maxAge || maxAge\n collCacheConfig = cachingOptions?.collections?.[collection.slug] || {}\n }\n\n // Set maxAge using collection-specific override\n maxAge = collCacheConfig?.maxAge || maxAge\n\n const cachingEnabled =\n cachingOptions !== false &&\n !!process.env.PAYLOAD_CLOUD_CACHE_KEY &&\n collCacheConfig?.enabled !== false\n\n return async (req, { params }) => {\n try {\n const { identityID, storageClient } = await getStorageClient()\n\n const Key = createKey({\n collection: collection.slug,\n filename: params.filename,\n identityID,\n })\n\n const object = await storageClient.getObject({\n Bucket: process.env.PAYLOAD_CLOUD_BUCKET,\n Key,\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 'Content-Length': String(object.ContentLength),\n 'Content-Type': object.ContentType,\n ...(cachingEnabled && { 'Cache-Control': `public, max-age=${maxAge}` }),\n ETag: object.ETag,\n }),\n status: 200,\n })\n } catch (err: unknown) {\n req.payload.logger.error({ err, msg: 'Error getting file from cloud storage' })\n return new Response('Internal Server Error', { status: 500 })\n }\n }\n}\n"],"names":["createKey","getStorageClient","streamToBuffer","readableStream","chunks","chunk","push","Buffer","from","concat","getStaticHandler","cachingOptions","collection","maxAge","collCacheConfig","collections","slug","cachingEnabled","process","env","PAYLOAD_CLOUD_CACHE_KEY","enabled","req","params","identityID","storageClient","Key","filename","object","getObject","Bucket","PAYLOAD_CLOUD_BUCKET","Body","Response","status","statusText","bodyBuffer","headers","Headers","String","ContentLength","ContentType","ETag","err","payload","logger","error","msg"],"mappings":"AAIA,SAASA,SAAS,QAAQ,2BAA0B;AACpD,SAASC,gBAAgB,QAAQ,kCAAiC;AAOlE,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,mBAAmB,CAAC,EAAEC,cAAc,EAAEC,UAAU,EAAQ;IACnE,IAAIC,SAAS,MAAM,mBAAmB;;IACtC,IAAIC;IACJ,IAAIH,mBAAmB,OAAO;QAC5B,wCAAwC;QACxCE,SAASF,gBAAgBE,UAAUA;QACnCC,kBAAkBH,gBAAgBI,aAAa,CAACH,WAAWI,IAAI,CAAC,IAAI,CAAC;IACvE;IAEA,gDAAgD;IAChDH,SAASC,iBAAiBD,UAAUA;IAEpC,MAAMI,iBACJN,mBAAmB,SACnB,CAAC,CAACO,QAAQC,GAAG,CAACC,uBAAuB,IACrCN,iBAAiBO,YAAY;IAE/B,OAAO,OAAOC,KAAK,EAAEC,MAAM,EAAE;QAC3B,IAAI;YACF,MAAM,EAAEC,UAAU,EAAEC,aAAa,EAAE,GAAG,MAAMxB;YAE5C,MAAMyB,MAAM1B,UAAU;gBACpBY,YAAYA,WAAWI,IAAI;gBAC3BW,UAAUJ,OAAOI,QAAQ;gBACzBH;YACF;YAEA,MAAMI,SAAS,MAAMH,cAAcI,SAAS,CAAC;gBAC3CC,QAAQZ,QAAQC,GAAG,CAACY,oBAAoB;gBACxCL;YACF;YAEA,IAAI,CAACE,OAAOI,IAAI,EAAE;gBAChB,OAAO,IAAIC,SAAS,MAAM;oBAAEC,QAAQ;oBAAKC,YAAY;gBAAY;YACnE;YAEA,MAAMC,aAAa,MAAMlC,eAAe0B,OAAOI,IAAI;YAEnD,OAAO,IAAIC,SAASG,YAAY;gBAC9BC,SAAS,IAAIC,QAAQ;oBACnB,kBAAkBC,OAAOX,OAAOY,aAAa;oBAC7C,gBAAgBZ,OAAOa,WAAW;oBAClC,GAAIxB,kBAAkB;wBAAE,iBAAiB,CAAC,gBAAgB,EAAEJ,OAAO,CAAC;oBAAC,CAAC;oBACtE6B,MAAMd,OAAOc,IAAI;gBACnB;gBACAR,QAAQ;YACV;QACF,EAAE,OAAOS,KAAc;YACrBrB,IAAIsB,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;gBAAEH;gBAAKI,KAAK;YAAwC;YAC7E,OAAO,IAAId,SAAS,yBAAyB;gBAAEC,QAAQ;YAAI;QAC7D;IACF;AACF,EAAC"}
@@ -0,0 +1,103 @@
1
+ import type { CollectionConfig, Config, FileData, PayloadRequest, TypeWithID } from 'payload';
2
+ export interface File {
3
+ buffer: Buffer;
4
+ filename: string;
5
+ filesize: number;
6
+ mimeType: string;
7
+ tempFilePath?: string;
8
+ }
9
+ export type HandleUpload = (args: {
10
+ collection: CollectionConfig;
11
+ data: any;
12
+ file: File;
13
+ req: PayloadRequest;
14
+ }) => Promise<void> | void;
15
+ export interface TypeWithPrefix {
16
+ prefix?: string;
17
+ }
18
+ export type HandleDelete = (args: {
19
+ collection: CollectionConfig;
20
+ doc: FileData & TypeWithID & TypeWithPrefix;
21
+ filename: string;
22
+ req: PayloadRequest;
23
+ }) => Promise<void> | void;
24
+ export type GenerateURL = (args: {
25
+ collection: CollectionConfig;
26
+ filename: string;
27
+ prefix?: string;
28
+ }) => Promise<string> | string;
29
+ export type StaticHandler = (req: PayloadRequest, args: {
30
+ params: {
31
+ collection: string;
32
+ filename: string;
33
+ };
34
+ }) => Promise<Response> | Promise<void> | Response | void;
35
+ export interface PayloadCloudEmailOptions {
36
+ apiKey: string;
37
+ config: Config;
38
+ defaultDomain: string;
39
+ defaultFromAddress?: string;
40
+ defaultFromName?: string;
41
+ skipVerify?: boolean;
42
+ }
43
+ export interface PluginOptions {
44
+ /** Payload Cloud Email
45
+ * @default true
46
+ */
47
+ email?: {
48
+ defaultFromAddress: string;
49
+ defaultFromName: string;
50
+ skipVerify?: boolean;
51
+ } | false;
52
+ /**
53
+ * Payload Cloud API endpoint
54
+ *
55
+ * @internal Endpoint override for developement
56
+ */
57
+ endpoint?: string;
58
+ /** Payload Cloud Storage
59
+ * @default true
60
+ */
61
+ storage?: false;
62
+ /**
63
+ * Upload caching. Defaults to 24 hours for all collections.
64
+ *
65
+ * Optionally configure caching per collection
66
+ *
67
+ * ```ts
68
+ * {
69
+ * collSlug1: {
70
+ * maxAge: 3600 // Custom value in seconds
71
+ * },
72
+ * collSlug2: {
73
+ * enabled: false // Disable caching for this collection
74
+ * }
75
+ * }
76
+ * ```
77
+ *
78
+ * @default true
79
+ */
80
+ uploadCaching?: {
81
+ /**
82
+ * Caching configuration per-collection
83
+ */
84
+ collections?: Record<string, CollectionCachingConfig>;
85
+ /** Caching in seconds override for all collections
86
+ * @default 86400 (24 hours)
87
+ */
88
+ maxAge?: number;
89
+ } | false;
90
+ }
91
+ export type CollectionCachingConfig = {
92
+ /**
93
+ * Enable/disable caching for this collection
94
+ *
95
+ * @default true
96
+ */
97
+ enabled?: boolean;
98
+ /** Caching in seconds override for this collection
99
+ * @default 86400 (24 hours)
100
+ */
101
+ maxAge?: number;
102
+ };
103
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAE7F,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE;IAChC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,IAAI,EAAE,GAAG,CAAA;IACT,IAAI,EAAE,IAAI,CAAA;IACV,GAAG,EAAE,cAAc,CAAA;CACpB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAE1B,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE;IAChC,UAAU,EAAE,gBAAgB,CAAA;IAC5B,GAAG,EAAE,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAA;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,cAAc,CAAA;CACpB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAE1B,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE;IAC/B,UAAU,EAAE,gBAAgB,CAAA;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAA;AAE9B,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;IAAE,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KACvD,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,GAAG,IAAI,CAAA;AAExD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,KAAK,CAAC,EACF;QACE,kBAAkB,EAAE,MAAM,CAAA;QAC1B,eAAe,EAAE,MAAM,CAAA;QACvB,UAAU,CAAC,EAAE,OAAO,CAAA;KACrB,GACD,KAAK,CAAA;IAET;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAA;IAEf;;;;;;;;;;;;;;;;;OAiBG;IAEH,aAAa,CAAC,EACV;QACE;;WAEG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAA;QACrD;;WAEG;QACH,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GACD,KAAK,CAAA;CACV;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { CollectionConfig, Config, FileData, PayloadRequest, TypeWithID } from 'payload'\n\nexport interface File {\n buffer: Buffer\n filename: string\n filesize: number\n mimeType: string\n tempFilePath?: string\n}\n\nexport type HandleUpload = (args: {\n collection: CollectionConfig\n data: any\n file: File\n req: PayloadRequest\n}) => Promise<void> | void\n\nexport interface TypeWithPrefix {\n prefix?: string\n}\n\nexport type HandleDelete = (args: {\n collection: CollectionConfig\n doc: FileData & TypeWithID & TypeWithPrefix\n filename: string\n req: PayloadRequest\n}) => Promise<void> | void\n\nexport type GenerateURL = (args: {\n collection: CollectionConfig\n filename: string\n prefix?: string\n}) => Promise<string> | string\n\nexport type StaticHandler = (\n req: PayloadRequest,\n args: { params: { collection: string; filename: string } },\n) => Promise<Response> | Promise<void> | Response | void\n\nexport interface PayloadCloudEmailOptions {\n apiKey: string\n config: Config\n defaultDomain: string\n defaultFromAddress?: string\n defaultFromName?: string\n skipVerify?: boolean\n}\n\nexport interface PluginOptions {\n /** Payload Cloud Email\n * @default true\n */\n email?:\n | {\n defaultFromAddress: string\n defaultFromName: string\n skipVerify?: boolean\n }\n | false\n\n /**\n * Payload Cloud API endpoint\n *\n * @internal Endpoint override for developement\n */\n endpoint?: string\n\n /** Payload Cloud Storage\n * @default true\n */\n storage?: false\n\n /**\n * Upload caching. Defaults to 24 hours for all collections.\n *\n * Optionally configure caching per collection\n *\n * ```ts\n * {\n * collSlug1: {\n * maxAge: 3600 // Custom value in seconds\n * },\n * collSlug2: {\n * enabled: false // Disable caching for this collection\n * }\n * }\n * ```\n *\n * @default true\n */\n\n uploadCaching?:\n | {\n /**\n * Caching configuration per-collection\n */\n collections?: Record<string, CollectionCachingConfig>\n /** Caching in seconds override for all collections\n * @default 86400 (24 hours)\n */\n maxAge?: number\n }\n | false\n}\n\nexport type CollectionCachingConfig = {\n /**\n * Enable/disable caching for this collection\n *\n * @default true\n */\n enabled?: boolean\n /** Caching in seconds override for this collection\n * @default 86400 (24 hours)\n */\n maxAge?: number\n}\n"],"names":[],"mappings":"AAyGA,WAWC"}
@@ -0,0 +1,3 @@
1
+ import type { CognitoUserSession } from 'amazon-cognito-identity-js';
2
+ export declare const authAsCognitoUser: (username: string, password: string) => Promise<CognitoUserSession>;
3
+ //# sourceMappingURL=authAsCognitoUser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authAsCognitoUser.d.ts","sourceRoot":"","sources":["../../src/utilities/authAsCognitoUser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAMpE,eAAO,MAAM,iBAAiB,aAClB,MAAM,YACN,MAAM,KACf,OAAO,CAAC,kBAAkB,CAmC5B,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { AuthenticationDetails, CognitoUser, CognitoUserPool } from 'amazon-cognito-identity-js';
2
+ let sessionAndToken = null;
3
+ export const authAsCognitoUser = async (username, password)=>{
4
+ // TODO: Check that isValid evaluates expiration
5
+ if (sessionAndToken?.isValid()) {
6
+ return sessionAndToken;
7
+ }
8
+ const userPool = new CognitoUserPool({
9
+ ClientId: process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_CLIENT_ID,
10
+ UserPoolId: process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID
11
+ });
12
+ const authenticationDetails = new AuthenticationDetails({
13
+ Password: password,
14
+ Username: username
15
+ });
16
+ const cognitoUser = new CognitoUser({
17
+ Pool: userPool,
18
+ Username: username
19
+ });
20
+ const result = await new Promise((resolve, reject)=>{
21
+ cognitoUser.authenticateUser(authenticationDetails, {
22
+ onFailure: (err)=>{
23
+ reject(err);
24
+ },
25
+ onSuccess: (res)=>{
26
+ resolve(res);
27
+ }
28
+ });
29
+ });
30
+ sessionAndToken = result;
31
+ return sessionAndToken;
32
+ };
33
+
34
+ //# sourceMappingURL=authAsCognitoUser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/authAsCognitoUser.ts"],"sourcesContent":["import type { CognitoUserSession } from 'amazon-cognito-identity-js'\n\nimport { AuthenticationDetails, CognitoUser, CognitoUserPool } from 'amazon-cognito-identity-js'\n\nlet sessionAndToken: CognitoUserSession | null = null\n\nexport const authAsCognitoUser = async (\n username: string,\n password: string,\n): Promise<CognitoUserSession> => {\n // TODO: Check that isValid evaluates expiration\n if (sessionAndToken?.isValid()) {\n return sessionAndToken\n }\n\n const userPool = new CognitoUserPool({\n ClientId: process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_CLIENT_ID,\n UserPoolId: process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID,\n })\n\n const authenticationDetails = new AuthenticationDetails({\n Password: password,\n Username: username,\n })\n\n const cognitoUser = new CognitoUser({\n Pool: userPool,\n Username: username,\n })\n\n const result: CognitoUserSession = await new Promise((resolve, reject) => {\n cognitoUser.authenticateUser(authenticationDetails, {\n onFailure: (err: Error) => {\n reject(err)\n },\n onSuccess: (res) => {\n resolve(res)\n },\n })\n })\n\n sessionAndToken = result\n\n return sessionAndToken\n}\n"],"names":["AuthenticationDetails","CognitoUser","CognitoUserPool","sessionAndToken","authAsCognitoUser","username","password","isValid","userPool","ClientId","process","env","PAYLOAD_CLOUD_COGNITO_USER_POOL_CLIENT_ID","UserPoolId","PAYLOAD_CLOUD_COGNITO_USER_POOL_ID","authenticationDetails","Password","Username","cognitoUser","Pool","result","Promise","resolve","reject","authenticateUser","onFailure","err","onSuccess","res"],"mappings":"AAEA,SAASA,qBAAqB,EAAEC,WAAW,EAAEC,eAAe,QAAQ,6BAA4B;AAEhG,IAAIC,kBAA6C;AAEjD,OAAO,MAAMC,oBAAoB,OAC/BC,UACAC;IAEA,gDAAgD;IAChD,IAAIH,iBAAiBI,WAAW;QAC9B,OAAOJ;IACT;IAEA,MAAMK,WAAW,IAAIN,gBAAgB;QACnCO,UAAUC,QAAQC,GAAG,CAACC,yCAAyC;QAC/DC,YAAYH,QAAQC,GAAG,CAACG,kCAAkC;IAC5D;IAEA,MAAMC,wBAAwB,IAAIf,sBAAsB;QACtDgB,UAAUV;QACVW,UAAUZ;IACZ;IAEA,MAAMa,cAAc,IAAIjB,YAAY;QAClCkB,MAAMX;QACNS,UAAUZ;IACZ;IAEA,MAAMe,SAA6B,MAAM,IAAIC,QAAQ,CAACC,SAASC;QAC7DL,YAAYM,gBAAgB,CAACT,uBAAuB;YAClDU,WAAW,CAACC;gBACVH,OAAOG;YACT;YACAC,WAAW,CAACC;gBACVN,QAAQM;YACV;QACF;IACF;IAEAzB,kBAAkBiB;IAElB,OAAOjB;AACT,EAAC"}
@@ -0,0 +1,8 @@
1
+ interface Args {
2
+ collection: string;
3
+ filename: string;
4
+ identityID: string;
5
+ }
6
+ export declare const createKey: ({ collection, filename, identityID }: Args) => string;
7
+ export {};
8
+ //# sourceMappingURL=createKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createKey.d.ts","sourceRoot":"","sources":["../../src/utilities/createKey.ts"],"names":[],"mappings":"AAAA,UAAU,IAAI;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,SAAS,yCAA0C,IAAI,KAAG,MACa,CAAA"}
@@ -0,0 +1,3 @@
1
+ export const createKey = ({ collection, filename, identityID })=>`${identityID}/${process.env.PAYLOAD_CLOUD_ENVIRONMENT}/${collection}/${filename}`;
2
+
3
+ //# sourceMappingURL=createKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/createKey.ts"],"sourcesContent":["interface Args {\n collection: string\n filename: string\n identityID: string\n}\n\nexport const createKey = ({ collection, filename, identityID }: Args): string =>\n `${identityID}/${process.env.PAYLOAD_CLOUD_ENVIRONMENT}/${collection}/${filename}`\n"],"names":["createKey","collection","filename","identityID","process","env","PAYLOAD_CLOUD_ENVIRONMENT"],"mappings":"AAMA,OAAO,MAAMA,YAAY,CAAC,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,UAAU,EAAQ,GAClE,CAAC,EAAEA,WAAW,CAAC,EAAEC,QAAQC,GAAG,CAACC,yBAAyB,CAAC,CAAC,EAAEL,WAAW,CAAC,EAAEC,SAAS,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { FileData, PayloadRequest } from 'payload';
2
+ import type { File } from '../types.js';
3
+ export declare function getIncomingFiles({ data, req, }: {
4
+ data: Partial<FileData>;
5
+ req: PayloadRequest;
6
+ }): File[];
7
+ //# sourceMappingURL=getIncomingFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getIncomingFiles.d.ts","sourceRoot":"","sources":["../../src/utilities/getIncomingFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAEvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAEvC,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;CACpB,GAAG,IAAI,EAAE,CAiCT"}
@@ -0,0 +1,33 @@
1
+ export function getIncomingFiles({ data, req }) {
2
+ const file = req.file;
3
+ let files = [];
4
+ if (file && data.filename && data.mimeType) {
5
+ const mainFile = {
6
+ buffer: file.data,
7
+ filename: data.filename,
8
+ filesize: file.size,
9
+ mimeType: data.mimeType,
10
+ tempFilePath: file.tempFilePath
11
+ };
12
+ files = [
13
+ mainFile
14
+ ];
15
+ if (data?.sizes) {
16
+ Object.entries(data.sizes).forEach(([key, resizedFileData])=>{
17
+ if (req.payloadUploadSizes?.[key] && data.mimeType) {
18
+ files = files.concat([
19
+ {
20
+ buffer: req.payloadUploadSizes[key],
21
+ filename: `${resizedFileData.filename}`,
22
+ filesize: req.payloadUploadSizes[key].length,
23
+ mimeType: data.mimeType
24
+ }
25
+ ]);
26
+ }
27
+ });
28
+ }
29
+ }
30
+ return files;
31
+ }
32
+
33
+ //# sourceMappingURL=getIncomingFiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/getIncomingFiles.ts"],"sourcesContent":["import type { FileData, PayloadRequest } from 'payload'\n\nimport type { File } from '../types.js'\n\nexport function getIncomingFiles({\n data,\n req,\n}: {\n data: Partial<FileData>\n req: PayloadRequest\n}): File[] {\n const file = req.file\n\n let files: File[] = []\n\n if (file && data.filename && data.mimeType) {\n const mainFile: File = {\n buffer: file.data,\n filename: data.filename,\n filesize: file.size,\n mimeType: data.mimeType,\n tempFilePath: file.tempFilePath,\n }\n\n files = [mainFile]\n\n if (data?.sizes) {\n Object.entries(data.sizes).forEach(([key, resizedFileData]) => {\n if (req.payloadUploadSizes?.[key] && data.mimeType) {\n files = files.concat([\n {\n buffer: req.payloadUploadSizes[key],\n filename: `${resizedFileData.filename}`,\n filesize: req.payloadUploadSizes[key].length,\n mimeType: data.mimeType,\n },\n ])\n }\n })\n }\n }\n\n return files\n}\n"],"names":["getIncomingFiles","data","req","file","files","filename","mimeType","mainFile","buffer","filesize","size","tempFilePath","sizes","Object","entries","forEach","key","resizedFileData","payloadUploadSizes","concat","length"],"mappings":"AAIA,OAAO,SAASA,iBAAiB,EAC/BC,IAAI,EACJC,GAAG,EAIJ;IACC,MAAMC,OAAOD,IAAIC,IAAI;IAErB,IAAIC,QAAgB,EAAE;IAEtB,IAAID,QAAQF,KAAKI,QAAQ,IAAIJ,KAAKK,QAAQ,EAAE;QAC1C,MAAMC,WAAiB;YACrBC,QAAQL,KAAKF,IAAI;YACjBI,UAAUJ,KAAKI,QAAQ;YACvBI,UAAUN,KAAKO,IAAI;YACnBJ,UAAUL,KAAKK,QAAQ;YACvBK,cAAcR,KAAKQ,YAAY;QACjC;QAEAP,QAAQ;YAACG;SAAS;QAElB,IAAIN,MAAMW,OAAO;YACfC,OAAOC,OAAO,CAACb,KAAKW,KAAK,EAAEG,OAAO,CAAC,CAAC,CAACC,KAAKC,gBAAgB;gBACxD,IAAIf,IAAIgB,kBAAkB,EAAE,CAACF,IAAI,IAAIf,KAAKK,QAAQ,EAAE;oBAClDF,QAAQA,MAAMe,MAAM,CAAC;wBACnB;4BACEX,QAAQN,IAAIgB,kBAAkB,CAACF,IAAI;4BACnCX,UAAU,CAAC,EAAEY,gBAAgBZ,QAAQ,CAAC,CAAC;4BACvCI,UAAUP,IAAIgB,kBAAkB,CAACF,IAAI,CAACI,MAAM;4BAC5Cd,UAAUL,KAAKK,QAAQ;wBACzB;qBACD;gBACH;YACF;QACF;IACF;IAEA,OAAOF;AACT"}
@@ -0,0 +1,7 @@
1
+ import * as AWS from '@aws-sdk/client-s3';
2
+ export type GetStorageClient = () => Promise<{
3
+ identityID: string;
4
+ storageClient: AWS.S3;
5
+ }>;
6
+ export declare const getStorageClient: GetStorageClient;
7
+ //# sourceMappingURL=getStorageClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getStorageClient.d.ts","sourceRoot":"","sources":["../../src/utilities/getStorageClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,oBAAoB,CAAA;AAKzC,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,GAAG,CAAC,EAAE,CAAA;CACtB,CAAC,CAAA;AAMF,eAAO,MAAM,gBAAgB,EAAE,gBAwC9B,CAAA"}
@@ -0,0 +1,40 @@
1
+ import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity';
2
+ import * as AWS from '@aws-sdk/client-s3';
3
+ import { fromCognitoIdentityPool } from '@aws-sdk/credential-providers';
4
+ import { authAsCognitoUser } from './authAsCognitoUser.js';
5
+ let storageClient = null;
6
+ let session = null;
7
+ let identityID;
8
+ export const getStorageClient = async ()=>{
9
+ if (storageClient && session?.isValid()) {
10
+ return {
11
+ identityID,
12
+ storageClient
13
+ };
14
+ }
15
+ session = await authAsCognitoUser(process.env.PAYLOAD_CLOUD_PROJECT_ID, process.env.PAYLOAD_CLOUD_COGNITO_PASSWORD);
16
+ const cognitoIdentity = new CognitoIdentityClient({
17
+ credentials: fromCognitoIdentityPool({
18
+ clientConfig: {
19
+ region: 'us-east-1'
20
+ },
21
+ identityPoolId: process.env.PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID,
22
+ logins: {
23
+ [`cognito-idp.us-east-1.amazonaws.com/${process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID}`]: session.getIdToken().getJwtToken()
24
+ }
25
+ })
26
+ });
27
+ const credentials = await cognitoIdentity.config.credentials();
28
+ // @ts-expect-error - Incorrect AWS types
29
+ identityID = credentials.identityId;
30
+ storageClient = new AWS.S3({
31
+ credentials,
32
+ region: process.env.PAYLOAD_CLOUD_BUCKET_REGION
33
+ });
34
+ return {
35
+ identityID,
36
+ storageClient
37
+ };
38
+ };
39
+
40
+ //# sourceMappingURL=getStorageClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/getStorageClient.ts"],"sourcesContent":["import type { CognitoUserSession } from 'amazon-cognito-identity-js'\n\nimport { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity'\nimport * as AWS from '@aws-sdk/client-s3'\nimport { fromCognitoIdentityPool } from '@aws-sdk/credential-providers'\n\nimport { authAsCognitoUser } from './authAsCognitoUser.js'\n\nexport type GetStorageClient = () => Promise<{\n identityID: string\n storageClient: AWS.S3\n}>\n\nlet storageClient: AWS.S3 | null = null\nlet session: CognitoUserSession | null = null\nlet identityID: string\n\nexport const getStorageClient: GetStorageClient = async () => {\n if (storageClient && session?.isValid()) {\n return {\n identityID,\n storageClient,\n }\n }\n\n session = await authAsCognitoUser(\n process.env.PAYLOAD_CLOUD_PROJECT_ID,\n process.env.PAYLOAD_CLOUD_COGNITO_PASSWORD,\n )\n\n const cognitoIdentity = new CognitoIdentityClient({\n credentials: fromCognitoIdentityPool({\n clientConfig: {\n region: 'us-east-1',\n },\n identityPoolId: process.env.PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID,\n logins: {\n [`cognito-idp.us-east-1.amazonaws.com/${process.env.PAYLOAD_CLOUD_COGNITO_USER_POOL_ID}`]:\n session.getIdToken().getJwtToken(),\n },\n }),\n })\n\n const credentials = await cognitoIdentity.config.credentials()\n\n // @ts-expect-error - Incorrect AWS types\n identityID = credentials.identityId\n\n storageClient = new AWS.S3({\n credentials,\n region: process.env.PAYLOAD_CLOUD_BUCKET_REGION,\n })\n\n return {\n identityID,\n storageClient,\n }\n}\n"],"names":["CognitoIdentityClient","AWS","fromCognitoIdentityPool","authAsCognitoUser","storageClient","session","identityID","getStorageClient","isValid","process","env","PAYLOAD_CLOUD_PROJECT_ID","PAYLOAD_CLOUD_COGNITO_PASSWORD","cognitoIdentity","credentials","clientConfig","region","identityPoolId","PAYLOAD_CLOUD_COGNITO_IDENTITY_POOL_ID","logins","PAYLOAD_CLOUD_COGNITO_USER_POOL_ID","getIdToken","getJwtToken","config","identityId","S3","PAYLOAD_CLOUD_BUCKET_REGION"],"mappings":"AAEA,SAASA,qBAAqB,QAAQ,mCAAkC;AACxE,YAAYC,SAAS,qBAAoB;AACzC,SAASC,uBAAuB,QAAQ,gCAA+B;AAEvE,SAASC,iBAAiB,QAAQ,yBAAwB;AAO1D,IAAIC,gBAA+B;AACnC,IAAIC,UAAqC;AACzC,IAAIC;AAEJ,OAAO,MAAMC,mBAAqC;IAChD,IAAIH,iBAAiBC,SAASG,WAAW;QACvC,OAAO;YACLF;YACAF;QACF;IACF;IAEAC,UAAU,MAAMF,kBACdM,QAAQC,GAAG,CAACC,wBAAwB,EACpCF,QAAQC,GAAG,CAACE,8BAA8B;IAG5C,MAAMC,kBAAkB,IAAIb,sBAAsB;QAChDc,aAAaZ,wBAAwB;YACnCa,cAAc;gBACZC,QAAQ;YACV;YACAC,gBAAgBR,QAAQC,GAAG,CAACQ,sCAAsC;YAClEC,QAAQ;gBACN,CAAC,CAAC,oCAAoC,EAAEV,QAAQC,GAAG,CAACU,kCAAkC,CAAC,CAAC,CAAC,EACvFf,QAAQgB,UAAU,GAAGC,WAAW;YACpC;QACF;IACF;IAEA,MAAMR,cAAc,MAAMD,gBAAgBU,MAAM,CAACT,WAAW;IAE5D,yCAAyC;IACzCR,aAAaQ,YAAYU,UAAU;IAEnCpB,gBAAgB,IAAIH,IAAIwB,EAAE,CAAC;QACzBX;QACAE,QAAQP,QAAQC,GAAG,CAACgB,2BAA2B;IACjD;IAEA,OAAO;QACLpB;QACAF;IACF;AACF,EAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@payloadcms/payload-cloud",
3
+ "version": "3.0.0-alpha.0",
4
+ "description": "The official Payload Cloud plugin",
5
+ "homepage": "https://payloadcms.com",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/payloadcms/payload.git",
9
+ "directory": "packages/payload-cloud"
10
+ },
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "exports": {
14
+ ".": {
15
+ "import": "./dist/index.js",
16
+ "types": "./dist/index.js",
17
+ "default": "./dist/index.js"
18
+ }
19
+ },
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "dependencies": {
26
+ "@aws-sdk/client-cognito-identity": "^3.614.0",
27
+ "@aws-sdk/client-s3": "^3.614.0",
28
+ "@aws-sdk/credential-providers": "^3.614.0",
29
+ "@aws-sdk/lib-storage": "^3.614.0",
30
+ "amazon-cognito-identity-js": "^6.1.2",
31
+ "nodemailer": "6.9.10",
32
+ "resend": "^0.17.2",
33
+ "@payloadcms/email-nodemailer": "3.0.0-beta.117"
34
+ },
35
+ "devDependencies": {
36
+ "@types/jest": "29.5.12",
37
+ "@types/nodemailer": "6.4.14",
38
+ "ts-jest": "^29.1.0",
39
+ "payload": "3.0.0-beta.117"
40
+ },
41
+ "peerDependencies": {
42
+ "payload": "3.0.0-beta.117"
43
+ },
44
+ "scripts": {
45
+ "build": "pnpm build:types && pnpm build:swc",
46
+ "build:swc": "swc ./src -d ./dist --config-file .swcrc-build --strip-leading-paths",
47
+ "build:types": "tsc --emitDeclarationOnly --outDir dist",
48
+ "clean": "rimraf {dist,*.tsbuildinfo}",
49
+ "lint": "eslint .",
50
+ "lint:fix": "eslint . --fix",
51
+ "test": "jest"
52
+ }
53
+ }