@mobilizehub/payload-plugin 0.1.0 → 0.3.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.
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/resend-adapter.d.ts +34 -0
- package/dist/adapters/resend-adapter.js +219 -0
- package/dist/adapters/resend-adapter.js.map +1 -0
- package/dist/collections/broadcasts/generateBroadcastsCollection.d.ts +3 -0
- package/dist/collections/broadcasts/generateBroadcastsCollection.js +241 -0
- package/dist/collections/broadcasts/generateBroadcastsCollection.js.map +1 -0
- package/dist/collections/emails/generateEmailsCollection.d.ts +3 -0
- package/dist/collections/emails/generateEmailsCollection.js +204 -0
- package/dist/collections/emails/generateEmailsCollection.js.map +1 -0
- package/dist/collections/emails/hooks/sync-status-from-activity.d.ts +5 -0
- package/dist/collections/emails/hooks/sync-status-from-activity.js +64 -0
- package/dist/collections/emails/hooks/sync-status-from-activity.js.map +1 -0
- package/dist/collections/pages/generatePagesCollection.d.ts +3 -0
- package/dist/collections/pages/generatePagesCollection.js +77 -0
- package/dist/collections/pages/generatePagesCollection.js.map +1 -0
- package/dist/collections/unsubscribe-tokens/generateUnsubscribeTokens.d.ts +2 -0
- package/dist/collections/unsubscribe-tokens/generateUnsubscribeTokens.js +48 -0
- package/dist/collections/unsubscribe-tokens/generateUnsubscribeTokens.js.map +1 -0
- package/dist/components/broadcast-metrics-card.d.ts +7 -0
- package/dist/components/broadcast-metrics-card.js +159 -0
- package/dist/components/broadcast-metrics-card.js.map +1 -0
- package/dist/components/broadcast-send-modal.d.ts +9 -0
- package/dist/components/broadcast-send-modal.js +51 -0
- package/dist/components/broadcast-send-modal.js.map +1 -0
- package/dist/components/broadcast-send-test-drawer.d.ts +7 -0
- package/dist/components/broadcast-send-test-drawer.js +154 -0
- package/dist/components/broadcast-send-test-drawer.js.map +1 -0
- package/dist/components/email-activity.d.ts +4 -0
- package/dist/components/email-activity.js +359 -0
- package/dist/components/email-activity.js.map +1 -0
- package/dist/components/email-preview.d.ts +2 -0
- package/dist/components/email-preview.js +95 -0
- package/dist/components/email-preview.js.map +1 -0
- package/dist/endpoints/sendBroadcastHandler.d.ts +9 -0
- package/dist/endpoints/sendBroadcastHandler.js +107 -0
- package/dist/endpoints/sendBroadcastHandler.js.map +1 -0
- package/dist/endpoints/sendTestBroadcastHandler.d.ts +10 -0
- package/dist/endpoints/sendTestBroadcastHandler.js +143 -0
- package/dist/endpoints/sendTestBroadcastHandler.js.map +1 -0
- package/dist/endpoints/unsubscribeHandler.d.ts +9 -0
- package/dist/endpoints/unsubscribeHandler.js +153 -0
- package/dist/endpoints/unsubscribeHandler.js.map +1 -0
- package/dist/exports/client.d.ts +3 -1
- package/dist/exports/client.js +3 -0
- package/dist/exports/client.js.map +1 -1
- package/dist/exports/rsc.d.ts +2 -1
- package/dist/exports/rsc.js +2 -0
- package/dist/exports/rsc.js.map +1 -1
- package/dist/fields/name.d.ts +5 -0
- package/dist/fields/name.js +12 -0
- package/dist/fields/name.js.map +1 -0
- package/dist/fields/publishedAt.d.ts +5 -0
- package/dist/fields/publishedAt.js +16 -0
- package/dist/fields/publishedAt.js.map +1 -0
- package/dist/fields/slug.d.ts +7 -0
- package/dist/fields/slug.js +47 -0
- package/dist/fields/slug.js.map +1 -0
- package/dist/fields/status.d.ts +5 -0
- package/dist/fields/status.js +25 -0
- package/dist/fields/status.js.map +1 -0
- package/dist/index.js +48 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/unsubscribe.d.ts +6 -0
- package/dist/react/unsubscribe.js +16 -0
- package/dist/react/unsubscribe.js.map +1 -0
- package/dist/tasks/sendBroadcastsTask.d.ts +11 -0
- package/dist/tasks/sendBroadcastsTask.js +196 -0
- package/dist/tasks/sendBroadcastsTask.js.map +1 -0
- package/dist/tasks/sendEmailTask.d.ts +9 -0
- package/dist/tasks/sendEmailTask.js +167 -0
- package/dist/tasks/sendEmailTask.js.map +1 -0
- package/dist/types/index.d.ts +133 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/api-response.d.ts +72 -0
- package/dist/utils/api-response.js +66 -0
- package/dist/utils/api-response.js.map +1 -0
- package/dist/utils/email.d.ts +36 -0
- package/dist/utils/email.js +40 -0
- package/dist/utils/email.js.map +1 -0
- package/dist/utils/lexical.d.ts +13 -0
- package/dist/utils/lexical.js +27 -0
- package/dist/utils/lexical.js.map +1 -0
- package/dist/utils/unsubscribe-token.d.ts +67 -0
- package/dist/utils/unsubscribe-token.js +103 -0
- package/dist/utils/unsubscribe-token.js.map +1 -0
- package/package.json +20 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fields/name.ts"],"sourcesContent":["import type { TextField } from 'payload'\n\n/**\n * Creates a 'name' text field configuration for a Collection.\n */\nexport const createNameField = (): TextField => {\n const field: TextField = {\n name: 'name',\n type: 'text',\n required: true,\n }\n\n return field\n}\n"],"names":["createNameField","field","name","type","required"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA,kBAAkB;IAC7B,MAAMC,QAAmB;QACvBC,MAAM;QACNC,MAAM;QACNC,UAAU;IACZ;IAEA,OAAOH;AACT,EAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a 'publishedAt' date field configuration for a Collection.
|
|
3
|
+
*/ export const createPublishedAtField = ()=>{
|
|
4
|
+
const field = {
|
|
5
|
+
name: 'publishedAt',
|
|
6
|
+
type: 'date',
|
|
7
|
+
admin: {
|
|
8
|
+
date: {
|
|
9
|
+
pickerAppearance: 'dayAndTime'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
return field;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=publishedAt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fields/publishedAt.ts"],"sourcesContent":["import type { DateField } from 'payload'\n\n/**\n * Creates a 'publishedAt' date field configuration for a Collection.\n */\nexport const createPublishedAtField = (): DateField => {\n const field: DateField = {\n name: 'publishedAt',\n type: 'date',\n admin: {\n date: {\n pickerAppearance: 'dayAndTime',\n },\n },\n }\n\n return field\n}\n"],"names":["createPublishedAtField","field","name","type","admin","date","pickerAppearance"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA,yBAAyB;IACpC,MAAMC,QAAmB;QACvBC,MAAM;QACNC,MAAM;QACNC,OAAO;YACLC,MAAM;gBACJC,kBAAkB;YACpB;QACF;IACF;IAEA,OAAOL;AACT,EAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TextField } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a 'slug' text field configuration for a Collection.
|
|
4
|
+
* The slug is auto-generated from the title if not provided,
|
|
5
|
+
* and is validated to ensure it is URL-friendly.
|
|
6
|
+
*/
|
|
7
|
+
export declare const createSlugField: () => TextField;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a 'slug' text field configuration for a Collection.
|
|
3
|
+
* The slug is auto-generated from the title if not provided,
|
|
4
|
+
* and is validated to ensure it is URL-friendly.
|
|
5
|
+
*/ export const createSlugField = ()=>{
|
|
6
|
+
const field = {
|
|
7
|
+
name: 'slug',
|
|
8
|
+
type: 'text',
|
|
9
|
+
admin: {
|
|
10
|
+
position: 'sidebar'
|
|
11
|
+
},
|
|
12
|
+
hooks: {
|
|
13
|
+
beforeChange: [
|
|
14
|
+
({ data, value })=>{
|
|
15
|
+
/**
|
|
16
|
+
* Auto-generate slug from title if not provided
|
|
17
|
+
*/ if (!value && data?.title) {
|
|
18
|
+
return data.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
beforeValidate: [
|
|
24
|
+
({ operation, value })=>{
|
|
25
|
+
if (operation === 'create' && !value) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
// Ensure slug is URL-friendly
|
|
29
|
+
return value?.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
required: true,
|
|
34
|
+
unique: true,
|
|
35
|
+
validate: (value)=>{
|
|
36
|
+
/**
|
|
37
|
+
* Custom validation to ensure slug format
|
|
38
|
+
*/ if (value && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value)) {
|
|
39
|
+
return 'Slug must be lowercase and can only contain letters, numbers, and hyphens.';
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return field;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=slug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fields/slug.ts"],"sourcesContent":["import type { TextField } from 'payload'\n\n/**\n * Creates a 'slug' text field configuration for a Collection.\n * The slug is auto-generated from the title if not provided,\n * and is validated to ensure it is URL-friendly.\n */\nexport const createSlugField = (): TextField => {\n const field: TextField = {\n name: 'slug',\n type: 'text',\n admin: {\n position: 'sidebar',\n },\n hooks: {\n beforeChange: [\n ({ data, value }) => {\n /**\n * Auto-generate slug from title if not provided\n */\n if (!value && data?.title) {\n return data.title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n }\n return value\n },\n ],\n beforeValidate: [\n ({ operation, value }) => {\n if (operation === 'create' && !value) {\n return value\n }\n // Ensure slug is URL-friendly\n return value\n ?.toLowerCase()\n .replace(/[^a-z0-9-]/g, '-')\n .replace(/-+/g, '-')\n },\n ],\n },\n required: true,\n unique: true,\n validate: (value: null | string | undefined) => {\n /**\n * Custom validation to ensure slug format\n */\n if (value && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value)) {\n return 'Slug must be lowercase and can only contain letters, numbers, and hyphens.'\n }\n\n return true\n },\n }\n\n return field\n}\n"],"names":["createSlugField","field","name","type","admin","position","hooks","beforeChange","data","value","title","toLowerCase","replace","beforeValidate","operation","required","unique","validate","test"],"mappings":"AAEA;;;;CAIC,GACD,OAAO,MAAMA,kBAAkB;IAC7B,MAAMC,QAAmB;QACvBC,MAAM;QACNC,MAAM;QACNC,OAAO;YACLC,UAAU;QACZ;QACAC,OAAO;YACLC,cAAc;gBACZ,CAAC,EAAEC,IAAI,EAAEC,KAAK,EAAE;oBACd;;WAEC,GACD,IAAI,CAACA,SAASD,MAAME,OAAO;wBACzB,OAAOF,KAAKE,KAAK,CACdC,WAAW,GACXC,OAAO,CAAC,eAAe,KACvBA,OAAO,CAAC,YAAY;oBACzB;oBACA,OAAOH;gBACT;aACD;YACDI,gBAAgB;gBACd,CAAC,EAAEC,SAAS,EAAEL,KAAK,EAAE;oBACnB,IAAIK,cAAc,YAAY,CAACL,OAAO;wBACpC,OAAOA;oBACT;oBACA,8BAA8B;oBAC9B,OAAOA,OACHE,cACDC,QAAQ,eAAe,KACvBA,QAAQ,OAAO;gBACpB;aACD;QACH;QACAG,UAAU;QACVC,QAAQ;QACRC,UAAU,CAACR;YACT;;OAEC,GACD,IAAIA,SAAS,CAAC,6BAA6BS,IAAI,CAACT,QAAQ;gBACtD,OAAO;YACT;YAEA,OAAO;QACT;IACF;IAEA,OAAOR;AACT,EAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a 'status' select field configuration for a Collection.
|
|
3
|
+
*/ export const createStatusField = ()=>{
|
|
4
|
+
const field = {
|
|
5
|
+
name: 'status',
|
|
6
|
+
type: 'select',
|
|
7
|
+
admin: {
|
|
8
|
+
position: 'sidebar'
|
|
9
|
+
},
|
|
10
|
+
defaultValue: 'draft',
|
|
11
|
+
options: [
|
|
12
|
+
{
|
|
13
|
+
label: 'Draft',
|
|
14
|
+
value: 'draft'
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: 'Published',
|
|
18
|
+
value: 'published'
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
return field;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/fields/status.ts"],"sourcesContent":["import type { SelectField } from 'payload'\n\n/**\n * Creates a 'status' select field configuration for a Collection.\n */\nexport const createStatusField = (): SelectField => {\n const field: SelectField = {\n name: 'status',\n type: 'select',\n admin: {\n position: 'sidebar',\n },\n defaultValue: 'draft',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Published', value: 'published' },\n ],\n }\n return field\n}\n"],"names":["createStatusField","field","name","type","admin","position","defaultValue","options","label","value"],"mappings":"AAEA;;CAEC,GACD,OAAO,MAAMA,oBAAoB;IAC/B,MAAMC,QAAqB;QACzBC,MAAM;QACNC,MAAM;QACNC,OAAO;YACLC,UAAU;QACZ;QACAC,cAAc;QACdC,SAAS;YACP;gBAAEC,OAAO;gBAASC,OAAO;YAAQ;YACjC;gBAAED,OAAO;gBAAaC,OAAO;YAAY;SAC1C;IACH;IACA,OAAOR;AACT,EAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,59 @@
|
|
|
1
|
+
import { generateBroadcastsCollection } from './collections/broadcasts/generateBroadcastsCollection.js';
|
|
1
2
|
import { generateContactsCollection } from './collections/contacts/generateContactsCollection.js';
|
|
3
|
+
import { generateEmailsCollection } from './collections/emails/generateEmailsCollection.js';
|
|
2
4
|
import { generateTagsCollection } from './collections/tags/generateTagsCollection.js';
|
|
5
|
+
import { generateUnsubscribeTokensCollection } from './collections/unsubscribe-tokens/generateUnsubscribeTokens.js';
|
|
6
|
+
import { sendBroadcastHandler } from './endpoints/sendBroadcastHandler.js';
|
|
7
|
+
import { sendTestEmailHandler } from './endpoints/sendTestBroadcastHandler.js';
|
|
8
|
+
import { unsubscribeHandler } from './endpoints/unsubscribeHandler.js';
|
|
9
|
+
import { createSendBroadcastsTask } from './tasks/sendBroadcastsTask.js';
|
|
10
|
+
import { createSendEmailTask } from './tasks/sendEmailTask.js';
|
|
3
11
|
export * from './types/index.js';
|
|
4
12
|
export const mobilizehubPlugin = (pluginOptions)=>(config)=>{
|
|
13
|
+
if (pluginOptions.disabled) {
|
|
14
|
+
return config;
|
|
15
|
+
}
|
|
5
16
|
if (!config.collections) {
|
|
6
17
|
config.collections = [];
|
|
7
18
|
}
|
|
8
|
-
config.collections.push(generateTagsCollection(pluginOptions), generateContactsCollection(pluginOptions));
|
|
9
|
-
if (
|
|
10
|
-
|
|
19
|
+
config.collections.push(generateTagsCollection(pluginOptions), generateContactsCollection(pluginOptions), generateBroadcastsCollection(pluginOptions), generateEmailsCollection(pluginOptions), generateUnsubscribeTokensCollection());
|
|
20
|
+
if (!config.endpoints) {
|
|
21
|
+
config.endpoints = [];
|
|
22
|
+
}
|
|
23
|
+
const endpoints = [
|
|
24
|
+
{
|
|
25
|
+
handler: sendBroadcastHandler(),
|
|
26
|
+
method: 'post',
|
|
27
|
+
path: '/send-broadcast'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
handler: sendTestEmailHandler(pluginOptions),
|
|
31
|
+
method: 'post',
|
|
32
|
+
path: '/send-test-email'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
handler: unsubscribeHandler(),
|
|
36
|
+
method: 'post',
|
|
37
|
+
path: '/unsubscribe'
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
config.endpoints = [
|
|
41
|
+
...config.endpoints,
|
|
42
|
+
...endpoints
|
|
43
|
+
];
|
|
44
|
+
if (!config.jobs) {
|
|
45
|
+
config.jobs = {
|
|
46
|
+
tasks: []
|
|
47
|
+
};
|
|
11
48
|
}
|
|
49
|
+
const tasks = [
|
|
50
|
+
createSendBroadcastsTask(pluginOptions),
|
|
51
|
+
createSendEmailTask(pluginOptions)
|
|
52
|
+
];
|
|
53
|
+
config.jobs.tasks = [
|
|
54
|
+
...config.jobs.tasks ?? [],
|
|
55
|
+
...tasks
|
|
56
|
+
];
|
|
12
57
|
const incomingOnInit = config.onInit;
|
|
13
58
|
config.onInit = async (payload)=>{
|
|
14
59
|
if (incomingOnInit) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { MobilizehubPluginConfig } from './types/index.js'\n\nimport { generateContactsCollection } from './collections/contacts/generateContactsCollection.js'\nimport { generateTagsCollection } from './collections/tags/generateTagsCollection.js'\n\nexport * from './types/index.js'\n\nexport const mobilizehubPlugin =\n (pluginOptions: MobilizehubPluginConfig) =>\n (config: Config): Config => {\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n generateTagsCollection(pluginOptions),\n generateContactsCollection(pluginOptions),\n )\n\n if (
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config, Endpoint, TaskConfig } from 'payload'\n\nimport type { MobilizehubPluginConfig } from './types/index.js'\n\nimport { generateBroadcastsCollection } from './collections/broadcasts/generateBroadcastsCollection.js'\nimport { generateContactsCollection } from './collections/contacts/generateContactsCollection.js'\nimport { generateEmailsCollection } from './collections/emails/generateEmailsCollection.js'\nimport { generateTagsCollection } from './collections/tags/generateTagsCollection.js'\nimport { generateUnsubscribeTokensCollection } from './collections/unsubscribe-tokens/generateUnsubscribeTokens.js'\nimport { sendBroadcastHandler } from './endpoints/sendBroadcastHandler.js'\nimport { sendTestEmailHandler } from './endpoints/sendTestBroadcastHandler.js'\nimport { unsubscribeHandler } from './endpoints/unsubscribeHandler.js'\nimport { createSendBroadcastsTask } from './tasks/sendBroadcastsTask.js'\nimport { createSendEmailTask } from './tasks/sendEmailTask.js'\n\nexport * from './types/index.js'\n\nexport const mobilizehubPlugin =\n (pluginOptions: MobilizehubPluginConfig) =>\n (config: Config): Config => {\n if (pluginOptions.disabled) {\n return config\n }\n\n if (!config.collections) {\n config.collections = []\n }\n\n config.collections.push(\n generateTagsCollection(pluginOptions),\n generateContactsCollection(pluginOptions),\n generateBroadcastsCollection(pluginOptions),\n generateEmailsCollection(pluginOptions),\n generateUnsubscribeTokensCollection(),\n )\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n const endpoints: Endpoint[] = [\n {\n handler: sendBroadcastHandler(),\n method: 'post',\n path: '/send-broadcast',\n },\n {\n handler: sendTestEmailHandler(pluginOptions),\n method: 'post',\n path: '/send-test-email',\n },\n {\n handler: unsubscribeHandler(),\n method: 'post',\n path: '/unsubscribe',\n },\n ]\n\n config.endpoints = [...config.endpoints, ...endpoints]\n\n if (!config.jobs) {\n config.jobs = {\n tasks: [],\n }\n }\n\n const tasks: TaskConfig[] = [\n createSendBroadcastsTask(pluginOptions),\n createSendEmailTask(pluginOptions),\n ]\n\n config.jobs.tasks = [...(config.jobs.tasks ?? []), ...tasks]\n\n const incomingOnInit = config.onInit\n\n config.onInit = async (payload) => {\n if (incomingOnInit) {\n await incomingOnInit(payload)\n }\n }\n\n return config\n }\n"],"names":["generateBroadcastsCollection","generateContactsCollection","generateEmailsCollection","generateTagsCollection","generateUnsubscribeTokensCollection","sendBroadcastHandler","sendTestEmailHandler","unsubscribeHandler","createSendBroadcastsTask","createSendEmailTask","mobilizehubPlugin","pluginOptions","config","disabled","collections","push","endpoints","handler","method","path","jobs","tasks","incomingOnInit","onInit","payload"],"mappings":"AAIA,SAASA,4BAA4B,QAAQ,2DAA0D;AACvG,SAASC,0BAA0B,QAAQ,uDAAsD;AACjG,SAASC,wBAAwB,QAAQ,mDAAkD;AAC3F,SAASC,sBAAsB,QAAQ,+CAA8C;AACrF,SAASC,mCAAmC,QAAQ,gEAA+D;AACnH,SAASC,oBAAoB,QAAQ,sCAAqC;AAC1E,SAASC,oBAAoB,QAAQ,0CAAyC;AAC9E,SAASC,kBAAkB,QAAQ,oCAAmC;AACtE,SAASC,wBAAwB,QAAQ,gCAA+B;AACxE,SAASC,mBAAmB,QAAQ,2BAA0B;AAE9D,cAAc,mBAAkB;AAEhC,OAAO,MAAMC,oBACX,CAACC,gBACD,CAACC;QACC,IAAID,cAAcE,QAAQ,EAAE;YAC1B,OAAOD;QACT;QAEA,IAAI,CAACA,OAAOE,WAAW,EAAE;YACvBF,OAAOE,WAAW,GAAG,EAAE;QACzB;QAEAF,OAAOE,WAAW,CAACC,IAAI,CACrBZ,uBAAuBQ,gBACvBV,2BAA2BU,gBAC3BX,6BAA6BW,gBAC7BT,yBAAyBS,gBACzBP;QAGF,IAAI,CAACQ,OAAOI,SAAS,EAAE;YACrBJ,OAAOI,SAAS,GAAG,EAAE;QACvB;QAEA,MAAMA,YAAwB;YAC5B;gBACEC,SAASZ;gBACTa,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASX,qBAAqBK;gBAC9BO,QAAQ;gBACRC,MAAM;YACR;YACA;gBACEF,SAASV;gBACTW,QAAQ;gBACRC,MAAM;YACR;SACD;QAEDP,OAAOI,SAAS,GAAG;eAAIJ,OAAOI,SAAS;eAAKA;SAAU;QAEtD,IAAI,CAACJ,OAAOQ,IAAI,EAAE;YAChBR,OAAOQ,IAAI,GAAG;gBACZC,OAAO,EAAE;YACX;QACF;QAEA,MAAMA,QAAsB;YAC1Bb,yBAAyBG;YACzBF,oBAAoBE;SACrB;QAEDC,OAAOQ,IAAI,CAACC,KAAK,GAAG;eAAKT,OAAOQ,IAAI,CAACC,KAAK,IAAI,EAAE;eAAMA;SAAM;QAE5D,MAAMC,iBAAiBV,OAAOW,MAAM;QAEpCX,OAAOW,MAAM,GAAG,OAAOC;YACrB,IAAIF,gBAAgB;gBAClB,MAAMA,eAAeE;YACvB;QACF;QAEA,OAAOZ;IACT,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { confirmUnsubscribe } from './unsubscribe.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts"],"sourcesContent":["export { confirmUnsubscribe } from './unsubscribe.js'\n"],"names":["confirmUnsubscribe"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,mBAAkB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const apiUrl = '/api/unsubscribe';
|
|
2
|
+
/**
|
|
3
|
+
* Confirms an unsubscribe request by sending the token to the backend.
|
|
4
|
+
*/ export async function confirmUnsubscribe({ token }) {
|
|
5
|
+
return fetch(apiUrl, {
|
|
6
|
+
body: JSON.stringify({
|
|
7
|
+
token
|
|
8
|
+
}),
|
|
9
|
+
headers: {
|
|
10
|
+
'Content-Type': 'application/json'
|
|
11
|
+
},
|
|
12
|
+
method: 'POST'
|
|
13
|
+
}).then((res)=>res.json());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=unsubscribe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/unsubscribe.ts"],"sourcesContent":["const apiUrl = '/api/unsubscribe'\n\n/**\n * Confirms an unsubscribe request by sending the token to the backend.\n */\nexport async function confirmUnsubscribe({ token }: { token: string }) {\n return fetch(apiUrl, {\n body: JSON.stringify({ token }),\n headers: {\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n }).then((res) => res.json())\n}\n"],"names":["apiUrl","confirmUnsubscribe","token","fetch","body","JSON","stringify","headers","method","then","res","json"],"mappings":"AAAA,MAAMA,SAAS;AAEf;;CAEC,GACD,OAAO,eAAeC,mBAAmB,EAAEC,KAAK,EAAqB;IACnE,OAAOC,MAAMH,QAAQ;QACnBI,MAAMC,KAAKC,SAAS,CAAC;YAAEJ;QAAM;QAC7BK,SAAS;YACP,gBAAgB;QAClB;QACAC,QAAQ;IACV,GAAGC,IAAI,CAAC,CAACC,MAAQA,IAAIC,IAAI;AAC3B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TaskConfig } from 'payload';
|
|
2
|
+
import type { MobilizehubPluginConfig } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates the send-broadcasts scheduled task.
|
|
5
|
+
*
|
|
6
|
+
* Processes broadcasts by polling for documents with status 'sending' and
|
|
7
|
+
* queuing batches of send-email jobs. Each invocation processes one broadcast
|
|
8
|
+
* and one batch of contacts, allowing the task to be distributed across
|
|
9
|
+
* multiple schedule intervals.
|
|
10
|
+
*/
|
|
11
|
+
export declare const createSendBroadcastsTask: (pluginConfig: MobilizehubPluginConfig) => TaskConfig;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Schema for validating broadcast documents before processing.
|
|
4
|
+
*/ const BroadcastSchema = z.object({
|
|
5
|
+
id: z.number(),
|
|
6
|
+
content: z.any().refine((val)=>val !== undefined && val !== null, {
|
|
7
|
+
message: 'Broadcast content is missing'
|
|
8
|
+
}),
|
|
9
|
+
fromAddress: z.email({
|
|
10
|
+
message: 'Invalid from address email format'
|
|
11
|
+
}),
|
|
12
|
+
fromName: z.string().min(1, {
|
|
13
|
+
message: 'From name is required'
|
|
14
|
+
}),
|
|
15
|
+
meta: z.object({
|
|
16
|
+
contactsCount: z.number().min(0),
|
|
17
|
+
lastProcessedContactId: z.number().min(0).default(0),
|
|
18
|
+
processedCount: z.number().min(0)
|
|
19
|
+
}),
|
|
20
|
+
subject: z.string().min(1, {
|
|
21
|
+
message: 'Subject is required'
|
|
22
|
+
}),
|
|
23
|
+
tags: z.array(z.any()).optional(),
|
|
24
|
+
to: z.literal('all').or(z.literal('tags'))
|
|
25
|
+
});
|
|
26
|
+
/**
|
|
27
|
+
* Validates a broadcast document against the schema.
|
|
28
|
+
* Returns typed data on success, or flattened field errors on failure.
|
|
29
|
+
*/ function safeParseBroadcast(broadcast) {
|
|
30
|
+
const result = BroadcastSchema.safeParse(broadcast);
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
return {
|
|
33
|
+
data: null,
|
|
34
|
+
errors: z.flattenError(result.error).fieldErrors,
|
|
35
|
+
success: false
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
data: result.data,
|
|
40
|
+
success: true
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the where clause for fetching the next batch of contacts.
|
|
45
|
+
* Uses cursor-based pagination (id > lastProcessedContactId) for consistent
|
|
46
|
+
* ordering and efficient queries at scale.
|
|
47
|
+
*/ function buildContactsWhereClause(broadcast, rawBroadcast) {
|
|
48
|
+
const conditions = [
|
|
49
|
+
{
|
|
50
|
+
emailOptIn: {
|
|
51
|
+
equals: true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: {
|
|
56
|
+
greater_than: broadcast.meta.lastProcessedContactId
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
// Tags may be populated objects or raw IDs depending on query depth
|
|
61
|
+
if (broadcast.to === 'tags' && Array.isArray(rawBroadcast.tags) && rawBroadcast.tags.length > 0) {
|
|
62
|
+
const tagIds = rawBroadcast.tags.map((t)=>typeof t === 'object' ? t.id : t);
|
|
63
|
+
conditions.push({
|
|
64
|
+
tags: {
|
|
65
|
+
in: tagIds
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
and: conditions
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extracts a numeric ID from a contact, handling string IDs from some database adapters.
|
|
75
|
+
*/ function getLastContactId(contact) {
|
|
76
|
+
return typeof contact.id === 'number' ? contact.id : parseInt(contact.id, 10);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates the send-broadcasts scheduled task.
|
|
80
|
+
*
|
|
81
|
+
* Processes broadcasts by polling for documents with status 'sending' and
|
|
82
|
+
* queuing batches of send-email jobs. Each invocation processes one broadcast
|
|
83
|
+
* and one batch of contacts, allowing the task to be distributed across
|
|
84
|
+
* multiple schedule intervals.
|
|
85
|
+
*/ export const createSendBroadcastsTask = (pluginConfig)=>{
|
|
86
|
+
const BATCH_SIZE = pluginConfig.broadcastConfig?.batchSize || 100;
|
|
87
|
+
const TASK_SCHEDULE = pluginConfig.broadcastConfig?.taskSchedule || '*/5 * * * *';
|
|
88
|
+
const QUEUE_NAME = pluginConfig.broadcastConfig?.broadcastQueueName || 'send-broadcasts';
|
|
89
|
+
return {
|
|
90
|
+
slug: 'send-broadcasts',
|
|
91
|
+
handler: async ({ req })=>{
|
|
92
|
+
const { payload } = req;
|
|
93
|
+
const logger = payload.logger;
|
|
94
|
+
logger.info('Send Broadcast task handler called');
|
|
95
|
+
const { docs } = await payload.find({
|
|
96
|
+
collection: 'broadcasts',
|
|
97
|
+
limit: 1,
|
|
98
|
+
sort: 'id',
|
|
99
|
+
where: {
|
|
100
|
+
status: {
|
|
101
|
+
equals: 'sending'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const rawBroadcast = docs[0];
|
|
106
|
+
if (!rawBroadcast) {
|
|
107
|
+
logger.info('No broadcasts with status "sending" found');
|
|
108
|
+
return {
|
|
109
|
+
output: {
|
|
110
|
+
success: true
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const parsed = safeParseBroadcast(rawBroadcast);
|
|
115
|
+
if (!parsed.success) {
|
|
116
|
+
logger.error({
|
|
117
|
+
errors: parsed.errors
|
|
118
|
+
}, `Broadcast ${rawBroadcast.id} validation failed`);
|
|
119
|
+
await payload.update({
|
|
120
|
+
id: rawBroadcast.id,
|
|
121
|
+
collection: 'broadcasts',
|
|
122
|
+
data: {
|
|
123
|
+
status: 'failed'
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
output: {
|
|
128
|
+
success: false
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const broadcast = parsed.data;
|
|
133
|
+
const whereClause = buildContactsWhereClause(broadcast, rawBroadcast);
|
|
134
|
+
const { docs: contacts } = await payload.find({
|
|
135
|
+
collection: 'contacts',
|
|
136
|
+
limit: BATCH_SIZE,
|
|
137
|
+
sort: 'id',
|
|
138
|
+
where: whereClause
|
|
139
|
+
});
|
|
140
|
+
if (contacts.length === 0) {
|
|
141
|
+
logger.info(`Broadcast ${broadcast.id} complete. ` + `Processed: ${broadcast.meta.processedCount}, Expected: ${broadcast.meta.contactsCount}`);
|
|
142
|
+
await payload.update({
|
|
143
|
+
id: broadcast.id,
|
|
144
|
+
collection: 'broadcasts',
|
|
145
|
+
data: {
|
|
146
|
+
status: 'sent'
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
output: {
|
|
151
|
+
success: true
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
await Promise.all(contacts.map((contact)=>payload.jobs.queue({
|
|
156
|
+
input: {
|
|
157
|
+
broadcastId: broadcast.id,
|
|
158
|
+
contactId: contact.id
|
|
159
|
+
},
|
|
160
|
+
queue: 'send-emails',
|
|
161
|
+
task: 'send-email'
|
|
162
|
+
})));
|
|
163
|
+
await payload.update({
|
|
164
|
+
id: broadcast.id,
|
|
165
|
+
collection: 'broadcasts',
|
|
166
|
+
data: {
|
|
167
|
+
meta: {
|
|
168
|
+
lastProcessedContactId: getLastContactId(contacts[contacts.length - 1]),
|
|
169
|
+
processedCount: broadcast.meta.processedCount + contacts.length
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
logger.info(`Broadcast ${broadcast.id}: queued ${contacts.length} emails, ` + `total processed: ${broadcast.meta.processedCount + contacts.length}`);
|
|
174
|
+
return {
|
|
175
|
+
output: {
|
|
176
|
+
success: true
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
outputSchema: [
|
|
181
|
+
{
|
|
182
|
+
name: 'success',
|
|
183
|
+
type: 'checkbox'
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
retries: 3,
|
|
187
|
+
schedule: [
|
|
188
|
+
{
|
|
189
|
+
cron: TASK_SCHEDULE,
|
|
190
|
+
queue: QUEUE_NAME
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
//# sourceMappingURL=sendBroadcastsTask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tasks/sendBroadcastsTask.ts"],"sourcesContent":["import type { TaskConfig, Where } from 'payload'\n\nimport z from 'zod'\n\nimport type { MobilizehubPluginConfig } from '../types/index.js'\n\n/**\n * Schema for validating broadcast documents before processing.\n */\nconst BroadcastSchema = z.object({\n id: z.number(),\n content: z.any().refine((val) => val !== undefined && val !== null, {\n message: 'Broadcast content is missing',\n }),\n fromAddress: z.email({ message: 'Invalid from address email format' }),\n fromName: z.string().min(1, { message: 'From name is required' }),\n meta: z.object({\n contactsCount: z.number().min(0),\n lastProcessedContactId: z.number().min(0).default(0),\n processedCount: z.number().min(0),\n }),\n subject: z.string().min(1, { message: 'Subject is required' }),\n tags: z.array(z.any()).optional(),\n to: z.literal('all').or(z.literal('tags')),\n})\n\ntype ParsedBroadcast = z.infer<typeof BroadcastSchema>\n\n/**\n * Validates a broadcast document against the schema.\n * Returns typed data on success, or flattened field errors on failure.\n */\nfunction safeParseBroadcast(broadcast: unknown) {\n const result = BroadcastSchema.safeParse(broadcast)\n\n if (!result.success) {\n return {\n data: null,\n errors: z.flattenError(result.error).fieldErrors,\n success: false as const,\n }\n }\n\n return {\n data: result.data,\n success: true as const,\n }\n}\n\n/**\n * Builds the where clause for fetching the next batch of contacts.\n * Uses cursor-based pagination (id > lastProcessedContactId) for consistent\n * ordering and efficient queries at scale.\n */\nfunction buildContactsWhereClause(\n broadcast: ParsedBroadcast,\n rawBroadcast: Record<string, unknown>,\n): Where {\n const conditions: Where[] = [\n { emailOptIn: { equals: true } },\n { id: { greater_than: broadcast.meta.lastProcessedContactId } },\n ]\n\n // Tags may be populated objects or raw IDs depending on query depth\n if (broadcast.to === 'tags' && Array.isArray(rawBroadcast.tags) && rawBroadcast.tags.length > 0) {\n const tagIds = rawBroadcast.tags.map((t: { id: number | string } | number | string) =>\n typeof t === 'object' ? t.id : t,\n )\n conditions.push({ tags: { in: tagIds } })\n }\n\n return { and: conditions }\n}\n\n/**\n * Extracts a numeric ID from a contact, handling string IDs from some database adapters.\n */\nfunction getLastContactId(contact: { id: number | string }): number {\n return typeof contact.id === 'number' ? contact.id : parseInt(contact.id, 10)\n}\n\n/**\n * Creates the send-broadcasts scheduled task.\n *\n * Processes broadcasts by polling for documents with status 'sending' and\n * queuing batches of send-email jobs. Each invocation processes one broadcast\n * and one batch of contacts, allowing the task to be distributed across\n * multiple schedule intervals.\n */\nexport const createSendBroadcastsTask = (pluginConfig: MobilizehubPluginConfig): TaskConfig => {\n const BATCH_SIZE = pluginConfig.broadcastConfig?.batchSize || 100\n const TASK_SCHEDULE = pluginConfig.broadcastConfig?.taskSchedule || '*/5 * * * *'\n const QUEUE_NAME = pluginConfig.broadcastConfig?.broadcastQueueName || 'send-broadcasts'\n\n return {\n slug: 'send-broadcasts',\n handler: async ({ req }) => {\n const { payload } = req\n const logger = payload.logger\n\n logger.info('Send Broadcast task handler called')\n\n const { docs } = await payload.find({\n collection: 'broadcasts',\n limit: 1,\n sort: 'id',\n where: { status: { equals: 'sending' } },\n })\n\n const rawBroadcast = docs[0]\n\n if (!rawBroadcast) {\n logger.info('No broadcasts with status \"sending\" found')\n return { output: { success: true } }\n }\n\n const parsed = safeParseBroadcast(rawBroadcast)\n\n if (!parsed.success) {\n logger.error({ errors: parsed.errors }, `Broadcast ${rawBroadcast.id} validation failed`)\n await payload.update({\n id: rawBroadcast.id,\n collection: 'broadcasts',\n data: { status: 'failed' },\n })\n return { output: { success: false } }\n }\n\n const broadcast = parsed.data\n const whereClause = buildContactsWhereClause(\n broadcast,\n rawBroadcast as Record<string, unknown>,\n )\n\n const { docs: contacts } = await payload.find({\n collection: 'contacts',\n limit: BATCH_SIZE,\n sort: 'id',\n where: whereClause,\n })\n\n if (contacts.length === 0) {\n logger.info(\n `Broadcast ${broadcast.id} complete. ` +\n `Processed: ${broadcast.meta.processedCount}, Expected: ${broadcast.meta.contactsCount}`,\n )\n await payload.update({\n id: broadcast.id,\n collection: 'broadcasts',\n data: { status: 'sent' },\n })\n return { output: { success: true } }\n }\n\n await Promise.all(\n contacts.map((contact) =>\n payload.jobs.queue({\n input: { broadcastId: broadcast.id, contactId: contact.id },\n queue: 'send-emails',\n task: 'send-email',\n }),\n ),\n )\n\n await payload.update({\n id: broadcast.id,\n collection: 'broadcasts',\n data: {\n meta: {\n lastProcessedContactId: getLastContactId(contacts[contacts.length - 1]),\n processedCount: broadcast.meta.processedCount + contacts.length,\n },\n },\n })\n\n logger.info(\n `Broadcast ${broadcast.id}: queued ${contacts.length} emails, ` +\n `total processed: ${broadcast.meta.processedCount + contacts.length}`,\n )\n\n return { output: { success: true } }\n },\n outputSchema: [\n {\n name: 'success',\n type: 'checkbox',\n },\n ],\n retries: 3,\n schedule: [\n {\n cron: TASK_SCHEDULE,\n queue: QUEUE_NAME,\n },\n ],\n }\n}\n"],"names":["z","BroadcastSchema","object","id","number","content","any","refine","val","undefined","message","fromAddress","email","fromName","string","min","meta","contactsCount","lastProcessedContactId","default","processedCount","subject","tags","array","optional","to","literal","or","safeParseBroadcast","broadcast","result","safeParse","success","data","errors","flattenError","error","fieldErrors","buildContactsWhereClause","rawBroadcast","conditions","emailOptIn","equals","greater_than","Array","isArray","length","tagIds","map","t","push","in","and","getLastContactId","contact","parseInt","createSendBroadcastsTask","pluginConfig","BATCH_SIZE","broadcastConfig","batchSize","TASK_SCHEDULE","taskSchedule","QUEUE_NAME","broadcastQueueName","slug","handler","req","payload","logger","info","docs","find","collection","limit","sort","where","status","output","parsed","update","whereClause","contacts","Promise","all","jobs","queue","input","broadcastId","contactId","task","outputSchema","name","type","retries","schedule","cron"],"mappings":"AAEA,OAAOA,OAAO,MAAK;AAInB;;CAEC,GACD,MAAMC,kBAAkBD,EAAEE,MAAM,CAAC;IAC/BC,IAAIH,EAAEI,MAAM;IACZC,SAASL,EAAEM,GAAG,GAAGC,MAAM,CAAC,CAACC,MAAQA,QAAQC,aAAaD,QAAQ,MAAM;QAClEE,SAAS;IACX;IACAC,aAAaX,EAAEY,KAAK,CAAC;QAAEF,SAAS;IAAoC;IACpEG,UAAUb,EAAEc,MAAM,GAAGC,GAAG,CAAC,GAAG;QAAEL,SAAS;IAAwB;IAC/DM,MAAMhB,EAAEE,MAAM,CAAC;QACbe,eAAejB,EAAEI,MAAM,GAAGW,GAAG,CAAC;QAC9BG,wBAAwBlB,EAAEI,MAAM,GAAGW,GAAG,CAAC,GAAGI,OAAO,CAAC;QAClDC,gBAAgBpB,EAAEI,MAAM,GAAGW,GAAG,CAAC;IACjC;IACAM,SAASrB,EAAEc,MAAM,GAAGC,GAAG,CAAC,GAAG;QAAEL,SAAS;IAAsB;IAC5DY,MAAMtB,EAAEuB,KAAK,CAACvB,EAAEM,GAAG,IAAIkB,QAAQ;IAC/BC,IAAIzB,EAAE0B,OAAO,CAAC,OAAOC,EAAE,CAAC3B,EAAE0B,OAAO,CAAC;AACpC;AAIA;;;CAGC,GACD,SAASE,mBAAmBC,SAAkB;IAC5C,MAAMC,SAAS7B,gBAAgB8B,SAAS,CAACF;IAEzC,IAAI,CAACC,OAAOE,OAAO,EAAE;QACnB,OAAO;YACLC,MAAM;YACNC,QAAQlC,EAAEmC,YAAY,CAACL,OAAOM,KAAK,EAAEC,WAAW;YAChDL,SAAS;QACX;IACF;IAEA,OAAO;QACLC,MAAMH,OAAOG,IAAI;QACjBD,SAAS;IACX;AACF;AAEA;;;;CAIC,GACD,SAASM,yBACPT,SAA0B,EAC1BU,YAAqC;IAErC,MAAMC,aAAsB;QAC1B;YAAEC,YAAY;gBAAEC,QAAQ;YAAK;QAAE;QAC/B;YAAEvC,IAAI;gBAAEwC,cAAcd,UAAUb,IAAI,CAACE,sBAAsB;YAAC;QAAE;KAC/D;IAED,oEAAoE;IACpE,IAAIW,UAAUJ,EAAE,KAAK,UAAUmB,MAAMC,OAAO,CAACN,aAAajB,IAAI,KAAKiB,aAAajB,IAAI,CAACwB,MAAM,GAAG,GAAG;QAC/F,MAAMC,SAASR,aAAajB,IAAI,CAAC0B,GAAG,CAAC,CAACC,IACpC,OAAOA,MAAM,WAAWA,EAAE9C,EAAE,GAAG8C;QAEjCT,WAAWU,IAAI,CAAC;YAAE5B,MAAM;gBAAE6B,IAAIJ;YAAO;QAAE;IACzC;IAEA,OAAO;QAAEK,KAAKZ;IAAW;AAC3B;AAEA;;CAEC,GACD,SAASa,iBAAiBC,OAAgC;IACxD,OAAO,OAAOA,QAAQnD,EAAE,KAAK,WAAWmD,QAAQnD,EAAE,GAAGoD,SAASD,QAAQnD,EAAE,EAAE;AAC5E;AAEA;;;;;;;CAOC,GACD,OAAO,MAAMqD,2BAA2B,CAACC;IACvC,MAAMC,aAAaD,aAAaE,eAAe,EAAEC,aAAa;IAC9D,MAAMC,gBAAgBJ,aAAaE,eAAe,EAAEG,gBAAgB;IACpE,MAAMC,aAAaN,aAAaE,eAAe,EAAEK,sBAAsB;IAEvE,OAAO;QACLC,MAAM;QACNC,SAAS,OAAO,EAAEC,GAAG,EAAE;YACrB,MAAM,EAAEC,OAAO,EAAE,GAAGD;YACpB,MAAME,SAASD,QAAQC,MAAM;YAE7BA,OAAOC,IAAI,CAAC;YAEZ,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMH,QAAQI,IAAI,CAAC;gBAClCC,YAAY;gBACZC,OAAO;gBACPC,MAAM;gBACNC,OAAO;oBAAEC,QAAQ;wBAAEnC,QAAQ;oBAAU;gBAAE;YACzC;YAEA,MAAMH,eAAegC,IAAI,CAAC,EAAE;YAE5B,IAAI,CAAChC,cAAc;gBACjB8B,OAAOC,IAAI,CAAC;gBACZ,OAAO;oBAAEQ,QAAQ;wBAAE9C,SAAS;oBAAK;gBAAE;YACrC;YAEA,MAAM+C,SAASnD,mBAAmBW;YAElC,IAAI,CAACwC,OAAO/C,OAAO,EAAE;gBACnBqC,OAAOjC,KAAK,CAAC;oBAAEF,QAAQ6C,OAAO7C,MAAM;gBAAC,GAAG,CAAC,UAAU,EAAEK,aAAapC,EAAE,CAAC,kBAAkB,CAAC;gBACxF,MAAMiE,QAAQY,MAAM,CAAC;oBACnB7E,IAAIoC,aAAapC,EAAE;oBACnBsE,YAAY;oBACZxC,MAAM;wBAAE4C,QAAQ;oBAAS;gBAC3B;gBACA,OAAO;oBAAEC,QAAQ;wBAAE9C,SAAS;oBAAM;gBAAE;YACtC;YAEA,MAAMH,YAAYkD,OAAO9C,IAAI;YAC7B,MAAMgD,cAAc3C,yBAClBT,WACAU;YAGF,MAAM,EAAEgC,MAAMW,QAAQ,EAAE,GAAG,MAAMd,QAAQI,IAAI,CAAC;gBAC5CC,YAAY;gBACZC,OAAOhB;gBACPiB,MAAM;gBACNC,OAAOK;YACT;YAEA,IAAIC,SAASpC,MAAM,KAAK,GAAG;gBACzBuB,OAAOC,IAAI,CACT,CAAC,UAAU,EAAEzC,UAAU1B,EAAE,CAAC,WAAW,CAAC,GACpC,CAAC,WAAW,EAAE0B,UAAUb,IAAI,CAACI,cAAc,CAAC,YAAY,EAAES,UAAUb,IAAI,CAACC,aAAa,EAAE;gBAE5F,MAAMmD,QAAQY,MAAM,CAAC;oBACnB7E,IAAI0B,UAAU1B,EAAE;oBAChBsE,YAAY;oBACZxC,MAAM;wBAAE4C,QAAQ;oBAAO;gBACzB;gBACA,OAAO;oBAAEC,QAAQ;wBAAE9C,SAAS;oBAAK;gBAAE;YACrC;YAEA,MAAMmD,QAAQC,GAAG,CACfF,SAASlC,GAAG,CAAC,CAACM,UACZc,QAAQiB,IAAI,CAACC,KAAK,CAAC;oBACjBC,OAAO;wBAAEC,aAAa3D,UAAU1B,EAAE;wBAAEsF,WAAWnC,QAAQnD,EAAE;oBAAC;oBAC1DmF,OAAO;oBACPI,MAAM;gBACR;YAIJ,MAAMtB,QAAQY,MAAM,CAAC;gBACnB7E,IAAI0B,UAAU1B,EAAE;gBAChBsE,YAAY;gBACZxC,MAAM;oBACJjB,MAAM;wBACJE,wBAAwBmC,iBAAiB6B,QAAQ,CAACA,SAASpC,MAAM,GAAG,EAAE;wBACtE1B,gBAAgBS,UAAUb,IAAI,CAACI,cAAc,GAAG8D,SAASpC,MAAM;oBACjE;gBACF;YACF;YAEAuB,OAAOC,IAAI,CACT,CAAC,UAAU,EAAEzC,UAAU1B,EAAE,CAAC,SAAS,EAAE+E,SAASpC,MAAM,CAAC,SAAS,CAAC,GAC7D,CAAC,iBAAiB,EAAEjB,UAAUb,IAAI,CAACI,cAAc,GAAG8D,SAASpC,MAAM,EAAE;YAGzE,OAAO;gBAAEgC,QAAQ;oBAAE9C,SAAS;gBAAK;YAAE;QACrC;QACA2D,cAAc;YACZ;gBACEC,MAAM;gBACNC,MAAM;YACR;SACD;QACDC,SAAS;QACTC,UAAU;YACR;gBACEC,MAAMnC;gBACNyB,OAAOvB;YACT;SACD;IACH;AACF,EAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TaskConfig } from 'payload';
|
|
2
|
+
import type { MobilizehubPluginConfig } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates the send-email task configuration.
|
|
5
|
+
*
|
|
6
|
+
* Handles delivery of a single email for one contact within a broadcast.
|
|
7
|
+
* Queued by the send-broadcasts task, one job per contact.
|
|
8
|
+
*/
|
|
9
|
+
export declare const createSendEmailTask: (pluginConfig: MobilizehubPluginConfig) => TaskConfig;
|