payload-subscribers-plugin 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,7 +38,7 @@ export default buildConfig({
38
38
  posts: true,
39
39
  },
40
40
 
41
- // Easily disable the collection logic.
41
+ // Easily disable the plugin logic while keep the collections schema changes.
42
42
  disabled: false,
43
43
 
44
44
  // Specify the collection to use as the subscribers collection
@@ -51,11 +51,11 @@ export default buildConfig({
51
51
  // Provide a custom expiration for magic link tokens. The default is 30 minutes.
52
52
  tokenExpiration: 60 * 60,
53
53
 
54
- // Provide your unsubscribe route. This route should include the Unsubscribe component. If not provided, your payload config must have serverURL defined, and the default will be serverURL+'/unsubscribe'
55
- unsubscribeURL?: string
54
+ // Provide your unsubscribe route. This route should include the Unsubscribe component, or implement your own with the useUnsubscribe hook. If not provided, your payload config must have serverURL defined, and the default will be serverURL+'/unsubscribe'
55
+ unsubscribeURL?: string,
56
56
 
57
- // Provide your verify route. This route should include the Unsubscribe component. If not provided, your payload config must have serverURL defined, and the default will be serverURL+'/verify'
58
- verifyURL?: string
57
+ // Provide your verify route. This route should include the Verify component, or implement your own with the useVerifyMagicLink hook. If not provided, your payload config must have serverURL defined, and the default will be serverURL+'/verify'
58
+ verifyURL?: string,
59
59
  }),
60
60
  ],
61
61
  })
@@ -128,8 +128,22 @@ You can specify collections in the plugin options which will be amended to inclu
128
128
 
129
129
  #### **disabled**
130
130
 
131
+ Easily disable the plugin logic while keep the collections schema changes.
132
+
131
133
  #### **tokenExpiration**
132
134
 
135
+ Provide a custom expiration for magic link tokens. The default is 30 minutes.
136
+
137
+ #### unsubscribeURL
138
+
139
+ Provide your unsubscribe route. This route should include the Unsubscribe component, or implement your own with the useUnsubscribe hook. If not provided, your payload config must have serverURL defined, and the default will be ```serverURL+'/unsubscribe'```
140
+
141
+
142
+ #### **verifyURL**
143
+
144
+ Provide your verify route. This route should include the Verify component, or implement your own with the useVerifyMagicLink hook. If not provided, your payload config must have serverURL defined, and the default will be ```serverURL+'/verify'```
145
+
146
+
133
147
  ### 🔵 Collections
134
148
 
135
149
  #### **optInChannels**
@@ -383,8 +397,6 @@ Shows the [Subscribe](#subscribe) component to authenticated subscribers, otherw
383
397
 
384
398
  ```typescript
385
399
  <RequestOrSubscribe
386
- // Provide the URL the user should go to after clicking the link in the email and having it verified
387
- afterVerifyUrl={new URL(window.href)}
388
400
  // Provide your own global class names to add to the component elements. Optional
389
401
  classNames={{
390
402
  button: 'customCssClassNames',
@@ -400,11 +412,6 @@ Shows the [Subscribe](#subscribe) component to authenticated subscribers, otherw
400
412
  handleMagicLinkRequested={async (result: RequestMagicLinkResponse) => {}}
401
413
  // Called after a subscribers opt-ins have been updated. Optional
402
414
  handleSubscribe={async (result: SubscribeResponse) => {}}
403
- // Provide your own button component. Optional
404
- renderButton={({ name, onClick, text }) =>
405
- <button name={name} onClick={onClick} type="button">
406
- {text}
407
- </button>
408
415
  }
409
416
  // Provide a payload of data to put on any verify link sent by either Request or Subscribe components
410
417
  verifyData={`forwardURL=${window.location.href}`}
@@ -419,8 +426,6 @@ Form to input email address and get a magic link email sent.
419
426
 
420
427
  ```typescript
421
428
  <RequestMagicLink
422
- // Provide the URL the user should go to after clicking the link in the email and having it verified
423
- afterVerifyUrl={new URL(window.href)}
424
429
  // Provide your own global class names to add to the component elements. Optional
425
430
  classNames={{
426
431
  button: 'customCssClassNames',
@@ -432,12 +437,6 @@ Form to input email address and get a magic link email sent.
432
437
  }}
433
438
  // Called after a subscribers opt-ins have been updated. Optional
434
439
  handleMagicLinkRequested={async (result: RequestMagicLinkResponse) => {}}
435
- // Provided your own button component. Optional
436
- renderButton={({ name, onClick, text }) =>
437
- <button name={name} onClick={onClick} type="button">
438
- {text}
439
- </button>
440
- }
441
440
  // Provide a payload of data to put on any verify link sent
442
441
  verifyData={`forwardURL=${window.location.href}`}
443
442
  />
@@ -475,12 +474,6 @@ Component that verifies a magic link using expected url parameters.
475
474
  handleMagicLinkRequested={async (result: RequestMagicLinkResponse) => {}}
476
475
  // Called after a magic link has been verified. Optional
477
476
  handleMagicLinkVerified={async (result: RequestMagicLinkResponse) => {}}
478
- // Provided your own button component. Optional
479
- renderButton={({ name, onClick, text }) =>
480
- <button name={name} onClick={onClick} type="button">
481
- {text}
482
- </button>
483
- }
484
477
  // Provide a payload of data to put on "request another" link sent
485
478
  verifyData={`forwardURL=${window.location.href}`}
486
479
  >
@@ -501,8 +494,8 @@ Component that verifies a magic link using expected url parameters.
501
494
  <p class="subscribers-loading">verifying...</p>
502
495
  <p class="subscribers-message">{result}</p>
503
496
  <div class="subscribers-form">
504
- {renderButton({ name: "request", onClick: handleRequestAnother, text:"Request another magic
505
- link", })} {children}
497
+ <!-- Form elements render here, before the component children provided -->
498
+ {children}
506
499
  </div>
507
500
  </div>
508
501
  ```
@@ -515,8 +508,6 @@ Allows a subscriber to select from among all active optInChannels.
515
508
 
516
509
  ```typescript
517
510
  <Subscribe
518
- // Provide the URL the user should go to after clicking the link in the email and having it verified
519
- afterVerifyUrl={new URL(window.href)}
520
511
  // Provide your own global class names to add to the component elements. Optional
521
512
  classNames={{
522
513
  button: 'customCssClassNames',
@@ -530,12 +521,6 @@ Allows a subscriber to select from among all active optInChannels.
530
521
  }}
531
522
  // Called after a subscribers opt-ins have been updated. Optional
532
523
  handleSubscribe={async (result: SubscribeResponse) => {}}
533
- // Provided your own button component. Optional
534
- renderButton={({ name, onClick, text }) =>
535
- <button name={name} onClick={onClick} type="button">
536
- {text}
537
- </button>
538
- }
539
524
  // Provide a payload of data to put on any verify link sent
540
525
  verifyData={`forwardURL=${window.location.href}`}
541
526
  />
@@ -28,7 +28,9 @@ const SubscriberContext = /*#__PURE__*/ createContext(undefined);
28
28
  });
29
29
  if (authResponse.ok) {
30
30
  // Call the server function to get the user data
31
- const { permissions, subscriber } = await authResponse.json();
31
+ const authResponseJson = await authResponse.json();
32
+ // console.log('authResponseJson', JSON.stringify(authResponseJson, undefined, 2))
33
+ const { permissions, subscriber } = authResponseJson;
32
34
  // console.log(`subscriber = `, subscriber)
33
35
  // console.log(`permissions = `, permissions)
34
36
  setPermissions(permissions);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/contexts/SubscriberProvider.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ReactNode, useCallback, useEffect } from 'react'\nimport { createContext, useContext, useMemo, useState } from 'react'\n\nimport type { Config, OptInChannel, Subscriber } from '../copied/payload-types.js'\n\nimport { useServerUrl } from '../react-hooks/useServerUrl.js'\n\n/** Value provided by SubscriberProvider: current subscriber, auth state, and actions. */\nexport type SubscriberContextType = {\n isLoaded: boolean\n logOut: () => void\n permissions: any\n refreshSubscriber: () => void\n subscriber: ({ optIns?: null | OptInChannel[] } & Omit<Subscriber, 'optIns'>) | null\n}\n\nconst SubscriberContext = createContext<SubscriberContextType | undefined>(undefined)\n\n/** Props for SubscriberProvider. */\ninterface ProviderProps {\n children?: ReactNode\n}\n\n/**\n * Provider that fetches and holds the current subscriber auth state (via POST /api/subscriberAuth).\n * Exposes subscriber, permissions, refreshSubscriber, and logOut to descendants. Must wrap any\n * component that uses useSubscriber().\n *\n * @param props.children - React tree to wrap\n * @returns SubscriberContext.Provider with current auth state and actions\n */\nexport function SubscriberProvider({ children }: ProviderProps) {\n // eslint-disable-next-line\n const [subscriber, setSubscriber] = useState<null | (Subscriber & { optIns: OptInChannel[] })>(\n null,\n )\n\n const { serverURL } = useServerUrl()\n\n // Keep track of if the selection content is loaded yet\n const [isLoaded, setIsLoaded] = useState(false)\n\n const [permissions, setPermissions] = useState<any>()\n\n const refreshSubscriber = useCallback(async () => {\n const initSubscriber = async () => {\n setIsLoaded(false)\n try {\n const authResponse = await fetch('/api/subscriberAuth', {\n // body: JSON.stringify({}),\n method: 'POST',\n })\n\n if (authResponse.ok) {\n // Call the server function to get the user data\n const { permissions, subscriber } = await authResponse.json()\n // console.log(`subscriber = `, subscriber)\n // console.log(`permissions = `, permissions)\n setPermissions(permissions)\n setSubscriber(subscriber)\n } else {\n setPermissions(null)\n setSubscriber(null)\n }\n } catch (error: unknown) {\n console.log(`authResponse error`, error)\n }\n setIsLoaded(true)\n }\n await initSubscriber()\n }, [serverURL])\n\n const logOut = useCallback(async () => {\n setIsLoaded(false)\n try {\n // const sdk = new PayloadSDK<Config>({\n // baseURL: serverURL || '',\n // })\n // const logoutResponse = await sdk.request({\n // json: {},\n // method: 'POST',\n // path: '/api/logout',\n // })\n // Unsure why sdk isn't working here\n const logoutResponse = await fetch('/api/logout', {\n method: 'POST',\n })\n\n // console.log(`logoutResponse`, logoutResponse)\n\n if (logoutResponse.ok) {\n setSubscriber(null)\n setPermissions(null)\n }\n } catch (error: unknown) {\n console.log(`logoutResponse error`, error)\n }\n setIsLoaded(true)\n }, [])\n\n useEffect(() => {\n void refreshSubscriber()\n }, [refreshSubscriber])\n\n // Memoize the value to prevent unnecessary re-renders in consumers\n const contextValue: SubscriberContextType = useMemo(\n () => ({\n isLoaded,\n logOut,\n permissions,\n refreshSubscriber,\n subscriber,\n }),\n [isLoaded, logOut, permissions, refreshSubscriber, subscriber],\n )\n\n return <SubscriberContext.Provider value={contextValue}>{children}</SubscriberContext.Provider>\n}\n\n/**\n * Consumes SubscriberContext. Use only inside a SubscriberProvider.\n *\n * @returns Current subscriber (or null), permissions, isLoaded, refreshSubscriber, and logOut\n * @throws Error if used outside SubscriberProvider\n */\nexport function useSubscriber() {\n const context = useContext(SubscriberContext)\n if (context === undefined) {\n throw new Error('useSubscriber must be used within a SubscriberProvider')\n }\n return context\n}\n"],"names":["useCallback","useEffect","createContext","useContext","useMemo","useState","useServerUrl","SubscriberContext","undefined","SubscriberProvider","children","subscriber","setSubscriber","serverURL","isLoaded","setIsLoaded","permissions","setPermissions","refreshSubscriber","initSubscriber","authResponse","fetch","method","ok","json","error","console","log","logOut","logoutResponse","contextValue","Provider","value","useSubscriber","context","Error"],"mappings":"AAAA;;AAGA,SAAyBA,WAAW,EAAEC,SAAS,QAAQ,QAAO;AAC9D,SAASC,aAAa,EAAEC,UAAU,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAIpE,SAASC,YAAY,QAAQ,iCAAgC;AAW7D,MAAMC,kCAAoBL,cAAiDM;AAO3E;;;;;;;CAOC,GACD,OAAO,SAASC,mBAAmB,EAAEC,QAAQ,EAAiB;IAC5D,2BAA2B;IAC3B,MAAM,CAACC,YAAYC,cAAc,GAAGP,SAClC;IAGF,MAAM,EAAEQ,SAAS,EAAE,GAAGP;IAEtB,uDAAuD;IACvD,MAAM,CAACQ,UAAUC,YAAY,GAAGV,SAAS;IAEzC,MAAM,CAACW,aAAaC,eAAe,GAAGZ;IAEtC,MAAMa,oBAAoBlB,YAAY;QACpC,MAAMmB,iBAAiB;YACrBJ,YAAY;YACZ,IAAI;gBACF,MAAMK,eAAe,MAAMC,MAAM,uBAAuB;oBACtD,4BAA4B;oBAC5BC,QAAQ;gBACV;gBAEA,IAAIF,aAAaG,EAAE,EAAE;oBACnB,gDAAgD;oBAChD,MAAM,EAAEP,WAAW,EAAEL,UAAU,EAAE,GAAG,MAAMS,aAAaI,IAAI;oBAC3D,2CAA2C;oBAC3C,6CAA6C;oBAC7CP,eAAeD;oBACfJ,cAAcD;gBAChB,OAAO;oBACLM,eAAe;oBACfL,cAAc;gBAChB;YACF,EAAE,OAAOa,OAAgB;gBACvBC,QAAQC,GAAG,CAAC,CAAC,kBAAkB,CAAC,EAAEF;YACpC;YACAV,YAAY;QACd;QACA,MAAMI;IACR,GAAG;QAACN;KAAU;IAEd,MAAMe,SAAS5B,YAAY;QACzBe,YAAY;QACZ,IAAI;YACF,uCAAuC;YACvC,8BAA8B;YAC9B,KAAK;YACL,6CAA6C;YAC7C,cAAc;YACd,oBAAoB;YACpB,yBAAyB;YACzB,KAAK;YACL,oCAAoC;YACpC,MAAMc,iBAAiB,MAAMR,MAAM,eAAe;gBAChDC,QAAQ;YACV;YAEA,gDAAgD;YAEhD,IAAIO,eAAeN,EAAE,EAAE;gBACrBX,cAAc;gBACdK,eAAe;YACjB;QACF,EAAE,OAAOQ,OAAgB;YACvBC,QAAQC,GAAG,CAAC,CAAC,oBAAoB,CAAC,EAAEF;QACtC;QACAV,YAAY;IACd,GAAG,EAAE;IAELd,UAAU;QACR,KAAKiB;IACP,GAAG;QAACA;KAAkB;IAEtB,mEAAmE;IACnE,MAAMY,eAAsC1B,QAC1C,IAAO,CAAA;YACLU;YACAc;YACAZ;YACAE;YACAP;QACF,CAAA,GACA;QAACG;QAAUc;QAAQZ;QAAaE;QAAmBP;KAAW;IAGhE,qBAAO,KAACJ,kBAAkBwB,QAAQ;QAACC,OAAOF;kBAAepB;;AAC3D;AAEA;;;;;CAKC,GACD,OAAO,SAASuB;IACd,MAAMC,UAAU/B,WAAWI;IAC3B,IAAI2B,YAAY1B,WAAW;QACzB,MAAM,IAAI2B,MAAM;IAClB;IACA,OAAOD;AACT"}
1
+ {"version":3,"sources":["../../src/contexts/SubscriberProvider.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ReactNode, useCallback, useEffect } from 'react'\nimport { createContext, useContext, useMemo, useState } from 'react'\n\nimport type { Config, OptInChannel, Subscriber } from '../copied/payload-types.js'\n\nimport { useServerUrl } from '../react-hooks/useServerUrl.js'\n\n/** Value provided by SubscriberProvider: current subscriber, auth state, and actions. */\nexport type SubscriberContextType = {\n isLoaded: boolean\n logOut: () => void\n permissions: any\n refreshSubscriber: () => void\n subscriber: ({ optIns?: null | OptInChannel[] } & Omit<Subscriber, 'optIns'>) | null\n}\n\nconst SubscriberContext = createContext<SubscriberContextType | undefined>(undefined)\n\n/** Props for SubscriberProvider. */\ninterface ProviderProps {\n children?: ReactNode\n}\n\n/**\n * Provider that fetches and holds the current subscriber auth state (via POST /api/subscriberAuth).\n * Exposes subscriber, permissions, refreshSubscriber, and logOut to descendants. Must wrap any\n * component that uses useSubscriber().\n *\n * @param props.children - React tree to wrap\n * @returns SubscriberContext.Provider with current auth state and actions\n */\nexport function SubscriberProvider({ children }: ProviderProps) {\n // eslint-disable-next-line\n const [subscriber, setSubscriber] = useState<null | (Subscriber & { optIns: OptInChannel[] })>(\n null,\n )\n\n const { serverURL } = useServerUrl()\n\n // Keep track of if the selection content is loaded yet\n const [isLoaded, setIsLoaded] = useState(false)\n\n const [permissions, setPermissions] = useState<any>()\n\n const refreshSubscriber = useCallback(async () => {\n const initSubscriber = async () => {\n setIsLoaded(false)\n try {\n const authResponse = await fetch('/api/subscriberAuth', {\n // body: JSON.stringify({}),\n method: 'POST',\n })\n\n if (authResponse.ok) {\n // Call the server function to get the user data\n const authResponseJson = await authResponse.json()\n // console.log('authResponseJson', JSON.stringify(authResponseJson, undefined, 2))\n const { permissions, subscriber } = authResponseJson\n // console.log(`subscriber = `, subscriber)\n // console.log(`permissions = `, permissions)\n setPermissions(permissions)\n setSubscriber(subscriber)\n } else {\n setPermissions(null)\n setSubscriber(null)\n }\n } catch (error: unknown) {\n console.log(`authResponse error`, error)\n }\n setIsLoaded(true)\n }\n await initSubscriber()\n }, [serverURL])\n\n const logOut = useCallback(async () => {\n setIsLoaded(false)\n try {\n // const sdk = new PayloadSDK<Config>({\n // baseURL: serverURL || '',\n // })\n // const logoutResponse = await sdk.request({\n // json: {},\n // method: 'POST',\n // path: '/api/logout',\n // })\n // Unsure why sdk isn't working here\n const logoutResponse = await fetch('/api/logout', {\n method: 'POST',\n })\n\n // console.log(`logoutResponse`, logoutResponse)\n\n if (logoutResponse.ok) {\n setSubscriber(null)\n setPermissions(null)\n }\n } catch (error: unknown) {\n console.log(`logoutResponse error`, error)\n }\n setIsLoaded(true)\n }, [])\n\n useEffect(() => {\n void refreshSubscriber()\n }, [refreshSubscriber])\n\n // Memoize the value to prevent unnecessary re-renders in consumers\n const contextValue: SubscriberContextType = useMemo(\n () => ({\n isLoaded,\n logOut,\n permissions,\n refreshSubscriber,\n subscriber,\n }),\n [isLoaded, logOut, permissions, refreshSubscriber, subscriber],\n )\n\n return <SubscriberContext.Provider value={contextValue}>{children}</SubscriberContext.Provider>\n}\n\n/**\n * Consumes SubscriberContext. Use only inside a SubscriberProvider.\n *\n * @returns Current subscriber (or null), permissions, isLoaded, refreshSubscriber, and logOut\n * @throws Error if used outside SubscriberProvider\n */\nexport function useSubscriber() {\n const context = useContext(SubscriberContext)\n if (context === undefined) {\n throw new Error('useSubscriber must be used within a SubscriberProvider')\n }\n return context\n}\n"],"names":["useCallback","useEffect","createContext","useContext","useMemo","useState","useServerUrl","SubscriberContext","undefined","SubscriberProvider","children","subscriber","setSubscriber","serverURL","isLoaded","setIsLoaded","permissions","setPermissions","refreshSubscriber","initSubscriber","authResponse","fetch","method","ok","authResponseJson","json","error","console","log","logOut","logoutResponse","contextValue","Provider","value","useSubscriber","context","Error"],"mappings":"AAAA;;AAGA,SAAyBA,WAAW,EAAEC,SAAS,QAAQ,QAAO;AAC9D,SAASC,aAAa,EAAEC,UAAU,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AAIpE,SAASC,YAAY,QAAQ,iCAAgC;AAW7D,MAAMC,kCAAoBL,cAAiDM;AAO3E;;;;;;;CAOC,GACD,OAAO,SAASC,mBAAmB,EAAEC,QAAQ,EAAiB;IAC5D,2BAA2B;IAC3B,MAAM,CAACC,YAAYC,cAAc,GAAGP,SAClC;IAGF,MAAM,EAAEQ,SAAS,EAAE,GAAGP;IAEtB,uDAAuD;IACvD,MAAM,CAACQ,UAAUC,YAAY,GAAGV,SAAS;IAEzC,MAAM,CAACW,aAAaC,eAAe,GAAGZ;IAEtC,MAAMa,oBAAoBlB,YAAY;QACpC,MAAMmB,iBAAiB;YACrBJ,YAAY;YACZ,IAAI;gBACF,MAAMK,eAAe,MAAMC,MAAM,uBAAuB;oBACtD,4BAA4B;oBAC5BC,QAAQ;gBACV;gBAEA,IAAIF,aAAaG,EAAE,EAAE;oBACnB,gDAAgD;oBAChD,MAAMC,mBAAmB,MAAMJ,aAAaK,IAAI;oBAChD,kFAAkF;oBAClF,MAAM,EAAET,WAAW,EAAEL,UAAU,EAAE,GAAGa;oBACpC,2CAA2C;oBAC3C,6CAA6C;oBAC7CP,eAAeD;oBACfJ,cAAcD;gBAChB,OAAO;oBACLM,eAAe;oBACfL,cAAc;gBAChB;YACF,EAAE,OAAOc,OAAgB;gBACvBC,QAAQC,GAAG,CAAC,CAAC,kBAAkB,CAAC,EAAEF;YACpC;YACAX,YAAY;QACd;QACA,MAAMI;IACR,GAAG;QAACN;KAAU;IAEd,MAAMgB,SAAS7B,YAAY;QACzBe,YAAY;QACZ,IAAI;YACF,uCAAuC;YACvC,8BAA8B;YAC9B,KAAK;YACL,6CAA6C;YAC7C,cAAc;YACd,oBAAoB;YACpB,yBAAyB;YACzB,KAAK;YACL,oCAAoC;YACpC,MAAMe,iBAAiB,MAAMT,MAAM,eAAe;gBAChDC,QAAQ;YACV;YAEA,gDAAgD;YAEhD,IAAIQ,eAAeP,EAAE,EAAE;gBACrBX,cAAc;gBACdK,eAAe;YACjB;QACF,EAAE,OAAOS,OAAgB;YACvBC,QAAQC,GAAG,CAAC,CAAC,oBAAoB,CAAC,EAAEF;QACtC;QACAX,YAAY;IACd,GAAG,EAAE;IAELd,UAAU;QACR,KAAKiB;IACP,GAAG;QAACA;KAAkB;IAEtB,mEAAmE;IACnE,MAAMa,eAAsC3B,QAC1C,IAAO,CAAA;YACLU;YACAe;YACAb;YACAE;YACAP;QACF,CAAA,GACA;QAACG;QAAUe;QAAQb;QAAaE;QAAmBP;KAAW;IAGhE,qBAAO,KAACJ,kBAAkByB,QAAQ;QAACC,OAAOF;kBAAerB;;AAC3D;AAEA;;;;;CAKC,GACD,OAAO,SAASwB;IACd,MAAMC,UAAUhC,WAAWI;IAC3B,IAAI4B,YAAY3B,WAAW;QACzB,MAAM,IAAI4B,MAAM;IAClB;IACA,OAAOD;AACT"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CollectionSlug, Config } from 'payload';
1
+ import type { CollectionSlug, Plugin } from 'payload';
2
2
  export type PayloadSubscribersConfig = {
3
3
  /**
4
4
  * List of collections to add a custom field
@@ -32,4 +32,16 @@ export type PayloadSubscribersConfig = {
32
32
  */
33
33
  verifyURL?: string;
34
34
  };
35
- export declare const payloadSubscribersPlugin: (pluginOptions: PayloadSubscribersConfig) => (config: Config) => Config;
35
+ /**
36
+ * Adds the payload-subscribers-plugin to your payload config
37
+ *
38
+ * @param pluginOptions - Plugin options
39
+ * @param pluginOptions.collections - (optional) An array of existing collection slugs to add an optIns relationship field to
40
+ * @param pluginOptions.disabled - (optional) A convenience option to disable the plugin
41
+ * @param pluginOptions.subscribersCollectionSlug - (optional) The slug of an existing collection to use for subscribers. If omitted, the plugin will create the 'subscribers' collection
42
+ * @param pluginOptions.tokenExpiration - (optional) The expiration time for a token, in milliseconds. Defaults to 30 minutes
43
+ * @param pluginOptions.unsubscribeURL - (optional) The route or full URL for unsubscribe links
44
+ * @param pluginOptions.verifyURL - (optional) The route or full URL for verify links
45
+ * @returns Payload config modified to include the plugin
46
+ */
47
+ export declare const payloadSubscribersPlugin: (pluginOptions: PayloadSubscribersConfig) => Plugin;
package/dist/index.js CHANGED
@@ -11,7 +11,18 @@ import createEndpointVerifyMagicLink from './endpoints/verifyMagicLink.js';
11
11
  import { getTestEmail } from './helpers/testData.js';
12
12
  import { getTokenAndHash } from './helpers/token.js';
13
13
  import { isAbsoluteURL } from './helpers/utilities.js';
14
- export const payloadSubscribersPlugin = (pluginOptions)=>(config)=>{
14
+ /**
15
+ * Adds the payload-subscribers-plugin to your payload config
16
+ *
17
+ * @param pluginOptions - Plugin options
18
+ * @param pluginOptions.collections - (optional) An array of existing collection slugs to add an optIns relationship field to
19
+ * @param pluginOptions.disabled - (optional) A convenience option to disable the plugin
20
+ * @param pluginOptions.subscribersCollectionSlug - (optional) The slug of an existing collection to use for subscribers. If omitted, the plugin will create the 'subscribers' collection
21
+ * @param pluginOptions.tokenExpiration - (optional) The expiration time for a token, in milliseconds. Defaults to 30 minutes
22
+ * @param pluginOptions.unsubscribeURL - (optional) The route or full URL for unsubscribe links
23
+ * @param pluginOptions.verifyURL - (optional) The route or full URL for verify links
24
+ * @returns Payload config modified to include the plugin
25
+ */ export const payloadSubscribersPlugin = (pluginOptions)=>(config)=>{
15
26
  if (!config.serverURL && !(pluginOptions.unsubscribeURL && pluginOptions.verifyURL)) {
16
27
  throw new Error('payloadSubscribersPlugin requires config.serverURL OR valid values for all URL options: unsubscribeURL, verifyURL');
17
28
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { BasePayload, CollectionSlug, Config } from 'payload'\n\nimport { OptedInChannels } from './collections/fields/OptedInChannels.js'\nimport OptInChannels from './collections/OptInChannels.js'\nimport {\n defaultTokenExpiration,\n SubscribersCollectionFactory,\n subscribersCollectionFields,\n} from './collections/Subscribers.js'\nimport getOptInChannelsEndpoint from './endpoints/getOptInChannels.js'\nimport createEndpointLogout from './endpoints/logout.js'\nimport createEndpointRequestMagicLink from './endpoints/requestMagicLink.js'\nimport createEndpointSubscribe from './endpoints/subscribe.js'\nimport createEndpointSubscriberAuth from './endpoints/subscriberAuth.js'\nimport createEndpointUnsubscribe from './endpoints/unsubscribe.js'\nimport createEndpointVerifyMagicLink from './endpoints/verifyMagicLink.js'\nimport { getTestEmail } from './helpers/testData.js'\nimport { getTokenAndHash } from './helpers/token.js'\nimport { isAbsoluteURL } from './helpers/utilities.js'\n\nexport type PayloadSubscribersConfig = {\n /**\n * List of collections to add a custom field\n */\n collections?: Partial<Record<CollectionSlug, true>>\n /**\n * Defaults to false-y. When true:\n * - Database schema changes are still made and seeded\n * - APIs return null or undefined success\n * - Admin components are not added\n * - App components return nothing\n */\n disabled?: boolean\n /**\n * The collection to use as the subscribers collection\n * - Optional. If not specified, the plugin will add a 'subscribers' collection.\n * - Sets the collection auth if not already.\n * - Adds (or overrides) fields: email, firstName, status, optIns, verificationToken, verificationTokenExpires.\n */\n subscribersCollectionSlug?: CollectionSlug\n /**\n * Defaults to 30 minutes\n */\n tokenExpiration?: number\n /**\n * The route or full URL for unsubscribe links\n */\n unsubscribeURL?: string\n /**\n * The route or full URL for verify links\n */\n verifyURL?: string\n}\n\nexport const payloadSubscribersPlugin =\n (pluginOptions: PayloadSubscribersConfig) =>\n (config: Config): Config => {\n if (!config.serverURL && !(pluginOptions.unsubscribeURL && pluginOptions.verifyURL)) {\n throw new Error(\n 'payloadSubscribersPlugin requires config.serverURL OR valid values for all URL options: unsubscribeURL, verifyURL',\n )\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(OptInChannels)\n\n const unsubscribeURL = !pluginOptions.unsubscribeURL\n ? new URL('/unsubscribe', config.serverURL)\n : isAbsoluteURL(pluginOptions.unsubscribeURL)\n ? new URL(pluginOptions.unsubscribeURL)\n : new URL(pluginOptions.unsubscribeURL, config.serverURL)\n\n // Get a URL object from the verifyURL option\n const verifyURL = !pluginOptions.verifyURL\n ? new URL('/verify', config.serverURL)\n : isAbsoluteURL(pluginOptions.verifyURL)\n ? new URL(pluginOptions.verifyURL)\n : new URL(pluginOptions.verifyURL, config.serverURL)\n\n let subscribersCollection = pluginOptions.subscribersCollectionSlug\n ? config.collections.find(\n (collection) => collection.slug == pluginOptions.subscribersCollectionSlug,\n )\n : undefined\n\n if (subscribersCollection) {\n // Configure the input collection to be the subscribers collection\n config.collections = config.collections.filter(\n (collection) => collection.slug != subscribersCollection?.slug,\n )\n subscribersCollection.fields.push(...subscribersCollectionFields)\n if (!subscribersCollection.auth) {\n subscribersCollection = {\n ...subscribersCollection,\n auth: { tokenExpiration: defaultTokenExpiration },\n }\n }\n if (!subscribersCollection.admin?.useAsTitle) {\n if (!subscribersCollection.admin) {\n subscribersCollection.admin = { useAsTitle: 'email' }\n } else {\n // Throw error? Or override?\n subscribersCollection.admin.useAsTitle = 'email'\n }\n }\n config.collections.push(subscribersCollection)\n } else {\n // Configure the default built-in subscribers collection\n subscribersCollection = SubscribersCollectionFactory({\n slug: pluginOptions.subscribersCollectionSlug,\n tokenExpiration: pluginOptions.tokenExpiration,\n })\n config.collections.push(subscribersCollection)\n }\n\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const collection = config.collections.find(\n (collection) => collection.slug === collectionSlug,\n )\n\n if (collection) {\n collection.fields.push(OptedInChannels)\n }\n }\n }\n\n /**\n * If the plugin is disabled, we still want to keep added collections/fields so the database schema is consistent which is important for migrations.\n * If your plugin heavily modifies the database schema, you may want to remove this property.\n */\n if (pluginOptions.disabled) {\n return config\n }\n\n if (!config.admin) {\n config.admin = {}\n }\n\n if (!config.admin.components) {\n config.admin.components = {}\n }\n\n if (!config.admin.components.beforeDashboard) {\n config.admin.components.beforeDashboard = []\n }\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n config.endpoints.push(\n getOptInChannelsEndpoint,\n createEndpointLogout({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointRequestMagicLink({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n unsubscribeURL,\n verifyURL,\n }),\n createEndpointSubscribe({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n unsubscribeURL,\n verifyURL,\n }),\n createEndpointSubscriberAuth({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointUnsubscribe({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointVerifyMagicLink({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n )\n\n const incomingOnInit = config.onInit\n\n const genInit = (testData: { testEmail: string }) => async (payload: BasePayload) => {\n // Ensure we are executing any existing onInit functions before running our own.\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n // console.log('Object.keys(payload.collections)', Object.keys(payload.collections))\n const { totalDocs: totalOptIns } = await payload.count({\n collection: 'opt-in-channels',\n where: {\n title: {\n equals: 'seeded-by-plugin',\n },\n },\n })\n\n if (totalOptIns === 0) {\n await payload.create({\n collection: 'opt-in-channels',\n data: {\n active: true,\n title: 'seeded-by-plugin',\n },\n })\n }\n\n // const { seededChannel } = await payload.find({\n // collection: 'opt-in-channels',\n // where: {\n // title: {\n // equals: 'seeded-by-plugin',\n // },\n // },\n // })\n\n const { totalDocs: totalSubscribers } = await payload.count({\n collection: subscribersCollection.slug as CollectionSlug,\n where: {\n email: {\n equals: testData.testEmail,\n },\n },\n })\n\n const { tokenHash } = getTokenAndHash() // Unknowable\n // payload.logger.info(`testData.testEmail == '${testData.testEmail}'`)\n if (totalSubscribers === 0) {\n await payload.create({\n collection: subscribersCollection.slug as CollectionSlug,\n data: {\n email: testData.testEmail,\n password: tokenHash,\n status: 'pending',\n },\n })\n }\n }\n\n // console.log(`getTestEmail == '${getTestEmail()}'`)\n config.onInit = genInit({ testEmail: getTestEmail() })\n\n return config\n }\n"],"names":["OptedInChannels","OptInChannels","defaultTokenExpiration","SubscribersCollectionFactory","subscribersCollectionFields","getOptInChannelsEndpoint","createEndpointLogout","createEndpointRequestMagicLink","createEndpointSubscribe","createEndpointSubscriberAuth","createEndpointUnsubscribe","createEndpointVerifyMagicLink","getTestEmail","getTokenAndHash","isAbsoluteURL","payloadSubscribersPlugin","pluginOptions","config","serverURL","unsubscribeURL","verifyURL","Error","collections","push","URL","subscribersCollection","subscribersCollectionSlug","find","collection","slug","undefined","filter","fields","auth","tokenExpiration","admin","useAsTitle","collectionSlug","disabled","components","beforeDashboard","endpoints","incomingOnInit","onInit","genInit","testData","payload","totalDocs","totalOptIns","count","where","title","equals","create","data","active","totalSubscribers","email","testEmail","tokenHash","password","status"],"mappings":"AAEA,SAASA,eAAe,QAAQ,0CAAyC;AACzE,OAAOC,mBAAmB,iCAAgC;AAC1D,SACEC,sBAAsB,EACtBC,4BAA4B,EAC5BC,2BAA2B,QACtB,+BAA8B;AACrC,OAAOC,8BAA8B,kCAAiC;AACtE,OAAOC,0BAA0B,wBAAuB;AACxD,OAAOC,oCAAoC,kCAAiC;AAC5E,OAAOC,6BAA6B,2BAA0B;AAC9D,OAAOC,kCAAkC,gCAA+B;AACxE,OAAOC,+BAA+B,6BAA4B;AAClE,OAAOC,mCAAmC,iCAAgC;AAC1E,SAASC,YAAY,QAAQ,wBAAuB;AACpD,SAASC,eAAe,QAAQ,qBAAoB;AACpD,SAASC,aAAa,QAAQ,yBAAwB;AAoCtD,OAAO,MAAMC,2BACX,CAACC,gBACD,CAACC;QACC,IAAI,CAACA,OAAOC,SAAS,IAAI,CAAEF,CAAAA,cAAcG,cAAc,IAAIH,cAAcI,SAAS,AAAD,GAAI;YACnF,MAAM,IAAIC,MACR;QAEJ;QAEA,IAAI,CAACJ,OAAOK,WAAW,EAAE;YACvBL,OAAOK,WAAW,GAAG,EAAE;QACzB;QAEAL,OAAOK,WAAW,CAACC,IAAI,CAACtB;QAExB,MAAMkB,iBAAiB,CAACH,cAAcG,cAAc,GAChD,IAAIK,IAAI,gBAAgBP,OAAOC,SAAS,IACxCJ,cAAcE,cAAcG,cAAc,IACxC,IAAIK,IAAIR,cAAcG,cAAc,IACpC,IAAIK,IAAIR,cAAcG,cAAc,EAAEF,OAAOC,SAAS;QAE5D,6CAA6C;QAC7C,MAAME,YAAY,CAACJ,cAAcI,SAAS,GACtC,IAAII,IAAI,WAAWP,OAAOC,SAAS,IACnCJ,cAAcE,cAAcI,SAAS,IACnC,IAAII,IAAIR,cAAcI,SAAS,IAC/B,IAAII,IAAIR,cAAcI,SAAS,EAAEH,OAAOC,SAAS;QAEvD,IAAIO,wBAAwBT,cAAcU,yBAAyB,GAC/DT,OAAOK,WAAW,CAACK,IAAI,CACrB,CAACC,aAAeA,WAAWC,IAAI,IAAIb,cAAcU,yBAAyB,IAE5EI;QAEJ,IAAIL,uBAAuB;YACzB,kEAAkE;YAClER,OAAOK,WAAW,GAAGL,OAAOK,WAAW,CAACS,MAAM,CAC5C,CAACH,aAAeA,WAAWC,IAAI,IAAIJ,uBAAuBI;YAE5DJ,sBAAsBO,MAAM,CAACT,IAAI,IAAInB;YACrC,IAAI,CAACqB,sBAAsBQ,IAAI,EAAE;gBAC/BR,wBAAwB;oBACtB,GAAGA,qBAAqB;oBACxBQ,MAAM;wBAAEC,iBAAiBhC;oBAAuB;gBAClD;YACF;YACA,IAAI,CAACuB,sBAAsBU,KAAK,EAAEC,YAAY;gBAC5C,IAAI,CAACX,sBAAsBU,KAAK,EAAE;oBAChCV,sBAAsBU,KAAK,GAAG;wBAAEC,YAAY;oBAAQ;gBACtD,OAAO;oBACL,4BAA4B;oBAC5BX,sBAAsBU,KAAK,CAACC,UAAU,GAAG;gBAC3C;YACF;YACAnB,OAAOK,WAAW,CAACC,IAAI,CAACE;QAC1B,OAAO;YACL,wDAAwD;YACxDA,wBAAwBtB,6BAA6B;gBACnD0B,MAAMb,cAAcU,yBAAyB;gBAC7CQ,iBAAiBlB,cAAckB,eAAe;YAChD;YACAjB,OAAOK,WAAW,CAACC,IAAI,CAACE;QAC1B;QAEA,IAAIT,cAAcM,WAAW,EAAE;YAC7B,IAAK,MAAMe,kBAAkBrB,cAAcM,WAAW,CAAE;gBACtD,MAAMM,aAAaX,OAAOK,WAAW,CAACK,IAAI,CACxC,CAACC,aAAeA,WAAWC,IAAI,KAAKQ;gBAGtC,IAAIT,YAAY;oBACdA,WAAWI,MAAM,CAACT,IAAI,CAACvB;gBACzB;YACF;QACF;QAEA;;;KAGC,GACD,IAAIgB,cAAcsB,QAAQ,EAAE;YAC1B,OAAOrB;QACT;QAEA,IAAI,CAACA,OAAOkB,KAAK,EAAE;YACjBlB,OAAOkB,KAAK,GAAG,CAAC;QAClB;QAEA,IAAI,CAAClB,OAAOkB,KAAK,CAACI,UAAU,EAAE;YAC5BtB,OAAOkB,KAAK,CAACI,UAAU,GAAG,CAAC;QAC7B;QAEA,IAAI,CAACtB,OAAOkB,KAAK,CAACI,UAAU,CAACC,eAAe,EAAE;YAC5CvB,OAAOkB,KAAK,CAACI,UAAU,CAACC,eAAe,GAAG,EAAE;QAC9C;QAEA,IAAI,CAACvB,OAAOwB,SAAS,EAAE;YACrBxB,OAAOwB,SAAS,GAAG,EAAE;QACvB;QAEAxB,OAAOwB,SAAS,CAAClB,IAAI,CACnBlB,0BACAC,qBAAqB;YACnBoB,2BAA2BD,sBAAsBI,IAAI;QACvD,IACAtB,+BAA+B;YAC7BmB,2BAA2BD,sBAAsBI,IAAI;YACrDV;YACAC;QACF,IACAZ,wBAAwB;YACtBkB,2BAA2BD,sBAAsBI,IAAI;YACrDV;YACAC;QACF,IACAX,6BAA6B;YAC3BiB,2BAA2BD,sBAAsBI,IAAI;QACvD,IACAnB,0BAA0B;YACxBgB,2BAA2BD,sBAAsBI,IAAI;QACvD,IACAlB,8BAA8B;YAC5Be,2BAA2BD,sBAAsBI,IAAI;QACvD;QAGF,MAAMa,iBAAiBzB,OAAO0B,MAAM;QAEpC,MAAMC,UAAU,CAACC,WAAoC,OAAOC;gBAC1D,gFAAgF;gBAChF,IAAIJ,gBAAgB;oBAClB,MAAMA,eAAeI;gBACvB;gBAEA,oFAAoF;gBACpF,MAAM,EAAEC,WAAWC,WAAW,EAAE,GAAG,MAAMF,QAAQG,KAAK,CAAC;oBACrDrB,YAAY;oBACZsB,OAAO;wBACLC,OAAO;4BACLC,QAAQ;wBACV;oBACF;gBACF;gBAEA,IAAIJ,gBAAgB,GAAG;oBACrB,MAAMF,QAAQO,MAAM,CAAC;wBACnBzB,YAAY;wBACZ0B,MAAM;4BACJC,QAAQ;4BACRJ,OAAO;wBACT;oBACF;gBACF;gBAEA,iDAAiD;gBACjD,mCAAmC;gBACnC,aAAa;gBACb,eAAe;gBACf,oCAAoC;gBACpC,SAAS;gBACT,OAAO;gBACP,KAAK;gBAEL,MAAM,EAAEJ,WAAWS,gBAAgB,EAAE,GAAG,MAAMV,QAAQG,KAAK,CAAC;oBAC1DrB,YAAYH,sBAAsBI,IAAI;oBACtCqB,OAAO;wBACLO,OAAO;4BACLL,QAAQP,SAASa,SAAS;wBAC5B;oBACF;gBACF;gBAEA,MAAM,EAAEC,SAAS,EAAE,GAAG9C,kBAAkB,aAAa;;gBACrD,uEAAuE;gBACvE,IAAI2C,qBAAqB,GAAG;oBAC1B,MAAMV,QAAQO,MAAM,CAAC;wBACnBzB,YAAYH,sBAAsBI,IAAI;wBACtCyB,MAAM;4BACJG,OAAOZ,SAASa,SAAS;4BACzBE,UAAUD;4BACVE,QAAQ;wBACV;oBACF;gBACF;YACF;QAEA,qDAAqD;QACrD5C,OAAO0B,MAAM,GAAGC,QAAQ;YAAEc,WAAW9C;QAAe;QAEpD,OAAOK;IACT,EAAC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { BasePayload, CollectionSlug, Config, Plugin } from 'payload'\n\nimport { OptedInChannels } from './collections/fields/OptedInChannels.js'\nimport OptInChannels from './collections/OptInChannels.js'\nimport {\n defaultTokenExpiration,\n SubscribersCollectionFactory,\n subscribersCollectionFields,\n} from './collections/Subscribers.js'\nimport getOptInChannelsEndpoint from './endpoints/getOptInChannels.js'\nimport createEndpointLogout from './endpoints/logout.js'\nimport createEndpointRequestMagicLink from './endpoints/requestMagicLink.js'\nimport createEndpointSubscribe from './endpoints/subscribe.js'\nimport createEndpointSubscriberAuth from './endpoints/subscriberAuth.js'\nimport createEndpointUnsubscribe from './endpoints/unsubscribe.js'\nimport createEndpointVerifyMagicLink from './endpoints/verifyMagicLink.js'\nimport { getTestEmail } from './helpers/testData.js'\nimport { getTokenAndHash } from './helpers/token.js'\nimport { isAbsoluteURL } from './helpers/utilities.js'\n\nexport type PayloadSubscribersConfig = {\n /**\n * List of collections to add a custom field\n */\n collections?: Partial<Record<CollectionSlug, true>>\n /**\n * Defaults to false-y. When true:\n * - Database schema changes are still made and seeded\n * - APIs return null or undefined success\n * - Admin components are not added\n * - App components return nothing\n */\n disabled?: boolean\n /**\n * The collection to use as the subscribers collection\n * - Optional. If not specified, the plugin will add a 'subscribers' collection.\n * - Sets the collection auth if not already.\n * - Adds (or overrides) fields: email, firstName, status, optIns, verificationToken, verificationTokenExpires.\n */\n subscribersCollectionSlug?: CollectionSlug\n /**\n * Defaults to 30 minutes\n */\n tokenExpiration?: number\n /**\n * The route or full URL for unsubscribe links\n */\n unsubscribeURL?: string\n /**\n * The route or full URL for verify links\n */\n verifyURL?: string\n}\n\n/**\n * Adds the payload-subscribers-plugin to your payload config\n *\n * @param pluginOptions - Plugin options\n * @param pluginOptions.collections - (optional) An array of existing collection slugs to add an optIns relationship field to\n * @param pluginOptions.disabled - (optional) A convenience option to disable the plugin\n * @param pluginOptions.subscribersCollectionSlug - (optional) The slug of an existing collection to use for subscribers. If omitted, the plugin will create the 'subscribers' collection\n * @param pluginOptions.tokenExpiration - (optional) The expiration time for a token, in milliseconds. Defaults to 30 minutes\n * @param pluginOptions.unsubscribeURL - (optional) The route or full URL for unsubscribe links\n * @param pluginOptions.verifyURL - (optional) The route or full URL for verify links\n * @returns Payload config modified to include the plugin\n */\nexport const payloadSubscribersPlugin =\n (pluginOptions: PayloadSubscribersConfig): Plugin =>\n (config: Config): Config => {\n if (!config.serverURL && !(pluginOptions.unsubscribeURL && pluginOptions.verifyURL)) {\n throw new Error(\n 'payloadSubscribersPlugin requires config.serverURL OR valid values for all URL options: unsubscribeURL, verifyURL',\n )\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(OptInChannels)\n\n const unsubscribeURL = !pluginOptions.unsubscribeURL\n ? new URL('/unsubscribe', config.serverURL)\n : isAbsoluteURL(pluginOptions.unsubscribeURL)\n ? new URL(pluginOptions.unsubscribeURL)\n : new URL(pluginOptions.unsubscribeURL, config.serverURL)\n\n // Get a URL object from the verifyURL option\n const verifyURL = !pluginOptions.verifyURL\n ? new URL('/verify', config.serverURL)\n : isAbsoluteURL(pluginOptions.verifyURL)\n ? new URL(pluginOptions.verifyURL)\n : new URL(pluginOptions.verifyURL, config.serverURL)\n\n let subscribersCollection = pluginOptions.subscribersCollectionSlug\n ? config.collections.find(\n (collection) => collection.slug == pluginOptions.subscribersCollectionSlug,\n )\n : undefined\n\n if (subscribersCollection) {\n // Configure the input collection to be the subscribers collection\n config.collections = config.collections.filter(\n (collection) => collection.slug != subscribersCollection?.slug,\n )\n subscribersCollection.fields.push(...subscribersCollectionFields)\n if (!subscribersCollection.auth) {\n subscribersCollection = {\n ...subscribersCollection,\n auth: { tokenExpiration: defaultTokenExpiration },\n }\n }\n if (!subscribersCollection.admin?.useAsTitle) {\n if (!subscribersCollection.admin) {\n subscribersCollection.admin = { useAsTitle: 'email' }\n } else {\n // Throw error? Or override?\n subscribersCollection.admin.useAsTitle = 'email'\n }\n }\n config.collections.push(subscribersCollection)\n } else {\n // Configure the default built-in subscribers collection\n subscribersCollection = SubscribersCollectionFactory({\n slug: pluginOptions.subscribersCollectionSlug,\n tokenExpiration: pluginOptions.tokenExpiration,\n })\n config.collections.push(subscribersCollection)\n }\n\n if (pluginOptions.collections) {\n for (const collectionSlug in pluginOptions.collections) {\n const collection = config.collections.find(\n (collection) => collection.slug === collectionSlug,\n )\n\n if (collection) {\n collection.fields.push(OptedInChannels)\n }\n }\n }\n\n /**\n * If the plugin is disabled, we still want to keep added collections/fields so the database schema is consistent which is important for migrations.\n * If your plugin heavily modifies the database schema, you may want to remove this property.\n */\n if (pluginOptions.disabled) {\n return config\n }\n\n if (!config.admin) {\n config.admin = {}\n }\n\n if (!config.admin.components) {\n config.admin.components = {}\n }\n\n if (!config.admin.components.beforeDashboard) {\n config.admin.components.beforeDashboard = []\n }\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n config.endpoints.push(\n getOptInChannelsEndpoint,\n createEndpointLogout({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointRequestMagicLink({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n unsubscribeURL,\n verifyURL,\n }),\n createEndpointSubscribe({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n unsubscribeURL,\n verifyURL,\n }),\n createEndpointSubscriberAuth({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointUnsubscribe({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n createEndpointVerifyMagicLink({\n subscribersCollectionSlug: subscribersCollection.slug as CollectionSlug,\n }),\n )\n\n const incomingOnInit = config.onInit\n\n const genInit = (testData: { testEmail: string }) => async (payload: BasePayload) => {\n // Ensure we are executing any existing onInit functions before running our own.\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n\n // console.log('Object.keys(payload.collections)', Object.keys(payload.collections))\n const { totalDocs: totalOptIns } = await payload.count({\n collection: 'opt-in-channels',\n where: {\n title: {\n equals: 'seeded-by-plugin',\n },\n },\n })\n\n if (totalOptIns === 0) {\n await payload.create({\n collection: 'opt-in-channels',\n data: {\n active: true,\n title: 'seeded-by-plugin',\n },\n })\n }\n\n // const { seededChannel } = await payload.find({\n // collection: 'opt-in-channels',\n // where: {\n // title: {\n // equals: 'seeded-by-plugin',\n // },\n // },\n // })\n\n const { totalDocs: totalSubscribers } = await payload.count({\n collection: subscribersCollection.slug as CollectionSlug,\n where: {\n email: {\n equals: testData.testEmail,\n },\n },\n })\n\n const { tokenHash } = getTokenAndHash() // Unknowable\n // payload.logger.info(`testData.testEmail == '${testData.testEmail}'`)\n if (totalSubscribers === 0) {\n await payload.create({\n collection: subscribersCollection.slug as CollectionSlug,\n data: {\n email: testData.testEmail,\n password: tokenHash,\n status: 'pending',\n },\n })\n }\n }\n\n // console.log(`getTestEmail == '${getTestEmail()}'`)\n config.onInit = genInit({ testEmail: getTestEmail() })\n\n return config\n }\n"],"names":["OptedInChannels","OptInChannels","defaultTokenExpiration","SubscribersCollectionFactory","subscribersCollectionFields","getOptInChannelsEndpoint","createEndpointLogout","createEndpointRequestMagicLink","createEndpointSubscribe","createEndpointSubscriberAuth","createEndpointUnsubscribe","createEndpointVerifyMagicLink","getTestEmail","getTokenAndHash","isAbsoluteURL","payloadSubscribersPlugin","pluginOptions","config","serverURL","unsubscribeURL","verifyURL","Error","collections","push","URL","subscribersCollection","subscribersCollectionSlug","find","collection","slug","undefined","filter","fields","auth","tokenExpiration","admin","useAsTitle","collectionSlug","disabled","components","beforeDashboard","endpoints","incomingOnInit","onInit","genInit","testData","payload","totalDocs","totalOptIns","count","where","title","equals","create","data","active","totalSubscribers","email","testEmail","tokenHash","password","status"],"mappings":"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"}
package/package.json CHANGED
@@ -69,7 +69,7 @@
69
69
  },
70
70
  "registry": "https://registry.npmjs.org/",
71
71
  "dependencies": {},
72
- "version": "0.0.12",
72
+ "version": "0.0.14",
73
73
  "scripts": {
74
74
  "build": "pnpm copyfiles && pnpm build:types && pnpm build:swc",
75
75
  "build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",