payload-plugin-marketing 0.9.1 → 0.9.2

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 (49) hide show
  1. package/README.md +47 -23
  2. package/dist/admin/audience-buttons.d.ts +6 -0
  3. package/dist/admin/audience-buttons.d.ts.map +1 -0
  4. package/dist/admin/broadcasts-table.d.ts +14 -0
  5. package/dist/admin/broadcasts-table.d.ts.map +1 -0
  6. package/dist/admin/components.d.ts +2 -1
  7. package/dist/admin/components.d.ts.map +1 -1
  8. package/dist/admin/contacts-table.d.ts +12 -0
  9. package/dist/admin/contacts-table.d.ts.map +1 -0
  10. package/dist/admin/create-broadcast-button.d.ts +6 -0
  11. package/dist/admin/create-broadcast-button.d.ts.map +1 -0
  12. package/dist/admin/date-format.d.ts +2 -0
  13. package/dist/admin/date-format.d.ts.map +1 -0
  14. package/dist/admin/index.cjs +1 -1
  15. package/dist/admin/index.cjs.map +1 -1
  16. package/dist/admin/index.js +1 -1
  17. package/dist/admin/index.js.map +1 -1
  18. package/dist/admin/paths.d.ts +2 -0
  19. package/dist/admin/paths.d.ts.map +1 -0
  20. package/dist/admin/payload-modal.d.ts +13 -0
  21. package/dist/admin/payload-modal.d.ts.map +1 -0
  22. package/dist/admin/provider-dashboard-link.d.ts +8 -0
  23. package/dist/admin/provider-dashboard-link.d.ts.map +1 -0
  24. package/dist/admin/use-marketing-api.d.ts +5 -0
  25. package/dist/admin/use-marketing-api.d.ts.map +1 -0
  26. package/dist/endpoints/marketing-endpoints.d.ts +3 -0
  27. package/dist/endpoints/marketing-endpoints.d.ts.map +1 -0
  28. package/dist/index.cjs +1 -1
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +3 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/marketing-integration.d.ts +15 -0
  35. package/dist/marketing-integration.d.ts.map +1 -0
  36. package/dist/plugin.d.ts.map +1 -1
  37. package/dist/types.d.ts +27 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/package.json +1 -6
  40. package/dist/actions/factories.d.ts +0 -18
  41. package/dist/actions/factories.d.ts.map +0 -1
  42. package/dist/actions/index.cjs +0 -2
  43. package/dist/actions/index.cjs.map +0 -1
  44. package/dist/actions/index.d.ts +0 -2
  45. package/dist/actions/index.d.ts.map +0 -1
  46. package/dist/actions/index.js +0 -2
  47. package/dist/actions/index.js.map +0 -1
  48. package/dist/chunk-RBBHOL35.js +0 -2
  49. package/dist/chunk-RBBHOL35.js.map +0 -1
package/README.md CHANGED
@@ -156,42 +156,68 @@ marketingPlugin({
156
156
 
157
157
  Components are also exported from `payload-plugin-marketing/admin`.
158
158
 
159
- ## Actions
159
+ ## Endpoint permissions
160
160
 
161
- Create adapter-backed actions with `createMarketingActions`:
161
+ Marketing REST routes (`GET /marketing/meta`, audiences, contacts, broadcasts) require an authenticated
162
+ admin user. You can narrow access with **`permissions`**: each of **`audiences`**, **`contacts`**, and
163
+ **`broadcasts`** accepts optional **`read`** and **`write`**. Omitted flags default to **`true`** for
164
+ that resource. If you omit **`permissions`** entirely, behavior matches previous releases (any signed-in
165
+ user can call all routes).
162
166
 
163
- ```ts
164
- import { createMarketingActions } from "payload-plugin-marketing"
165
- import { resendAdapter } from "payload-plugin-marketing/adapters/resend"
167
+ **`GET /marketing/meta`** is allowed when at least one resource has **`read: true`** after resolution.
166
168
 
167
- const actions = createMarketingActions({
169
+ ```ts
170
+ marketingPlugin({
168
171
  adapter: resendAdapter({ apiKey: process.env.RESEND_API_KEY }),
172
+ permissions: {
173
+ audiences: { read: true, write: true },
174
+ contacts: { read: true, write: false },
175
+ broadcasts: { read: true, write: true },
176
+ },
169
177
  })
178
+ ```
179
+
180
+ Denied requests respond with **403** and `{ message: "Forbidden" }`.
181
+
182
+ ## Using the adapter in your app
170
183
 
171
- await actions.createAudience({ name: "Newsletter" })
172
- await actions.newsletterSubscribe({ email: "person@example.com" })
184
+ The plugin attaches your **`MarketingAdapter`** to **`config.custom.payloadPluginMarketing`** (server-only; not sent to the admin client bundle). Resolve it from **`payload`** anywhere you already have **`Payload`**:
185
+
186
+ ```ts
187
+ import { getMarketingIntegration } from "payload-plugin-marketing"
188
+
189
+ const { adapter } = getMarketingIntegration(req.payload)
190
+ await adapter.audiences.create({ name: "Newsletter" })
191
+ ```
192
+
193
+ Subscribe an email to your first audience (pick a concrete **`audienceId`** if you prefer):
194
+
195
+ ```ts
196
+ const { adapter } = getMarketingIntegration(req.payload)
197
+ const audienceId = (await adapter.audiences.list())[0]?.id
198
+ if (!audienceId) {
199
+ throw new Error("No audience found. Create one in the admin first.")
200
+ }
201
+ await adapter.contacts.upsert({ audienceId, email: "person@example.com", subscribed: true })
173
202
  ```
174
203
 
175
204
  ## Broadcasts
176
205
 
177
- Use `createMarketingActions` with the same adapter as the plugin. `createBroadcast` and `sendBroadcast`
178
- return a boolean; `broadcastId` for send/delete comes from your provider (for example `adapter.broadcasts.list()` after create, or the provider dashboard).
206
+ Same adapter as **`marketingPlugin`**. **`broadcastId`** for send/delete comes from your provider (for example **`adapter.broadcasts.list()`** after create, or the provider dashboard).
179
207
 
180
208
  ### Resend (HTML or React)
181
209
 
182
210
  `defaultSender` on `resendAdapter` is sent as `from`. **`templateId` is not supported** and will throw.
183
211
 
184
212
  ```ts
185
- import { createMarketingActions } from "payload-plugin-marketing"
186
213
  import { resendAdapter } from "payload-plugin-marketing/adapters/resend"
187
214
 
188
215
  const adapter = resendAdapter({
189
216
  apiKey: process.env.RESEND_API_KEY!,
190
217
  defaultSender: "Acme <newsletter@example.com>",
191
218
  })
192
- const actions = createMarketingActions({ adapter })
193
219
 
194
- await actions.createBroadcast({
220
+ await adapter.broadcasts.create({
195
221
  audienceId: "<segment-or-audience-id>",
196
222
  name: "January update",
197
223
  subject: "What we shipped",
@@ -203,16 +229,15 @@ await actions.createBroadcast({
203
229
  const drafts = await adapter.broadcasts.list()
204
230
  const id = drafts[0]?.id
205
231
  if (id) {
206
- await actions.sendBroadcast({ broadcastId: id })
232
+ await adapter.broadcasts.send({ broadcastId: id })
207
233
  // optional ISO 8601 or natural language, depending on Resend SDK:
208
- // await actions.sendBroadcast({ broadcastId: id, scheduledAt: "2026-12-01T15:00:00.000Z" })
234
+ // await adapter.broadcasts.send({ broadcastId: id, scheduledAt: "2026-12-01T15:00:00.000Z" })
209
235
  }
210
236
  ```
211
237
 
212
238
  ### Mailchimp (HTML body)
213
239
 
214
240
  ```ts
215
- import { createMarketingActions } from "payload-plugin-marketing"
216
241
  import { mailchimpAdapter } from "payload-plugin-marketing/adapters/mailchimp"
217
242
 
218
243
  const adapter = mailchimpAdapter({
@@ -220,9 +245,8 @@ const adapter = mailchimpAdapter({
220
245
  defaultSender: "newsletter@example.com",
221
246
  siteName: "Acme",
222
247
  })
223
- const actions = createMarketingActions({ adapter })
224
248
 
225
- await actions.createBroadcast({
249
+ await adapter.broadcasts.create({
226
250
  audienceId: "<list-id>",
227
251
  name: "January update",
228
252
  subject: "What we shipped",
@@ -232,18 +256,18 @@ await actions.createBroadcast({
232
256
  const campaigns = await adapter.broadcasts.list()
233
257
  const id = campaigns[0]?.id
234
258
  if (id) {
235
- await actions.sendBroadcast({ broadcastId: id })
259
+ await adapter.broadcasts.send({ broadcastId: id })
236
260
  // or schedule:
237
- // await actions.sendBroadcast({ broadcastId: id, scheduledAt: "2026-12-01T15:00:00.000Z" })
261
+ // await adapter.broadcasts.send({ broadcastId: id, scheduledAt: "2026-12-01T15:00:00.000Z" })
238
262
  }
239
263
  ```
240
264
 
241
265
  ### Mailchimp (saved template)
242
266
 
243
- Use the numeric template id from your Mailchimp account as a string. Do not pass **`html`** in the same call. Reuse `actions` from the Mailchimp example above (same adapter and `createMarketingActions`).
267
+ Use the numeric template id from your Mailchimp account as a string. Do not pass **`html`** in the same call.
244
268
 
245
269
  ```ts
246
- await actions.createBroadcast({
270
+ await adapter.broadcasts.create({
247
271
  audienceId: "<list-id>",
248
272
  name: "Monthly newsletter",
249
273
  subject: "News from Acme",
@@ -254,5 +278,5 @@ await actions.createBroadcast({
254
278
  ### Delete a draft broadcast
255
279
 
256
280
  ```ts
257
- await actions.deleteBroadcast({ broadcastId: "<broadcast-or-campaign-id>" })
281
+ await adapter.broadcasts.delete({ broadcastId: "<broadcast-or-campaign-id>" })
258
282
  ```
@@ -0,0 +1,6 @@
1
+ export declare function CreateAudienceButton(): import("react/jsx-runtime").JSX.Element;
2
+ export declare function DeleteAudienceButton({ audienceId, audienceName, }: {
3
+ audienceId: string;
4
+ audienceName: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=audience-buttons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audience-buttons.d.ts","sourceRoot":"","sources":["../../src/admin/audience-buttons.tsx"],"names":[],"mappings":"AA4BA,wBAAgB,oBAAoB,4CAYnC;AA6DD,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,YAAY,GACb,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;CACrB,2CA4CA"}
@@ -0,0 +1,14 @@
1
+ import type { MarketingBroadcast } from "../types";
2
+ export interface MarketingBroadcastRow extends MarketingBroadcast {
3
+ externalDashboardUrl?: string;
4
+ }
5
+ interface BroadcastsTableProps {
6
+ broadcasts: MarketingBroadcastRow[];
7
+ }
8
+ export declare function BroadcastsTable({ broadcasts }: BroadcastsTableProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function SendBroadcastButton({ broadcastId, broadcastName, }: {
10
+ broadcastId: string;
11
+ broadcastName: string;
12
+ }): import("react/jsx-runtime").JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=broadcasts-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broadcasts-table.d.ts","sourceRoot":"","sources":["../../src/admin/broadcasts-table.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAGlD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,UAAU,oBAAoB;IAC5B,UAAU,EAAE,qBAAqB,EAAE,CAAA;CACpC;AAED,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,EAAE,oBAAoB,2CAgFnE;AAsED,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,aAAa,GACd,EAAE;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;CACtB,2CAkEA"}
@@ -1,4 +1,5 @@
1
- export declare function AudienceSelect(): null;
1
+ import type { TextFieldClientComponent } from "payload";
2
+ export declare const AudienceSelect: TextFieldClientComponent;
2
3
  export declare function MarketingMenu({ basePath }: {
3
4
  basePath?: string;
4
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/admin/components.tsx"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,SAE7B;AAOD,wBAAgB,aAAa,CAAC,EAAE,QAAa,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,2CAOrE;AAED,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,2CAY9F;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,2CAY7F;AAED,wBAAgB,eAAe,CAAC,EAC9B,UAAU,GACX,EAAE;IACD,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChD,2CAYA"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/admin/components.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAiBvD,eAAO,MAAM,cAAc,EAAE,wBA6C5B,CAAA;AAOD,wBAAgB,aAAa,CAAC,EAAE,QAAa,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,2CAWrE;AAED,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,2CAY9F;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,2CAY7F;AAED,wBAAgB,eAAe,CAAC,EAC9B,UAAU,GACX,EAAE;IACD,UAAU,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAChD,2CAYA"}
@@ -0,0 +1,12 @@
1
+ import type { MarketingContact } from "../types";
2
+ interface ContactsTableProps {
3
+ audienceId: string;
4
+ contacts: MarketingContact[];
5
+ }
6
+ export declare function ContactsTable({ audienceId, contacts }: ContactsTableProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function EditContactButton({ audienceId, contact, }: {
8
+ audienceId: string;
9
+ contact: MarketingContact | null;
10
+ }): import("react/jsx-runtime").JSX.Element;
11
+ export {};
12
+ //# sourceMappingURL=contacts-table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts-table.d.ts","sourceRoot":"","sources":["../../src/admin/contacts-table.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAIhD,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,kBAAkB,2CAgFzE;AAwDD,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,OAAO,GACR,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAA;CACjC,2CAgBA"}
@@ -0,0 +1,6 @@
1
+ import type { MarketingAudience } from "../types";
2
+ export declare function CreateBroadcastButton({ audiences, provider, }: {
3
+ audiences: MarketingAudience[];
4
+ provider: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=create-broadcast-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-broadcast-button.d.ts","sourceRoot":"","sources":["../../src/admin/create-broadcast-button.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAMjD,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,GACT,EAAE;IACD,SAAS,EAAE,iBAAiB,EAAE,CAAA;IAC9B,QAAQ,EAAE,MAAM,CAAA;CACjB,2CAYA"}
@@ -0,0 +1,2 @@
1
+ export declare function formatMarketingDate(iso?: string | null): string;
2
+ //# sourceMappingURL=date-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-format.d.ts","sourceRoot":"","sources":["../../src/admin/date-format.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAM/D"}
@@ -1,2 +1,2 @@
1
- "use strict";var d=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var v=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},B=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of y(t))!x.call(e,i)&&i!==r&&d(e,i,{get:()=>t[i],enumerable:!(o=A(t,i))||o.enumerable});return e};var k=e=>B(d({},"__esModule",{value:!0}),e);var L={};v(L,{AudienceDetail:()=>f,AudienceList:()=>b,AudienceSelect:()=>u,AudienceTable:()=>l,BroadcastList:()=>g,BroadcastsTable:()=>p,ContactsTable:()=>m,MarketingMenu:()=>s,defaultAdminComponentPath:()=>T});module.exports=k(L);var n=require("react/jsx-runtime");function u(){return null}function c(e,t){return["/admin",e?.replace(/^\/+|\/+$/g,""),t].filter(Boolean).join("/")}function s({basePath:e=""}){return(0,n.jsxs)("nav",{children:[(0,n.jsx)("a",{href:c(e,"audience"),children:"Audience"}),(0,n.jsx)("a",{href:c(e,"broadcast"),children:"Broadcasts"})]})}function l({audiences:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.name})},t.id))})})}function m({contacts:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.email})},t.id))})})}function p({broadcasts:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.name})},t.id))})})}var a=require("react/jsx-runtime");function b(){return(0,a.jsx)("div",{children:"Audience"})}function f(){return(0,a.jsx)("div",{children:"Audience Detail"})}function g(){return(0,a.jsx)("div",{children:"Broadcasts"})}var T="payload-plugin-marketing/admin";0&&(module.exports={AudienceDetail,AudienceList,AudienceSelect,AudienceTable,BroadcastList,BroadcastsTable,ContactsTable,MarketingMenu,defaultAdminComponentPath});
1
+ "use strict";var R=Object.create;var p=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var S=(e,t)=>{for(var r in t)p(e,r,{get:t[r],enumerable:!0})},b=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of N(t))!E.call(e,i)&&i!==r&&p(e,i,{get:()=>t[i],enumerable:!(o=$(t,i))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?R(q(e)):{},b(t||!e||!e.__esModule?p(r,"default",{value:e,enumerable:!0}):r,e)),F=e=>b(p({},"__esModule",{value:!0}),e);var I={};S(I,{AudienceDetail:()=>T,AudienceList:()=>L,AudienceSelect:()=>h,AudienceTable:()=>M,BroadcastList:()=>B,BroadcastsTable:()=>C,ContactsTable:()=>w,MarketingMenu:()=>x,defaultAdminComponentPath:()=>D});module.exports=F(I);var f=_(require("react"),1),c=require("@payloadcms/ui");var A=require("@payloadcms/ui"),m=require("react");function k(){let e=(0,A.useConfig)(),t=(0,m.useMemo)(()=>`${e.serverURL??""}${e.routes?.api??"/api"}`,[e.routes?.api,e.serverURL]),r=(0,m.useCallback)(async(o,i)=>{let{headers:l,...s}=i??{},u=new Headers(i?.headers);s.body!==void 0&&s.body!==""&&s.body!==null&&(u.has("Content-Type")||u.set("Content-Type","application/json"));let a=await fetch(`${t}${o}`,{...s,credentials:"include",headers:u});if(!a.ok){let d=`${a.status} ${a.statusText}`;try{let y=await a.json();typeof y.message=="string"&&(d=y.message)}catch{}throw new Error(d)}if(a.status!==204)try{return await a.json()}catch{return}},[t]);return{base:t,requestJson:r}}var n=require("react/jsx-runtime");function j(e){if(!Array.isArray(e))return[];let t=[];for(let r of e){if(!r||typeof r!="object")continue;let o=r,i=o.id,l=o.name;typeof i=="string"&&typeof l=="string"&&t.push({id:i,name:l})}return t}var h=({field:e,path:t,readOnly:r})=>{let{requestJson:o}=k(),[i,l]=f.default.useState([]),[s,u]=f.default.useState(null);return f.default.useEffect(()=>{let a=!1;return(async()=>{try{let d=await o("/marketing/audiences");a||(l(j(d)),u(null))}catch(d){a||u(d instanceof Error?d.message:"Failed to load audiences")}})(),()=>{a=!0}},[o]),(0,n.jsxs)("div",{className:"field-type relative",children:[s?(0,n.jsx)("p",{className:"text-red-500",role:"alert",children:s}):null,(0,n.jsx)(c.SelectField,{field:{label:typeof e.label=="string"?e.label:"Audience",name:e.name,options:i.map(a=>({label:a.name,value:a.id})),required:e.required===!0,type:"select"},path:t,readOnly:r})]})};function v(e,t){return["/admin",e?.replace(/^\/+|\/+$/g,""),t].filter(Boolean).join("/")}function x({basePath:e=""}){return(0,n.jsxs)(c.NavGroup,{isOpen:!0,label:"Marketing",children:[(0,n.jsx)(c.Link,{className:"nav__link",href:v(e,"audience"),children:"Audience"}),(0,n.jsx)(c.Link,{className:"nav__link",href:v(e,"broadcast"),children:"Broadcast"})]})}function M({audiences:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.name})},t.id))})})}function w({contacts:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.email})},t.id))})})}function C({broadcasts:e}){return(0,n.jsx)("table",{children:(0,n.jsx)("tbody",{children:e.map(t=>(0,n.jsx)("tr",{children:(0,n.jsx)("td",{children:t.name})},t.id))})})}var g=require("react/jsx-runtime");function L(){return(0,g.jsx)("div",{children:"Audience"})}function T(){return(0,g.jsx)("div",{children:"Audience Detail"})}function B(){return(0,g.jsx)("div",{children:"Broadcasts"})}var D="payload-plugin-marketing/admin";0&&(module.exports={AudienceDetail,AudienceList,AudienceSelect,AudienceTable,BroadcastList,BroadcastsTable,ContactsTable,MarketingMenu,defaultAdminComponentPath});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/index.ts","../../src/admin/components.tsx","../../src/admin/views.tsx"],"sourcesContent":["export const defaultAdminComponentPath = \"payload-plugin-marketing/admin\"\n\nexport {\n AudienceSelect,\n AudienceTable,\n BroadcastsTable,\n ContactsTable,\n MarketingMenu,\n} from \"./components\"\nexport { AudienceDetail, AudienceList, BroadcastList } from \"./views\"\n","\"use client\"\n\nimport React from \"react\"\n\nexport function AudienceSelect() {\n return null\n}\n\nfunction adminHref(basePath: string | undefined, segment: string): string {\n const normalized = basePath?.replace(/^\\/+|\\/+$/g, \"\")\n return [\"/admin\", normalized, segment].filter(Boolean).join(\"/\")\n}\n\nexport function MarketingMenu({ basePath = \"\" }: { basePath?: string }) {\n return (\n <nav>\n <a href={adminHref(basePath, \"audience\")}>Audience</a>\n <a href={adminHref(basePath, \"broadcast\")}>Broadcasts</a>\n </nav>\n )\n}\n\nexport function AudienceTable({ audiences }: { audiences: Array<{ id: string; name: string }> }) {\n return (\n <table>\n <tbody>\n {audiences.map((audience) => (\n <tr key={audience.id}>\n <td>{audience.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function ContactsTable({ contacts }: { contacts: Array<{ email: string; id: string }> }) {\n return (\n <table>\n <tbody>\n {contacts.map((contact) => (\n <tr key={contact.id}>\n <td>{contact.email}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function BroadcastsTable({\n broadcasts,\n}: {\n broadcasts: Array<{ id: string; name: string }>\n}) {\n return (\n <table>\n <tbody>\n {broadcasts.map((broadcast) => (\n <tr key={broadcast.id}>\n <td>{broadcast.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n","import React from \"react\"\n\nexport function AudienceList() {\n return <div>Audience</div>\n}\n\nexport function AudienceDetail() {\n return <div>Audience Detail</div>\n}\n\nexport function BroadcastList() {\n return <div>Broadcasts</div>\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,EAAA,iBAAAC,EAAA,mBAAAC,EAAA,kBAAAC,EAAA,kBAAAC,EAAA,oBAAAC,EAAA,kBAAAC,EAAA,kBAAAC,EAAA,8BAAAC,IAAA,eAAAC,EAAAX,GCeI,IAAAY,EAAA,6BAXG,SAASC,GAAiB,CAC/B,OAAO,IACT,CAEA,SAASC,EAAUC,EAA8BC,EAAyB,CAExE,MAAO,CAAC,SADWD,GAAU,QAAQ,aAAc,EAAE,EACvBC,CAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CACjE,CAEO,SAASC,EAAc,CAAE,SAAAF,EAAW,EAAG,EAA0B,CACtE,SACE,QAAC,OACC,oBAAC,KAAE,KAAMD,EAAUC,EAAU,UAAU,EAAG,oBAAQ,KAClD,OAAC,KAAE,KAAMD,EAAUC,EAAU,WAAW,EAAG,sBAAU,GACvD,CAEJ,CAEO,SAASG,EAAc,CAAE,UAAAC,CAAU,EAAuD,CAC/F,SACE,OAAC,SACC,mBAAC,SACE,SAAAA,EAAU,IAAKC,MACd,OAAC,MACC,mBAAC,MAAI,SAAAA,EAAS,KAAK,GADZA,EAAS,EAElB,CACD,EACH,EACF,CAEJ,CAEO,SAASC,EAAc,CAAE,SAAAC,CAAS,EAAuD,CAC9F,SACE,OAAC,SACC,mBAAC,SACE,SAAAA,EAAS,IAAKC,MACb,OAAC,MACC,mBAAC,MAAI,SAAAA,EAAQ,MAAM,GADZA,EAAQ,EAEjB,CACD,EACH,EACF,CAEJ,CAEO,SAASC,EAAgB,CAC9B,WAAAC,CACF,EAEG,CACD,SACE,OAAC,SACC,mBAAC,SACE,SAAAA,EAAW,IAAKC,MACf,OAAC,MACC,mBAAC,MAAI,SAAAA,EAAU,KAAK,GADbA,EAAU,EAEnB,CACD,EACH,EACF,CAEJ,CC/DS,IAAAC,EAAA,6BADF,SAASC,GAAe,CAC7B,SAAO,OAAC,OAAI,oBAAQ,CACtB,CAEO,SAASC,GAAiB,CAC/B,SAAO,OAAC,OAAI,2BAAe,CAC7B,CAEO,SAASC,GAAgB,CAC9B,SAAO,OAAC,OAAI,sBAAU,CACxB,CFZO,IAAMC,EAA4B","names":["admin_exports","__export","AudienceDetail","AudienceList","AudienceSelect","AudienceTable","BroadcastList","BroadcastsTable","ContactsTable","MarketingMenu","defaultAdminComponentPath","__toCommonJS","import_jsx_runtime","AudienceSelect","adminHref","basePath","segment","MarketingMenu","AudienceTable","audiences","audience","ContactsTable","contacts","contact","BroadcastsTable","broadcasts","broadcast","import_jsx_runtime","AudienceList","AudienceDetail","BroadcastList","defaultAdminComponentPath"]}
1
+ {"version":3,"sources":["../../src/admin/index.ts","../../src/admin/components.tsx","../../src/admin/use-marketing-api.ts","../../src/admin/views.tsx"],"sourcesContent":["export const defaultAdminComponentPath = \"payload-plugin-marketing/admin\"\n\nexport {\n AudienceSelect,\n AudienceTable,\n BroadcastsTable,\n ContactsTable,\n MarketingMenu,\n} from \"./components\"\nexport { AudienceDetail, AudienceList, BroadcastList } from \"./views\"\n","\"use client\"\n\nimport React from \"react\"\nimport { Link, NavGroup, SelectField } from \"@payloadcms/ui\"\n\nimport { useMarketingApi } from \"./use-marketing-api\"\n\nimport type { MarketingAudience } from \"../types\"\nimport type { TextFieldClientComponent } from \"payload\"\n\nfunction parseAudiences(payload: unknown): MarketingAudience[] {\n if (!Array.isArray(payload)) return []\n const out: MarketingAudience[] = []\n for (const item of payload) {\n if (!item || typeof item !== \"object\") continue\n const rec = item as Record<string, unknown>\n const id = rec.id\n const name = rec.name\n if (typeof id === \"string\" && typeof name === \"string\") {\n out.push({ id, name })\n }\n }\n return out\n}\n\nexport const AudienceSelect: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { requestJson } = useMarketingApi()\n const [audiences, setAudiences] = React.useState<MarketingAudience[]>([])\n const [loadError, setLoadError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const data = await requestJson(\"/marketing/audiences\")\n if (!cancelled) {\n setAudiences(parseAudiences(data))\n setLoadError(null)\n }\n } catch (err) {\n if (!cancelled) {\n setLoadError(err instanceof Error ? err.message : \"Failed to load audiences\")\n }\n }\n })()\n return () => {\n cancelled = true\n }\n }, [requestJson])\n\n return (\n <div className=\"field-type relative\">\n {loadError ? (\n <p className=\"text-red-500\" role=\"alert\">\n {loadError}\n </p>\n ) : null}\n <SelectField\n field={{\n label: typeof field.label === \"string\" ? field.label : \"Audience\",\n name: field.name,\n options: audiences.map((a) => ({ label: a.name, value: a.id })),\n required: field.required === true,\n type: \"select\",\n }}\n path={path}\n readOnly={readOnly}\n />\n </div>\n )\n}\n\nfunction adminHref(basePath: string | undefined, segment: string): string {\n const normalized = basePath?.replace(/^\\/+|\\/+$/g, \"\")\n return [\"/admin\", normalized, segment].filter(Boolean).join(\"/\")\n}\n\nexport function MarketingMenu({ basePath = \"\" }: { basePath?: string }) {\n return (\n <NavGroup isOpen label=\"Marketing\">\n <Link className=\"nav__link\" href={adminHref(basePath, \"audience\")}>\n Audience\n </Link>\n <Link className=\"nav__link\" href={adminHref(basePath, \"broadcast\")}>\n Broadcast\n </Link>\n </NavGroup>\n )\n}\n\nexport function AudienceTable({ audiences }: { audiences: Array<{ id: string; name: string }> }) {\n return (\n <table>\n <tbody>\n {audiences.map((audience) => (\n <tr key={audience.id}>\n <td>{audience.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function ContactsTable({ contacts }: { contacts: Array<{ email: string; id: string }> }) {\n return (\n <table>\n <tbody>\n {contacts.map((contact) => (\n <tr key={contact.id}>\n <td>{contact.email}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function BroadcastsTable({\n broadcasts,\n}: {\n broadcasts: Array<{ id: string; name: string }>\n}) {\n return (\n <table>\n <tbody>\n {broadcasts.map((broadcast) => (\n <tr key={broadcast.id}>\n <td>{broadcast.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n","\"use client\"\n\nimport { useConfig } from \"@payloadcms/ui\"\nimport { useCallback, useMemo } from \"react\"\n\nexport function useMarketingApi() {\n const context = useConfig() as unknown as {\n routes?: { api?: string }\n serverURL?: string\n }\n\n const base = useMemo(() => `${context.serverURL ?? \"\"}${context.routes?.api ?? \"/api\"}`, [\n context.routes?.api,\n context.serverURL,\n ])\n\n const requestJson = useCallback(\n async (pathSegment: string, init?: RequestInit): Promise<unknown> => {\n const { headers: _headersIgnored, ...restInit } = init ?? {}\n const headers = new Headers(init?.headers)\n if (\n restInit.body !== undefined &&\n restInit.body !== \"\" &&\n restInit.body !== null\n ) {\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\")\n }\n }\n\n const res = await fetch(`${base}${pathSegment}`, {\n ...restInit,\n credentials: \"include\",\n headers,\n })\n\n if (!res.ok) {\n let detail = `${res.status} ${res.statusText}`\n try {\n const parsed = (await res.json()) as { message?: string }\n if (typeof parsed.message === \"string\") detail = parsed.message\n } catch {\n //\n }\n throw new Error(detail)\n }\n\n if (res.status === 204) {\n return undefined\n }\n\n try {\n return await res.json()\n } catch {\n return undefined\n }\n },\n [base],\n )\n\n return { base, requestJson }\n}\n","import React from \"react\"\n\nexport function AudienceList() {\n return <div>Audience</div>\n}\n\nexport function AudienceDetail() {\n return <div>Audience Detail</div>\n}\n\nexport function BroadcastList() {\n return <div>Broadcasts</div>\n}\n"],"mappings":"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","names":["admin_exports","__export","AudienceDetail","AudienceList","AudienceSelect","AudienceTable","BroadcastList","BroadcastsTable","ContactsTable","MarketingMenu","defaultAdminComponentPath","__toCommonJS","import_react","import_ui","import_ui","import_react","useMarketingApi","context","base","requestJson","pathSegment","init","_headersIgnored","restInit","headers","res","detail","parsed","import_jsx_runtime","parseAudiences","payload","out","item","rec","id","name","AudienceSelect","field","path","readOnly","requestJson","useMarketingApi","audiences","setAudiences","React","loadError","setLoadError","cancelled","data","err","adminHref","basePath","segment","MarketingMenu","AudienceTable","audience","ContactsTable","contacts","contact","BroadcastsTable","broadcasts","broadcast","import_jsx_runtime","AudienceList","AudienceDetail","BroadcastList","defaultAdminComponentPath"]}
@@ -1,2 +1,2 @@
1
- import{jsx as t,jsxs as s}from"react/jsx-runtime";function a(){return null}function i(e,n){return["/admin",e?.replace(/^\/+|\/+$/g,""),n].filter(Boolean).join("/")}function d({basePath:e=""}){return s("nav",{children:[t("a",{href:i(e,"audience"),children:"Audience"}),t("a",{href:i(e,"broadcast"),children:"Broadcasts"})]})}function o({audiences:e}){return t("table",{children:t("tbody",{children:e.map(n=>t("tr",{children:t("td",{children:n.name})},n.id))})})}function c({contacts:e}){return t("table",{children:t("tbody",{children:e.map(n=>t("tr",{children:t("td",{children:n.email})},n.id))})})}function u({broadcasts:e}){return t("table",{children:t("tbody",{children:e.map(n=>t("tr",{children:t("td",{children:n.name})},n.id))})})}import{jsx as r}from"react/jsx-runtime";function l(){return r("div",{children:"Audience"})}function m(){return r("div",{children:"Audience Detail"})}function p(){return r("div",{children:"Broadcasts"})}var x="payload-plugin-marketing/admin";export{m as AudienceDetail,l as AudienceList,a as AudienceSelect,o as AudienceTable,p as BroadcastList,u as BroadcastsTable,c as ContactsTable,d as MarketingMenu,x as defaultAdminComponentPath};
1
+ import l from"react";import{Link as g,NavGroup as h,SelectField as x}from"@payloadcms/ui";import{useConfig as A}from"@payloadcms/ui";import{useCallback as k,useMemo as v}from"react";function f(){let e=A(),t=v(()=>`${e.serverURL??""}${e.routes?.api??"/api"}`,[e.routes?.api,e.serverURL]),i=k(async(a,o)=>{let{headers:u,...s}=o??{},c=new Headers(o?.headers);s.body!==void 0&&s.body!==""&&s.body!==null&&(c.has("Content-Type")||c.set("Content-Type","application/json"));let r=await fetch(`${t}${a}`,{...s,credentials:"include",headers:c});if(!r.ok){let d=`${r.status} ${r.statusText}`;try{let m=await r.json();typeof m.message=="string"&&(d=m.message)}catch{}throw new Error(d)}if(r.status!==204)try{return await r.json()}catch{return}},[t]);return{base:t,requestJson:i}}import{jsx as n,jsxs as b}from"react/jsx-runtime";function M(e){if(!Array.isArray(e))return[];let t=[];for(let i of e){if(!i||typeof i!="object")continue;let a=i,o=a.id,u=a.name;typeof o=="string"&&typeof u=="string"&&t.push({id:o,name:u})}return t}var w=({field:e,path:t,readOnly:i})=>{let{requestJson:a}=f(),[o,u]=l.useState([]),[s,c]=l.useState(null);return l.useEffect(()=>{let r=!1;return(async()=>{try{let d=await a("/marketing/audiences");r||(u(M(d)),c(null))}catch(d){r||c(d instanceof Error?d.message:"Failed to load audiences")}})(),()=>{r=!0}},[a]),b("div",{className:"field-type relative",children:[s?n("p",{className:"text-red-500",role:"alert",children:s}):null,n(x,{field:{label:typeof e.label=="string"?e.label:"Audience",name:e.name,options:o.map(r=>({label:r.name,value:r.id})),required:e.required===!0,type:"select"},path:t,readOnly:i})]})};function y(e,t){return["/admin",e?.replace(/^\/+|\/+$/g,""),t].filter(Boolean).join("/")}function C({basePath:e=""}){return b(h,{isOpen:!0,label:"Marketing",children:[n(g,{className:"nav__link",href:y(e,"audience"),children:"Audience"}),n(g,{className:"nav__link",href:y(e,"broadcast"),children:"Broadcast"})]})}function L({audiences:e}){return n("table",{children:n("tbody",{children:e.map(t=>n("tr",{children:n("td",{children:t.name})},t.id))})})}function T({contacts:e}){return n("table",{children:n("tbody",{children:e.map(t=>n("tr",{children:n("td",{children:t.email})},t.id))})})}function B({broadcasts:e}){return n("table",{children:n("tbody",{children:e.map(t=>n("tr",{children:n("td",{children:t.name})},t.id))})})}import{jsx as p}from"react/jsx-runtime";function R(){return p("div",{children:"Audience"})}function $(){return p("div",{children:"Audience Detail"})}function N(){return p("div",{children:"Broadcasts"})}var G="payload-plugin-marketing/admin";export{$ as AudienceDetail,R as AudienceList,w as AudienceSelect,L as AudienceTable,N as BroadcastList,B as BroadcastsTable,T as ContactsTable,C as MarketingMenu,G as defaultAdminComponentPath};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/components.tsx","../../src/admin/views.tsx","../../src/admin/index.ts"],"sourcesContent":["\"use client\"\n\nimport React from \"react\"\n\nexport function AudienceSelect() {\n return null\n}\n\nfunction adminHref(basePath: string | undefined, segment: string): string {\n const normalized = basePath?.replace(/^\\/+|\\/+$/g, \"\")\n return [\"/admin\", normalized, segment].filter(Boolean).join(\"/\")\n}\n\nexport function MarketingMenu({ basePath = \"\" }: { basePath?: string }) {\n return (\n <nav>\n <a href={adminHref(basePath, \"audience\")}>Audience</a>\n <a href={adminHref(basePath, \"broadcast\")}>Broadcasts</a>\n </nav>\n )\n}\n\nexport function AudienceTable({ audiences }: { audiences: Array<{ id: string; name: string }> }) {\n return (\n <table>\n <tbody>\n {audiences.map((audience) => (\n <tr key={audience.id}>\n <td>{audience.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function ContactsTable({ contacts }: { contacts: Array<{ email: string; id: string }> }) {\n return (\n <table>\n <tbody>\n {contacts.map((contact) => (\n <tr key={contact.id}>\n <td>{contact.email}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function BroadcastsTable({\n broadcasts,\n}: {\n broadcasts: Array<{ id: string; name: string }>\n}) {\n return (\n <table>\n <tbody>\n {broadcasts.map((broadcast) => (\n <tr key={broadcast.id}>\n <td>{broadcast.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n","import React from \"react\"\n\nexport function AudienceList() {\n return <div>Audience</div>\n}\n\nexport function AudienceDetail() {\n return <div>Audience Detail</div>\n}\n\nexport function BroadcastList() {\n return <div>Broadcasts</div>\n}\n","export const defaultAdminComponentPath = \"payload-plugin-marketing/admin\"\n\nexport {\n AudienceSelect,\n AudienceTable,\n BroadcastsTable,\n ContactsTable,\n MarketingMenu,\n} from \"./components\"\nexport { AudienceDetail, AudienceList, BroadcastList } from \"./views\"\n"],"mappings":"AAeI,OACE,OAAAA,EADF,QAAAC,MAAA,oBAXG,SAASC,GAAiB,CAC/B,OAAO,IACT,CAEA,SAASC,EAAUC,EAA8BC,EAAyB,CAExE,MAAO,CAAC,SADWD,GAAU,QAAQ,aAAc,EAAE,EACvBC,CAAO,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CACjE,CAEO,SAASC,EAAc,CAAE,SAAAF,EAAW,EAAG,EAA0B,CACtE,OACEH,EAAC,OACC,UAAAD,EAAC,KAAE,KAAMG,EAAUC,EAAU,UAAU,EAAG,oBAAQ,EAClDJ,EAAC,KAAE,KAAMG,EAAUC,EAAU,WAAW,EAAG,sBAAU,GACvD,CAEJ,CAEO,SAASG,EAAc,CAAE,UAAAC,CAAU,EAAuD,CAC/F,OACER,EAAC,SACC,SAAAA,EAAC,SACE,SAAAQ,EAAU,IAAKC,GACdT,EAAC,MACC,SAAAA,EAAC,MAAI,SAAAS,EAAS,KAAK,GADZA,EAAS,EAElB,CACD,EACH,EACF,CAEJ,CAEO,SAASC,EAAc,CAAE,SAAAC,CAAS,EAAuD,CAC9F,OACEX,EAAC,SACC,SAAAA,EAAC,SACE,SAAAW,EAAS,IAAKC,GACbZ,EAAC,MACC,SAAAA,EAAC,MAAI,SAAAY,EAAQ,MAAM,GADZA,EAAQ,EAEjB,CACD,EACH,EACF,CAEJ,CAEO,SAASC,EAAgB,CAC9B,WAAAC,CACF,EAEG,CACD,OACEd,EAAC,SACC,SAAAA,EAAC,SACE,SAAAc,EAAW,IAAKC,GACff,EAAC,MACC,SAAAA,EAAC,MAAI,SAAAe,EAAU,KAAK,GADbA,EAAU,EAEnB,CACD,EACH,EACF,CAEJ,CC/DS,cAAAC,MAAA,oBADF,SAASC,GAAe,CAC7B,OAAOD,EAAC,OAAI,oBAAQ,CACtB,CAEO,SAASE,GAAiB,CAC/B,OAAOF,EAAC,OAAI,2BAAe,CAC7B,CAEO,SAASG,GAAgB,CAC9B,OAAOH,EAAC,OAAI,sBAAU,CACxB,CCZO,IAAMI,EAA4B","names":["jsx","jsxs","AudienceSelect","adminHref","basePath","segment","MarketingMenu","AudienceTable","audiences","audience","ContactsTable","contacts","contact","BroadcastsTable","broadcasts","broadcast","jsx","AudienceList","AudienceDetail","BroadcastList","defaultAdminComponentPath"]}
1
+ {"version":3,"sources":["../../src/admin/components.tsx","../../src/admin/use-marketing-api.ts","../../src/admin/views.tsx","../../src/admin/index.ts"],"sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { Link, NavGroup, SelectField } from \"@payloadcms/ui\"\n\nimport { useMarketingApi } from \"./use-marketing-api\"\n\nimport type { MarketingAudience } from \"../types\"\nimport type { TextFieldClientComponent } from \"payload\"\n\nfunction parseAudiences(payload: unknown): MarketingAudience[] {\n if (!Array.isArray(payload)) return []\n const out: MarketingAudience[] = []\n for (const item of payload) {\n if (!item || typeof item !== \"object\") continue\n const rec = item as Record<string, unknown>\n const id = rec.id\n const name = rec.name\n if (typeof id === \"string\" && typeof name === \"string\") {\n out.push({ id, name })\n }\n }\n return out\n}\n\nexport const AudienceSelect: TextFieldClientComponent = ({ field, path, readOnly }) => {\n const { requestJson } = useMarketingApi()\n const [audiences, setAudiences] = React.useState<MarketingAudience[]>([])\n const [loadError, setLoadError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let cancelled = false\n void (async () => {\n try {\n const data = await requestJson(\"/marketing/audiences\")\n if (!cancelled) {\n setAudiences(parseAudiences(data))\n setLoadError(null)\n }\n } catch (err) {\n if (!cancelled) {\n setLoadError(err instanceof Error ? err.message : \"Failed to load audiences\")\n }\n }\n })()\n return () => {\n cancelled = true\n }\n }, [requestJson])\n\n return (\n <div className=\"field-type relative\">\n {loadError ? (\n <p className=\"text-red-500\" role=\"alert\">\n {loadError}\n </p>\n ) : null}\n <SelectField\n field={{\n label: typeof field.label === \"string\" ? field.label : \"Audience\",\n name: field.name,\n options: audiences.map((a) => ({ label: a.name, value: a.id })),\n required: field.required === true,\n type: \"select\",\n }}\n path={path}\n readOnly={readOnly}\n />\n </div>\n )\n}\n\nfunction adminHref(basePath: string | undefined, segment: string): string {\n const normalized = basePath?.replace(/^\\/+|\\/+$/g, \"\")\n return [\"/admin\", normalized, segment].filter(Boolean).join(\"/\")\n}\n\nexport function MarketingMenu({ basePath = \"\" }: { basePath?: string }) {\n return (\n <NavGroup isOpen label=\"Marketing\">\n <Link className=\"nav__link\" href={adminHref(basePath, \"audience\")}>\n Audience\n </Link>\n <Link className=\"nav__link\" href={adminHref(basePath, \"broadcast\")}>\n Broadcast\n </Link>\n </NavGroup>\n )\n}\n\nexport function AudienceTable({ audiences }: { audiences: Array<{ id: string; name: string }> }) {\n return (\n <table>\n <tbody>\n {audiences.map((audience) => (\n <tr key={audience.id}>\n <td>{audience.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function ContactsTable({ contacts }: { contacts: Array<{ email: string; id: string }> }) {\n return (\n <table>\n <tbody>\n {contacts.map((contact) => (\n <tr key={contact.id}>\n <td>{contact.email}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n\nexport function BroadcastsTable({\n broadcasts,\n}: {\n broadcasts: Array<{ id: string; name: string }>\n}) {\n return (\n <table>\n <tbody>\n {broadcasts.map((broadcast) => (\n <tr key={broadcast.id}>\n <td>{broadcast.name}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n}\n","\"use client\"\n\nimport { useConfig } from \"@payloadcms/ui\"\nimport { useCallback, useMemo } from \"react\"\n\nexport function useMarketingApi() {\n const context = useConfig() as unknown as {\n routes?: { api?: string }\n serverURL?: string\n }\n\n const base = useMemo(() => `${context.serverURL ?? \"\"}${context.routes?.api ?? \"/api\"}`, [\n context.routes?.api,\n context.serverURL,\n ])\n\n const requestJson = useCallback(\n async (pathSegment: string, init?: RequestInit): Promise<unknown> => {\n const { headers: _headersIgnored, ...restInit } = init ?? {}\n const headers = new Headers(init?.headers)\n if (\n restInit.body !== undefined &&\n restInit.body !== \"\" &&\n restInit.body !== null\n ) {\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\")\n }\n }\n\n const res = await fetch(`${base}${pathSegment}`, {\n ...restInit,\n credentials: \"include\",\n headers,\n })\n\n if (!res.ok) {\n let detail = `${res.status} ${res.statusText}`\n try {\n const parsed = (await res.json()) as { message?: string }\n if (typeof parsed.message === \"string\") detail = parsed.message\n } catch {\n //\n }\n throw new Error(detail)\n }\n\n if (res.status === 204) {\n return undefined\n }\n\n try {\n return await res.json()\n } catch {\n return undefined\n }\n },\n [base],\n )\n\n return { base, requestJson }\n}\n","import React from \"react\"\n\nexport function AudienceList() {\n return <div>Audience</div>\n}\n\nexport function AudienceDetail() {\n return <div>Audience Detail</div>\n}\n\nexport function BroadcastList() {\n return <div>Broadcasts</div>\n}\n","export const defaultAdminComponentPath = \"payload-plugin-marketing/admin\"\n\nexport {\n AudienceSelect,\n AudienceTable,\n BroadcastsTable,\n ContactsTable,\n MarketingMenu,\n} from \"./components\"\nexport { AudienceDetail, AudienceList, BroadcastList } from \"./views\"\n"],"mappings":"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","names":["React","Link","NavGroup","SelectField","useConfig","useCallback","useMemo","useMarketingApi","context","base","requestJson","pathSegment","init","_headersIgnored","restInit","headers","res","detail","parsed","jsx","jsxs","parseAudiences","payload","out","item","rec","id","name","AudienceSelect","field","path","readOnly","requestJson","useMarketingApi","audiences","setAudiences","React","loadError","setLoadError","cancelled","data","err","SelectField","a","adminHref","basePath","segment","MarketingMenu","NavGroup","Link","AudienceTable","audience","ContactsTable","contacts","contact","BroadcastsTable","broadcasts","broadcast","jsx","AudienceList","AudienceDetail","BroadcastList","defaultAdminComponentPath"]}
@@ -0,0 +1,2 @@
1
+ export declare function joinAdminSegments(adminRoute: string, ...segments: string[]): string;
2
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/admin/paths.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CASnF"}
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { Button, Modal } from "@payloadcms/ui";
3
+ interface PayloadModalProps extends React.ComponentProps<typeof Modal> {
4
+ children: React.ReactNode;
5
+ }
6
+ declare function PayloadModal({ children, className: _className, slug: modalSlug, ...props }: PayloadModalProps): import("react/jsx-runtime").JSX.Element;
7
+ declare function PayloadModalContent({ children, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
8
+ declare function PayloadModalBody({ children, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
9
+ declare function PayloadModalTitle({ children, ...props }: React.ComponentProps<"h1">): import("react/jsx-runtime").JSX.Element;
10
+ declare function PayloadModalFooter({ children, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
11
+ declare function PayloadModalClose({ children, className: _className, ...props }: React.ComponentProps<typeof Button>): import("react/jsx-runtime").JSX.Element;
12
+ export { PayloadModal, PayloadModalBody, PayloadModalClose, PayloadModalContent, PayloadModalFooter, PayloadModalTitle, };
13
+ //# sourceMappingURL=payload-modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload-modal.d.ts","sourceRoot":"","sources":["../../src/admin/payload-modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,EAAE,KAAK,EAA4B,MAAM,gBAAgB,CAAA;AAIxE,UAAU,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,OAAO,KAAK,CAAC;IACpE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,2CAgBtG;AAED,iBAAS,mBAAmB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAM/E;AAED,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAM5E;AAED,iBAAS,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,2CAM5E;AAED,iBAAS,kBAAkB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAM9E;AAED,iBAAS,iBAAiB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,2CAmB5G;AAED,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAClB,CAAA"}
@@ -0,0 +1,8 @@
1
+ export interface ProviderDashboardLinkProps {
2
+ children: React.ReactNode;
3
+ className?: string;
4
+ dashboardUrl?: string;
5
+ }
6
+ /** External link styled like the Acme template’s “powered by” row. Provider name is baked into anchor text via children. */
7
+ export declare function ProviderDashboardLink({ children, dashboardUrl }: ProviderDashboardLinkProps): import("react/jsx-runtime").JSX.Element | null;
8
+ //# sourceMappingURL=provider-dashboard-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-dashboard-link.d.ts","sourceRoot":"","sources":["../../src/admin/provider-dashboard-link.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,4HAA4H;AAC5H,wBAAgB,qBAAqB,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,0BAA0B,kDAe3F"}
@@ -0,0 +1,5 @@
1
+ export declare function useMarketingApi(): {
2
+ base: string;
3
+ requestJson: (pathSegment: string, init?: RequestInit) => Promise<unknown>;
4
+ };
5
+ //# sourceMappingURL=use-marketing-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-marketing-api.d.ts","sourceRoot":"","sources":["../../src/admin/use-marketing-api.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe;;+BAYP,MAAM,SAAS,WAAW,KAAG,OAAO,CAAC,OAAO,CAAC;EA4CpE"}
@@ -0,0 +1,3 @@
1
+ import type { Endpoint } from "payload";
2
+ export declare function createMarketingEndpoints(): Endpoint[];
3
+ //# sourceMappingURL=marketing-endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketing-endpoints.d.ts","sourceRoot":"","sources":["../../src/endpoints/marketing-endpoints.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AA8CvD,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CA8SrD"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var b=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var E=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},q=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of L(t))!V.call(e,s)&&s!==n&&b(e,s,{get:()=>t[s],enumerable:!(r=N(t,s))||r.enumerable});return e};var H=e=>q(b({},"__esModule",{value:!0}),e);var Z={};E(Z,{createAcceptanceBlock:()=>p,createMarketingActions:()=>k,createMarketingFormFields:()=>m,default:()=>w,marketingPlugin:()=>w});module.exports=H(Z);function k({adapter:e}){return{async createAudience(t){return await e.audiences.create(t),!0},async createBroadcast(t){return await e.broadcasts.create(t),!0},async deleteAudience(t){return await e.audiences.delete(t),!0},async deleteBroadcast(t){return await e.broadcasts.delete(t),!0},async deleteContact(t){return await e.contacts.delete(t),!0},async newsletterSubscribe(t){let n=t.audienceId??(await e.audiences.list())[0]?.id;if(!n)throw new Error("No audience found. Create one in the admin first.");return await e.contacts.upsert({audienceId:n,email:t.email,subscribed:!0}),!0},async sendBroadcast(t){return await e.broadcasts.send(t),!0},async updateContact(t){return await e.contacts.upsert(t),!0}}}function d(e,t){if(!t)return e;let{overrides:n,...r}=t;return{...e,...r,...n??{},admin:{..."admin"in e?e.admin:void 0,...r.admin??{},...n?.admin??{}}}}function y(e){return{type:"row",fields:e}}function M(e,t,n){let r=n?.fields??{};return{...{slug:e,labels:n?.labels??t,fields:[y([d({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},r.name),d({name:"label",type:"text",label:"Label",localized:!0,admin:{width:"50%"}},r.label)]),y([d({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"33%"}},r.width),d({name:"placeholder",type:"text",label:"Placeholder",localized:!0,admin:{width:"33%"}},r.placeholder),d({name:"defaultValue",type:"text",label:"Default Value",localized:!0,admin:{width:"33%"}},r.defaultValue)]),d({name:"required",type:"checkbox",label:"Required"},r.required)]},...n?.overrides??{}}}function p(e){let t=e?.fields??{};return{...{slug:"acceptance",labels:e?.labels??{singular:"Acceptance",plural:"Acceptances"},fields:[d({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},t.name),d({name:"label",type:"richText",label:"Label",localized:!0,admin:{width:"50%"}},t.label),y([d({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"50%"}},t.width),d({name:"required",type:"checkbox",label:"Required"},t.required)])]},...e?.overrides??{}}}function m(e={}){return{url:M("url",{singular:"URL",plural:"URLs"},e.url||void 0),phone:M("phone",{singular:"Phone",plural:"Phones"},e.phone||void 0),acceptance:p(e.acceptance||void 0)}}var C="__website",I="__startedAt";var B={acceptance:5,checkbox:5,country:200,date:100,email:320,message:5e3,number:64,payment:1e3,phone:50,select:200,state:200,text:200,textarea:5e3,upload:1e3,url:2048};function U(e){return e===C||e===I}function $(e){let t=e.find(r=>r.field===C)?.value,n=e.find(r=>r.field===I)?.value;return{honeypot:typeof t=="string"?t:"",startedAt:typeof n=="string"||typeof n=="number"?String(n):""}}function x(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)?String(e):typeof e=="string"?e.trim():""}function j(e,t){if(!t)return!e.required;if(t.length>(B[e.blockType]??1e3))return!1;if(e.blockType==="email")return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);if(e.blockType==="url")try{return new URL(t),!0}catch{return!1}return e.blockType==="number"?Number.isFinite(Number(t)):e.blockType==="checkbox"||e.blockType==="acceptance"?t==="true"||t==="false":e.blockType==="select"&&e.options?.length?e.options.some(n=>n.value===t):!0}function z(e,t){return e.required?e.blockType==="acceptance"?t==="true":!!t:!0}function A(e){let t=$(e.submissionData??[]);if(t.honeypot.trim())return{ok:!1,error:"Invalid submission."};let n=Number(t.startedAt);if(!Number.isFinite(n))return{ok:!1,error:"Invalid submission."};if(e.now-n<1500)return{ok:!1,error:"Form submitted too quickly."};let r=e.formFields.flatMap(o=>o.name&&o.blockType in B?[{...o,name:o.name}]:[]),s=new Map(r.map(o=>[o.name,o])),l=[],u=new Set;for(let o of e.submissionData??[]){let i=o.field?.trim();if(!i||U(i))continue;if(u.has(i))return{ok:!1,error:`Field "${i}" was submitted more than once.`};u.add(i);let c=s.get(i);if(!c)return{ok:!1,error:`Unexpected field "${i}".`};let a=x(o.value);if(!j(c,a))return{ok:!1,error:`Field "${i}" is invalid.`};l.push({field:i,value:a})}for(let o of r){let i=l.find(c=>c.field===o.name)?.value;if(!z(o,i))return{ok:!1,error:`Field "${o.name}" is required.`}}return{ok:!0,data:l}}function O(e){return Object.fromEntries(e.flatMap(t=>t.field?[[t.field,x(t.value)]]:[]))}function G(e,t){return e.replace(/\{\{\s*([\w.-]+)\s*\}\}/g,(n,r)=>t[r]??"")}function P(e,t){return(e??"").split(",").map(n=>G(n,t).trim()).filter(Boolean)}function F(e,t){let n=e.submissionData?.find(r=>r.field===t)?.value;if(typeof n=="string")return n;if(n!=null&&(typeof n=="number"&&Number.isFinite(n)||typeof n=="boolean"))return String(n)}async function v(e,t,n="forms"){return typeof e.form=="string"?await t.payload.findByID({collection:n,depth:0,id:e.form,overrideAccess:!0}):e.form}function _(e={}){return async({data:t,operation:n,req:r})=>{if(n!=="create")return t;let s=await v(t,r,e.formsSlug),l=A({formFields:s?.fields??[],now:Date.now(),submissionData:t?.submissionData??[]});if(!l.ok)throw new Error(l.error);return t.submissionData=l.data,t}}function D(e,t={}){return async({data:n,operation:r,req:s})=>{if(r!=="create")return n;let u=await v(n,s,t.formsSlug);if(u?.event!=="lead"||!u.audienceId)return n;let o=n,i=F(o,"email");if(!i)return n;let c=O(o.submissionData??[]),a=P(u.tags,c);return await e.contacts.upsert({audienceId:u.audienceId,email:i,firstName:F(o,"firstName"),lastName:F(o,"lastName"),properties:a.length>0?{tags:a.join(",")}:void 0,subscribed:!0}),n}}function S(e,t){return"name"in e&&e.name===t}function T(e){return!!(e&&typeof e=="object"&&"slug"in e&&typeof e.slug=="string")}function K(e){return!!(e&&typeof e=="object")}function Y(e,t){return!("name"in t)||!t.name?[...e,t]:e.some(n=>S(n,t.name))?e.map(n=>S(n,t.name)?t:n):[...e,t]}function W(e){let t=e.admin?.components?.audienceSelect??{path:"payload-plugin-marketing/admin",exportName:"AudienceSelect"};return[{name:"event",type:"select",defaultValue:"submission",options:[{label:"Submission",value:"submission"},{label:"Lead",value:"lead"}]},{name:"audienceId",type:"text",label:"Audience ID",required:!1,admin:{condition:(n,r)=>r?.event==="lead",components:{Field:t}},validate:(n,{siblingData:r}={})=>r?.event==="lead"&&!n?"Audience is required for lead forms.":!0},{name:"tags",type:"textarea",label:"Tags",admin:{condition:(n,r)=>r?.event==="lead",description:"Optional comma-separated tags. Use {{fieldName}} to insert submitted values."}}]}function X(e,t){let n=[...e.fields],r=n.findIndex(a=>S(a,"fields")&&a.type==="blocks");if(r<0){if(t.formBuilder?.strict===!1)return e;throw new Error(`Could not find a blocks field named "fields" on form-builder forms collection "${e.slug}".`)}let s=n[r],l=Array.isArray(s.blocks)?s.blocks:[],u=t.formBuilder?.fields??{},o=l.map(a=>{if(!T(a))return a;let f=u[a.slug];return!f||!K(a)?a:{...a,...f.overrides??{},...f.labels?{labels:f.labels}:{}}}),i=new Set(o.flatMap(a=>T(a)?[a.slug]:[])),c=Object.values(m(t.formBuilder?.fields)).filter(a=>!i.has(a.slug));n[r]={...s,blocks:[...o,...c]};for(let a of W(t))n.splice(0,n.length,...Y(n,a));return{...e,fields:n}}function J(e,t){let n=e.hooks??{};return{...e,hooks:{...n,beforeChange:[...n.beforeChange??[],_({formsSlug:t.formBuilder?.formsSlug}),D(t.adapter,{formsSlug:t.formBuilder?.formsSlug})]}}}function R(e,t){let n=t.formBuilder?.formsSlug??"forms",r=t.formBuilder?.submissionsSlug??"form-submissions",s=t.formBuilder?.strict??!0,l=e??[],u=l.some(i=>i.slug===n),o=l.some(i=>i.slug===r);if(s&&!u)throw new Error(`Could not find form-builder forms collection "${n}".`);if(s&&!o)throw new Error(`Could not find form-builder submissions collection "${r}".`);return l.map(i=>i.slug===n?X(i,t):i.slug===r?J(i,t):i)}function g(e,t){return{path:"payload-plugin-marketing/admin",exportName:e,...t?{clientProps:t}:{}}}function h(e,...t){return`/${[e.replace(/^\/+|\/+$/g,""),...t].filter(Boolean).join("/")}`}function Q(e,t){if(t.admin?.enabled===!1)return e;let n=t.admin?.basePath??"",r=t.admin?.components??{},s=r.marketingMenu??g("MarketingMenu",{basePath:n});return{...e,admin:{...e.admin??{},components:{...e.admin?.components??{},afterNavLinks:[...e.admin?.components?.afterNavLinks??[],s],views:{...e.admin?.components?.views??{},audienceList:{Component:r.audienceList??g("AudienceList"),path:h(n,"audience")},audienceDetail:{Component:r.audienceDetail??g("AudienceDetail"),path:h(n,"audience",":id")},broadcastList:{Component:r.broadcastList??g("BroadcastList"),path:h(n,"broadcast")}}}}}}function w(e){let t=n=>Q({...n,collections:R(n.collections,e)},e);return t.slug="marketing",t.order=10,t.options=e,t}0&&(module.exports={createAcceptanceBlock,createMarketingActions,createMarketingFormFields,marketingPlugin});
1
+ "use strict";var F=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var ee=(e,n)=>{for(var t in n)F(e,t,{get:n[t],enumerable:!0})},te=(e,n,t,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let a of Q(n))!Z.call(e,a)&&a!==t&&F(e,a,{get:()=>n[a],enumerable:!(r=X(n,a))||r.enumerable});return e};var ne=e=>te(F({},"__esModule",{value:!0}),e);var ke={};ee(ke,{MARKETING_CUSTOM_CONFIG_KEY:()=>k,createAcceptanceBlock:()=>y,createMarketingFormFields:()=>b,default:()=>A,getMarketingIntegration:()=>x,getMarketingIntegrationFromRequest:()=>f,marketingMetaAllowed:()=>M,marketingPlugin:()=>A,resolveMarketingPermissions:()=>h,tryGetMarketingIntegration:()=>z});module.exports=ne(ke);function m(e,n){if(!n)return e;let{overrides:t,...r}=n;return{...e,...r,...t??{},admin:{..."admin"in e?e.admin:void 0,...r.admin??{},...t?.admin??{}}}}function P(e){return{type:"row",fields:e}}function _(e,n,t){let r=t?.fields??{};return{...{slug:e,labels:t?.labels??n,fields:[P([m({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},r.name),m({name:"label",type:"text",label:"Label",localized:!0,admin:{width:"50%"}},r.label)]),P([m({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"33%"}},r.width),m({name:"placeholder",type:"text",label:"Placeholder",localized:!0,admin:{width:"33%"}},r.placeholder),m({name:"defaultValue",type:"text",label:"Default Value",localized:!0,admin:{width:"33%"}},r.defaultValue)]),m({name:"required",type:"checkbox",label:"Required"},r.required)]},...t?.overrides??{}}}function y(e){let n=e?.fields??{};return{...{slug:"acceptance",labels:e?.labels??{singular:"Acceptance",plural:"Acceptances"},fields:[m({name:"name",type:"text",label:"Name (lowercase, no special characters)",required:!0,admin:{width:"50%"}},n.name),m({name:"label",type:"richText",label:"Label",localized:!0,admin:{width:"50%"}},n.label),P([m({name:"width",type:"number",label:"Field Width (percentage)",admin:{width:"50%"}},n.width),m({name:"required",type:"checkbox",label:"Required"},n.required)])]},...e?.overrides??{}}}function b(e={}){return{url:_("url",{singular:"URL",plural:"URLs"},e.url||void 0),phone:_("phone",{singular:"Phone",plural:"Phones"},e.phone||void 0),acceptance:y(e.acceptance||void 0)}}var O="__website",T="__startedAt";var N={acceptance:5,checkbox:5,country:200,date:100,email:320,message:5e3,number:64,payment:1e3,phone:50,select:200,state:200,text:200,textarea:5e3,upload:1e3,url:2048};function re(e){return e===O||e===T}function ae(e){let n=e.find(r=>r.field===O)?.value,t=e.find(r=>r.field===T)?.value;return{honeypot:typeof n=="string"?n:"",startedAt:typeof t=="string"||typeof t=="number"?String(t):""}}function j(e){return typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e)?String(e):typeof e=="string"?e.trim():""}function ie(e,n){if(!n)return!e.required;if(n.length>(N[e.blockType]??1e3))return!1;if(e.blockType==="email")return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(n);if(e.blockType==="url")try{return new URL(n),!0}catch{return!1}return e.blockType==="number"?Number.isFinite(Number(n)):e.blockType==="checkbox"||e.blockType==="acceptance"?n==="true"||n==="false":e.blockType==="select"&&e.options?.length?e.options.some(t=>t.value===n):!0}function oe(e,n){return e.required?e.blockType==="acceptance"?n==="true":!!n:!0}function E(e){let n=ae(e.submissionData??[]);if(n.honeypot.trim())return{ok:!1,error:"Invalid submission."};let t=Number(n.startedAt);if(!Number.isFinite(t))return{ok:!1,error:"Invalid submission."};if(e.now-t<1500)return{ok:!1,error:"Form submitted too quickly."};let r=e.formFields.flatMap(s=>s.name&&s.blockType in N?[{...s,name:s.name}]:[]),a=new Map(r.map(s=>[s.name,s])),i=[],u=new Set;for(let s of e.submissionData??[]){let o=s.field?.trim();if(!o||re(o))continue;if(u.has(o))return{ok:!1,error:`Field "${o}" was submitted more than once.`};u.add(o);let l=a.get(o);if(!l)return{ok:!1,error:`Unexpected field "${o}".`};let d=j(s.value);if(!ie(l,d))return{ok:!1,error:`Field "${o}" is invalid.`};i.push({field:o,value:d})}for(let s of r){let o=i.find(l=>l.field===s.name)?.value;if(!oe(s,o))return{ok:!1,error:`Field "${s.name}" is required.`}}return{ok:!0,data:i}}function D(e){return Object.fromEntries(e.flatMap(n=>n.field?[[n.field,j(n.value)]]:[]))}function se(e,n){return e.replace(/\{\{\s*([\w.-]+)\s*\}\}/g,(t,r)=>n[r]??"")}function L(e,n){return(e??"").split(",").map(t=>se(t,n).trim()).filter(Boolean)}function R(e,n){let t=e.submissionData?.find(r=>r.field===n)?.value;if(typeof t=="string")return t;if(t!=null&&(typeof t=="number"&&Number.isFinite(t)||typeof t=="boolean"))return String(t)}async function V(e,n,t="forms"){return typeof e.form=="string"?await n.payload.findByID({collection:t,depth:0,id:e.form,overrideAccess:!0}):e.form}function U(e={}){return async({data:n,operation:t,req:r})=>{if(t!=="create")return n;let a=await V(n,r,e.formsSlug),i=E({formFields:a?.fields??[],now:Date.now(),submissionData:n?.submissionData??[]});if(!i.ok)throw new Error(i.error);return n.submissionData=i.data,n}}function H(e,n={}){return async({data:t,operation:r,req:a})=>{if(r!=="create")return t;let u=await V(t,a,n.formsSlug);if(u?.event!=="lead"||!u.audienceId)return t;let s=t,o=R(s,"email");if(!o)return t;let l=D(s.submissionData??[]),d=L(u.tags,l);return await e.contacts.upsert({audienceId:u.audienceId,email:o,firstName:R(s,"firstName"),lastName:R(s,"lastName"),properties:d.length>0?{tags:d.join(",")}:void 0,subscribed:!0}),t}}function S(e,n){return"name"in e&&e.name===n}function $(e){return!!(e&&typeof e=="object"&&"slug"in e&&typeof e.slug=="string")}function de(e){return!!(e&&typeof e=="object")}function ue(e,n){return!("name"in n)||!n.name?[...e,n]:e.some(t=>S(t,n.name))?e.map(t=>S(t,n.name)?n:t):[...e,n]}function le(e){let n=e.admin?.components?.audienceSelect??{path:"payload-plugin-marketing/admin",exportName:"AudienceSelect"};return[{name:"event",type:"select",defaultValue:"submission",options:[{label:"Submission",value:"submission"},{label:"Lead",value:"lead"}]},{name:"audienceId",type:"text",label:"Audience ID",required:!1,admin:{condition:(t,r)=>r?.event==="lead",components:{Field:n}},validate:(t,{siblingData:r}={})=>r?.event==="lead"&&!t?"Audience is required for lead forms.":!0},{name:"tags",type:"textarea",label:"Tags",admin:{condition:(t,r)=>r?.event==="lead",description:"Optional comma-separated tags. Use {{fieldName}} to insert submitted values."}}]}function ce(e,n){let t=[...e.fields],r=t.findIndex(d=>S(d,"fields")&&d.type==="blocks");if(r<0){if(n.formBuilder?.strict===!1)return e;throw new Error(`Could not find a blocks field named "fields" on form-builder forms collection "${e.slug}".`)}let a=t[r],i=Array.isArray(a.blocks)?a.blocks:[],u=n.formBuilder?.fields??{},s=i.map(d=>{if(!$(d))return d;let p=u[d.slug];return!p||!de(d)?d:{...d,...p.overrides??{},...p.labels?{labels:p.labels}:{}}}),o=new Set(s.flatMap(d=>$(d)?[d.slug]:[])),l=Object.values(b(n.formBuilder?.fields)).filter(d=>!o.has(d.slug));t[r]={...a,blocks:[...s,...l]};for(let d of le(n))t.splice(0,t.length,...ue(t,d));return{...e,fields:t}}function me(e,n){let t=e.hooks??{};return{...e,hooks:{...t,beforeChange:[...t.beforeChange??[],U({formsSlug:n.formBuilder?.formsSlug}),H(n.adapter,{formsSlug:n.formBuilder?.formsSlug})]}}}function G(e,n){let t=n.formBuilder?.formsSlug??"forms",r=n.formBuilder?.submissionsSlug??"form-submissions",a=n.formBuilder?.strict??!0,i=e??[],u=i.some(o=>o.slug===t),s=i.some(o=>o.slug===r);if(a&&!u)throw new Error(`Could not find form-builder forms collection "${t}".`);if(a&&!s)throw new Error(`Could not find form-builder submissions collection "${r}".`);return i.map(o=>o.slug===t?ce(o,n):o.slug===r?me(o,n):o)}var k="payloadPluginMarketing";function C(e){return{read:e?.read??!0,write:e?.write??!0}}function h(e){return e?{audiences:C(e.audiences),contacts:C(e.contacts),broadcasts:C(e.broadcasts)}:{audiences:{read:!0,write:!0},broadcasts:{read:!0,write:!0},contacts:{read:!0,write:!0}}}function M(e){return e.audiences.read||e.contacts.read||e.broadcasts.read}function K(e){let n=e.config.custom;if(!n||typeof n!="object")return;let t=n[k];if(t?.adapter)return t}function x(e){let n=K(e);if(!n)throw new Error(`${k}: adapter missing on Payload config. Is marketingPlugin() registered?`);return n}function z(e){return K(e)}function f(e){return x(e.payload)}function fe(){return Response.json({message:"Unauthorized"},{status:401})}function Y(){return Response.json({message:"Forbidden"},{status:403})}function q(e){return e.user?null:fe()}function J(e){let{permissions:n}=f(e);return h(n)}function c(e,n,t){let r=q(e);return r||(J(e)[n][t]?null:Y())}function w(e){return!!(e&&typeof e=="object")}async function v(e){return await e.json()}function g(e){return f(e).adapter}function W(){return[{handler:e=>{let n=q(e);if(n)return n;if(!M(J(e)))return Y();let{adapter:t}=f(e);return Response.json({label:t.label,provider:t.provider,urls:{audience:t.urls?.audiences,broadcasts:t.urls?.broadcasts}})},method:"get",path:"/marketing/meta"},{handler:async e=>{let n=c(e,"audiences","read");if(n)return n;let t=f(e).adapter;return Response.json(await t.audiences.list())},method:"get",path:"/marketing/audiences"},{handler:async e=>{let n=c(e,"audiences","write");if(n)return n;let t=await v(e),r=typeof t?.name=="string"?t.name.trim():"";return r?(await g(e).audiences.create({name:r}),Response.json({ok:!0})):Response.json({message:"name is required"},{status:400})},method:"post",path:"/marketing/audiences"},{handler:async e=>{let n=c(e,"audiences","read");if(n)return n;let t=typeof e.routeParams?.id=="string"?e.routeParams.id:"";if(!t)return Response.json({message:"Missing audience id"},{status:400});let a=await f(e).adapter.audiences.get(t);return a?Response.json(a):Response.json({message:"Not found"},{status:404})},method:"get",path:"/marketing/audiences/:id"},{handler:async e=>{let n=c(e,"audiences","write");if(n)return n;let t=typeof e.routeParams?.id=="string"?e.routeParams.id:"";return t?(await g(e).audiences.delete({audienceId:t}),Response.json({ok:!0})):Response.json({message:"Missing audience id"},{status:400})},method:"delete",path:"/marketing/audiences/:id"},{handler:async e=>{let n=c(e,"contacts","read");if(n)return n;let t=typeof e.routeParams?.audienceId=="string"?e.routeParams.audienceId:"";if(!t)return Response.json({message:"Missing audience id"},{status:400});let r=f(e).adapter;return Response.json(await r.contacts.list({audienceId:t}))},method:"get",path:"/marketing/audiences/:audienceId/contacts"},{handler:async e=>{let n=c(e,"contacts","write");if(n)return n;let t=typeof e.routeParams?.audienceId=="string"?e.routeParams.audienceId:"",r=typeof e.routeParams?.contactId=="string"?e.routeParams.contactId:"";return!t||!r?Response.json({message:"Missing audienceId or contactId"},{status:400}):(await g(e).contacts.delete({audienceId:t,contactId:r}),Response.json({ok:!0}))},method:"delete",path:"/marketing/audiences/:audienceId/contacts/:contactId"},{handler:async e=>{let n=c(e,"contacts","write");if(n)return n;let t=await v(e);if(!w(t))return Response.json({message:"Invalid JSON"},{status:400});let r=typeof t.email=="string"?t.email.trim():void 0,a=typeof t.audienceId=="string"?t.audienceId:void 0;if(!a||!r)return Response.json({message:"audienceId and email are required"},{status:400});let i={audienceId:a,email:r,subscribed:typeof t.subscribed=="boolean"?t.subscribed:!0};return typeof t.id=="string"&&t.id&&(i.id=t.id),typeof t.firstName=="string"&&(i.firstName=t.firstName),typeof t.lastName=="string"&&(i.lastName=t.lastName),w(t.properties)&&(i.properties=t.properties),await g(e).contacts.upsert(i),Response.json({ok:!0})},method:"post",path:"/marketing/contacts"},{handler:async e=>{let n=c(e,"broadcasts","read");if(n)return n;let t=f(e).adapter,a=(await t.broadcasts.list()).map(i=>({...i,externalDashboardUrl:t.urls?.broadcast?.(i.id)}));return Response.json(a)},method:"get",path:"/marketing/broadcasts"},{handler:async e=>{let n=c(e,"broadcasts","write");if(n)return n;let t=await v(e);if(!w(t))return Response.json({message:"Invalid JSON"},{status:400});let r=typeof t.audienceId=="string"?t.audienceId.trim():"",a=typeof t.name=="string"?t.name.trim():"",i=typeof t.subject=="string"?t.subject.trim():"",u=typeof t.templateId=="string"?t.templateId.trim():"",s=typeof t.html=="string"?t.html.trim():"",o=typeof t.replyTo=="string"?t.replyTo.trim():void 0,l=typeof t.locale=="string"?t.locale:void 0;if(!r||!a||!i)return Response.json({message:"audienceId, name, and subject are required"},{status:400});let d=u!=="";if(!d&&!s)return Response.json({message:"Provide HTML body or a template id."},{status:400});let p;return d&&s!==""?Response.json({message:"Use either HTML or template id, not both."},{status:400}):(d?p={audienceId:r,locale:l,name:a,replyTo:o,subject:i,templateId:u}:p={audienceId:r,html:s,locale:l,name:a,replyTo:o,subject:i},await g(e).broadcasts.create(p),Response.json({ok:!0}))},method:"post",path:"/marketing/broadcasts"},{handler:async e=>{let n=c(e,"broadcasts","write");if(n)return n;let t=typeof e.routeParams?.broadcastId=="string"?e.routeParams.broadcastId:"";return t?(await g(e).broadcasts.delete({broadcastId:t}),Response.json({ok:!0})):Response.json({message:"Missing broadcast id"},{status:400})},method:"delete",path:"/marketing/broadcasts/:broadcastId"},{handler:async e=>{let n=c(e,"broadcasts","write");if(n)return n;let t=typeof e.routeParams?.broadcastId=="string"?e.routeParams.broadcastId:"";if(!t)return Response.json({message:"Missing broadcast id"},{status:400});let r;try{let i=await e.clone().json();w(i)&&typeof i.scheduledAt=="string"&&(r=i.scheduledAt)}catch{r=void 0}return await g(e).broadcasts.send({broadcastId:t,scheduledAt:r}),Response.json({ok:!0})},method:"post",path:"/marketing/broadcasts/:broadcastId/send"}]}function pe(e,n){let t=e.custom,r=typeof t=="object"&&t!==null&&!Array.isArray(t)?{...t}:{};return r[k]=n,r}function I(e,n){return{path:"payload-plugin-marketing/admin",exportName:e,...n?{clientProps:n}:{}}}function B(e,...n){return`/${[e.replace(/^\/+|\/+$/g,""),...n].filter(Boolean).join("/")}`}function ge(e,n){if(n.admin?.enabled===!1)return e;let t=n.admin?.basePath??"",r=n.admin?.components??{},a=r.marketingMenu??I("MarketingMenu",{basePath:t}),i={basePath:t},u={adapter:n.adapter,adminBasePath:t,permissions:n.permissions};return{...e,custom:pe(e,u),endpoints:[...e.endpoints??[],...W()],admin:{...e.admin??{},components:{...e.admin?.components??{},afterNavLinks:[...e.admin?.components?.afterNavLinks??[],a],views:{...e.admin?.components?.views??{},audienceList:{Component:r.audienceList??I("AudienceList",i),path:B(t,"audience")},audienceDetail:{Component:r.audienceDetail??I("AudienceDetail",i),path:B(t,"audience",":id")},broadcastList:{Component:r.broadcastList??I("BroadcastList",i),path:B(t,"broadcast")}}}}}}function A(e){let n=t=>ge({...t,collections:G(t.collections,e)},e);return n.slug="marketing",n.order=10,n.options=e,n}0&&(module.exports={MARKETING_CUSTOM_CONFIG_KEY,createAcceptanceBlock,createMarketingFormFields,getMarketingIntegration,getMarketingIntegrationFromRequest,marketingMetaAllowed,marketingPlugin,resolveMarketingPermissions,tryGetMarketingIntegration});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/actions/factories.ts","../src/form-builder/fields.ts","../src/form-builder/submission.ts","../src/form-builder/hooks.ts","../src/form-builder/mutate-collections.ts","../src/plugin.ts"],"sourcesContent":["export { createMarketingActions } from \"./actions\"\nexport { createAcceptanceBlock, createMarketingFormFields } from \"./form-builder\"\nexport { marketingPlugin } from \"./plugin\"\nexport type {\n CreateAudienceInput,\n CreateBroadcastInput,\n DeleteAudienceInput,\n DeleteBroadcastInput,\n DeleteContactInput,\n ListContactsInput,\n MarketingAdapter,\n MarketingAudience,\n MarketingBroadcast,\n MarketingContact,\n MarketingFormFieldOverrides,\n PayloadComponentOverride,\n PayloadPluginMarketingOptions,\n SendBroadcastInput,\n UpsertContactInput,\n} from \"./types\"\n\nexport { marketingPlugin as default } from \"./plugin\"\n","import type {\n CreateAudienceInput,\n CreateBroadcastInput,\n DeleteAudienceInput,\n DeleteBroadcastInput,\n DeleteContactInput,\n MarketingAdapter,\n SendBroadcastInput,\n UpsertContactInput,\n} from \"../types\"\n\nexport interface CreateMarketingActionsOptions {\n adapter: MarketingAdapter\n}\n\nexport function createMarketingActions({ adapter }: CreateMarketingActionsOptions) {\n return {\n async createAudience(input: CreateAudienceInput) {\n await adapter.audiences.create(input)\n return true\n },\n async createBroadcast(input: CreateBroadcastInput) {\n await adapter.broadcasts.create(input)\n return true\n },\n async deleteAudience(input: DeleteAudienceInput) {\n await adapter.audiences.delete(input)\n return true\n },\n async deleteBroadcast(input: DeleteBroadcastInput) {\n await adapter.broadcasts.delete(input)\n return true\n },\n async deleteContact(input: DeleteContactInput) {\n await adapter.contacts.delete(input)\n return true\n },\n async newsletterSubscribe(input: { audienceId?: string; email: string }) {\n const audienceId = input.audienceId ?? (await adapter.audiences.list())[0]?.id\n if (!audienceId) {\n throw new Error(\"No audience found. Create one in the admin first.\")\n }\n await adapter.contacts.upsert({ audienceId, email: input.email, subscribed: true })\n return true\n },\n async sendBroadcast(input: SendBroadcastInput) {\n await adapter.broadcasts.send(input)\n return true\n },\n async updateContact(input: UpsertContactInput) {\n await adapter.contacts.upsert(input)\n return true\n },\n }\n}\n","import type { FieldOverride, MarketingBlockOptions, MarketingFormFieldOverrides } from \"../types\"\nimport type { Block, Field } from \"payload\"\n\nexport const CUSTOM_MARKETING_FIELD_NAMES = [\"url\", \"phone\", \"acceptance\"] as const\n\nfunction mergeField(base: Field, override?: FieldOverride): Field {\n if (!override) {\n return base\n }\n\n const { overrides, ...direct } = override\n return {\n ...base,\n ...direct,\n ...(overrides ?? {}),\n admin: {\n ...(\"admin\" in base ? base.admin : undefined),\n ...(direct.admin ?? {}),\n ...(overrides?.admin ?? {}),\n },\n } as Field\n}\n\nfunction row(fields: Field[]): Field {\n return { type: \"row\", fields } as Field\n}\n\nfunction textLikeBlock(\n slug: \"phone\" | \"url\",\n labels: Required<Block>[\"labels\"],\n options?: MarketingBlockOptions,\n): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug,\n labels: options?.labels ?? labels,\n fields: [\n row([\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"text\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n ]),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"33%\" },\n },\n fields.width,\n ),\n mergeField(\n {\n name: \"placeholder\",\n type: \"text\",\n label: \"Placeholder\",\n localized: true,\n admin: { width: \"33%\" },\n },\n fields.placeholder,\n ),\n mergeField(\n {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n admin: { width: \"33%\" },\n },\n fields.defaultValue,\n ),\n ]),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createAcceptanceBlock(options?: MarketingBlockOptions): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug: \"acceptance\",\n labels: options?.labels ?? { singular: \"Acceptance\", plural: \"Acceptances\" },\n fields: [\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"richText\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"50%\" },\n },\n fields.width,\n ),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ]),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createMarketingFormFields(\n overrides: MarketingFormFieldOverrides = {},\n): Record<(typeof CUSTOM_MARKETING_FIELD_NAMES)[number], Block> {\n return {\n url: textLikeBlock(\"url\", { singular: \"URL\", plural: \"URLs\" }, overrides.url || undefined),\n phone: textLikeBlock(\n \"phone\",\n { singular: \"Phone\", plural: \"Phones\" },\n overrides.phone || undefined,\n ),\n acceptance: createAcceptanceBlock(overrides.acceptance || undefined),\n }\n}\n\nexport function createMarketingBlocksForMutation(\n overrides: MarketingFormFieldOverrides = {},\n): Block[] {\n return Object.values(createMarketingFormFields(overrides))\n}\n","export const FORM_HONEYPOT_FIELD = \"__website\"\nexport const FORM_STARTED_AT_FIELD = \"__startedAt\"\nexport const MIN_SUBMISSION_TIME_MS = 1_500\n\nconst MAX_LENGTH_BY_BLOCK: Record<string, number> = {\n acceptance: 5,\n checkbox: 5,\n country: 200,\n date: 100,\n email: 320,\n message: 5_000,\n number: 64,\n payment: 1_000,\n phone: 50,\n select: 200,\n state: 200,\n text: 200,\n textarea: 5_000,\n upload: 1_000,\n url: 2_048,\n}\n\nexport interface ValidationFormField {\n blockType: string\n name?: string | null\n options?: Array<{ value: string }> | null\n required?: boolean | null\n}\n\nexport interface ValidationSubmissionField {\n field?: string | null\n value?: unknown\n}\n\nexport type SubmissionValidationResult =\n | { data: Array<{ field: string; value: string }>; ok: true }\n | { error: string; ok: false }\n\nfunction isControlField(fieldName: string): boolean {\n return fieldName === FORM_HONEYPOT_FIELD || fieldName === FORM_STARTED_AT_FIELD\n}\n\nfunction extractControlFields(submissionData: ValidationSubmissionField[]): {\n honeypot: string\n startedAt: string\n} {\n const honeypot = submissionData.find((entry) => entry.field === FORM_HONEYPOT_FIELD)?.value\n const startedAt = submissionData.find((entry) => entry.field === FORM_STARTED_AT_FIELD)?.value\n return {\n honeypot: typeof honeypot === \"string\" ? honeypot : \"\",\n startedAt:\n typeof startedAt === \"string\" || typeof startedAt === \"number\" ? String(startedAt) : \"\",\n }\n}\n\nfunction stringifySubmissionValue(value: unknown): string {\n if (typeof value === \"boolean\") {\n return String(value)\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n return typeof value === \"string\" ? value.trim() : \"\"\n}\n\nfunction isValidFieldValue(field: ValidationFormField, value: string): boolean {\n if (!value) {\n return !field.required\n }\n if (value.length > (MAX_LENGTH_BY_BLOCK[field.blockType] ?? 1_000)) {\n return false\n }\n if (field.blockType === \"email\") {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n }\n if (field.blockType === \"url\") {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n }\n if (field.blockType === \"number\") {\n return Number.isFinite(Number(value))\n }\n if (field.blockType === \"checkbox\" || field.blockType === \"acceptance\") {\n return value === \"true\" || value === \"false\"\n }\n if (field.blockType === \"select\" && field.options?.length) {\n return field.options.some((option) => option.value === value)\n }\n return true\n}\n\nfunction requiredValueIsPresent(field: ValidationFormField, value: string | undefined): boolean {\n if (!field.required) {\n return true\n }\n if (field.blockType === \"acceptance\") {\n return value === \"true\"\n }\n return Boolean(value)\n}\n\nexport function validateSubmissionInput(input: {\n formFields: ValidationFormField[]\n now: number\n submissionData: ValidationSubmissionField[] | null | undefined\n}): SubmissionValidationResult {\n const controlFields = extractControlFields(input.submissionData ?? [])\n if (controlFields.honeypot.trim()) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n const startedAt = Number(controlFields.startedAt)\n if (!Number.isFinite(startedAt)) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n if (input.now - startedAt < MIN_SUBMISSION_TIME_MS) {\n return { ok: false, error: \"Form submitted too quickly.\" }\n }\n\n const supportedFields = input.formFields.flatMap((field) =>\n field.name && field.blockType in MAX_LENGTH_BY_BLOCK ? [{ ...field, name: field.name }] : [],\n )\n const formFieldMap = new Map(supportedFields.map((field) => [field.name, field]))\n const normalized: Array<{ field: string; value: string }> = []\n const seenFields = new Set<string>()\n\n for (const entry of input.submissionData ?? []) {\n const fieldName = entry.field?.trim()\n if (!fieldName || isControlField(fieldName)) {\n continue\n }\n if (seenFields.has(fieldName)) {\n return { ok: false, error: `Field \"${fieldName}\" was submitted more than once.` }\n }\n seenFields.add(fieldName)\n const formField = formFieldMap.get(fieldName)\n if (!formField) {\n return { ok: false, error: `Unexpected field \"${fieldName}\".` }\n }\n const value = stringifySubmissionValue(entry.value)\n if (!isValidFieldValue(formField, value)) {\n return { ok: false, error: `Field \"${fieldName}\" is invalid.` }\n }\n normalized.push({ field: fieldName, value })\n }\n\n for (const field of supportedFields) {\n const value = normalized.find((entry) => entry.field === field.name)?.value\n if (!requiredValueIsPresent(field, value)) {\n return { ok: false, error: `Field \"${field.name}\" is required.` }\n }\n }\n\n return { ok: true, data: normalized }\n}\n\nexport function submissionDataToPlainRecord(\n submissionData: ValidationSubmissionField[],\n): Record<string, string> {\n return Object.fromEntries(\n submissionData.flatMap((entry) =>\n entry.field ? [[entry.field, stringifySubmissionValue(entry.value)]] : [],\n ),\n )\n}\n\nexport function substituteSubmissionPlaceholders(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(\n /\\{\\{\\s*([\\w.-]+)\\s*\\}\\}/g,\n (_, fieldName: string) => values[fieldName] ?? \"\",\n )\n}\n\nexport function resolveCommaSeparatedSubmissionTags(\n tags: string | null | undefined,\n values: Record<string, string>,\n): string[] {\n return (tags ?? \"\")\n .split(\",\")\n .map((tag) => substituteSubmissionPlaceholders(tag, values).trim())\n .filter(Boolean)\n}\n","import {\n resolveCommaSeparatedSubmissionTags,\n submissionDataToPlainRecord,\n validateSubmissionInput,\n} from \"./submission\"\n\nimport type { MarketingAdapter } from \"../types\"\nimport type { CollectionBeforeChangeHook, PayloadRequest } from \"payload\"\n\ninterface FormSubmissionData {\n form?: unknown\n submissionData?: Array<{ field?: string | null; value?: unknown }>\n}\n\nfunction getStringField(data: FormSubmissionData, field: string): string | undefined {\n const value = data.submissionData?.find((row) => row.field === field)?.value\n if (typeof value === \"string\") {\n return value\n }\n if (value == null) {\n return undefined\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n if (typeof value === \"boolean\") {\n return String(value)\n }\n return undefined\n}\n\ninterface HookOptions {\n formsSlug?: string\n minSubmitDurationMs?: number\n}\n\nasync function resolveMarketingForm(\n data: { form?: unknown },\n req: PayloadRequest,\n formsSlug = \"forms\",\n): Promise<unknown> {\n if (typeof data.form === \"string\") {\n return await req.payload.findByID({\n collection: formsSlug,\n depth: 0,\n id: data.form,\n overrideAccess: true,\n })\n }\n return data.form\n}\n\nexport function createValidateFormSubmissionHook(\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const result = validateSubmissionInput({\n formFields: ((form as { fields?: unknown[] } | undefined)?.fields ?? []) as never,\n now: Date.now(),\n submissionData: (data?.submissionData ?? []) as never,\n })\n if (!result.ok) {\n throw new Error(result.error)\n }\n data.submissionData = result.data\n return data\n }\n}\n\nexport function createCreateLeadHook(\n adapter: MarketingAdapter,\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const formRecord = form as\n | { audienceId?: string; event?: string; tags?: string | null }\n | undefined\n if (formRecord?.event !== \"lead\" || !formRecord.audienceId) {\n return data\n }\n\n const submission = data as FormSubmissionData\n const email = getStringField(submission, \"email\")\n if (!email) {\n return data\n }\n\n const fieldValues = submissionDataToPlainRecord(submission.submissionData ?? [])\n const tags = resolveCommaSeparatedSubmissionTags(formRecord.tags, fieldValues)\n await adapter.contacts.upsert({\n audienceId: formRecord.audienceId,\n email,\n firstName: getStringField(submission, \"firstName\"),\n lastName: getStringField(submission, \"lastName\"),\n properties: tags.length > 0 ? { tags: tags.join(\",\") } : undefined,\n subscribed: true,\n })\n return data\n }\n}\n","import { createMarketingFormFields } from \"./fields\"\nimport { createCreateLeadHook, createValidateFormSubmissionHook } from \"./hooks\"\n\nimport type { PayloadPluginMarketingOptions } from \"../types\"\nimport type { CollectionConfig, Field } from \"payload\"\n\nfunction isNamedField(field: Field, name: string): field is Field & { name: string } {\n return \"name\" in field && field.name === name\n}\n\nfunction hasSlug(item: unknown): item is { slug: string } {\n return Boolean(\n item && typeof item === \"object\" && \"slug\" in item && typeof item.slug === \"string\",\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\")\n}\n\nfunction upsertField(fields: Field[], field: Field): Field[] {\n if (!(\"name\" in field) || !field.name) {\n return [...fields, field]\n }\n return fields.some((existing) => isNamedField(existing, field.name))\n ? fields.map((existing) => (isNamedField(existing, field.name) ? field : existing))\n : [...fields, field]\n}\n\nfunction createMarketingConfigFields(options: PayloadPluginMarketingOptions): Field[] {\n const audienceSelect = options.admin?.components?.audienceSelect ?? {\n path: \"payload-plugin-marketing/admin\",\n exportName: \"AudienceSelect\",\n }\n return [\n {\n name: \"event\",\n type: \"select\",\n defaultValue: \"submission\",\n options: [\n { label: \"Submission\", value: \"submission\" },\n { label: \"Lead\", value: \"lead\" },\n ],\n },\n {\n name: \"audienceId\",\n type: \"text\",\n label: \"Audience ID\",\n required: false,\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n components: { Field: audienceSelect },\n },\n validate: (value: unknown, { siblingData }: { siblingData?: { event?: string } } = {}) =>\n siblingData?.event === \"lead\" && !value ? \"Audience is required for lead forms.\" : true,\n },\n {\n name: \"tags\",\n type: \"textarea\",\n label: \"Tags\",\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n description: \"Optional comma-separated tags. Use {{fieldName}} to insert submitted values.\",\n },\n },\n ] as Field[]\n}\n\nfunction mutateFormsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const fields = [...collection.fields]\n const fieldsIndex = fields.findIndex(\n (field) => isNamedField(field, \"fields\") && field.type === \"blocks\",\n )\n if (fieldsIndex < 0) {\n if (options.formBuilder?.strict === false) {\n return collection\n }\n throw new Error(\n `Could not find a blocks field named \"fields\" on form-builder forms collection \"${collection.slug}\".`,\n )\n }\n\n const fieldsField = fields[fieldsIndex] as Field & { blocks: unknown[] }\n const existingBlocks = Array.isArray(fieldsField.blocks) ? fieldsField.blocks : []\n const blockOverrides = options.formBuilder?.fields ?? {}\n const overriddenExistingBlocks = existingBlocks.map((block) => {\n if (!hasSlug(block)) {\n return block\n }\n const override = blockOverrides[block.slug as keyof typeof blockOverrides]\n if (!override || !isRecord(block)) {\n return block\n }\n return {\n ...block,\n ...(override.overrides ?? {}),\n ...(override.labels ? { labels: override.labels } : {}),\n }\n })\n const existingSlugs = new Set(\n overriddenExistingBlocks.flatMap((block) => (hasSlug(block) ? [block.slug] : [])),\n )\n const marketingBlocks = Object.values(\n createMarketingFormFields(options.formBuilder?.fields),\n ).filter((block) => !existingSlugs.has(block.slug))\n\n fields[fieldsIndex] = {\n ...fieldsField,\n blocks: [...overriddenExistingBlocks, ...marketingBlocks],\n } as Field\n\n for (const field of createMarketingConfigFields(options)) {\n fields.splice(0, fields.length, ...upsertField(fields, field))\n }\n\n return { ...collection, fields }\n}\n\nfunction mutateSubmissionsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const hooks = collection.hooks ?? {}\n return {\n ...collection,\n hooks: {\n ...hooks,\n beforeChange: [\n ...(hooks.beforeChange ?? []),\n createValidateFormSubmissionHook({ formsSlug: options.formBuilder?.formsSlug }),\n createCreateLeadHook(options.adapter, { formsSlug: options.formBuilder?.formsSlug }),\n ],\n },\n }\n}\n\nexport function mutateFormBuilderCollections(\n collections: CollectionConfig[] | undefined,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig[] | undefined {\n const formsSlug = options.formBuilder?.formsSlug ?? \"forms\"\n const submissionsSlug = options.formBuilder?.submissionsSlug ?? \"form-submissions\"\n const strict = options.formBuilder?.strict ?? true\n const list = collections ?? []\n const hasForms = list.some((collection) => collection.slug === formsSlug)\n const hasSubmissions = list.some((collection) => collection.slug === submissionsSlug)\n\n if (strict && !hasForms) {\n throw new Error(`Could not find form-builder forms collection \"${formsSlug}\".`)\n }\n if (strict && !hasSubmissions) {\n throw new Error(`Could not find form-builder submissions collection \"${submissionsSlug}\".`)\n }\n\n return list.map((collection) => {\n if (collection.slug === formsSlug) {\n return mutateFormsCollection(collection, options)\n }\n if (collection.slug === submissionsSlug) {\n return mutateSubmissionsCollection(collection, options)\n }\n return collection\n })\n}\n","import { mutateFormBuilderCollections } from \"./form-builder/mutate-collections\"\n\nimport type { PayloadMarketingPlugin, PayloadPluginMarketingOptions } from \"./types\"\nimport type { Config } from \"payload\"\n\nfunction component(exportName: string, clientProps?: Record<string, unknown>) {\n return {\n path: \"payload-plugin-marketing/admin\",\n exportName,\n ...(clientProps ? { clientProps } : {}),\n }\n}\n\nfunction adminViewPath(basePath: string, ...segments: string[]): `/${string}` {\n const trimmed = basePath.replace(/^\\/+|\\/+$/g, \"\")\n const body = [trimmed, ...segments].filter(Boolean).join(\"/\")\n return `/${body}`\n}\n\nfunction withMarketingAdmin(config: Config, options: PayloadPluginMarketingOptions): Config {\n if (options.admin?.enabled === false) {\n return config\n }\n const basePath = options.admin?.basePath ?? \"\"\n const components = options.admin?.components ?? {}\n const menuComponent = components.marketingMenu ?? component(\"MarketingMenu\", { basePath })\n return {\n ...config,\n admin: {\n ...(config.admin ?? {}),\n components: {\n ...(config.admin?.components ?? {}),\n afterNavLinks: [\n ...((config.admin?.components?.afterNavLinks as unknown[]) ?? []),\n menuComponent,\n ],\n views: {\n ...((config.admin?.components?.views as Record<string, unknown> | undefined) ?? {}),\n audienceList: {\n Component: components.audienceList ?? component(\"AudienceList\"),\n path: adminViewPath(basePath, \"audience\"),\n },\n audienceDetail: {\n Component: components.audienceDetail ?? component(\"AudienceDetail\"),\n path: adminViewPath(basePath, \"audience\", \":id\"),\n },\n broadcastList: {\n Component: components.broadcastList ?? component(\"BroadcastList\"),\n path: adminViewPath(basePath, \"broadcast\"),\n },\n },\n },\n },\n } as Config\n}\n\nexport function marketingPlugin(\n options: PayloadPluginMarketingOptions,\n): PayloadMarketingPlugin {\n const plugin: PayloadMarketingPlugin = (config) =>\n withMarketingAdmin(\n {\n ...config,\n collections: mutateFormBuilderCollections(config.collections, options),\n },\n options,\n )\n plugin.slug = \"marketing\"\n plugin.order = 10\n plugin.options = options as unknown as Record<string, unknown>\n return plugin\n}\n"],"mappings":"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","names":["index_exports","__export","createAcceptanceBlock","createMarketingActions","createMarketingFormFields","marketingPlugin","__toCommonJS","createMarketingActions","adapter","input","audienceId","mergeField","base","override","overrides","direct","row","fields","textLikeBlock","slug","labels","options","createAcceptanceBlock","createMarketingFormFields","FORM_HONEYPOT_FIELD","FORM_STARTED_AT_FIELD","MAX_LENGTH_BY_BLOCK","isControlField","fieldName","FORM_HONEYPOT_FIELD","FORM_STARTED_AT_FIELD","extractControlFields","submissionData","honeypot","entry","startedAt","stringifySubmissionValue","value","isValidFieldValue","field","option","requiredValueIsPresent","validateSubmissionInput","input","controlFields","supportedFields","formFieldMap","normalized","seenFields","formField","submissionDataToPlainRecord","substituteSubmissionPlaceholders","template","values","_","resolveCommaSeparatedSubmissionTags","tags","tag","getStringField","data","field","value","row","resolveMarketingForm","req","formsSlug","createValidateFormSubmissionHook","options","operation","form","result","validateSubmissionInput","createCreateLeadHook","adapter","formRecord","submission","email","fieldValues","submissionDataToPlainRecord","tags","resolveCommaSeparatedSubmissionTags","isNamedField","field","name","hasSlug","item","isRecord","value","upsertField","fields","existing","createMarketingConfigFields","options","audienceSelect","_data","siblingData","mutateFormsCollection","collection","fieldsIndex","fieldsField","existingBlocks","blockOverrides","overriddenExistingBlocks","block","override","existingSlugs","marketingBlocks","createMarketingFormFields","mutateSubmissionsCollection","hooks","createValidateFormSubmissionHook","createCreateLeadHook","mutateFormBuilderCollections","collections","formsSlug","submissionsSlug","strict","list","hasForms","hasSubmissions","component","exportName","clientProps","adminViewPath","basePath","segments","withMarketingAdmin","config","options","components","menuComponent","marketingPlugin","plugin","mutateFormBuilderCollections"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/form-builder/fields.ts","../src/form-builder/submission.ts","../src/form-builder/hooks.ts","../src/form-builder/mutate-collections.ts","../src/marketing-integration.ts","../src/endpoints/marketing-endpoints.ts","../src/plugin.ts"],"sourcesContent":["export { createAcceptanceBlock, createMarketingFormFields } from \"./form-builder\"\nexport {\n getMarketingIntegration,\n getMarketingIntegrationFromRequest,\n marketingMetaAllowed,\n MARKETING_CUSTOM_CONFIG_KEY,\n resolveMarketingPermissions,\n tryGetMarketingIntegration,\n} from \"./marketing-integration\"\nexport type { MarketingIntegrationState } from \"./marketing-integration\"\nexport { marketingPlugin } from \"./plugin\"\nexport type {\n CreateAudienceInput,\n CreateBroadcastInput,\n DeleteAudienceInput,\n DeleteBroadcastInput,\n DeleteContactInput,\n ListContactsInput,\n MarketingAdapter,\n MarketingAudience,\n MarketingBroadcast,\n MarketingContact,\n MarketingEffectivePermissions,\n MarketingFormFieldOverrides,\n MarketingPluginPermissions,\n MarketingResourcePermissions,\n PayloadComponentOverride,\n PayloadPluginMarketingOptions,\n SendBroadcastInput,\n UpsertContactInput,\n} from \"./types\"\n\nexport { marketingPlugin as default } from \"./plugin\"\n","import type { FieldOverride, MarketingBlockOptions, MarketingFormFieldOverrides } from \"../types\"\nimport type { Block, Field } from \"payload\"\n\nexport const CUSTOM_MARKETING_FIELD_NAMES = [\"url\", \"phone\", \"acceptance\"] as const\n\nfunction mergeField(base: Field, override?: FieldOverride): Field {\n if (!override) {\n return base\n }\n\n const { overrides, ...direct } = override\n return {\n ...base,\n ...direct,\n ...(overrides ?? {}),\n admin: {\n ...(\"admin\" in base ? base.admin : undefined),\n ...(direct.admin ?? {}),\n ...(overrides?.admin ?? {}),\n },\n } as Field\n}\n\nfunction row(fields: Field[]): Field {\n return { type: \"row\", fields } as Field\n}\n\nfunction textLikeBlock(\n slug: \"phone\" | \"url\",\n labels: Required<Block>[\"labels\"],\n options?: MarketingBlockOptions,\n): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug,\n labels: options?.labels ?? labels,\n fields: [\n row([\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"text\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n ]),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"33%\" },\n },\n fields.width,\n ),\n mergeField(\n {\n name: \"placeholder\",\n type: \"text\",\n label: \"Placeholder\",\n localized: true,\n admin: { width: \"33%\" },\n },\n fields.placeholder,\n ),\n mergeField(\n {\n name: \"defaultValue\",\n type: \"text\",\n label: \"Default Value\",\n localized: true,\n admin: { width: \"33%\" },\n },\n fields.defaultValue,\n ),\n ]),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createAcceptanceBlock(options?: MarketingBlockOptions): Block {\n const fields = options?.fields ?? {}\n const block: Block = {\n slug: \"acceptance\",\n labels: options?.labels ?? { singular: \"Acceptance\", plural: \"Acceptances\" },\n fields: [\n mergeField(\n {\n name: \"name\",\n type: \"text\",\n label: \"Name (lowercase, no special characters)\",\n required: true,\n admin: { width: \"50%\" },\n },\n fields.name,\n ),\n mergeField(\n {\n name: \"label\",\n type: \"richText\",\n label: \"Label\",\n localized: true,\n admin: { width: \"50%\" },\n },\n fields.label,\n ),\n row([\n mergeField(\n {\n name: \"width\",\n type: \"number\",\n label: \"Field Width (percentage)\",\n admin: { width: \"50%\" },\n },\n fields.width,\n ),\n mergeField({ name: \"required\", type: \"checkbox\", label: \"Required\" }, fields.required),\n ]),\n ],\n }\n\n return { ...block, ...(options?.overrides ?? {}) }\n}\n\nexport function createMarketingFormFields(\n overrides: MarketingFormFieldOverrides = {},\n): Record<(typeof CUSTOM_MARKETING_FIELD_NAMES)[number], Block> {\n return {\n url: textLikeBlock(\"url\", { singular: \"URL\", plural: \"URLs\" }, overrides.url || undefined),\n phone: textLikeBlock(\n \"phone\",\n { singular: \"Phone\", plural: \"Phones\" },\n overrides.phone || undefined,\n ),\n acceptance: createAcceptanceBlock(overrides.acceptance || undefined),\n }\n}\n\nexport function createMarketingBlocksForMutation(\n overrides: MarketingFormFieldOverrides = {},\n): Block[] {\n return Object.values(createMarketingFormFields(overrides))\n}\n","export const FORM_HONEYPOT_FIELD = \"__website\"\nexport const FORM_STARTED_AT_FIELD = \"__startedAt\"\nexport const MIN_SUBMISSION_TIME_MS = 1_500\n\nconst MAX_LENGTH_BY_BLOCK: Record<string, number> = {\n acceptance: 5,\n checkbox: 5,\n country: 200,\n date: 100,\n email: 320,\n message: 5_000,\n number: 64,\n payment: 1_000,\n phone: 50,\n select: 200,\n state: 200,\n text: 200,\n textarea: 5_000,\n upload: 1_000,\n url: 2_048,\n}\n\nexport interface ValidationFormField {\n blockType: string\n name?: string | null\n options?: Array<{ value: string }> | null\n required?: boolean | null\n}\n\nexport interface ValidationSubmissionField {\n field?: string | null\n value?: unknown\n}\n\nexport type SubmissionValidationResult =\n | { data: Array<{ field: string; value: string }>; ok: true }\n | { error: string; ok: false }\n\nfunction isControlField(fieldName: string): boolean {\n return fieldName === FORM_HONEYPOT_FIELD || fieldName === FORM_STARTED_AT_FIELD\n}\n\nfunction extractControlFields(submissionData: ValidationSubmissionField[]): {\n honeypot: string\n startedAt: string\n} {\n const honeypot = submissionData.find((entry) => entry.field === FORM_HONEYPOT_FIELD)?.value\n const startedAt = submissionData.find((entry) => entry.field === FORM_STARTED_AT_FIELD)?.value\n return {\n honeypot: typeof honeypot === \"string\" ? honeypot : \"\",\n startedAt:\n typeof startedAt === \"string\" || typeof startedAt === \"number\" ? String(startedAt) : \"\",\n }\n}\n\nfunction stringifySubmissionValue(value: unknown): string {\n if (typeof value === \"boolean\") {\n return String(value)\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n return typeof value === \"string\" ? value.trim() : \"\"\n}\n\nfunction isValidFieldValue(field: ValidationFormField, value: string): boolean {\n if (!value) {\n return !field.required\n }\n if (value.length > (MAX_LENGTH_BY_BLOCK[field.blockType] ?? 1_000)) {\n return false\n }\n if (field.blockType === \"email\") {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n }\n if (field.blockType === \"url\") {\n try {\n new URL(value)\n return true\n } catch {\n return false\n }\n }\n if (field.blockType === \"number\") {\n return Number.isFinite(Number(value))\n }\n if (field.blockType === \"checkbox\" || field.blockType === \"acceptance\") {\n return value === \"true\" || value === \"false\"\n }\n if (field.blockType === \"select\" && field.options?.length) {\n return field.options.some((option) => option.value === value)\n }\n return true\n}\n\nfunction requiredValueIsPresent(field: ValidationFormField, value: string | undefined): boolean {\n if (!field.required) {\n return true\n }\n if (field.blockType === \"acceptance\") {\n return value === \"true\"\n }\n return Boolean(value)\n}\n\nexport function validateSubmissionInput(input: {\n formFields: ValidationFormField[]\n now: number\n submissionData: ValidationSubmissionField[] | null | undefined\n}): SubmissionValidationResult {\n const controlFields = extractControlFields(input.submissionData ?? [])\n if (controlFields.honeypot.trim()) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n const startedAt = Number(controlFields.startedAt)\n if (!Number.isFinite(startedAt)) {\n return { ok: false, error: \"Invalid submission.\" }\n }\n if (input.now - startedAt < MIN_SUBMISSION_TIME_MS) {\n return { ok: false, error: \"Form submitted too quickly.\" }\n }\n\n const supportedFields = input.formFields.flatMap((field) =>\n field.name && field.blockType in MAX_LENGTH_BY_BLOCK ? [{ ...field, name: field.name }] : [],\n )\n const formFieldMap = new Map(supportedFields.map((field) => [field.name, field]))\n const normalized: Array<{ field: string; value: string }> = []\n const seenFields = new Set<string>()\n\n for (const entry of input.submissionData ?? []) {\n const fieldName = entry.field?.trim()\n if (!fieldName || isControlField(fieldName)) {\n continue\n }\n if (seenFields.has(fieldName)) {\n return { ok: false, error: `Field \"${fieldName}\" was submitted more than once.` }\n }\n seenFields.add(fieldName)\n const formField = formFieldMap.get(fieldName)\n if (!formField) {\n return { ok: false, error: `Unexpected field \"${fieldName}\".` }\n }\n const value = stringifySubmissionValue(entry.value)\n if (!isValidFieldValue(formField, value)) {\n return { ok: false, error: `Field \"${fieldName}\" is invalid.` }\n }\n normalized.push({ field: fieldName, value })\n }\n\n for (const field of supportedFields) {\n const value = normalized.find((entry) => entry.field === field.name)?.value\n if (!requiredValueIsPresent(field, value)) {\n return { ok: false, error: `Field \"${field.name}\" is required.` }\n }\n }\n\n return { ok: true, data: normalized }\n}\n\nexport function submissionDataToPlainRecord(\n submissionData: ValidationSubmissionField[],\n): Record<string, string> {\n return Object.fromEntries(\n submissionData.flatMap((entry) =>\n entry.field ? [[entry.field, stringifySubmissionValue(entry.value)]] : [],\n ),\n )\n}\n\nexport function substituteSubmissionPlaceholders(\n template: string,\n values: Record<string, string>,\n): string {\n return template.replace(\n /\\{\\{\\s*([\\w.-]+)\\s*\\}\\}/g,\n (_, fieldName: string) => values[fieldName] ?? \"\",\n )\n}\n\nexport function resolveCommaSeparatedSubmissionTags(\n tags: string | null | undefined,\n values: Record<string, string>,\n): string[] {\n return (tags ?? \"\")\n .split(\",\")\n .map((tag) => substituteSubmissionPlaceholders(tag, values).trim())\n .filter(Boolean)\n}\n","import {\n resolveCommaSeparatedSubmissionTags,\n submissionDataToPlainRecord,\n validateSubmissionInput,\n} from \"./submission\"\n\nimport type { MarketingAdapter } from \"../types\"\nimport type { CollectionBeforeChangeHook, PayloadRequest } from \"payload\"\n\ninterface FormSubmissionData {\n form?: unknown\n submissionData?: Array<{ field?: string | null; value?: unknown }>\n}\n\nfunction getStringField(data: FormSubmissionData, field: string): string | undefined {\n const value = data.submissionData?.find((row) => row.field === field)?.value\n if (typeof value === \"string\") {\n return value\n }\n if (value == null) {\n return undefined\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value)\n }\n if (typeof value === \"boolean\") {\n return String(value)\n }\n return undefined\n}\n\ninterface HookOptions {\n formsSlug?: string\n minSubmitDurationMs?: number\n}\n\nasync function resolveMarketingForm(\n data: { form?: unknown },\n req: PayloadRequest,\n formsSlug = \"forms\",\n): Promise<unknown> {\n if (typeof data.form === \"string\") {\n return await req.payload.findByID({\n collection: formsSlug,\n depth: 0,\n id: data.form,\n overrideAccess: true,\n })\n }\n return data.form\n}\n\nexport function createValidateFormSubmissionHook(\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const result = validateSubmissionInput({\n formFields: ((form as { fields?: unknown[] } | undefined)?.fields ?? []) as never,\n now: Date.now(),\n submissionData: (data?.submissionData ?? []) as never,\n })\n if (!result.ok) {\n throw new Error(result.error)\n }\n data.submissionData = result.data\n return data\n }\n}\n\nexport function createCreateLeadHook(\n adapter: MarketingAdapter,\n options: HookOptions = {},\n): CollectionBeforeChangeHook {\n return async ({ data, operation, req }) => {\n if (operation !== \"create\") {\n return data\n }\n const form = await resolveMarketingForm(data as { form?: unknown }, req, options.formsSlug)\n const formRecord = form as\n | { audienceId?: string; event?: string; tags?: string | null }\n | undefined\n if (formRecord?.event !== \"lead\" || !formRecord.audienceId) {\n return data\n }\n\n const submission = data as FormSubmissionData\n const email = getStringField(submission, \"email\")\n if (!email) {\n return data\n }\n\n const fieldValues = submissionDataToPlainRecord(submission.submissionData ?? [])\n const tags = resolveCommaSeparatedSubmissionTags(formRecord.tags, fieldValues)\n await adapter.contacts.upsert({\n audienceId: formRecord.audienceId,\n email,\n firstName: getStringField(submission, \"firstName\"),\n lastName: getStringField(submission, \"lastName\"),\n properties: tags.length > 0 ? { tags: tags.join(\",\") } : undefined,\n subscribed: true,\n })\n return data\n }\n}\n","import { createMarketingFormFields } from \"./fields\"\nimport { createCreateLeadHook, createValidateFormSubmissionHook } from \"./hooks\"\n\nimport type { PayloadPluginMarketingOptions } from \"../types\"\nimport type { CollectionConfig, Field } from \"payload\"\n\nfunction isNamedField(field: Field, name: string): field is Field & { name: string } {\n return \"name\" in field && field.name === name\n}\n\nfunction hasSlug(item: unknown): item is { slug: string } {\n return Boolean(\n item && typeof item === \"object\" && \"slug\" in item && typeof item.slug === \"string\",\n )\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\")\n}\n\nfunction upsertField(fields: Field[], field: Field): Field[] {\n if (!(\"name\" in field) || !field.name) {\n return [...fields, field]\n }\n return fields.some((existing) => isNamedField(existing, field.name))\n ? fields.map((existing) => (isNamedField(existing, field.name) ? field : existing))\n : [...fields, field]\n}\n\nfunction createMarketingConfigFields(options: PayloadPluginMarketingOptions): Field[] {\n const audienceSelect = options.admin?.components?.audienceSelect ?? {\n path: \"payload-plugin-marketing/admin\",\n exportName: \"AudienceSelect\",\n }\n return [\n {\n name: \"event\",\n type: \"select\",\n defaultValue: \"submission\",\n options: [\n { label: \"Submission\", value: \"submission\" },\n { label: \"Lead\", value: \"lead\" },\n ],\n },\n {\n name: \"audienceId\",\n type: \"text\",\n label: \"Audience ID\",\n required: false,\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n components: { Field: audienceSelect },\n },\n validate: (value: unknown, { siblingData }: { siblingData?: { event?: string } } = {}) =>\n siblingData?.event === \"lead\" && !value ? \"Audience is required for lead forms.\" : true,\n },\n {\n name: \"tags\",\n type: \"textarea\",\n label: \"Tags\",\n admin: {\n condition: (_data, siblingData) => siblingData?.event === \"lead\",\n description: \"Optional comma-separated tags. Use {{fieldName}} to insert submitted values.\",\n },\n },\n ] as Field[]\n}\n\nfunction mutateFormsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const fields = [...collection.fields]\n const fieldsIndex = fields.findIndex(\n (field) => isNamedField(field, \"fields\") && field.type === \"blocks\",\n )\n if (fieldsIndex < 0) {\n if (options.formBuilder?.strict === false) {\n return collection\n }\n throw new Error(\n `Could not find a blocks field named \"fields\" on form-builder forms collection \"${collection.slug}\".`,\n )\n }\n\n const fieldsField = fields[fieldsIndex] as Field & { blocks: unknown[] }\n const existingBlocks = Array.isArray(fieldsField.blocks) ? fieldsField.blocks : []\n const blockOverrides = options.formBuilder?.fields ?? {}\n const overriddenExistingBlocks = existingBlocks.map((block) => {\n if (!hasSlug(block)) {\n return block\n }\n const override = blockOverrides[block.slug as keyof typeof blockOverrides]\n if (!override || !isRecord(block)) {\n return block\n }\n return {\n ...block,\n ...(override.overrides ?? {}),\n ...(override.labels ? { labels: override.labels } : {}),\n }\n })\n const existingSlugs = new Set(\n overriddenExistingBlocks.flatMap((block) => (hasSlug(block) ? [block.slug] : [])),\n )\n const marketingBlocks = Object.values(\n createMarketingFormFields(options.formBuilder?.fields),\n ).filter((block) => !existingSlugs.has(block.slug))\n\n fields[fieldsIndex] = {\n ...fieldsField,\n blocks: [...overriddenExistingBlocks, ...marketingBlocks],\n } as Field\n\n for (const field of createMarketingConfigFields(options)) {\n fields.splice(0, fields.length, ...upsertField(fields, field))\n }\n\n return { ...collection, fields }\n}\n\nfunction mutateSubmissionsCollection(\n collection: CollectionConfig,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig {\n const hooks = collection.hooks ?? {}\n return {\n ...collection,\n hooks: {\n ...hooks,\n beforeChange: [\n ...(hooks.beforeChange ?? []),\n createValidateFormSubmissionHook({ formsSlug: options.formBuilder?.formsSlug }),\n createCreateLeadHook(options.adapter, { formsSlug: options.formBuilder?.formsSlug }),\n ],\n },\n }\n}\n\nexport function mutateFormBuilderCollections(\n collections: CollectionConfig[] | undefined,\n options: PayloadPluginMarketingOptions,\n): CollectionConfig[] | undefined {\n const formsSlug = options.formBuilder?.formsSlug ?? \"forms\"\n const submissionsSlug = options.formBuilder?.submissionsSlug ?? \"form-submissions\"\n const strict = options.formBuilder?.strict ?? true\n const list = collections ?? []\n const hasForms = list.some((collection) => collection.slug === formsSlug)\n const hasSubmissions = list.some((collection) => collection.slug === submissionsSlug)\n\n if (strict && !hasForms) {\n throw new Error(`Could not find form-builder forms collection \"${formsSlug}\".`)\n }\n if (strict && !hasSubmissions) {\n throw new Error(`Could not find form-builder submissions collection \"${submissionsSlug}\".`)\n }\n\n return list.map((collection) => {\n if (collection.slug === formsSlug) {\n return mutateFormsCollection(collection, options)\n }\n if (collection.slug === submissionsSlug) {\n return mutateSubmissionsCollection(collection, options)\n }\n return collection\n })\n}\n","import type {\n MarketingAdapter,\n MarketingEffectivePermissions,\n MarketingPluginPermissions,\n} from \"./types\"\nimport type { Payload, PayloadRequest } from \"payload\"\n\nexport const MARKETING_CUSTOM_CONFIG_KEY = \"payloadPluginMarketing\"\n\nexport interface MarketingIntegrationState {\n adapter: MarketingAdapter\n adminBasePath: string\n permissions?: MarketingPluginPermissions\n}\n\nfunction effectiveResource(slice: { read?: boolean; write?: boolean } | undefined): {\n read: boolean\n write: boolean\n} {\n return {\n read: slice?.read ?? true,\n write: slice?.write ?? true,\n }\n}\n\n/** Resolves endpoint access flags. If `permissions` is absent (plugin option omitted), all actions are allowed for authenticated users. */\nexport function resolveMarketingPermissions(\n permissions: MarketingPluginPermissions | undefined,\n): MarketingEffectivePermissions {\n if (!permissions) {\n return {\n audiences: { read: true, write: true },\n broadcasts: { read: true, write: true },\n contacts: { read: true, write: true },\n }\n }\n return {\n audiences: effectiveResource(permissions.audiences),\n contacts: effectiveResource(permissions.contacts),\n broadcasts: effectiveResource(permissions.broadcasts),\n }\n}\n\nexport function marketingMetaAllowed(effective: MarketingEffectivePermissions): boolean {\n return effective.audiences.read || effective.contacts.read || effective.broadcasts.read\n}\n\nfunction readIntegration(payload: Payload): MarketingIntegrationState | undefined {\n const custom = payload.config.custom as Record<string, unknown> | undefined\n if (!custom || typeof custom !== \"object\") {\n return undefined\n }\n const slice = custom[MARKETING_CUSTOM_CONFIG_KEY] as MarketingIntegrationState | undefined\n if (!slice?.adapter) {\n return undefined\n }\n return slice\n}\n\nexport function getMarketingIntegration(payload: Payload): MarketingIntegrationState {\n const state = readIntegration(payload)\n if (!state) {\n throw new Error(\n `${MARKETING_CUSTOM_CONFIG_KEY}: adapter missing on Payload config. Is marketingPlugin() registered?`,\n )\n }\n return state\n}\n\nexport function tryGetMarketingIntegration(payload: Payload): MarketingIntegrationState | undefined {\n return readIntegration(payload)\n}\n\nexport function getMarketingIntegrationFromRequest(req: PayloadRequest): MarketingIntegrationState {\n return getMarketingIntegration(req.payload)\n}\n","import {\n getMarketingIntegrationFromRequest,\n marketingMetaAllowed,\n resolveMarketingPermissions,\n} from \"../marketing-integration\"\n\nimport type { CreateBroadcastInput, UpsertContactInput } from \"../types\"\nimport type { Endpoint, PayloadRequest } from \"payload\"\n\ntype MarketingPermissionResource = \"audiences\" | \"broadcasts\" | \"contacts\"\n\nfunction unauthorized() {\n return Response.json({ message: \"Unauthorized\" }, { status: 401 })\n}\n\nfunction forbidden() {\n return Response.json({ message: \"Forbidden\" }, { status: 403 })\n}\n\nfunction assertAuthenticated(req: PayloadRequest): Response | null {\n if (!req.user) return unauthorized()\n return null\n}\n\nfunction effectiveForRequest(req: PayloadRequest) {\n const { permissions } = getMarketingIntegrationFromRequest(req)\n return resolveMarketingPermissions(permissions)\n}\n\nfunction assertMarketingPermission(\n req: PayloadRequest,\n resource: MarketingPermissionResource,\n action: \"read\" | \"write\",\n): Response | null {\n const auth = assertAuthenticated(req)\n if (auth) return auth\n const eff = effectiveForRequest(req)\n if (!eff[resource][action]) return forbidden()\n return null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\")\n}\n\nasync function parseRequestJson(req: PayloadRequest): Promise<unknown> {\n return (await (req as unknown as Request).json()) as unknown\n}\n\nfunction adapterFor(req: PayloadRequest) {\n return getMarketingIntegrationFromRequest(req).adapter\n}\n\nexport function createMarketingEndpoints(): Endpoint[] {\n return [\n {\n handler: (req) => {\n const auth = assertAuthenticated(req)\n if (auth) return auth\n if (!marketingMetaAllowed(effectiveForRequest(req))) return forbidden()\n const { adapter } = getMarketingIntegrationFromRequest(req)\n return Response.json({\n label: adapter.label,\n provider: adapter.provider,\n urls: {\n audience: adapter.urls?.audiences,\n broadcasts: adapter.urls?.broadcasts,\n },\n })\n },\n method: \"get\",\n path: \"/marketing/meta\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"read\")\n if (denied) return denied\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n return Response.json(await adapter.audiences.list())\n },\n method: \"get\",\n path: \"/marketing/audiences\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n const name =\n typeof (bodyUnknown as { name?: unknown })?.name === \"string\"\n ? (bodyUnknown as { name: string }).name.trim()\n : \"\"\n if (!name) {\n return Response.json({ message: \"name is required\" }, { status: 400 })\n }\n await adapterFor(req).audiences.create({ name })\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/audiences\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"read\")\n if (denied) return denied\n const id = typeof req.routeParams?.id === \"string\" ? req.routeParams.id : \"\"\n if (!id) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n const audience = await adapter.audiences.get(id)\n if (!audience) {\n return Response.json({ message: \"Not found\" }, { status: 404 })\n }\n return Response.json(audience)\n },\n method: \"get\",\n path: \"/marketing/audiences/:id\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"write\")\n if (denied) return denied\n const id = typeof req.routeParams?.id === \"string\" ? req.routeParams.id : \"\"\n if (!id) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n await adapterFor(req).audiences.delete({ audienceId: id })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/audiences/:id\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"read\")\n if (denied) return denied\n const audienceId =\n typeof req.routeParams?.audienceId === \"string\" ? req.routeParams.audienceId : \"\"\n if (!audienceId) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n return Response.json(await adapter.contacts.list({ audienceId }))\n },\n method: \"get\",\n path: \"/marketing/audiences/:audienceId/contacts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"write\")\n if (denied) return denied\n const audienceId =\n typeof req.routeParams?.audienceId === \"string\" ? req.routeParams.audienceId : \"\"\n const contactId =\n typeof req.routeParams?.contactId === \"string\" ? req.routeParams.contactId : \"\"\n if (!audienceId || !contactId) {\n return Response.json({ message: \"Missing audienceId or contactId\" }, { status: 400 })\n }\n await adapterFor(req).contacts.delete({ audienceId, contactId })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/audiences/:audienceId/contacts/:contactId\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n if (!isRecord(bodyUnknown)) {\n return Response.json({ message: \"Invalid JSON\" }, { status: 400 })\n }\n\n const email =\n typeof bodyUnknown.email === \"string\" ? bodyUnknown.email.trim() : undefined\n const audienceId =\n typeof bodyUnknown.audienceId === \"string\" ? bodyUnknown.audienceId : undefined\n\n if (!audienceId || !email) {\n return Response.json(\n { message: \"audienceId and email are required\" },\n { status: 400 },\n )\n }\n\n const payloadUpsert: UpsertContactInput = {\n audienceId,\n email,\n subscribed:\n typeof bodyUnknown.subscribed === \"boolean\" ? bodyUnknown.subscribed : true,\n }\n\n if (typeof bodyUnknown.id === \"string\" && bodyUnknown.id) {\n payloadUpsert.id = bodyUnknown.id\n }\n if (typeof bodyUnknown.firstName === \"string\") {\n payloadUpsert.firstName = bodyUnknown.firstName\n }\n if (typeof bodyUnknown.lastName === \"string\") {\n payloadUpsert.lastName = bodyUnknown.lastName\n }\n if (isRecord(bodyUnknown.properties)) {\n payloadUpsert.properties = bodyUnknown.properties as Record<\n string,\n string | number | null\n >\n }\n\n await adapterFor(req).contacts.upsert(payloadUpsert)\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/contacts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"read\")\n if (denied) return denied\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n const broadcasts = await adapter.broadcasts.list()\n const enriched = broadcasts.map((b) => ({\n ...b,\n externalDashboardUrl: adapter.urls?.broadcast?.(b.id),\n }))\n return Response.json(enriched)\n },\n method: \"get\",\n path: \"/marketing/broadcasts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n if (!isRecord(bodyUnknown)) {\n return Response.json({ message: \"Invalid JSON\" }, { status: 400 })\n }\n\n const audienceIdRaw =\n typeof bodyUnknown.audienceId === \"string\" ? bodyUnknown.audienceId.trim() : \"\"\n const name = typeof bodyUnknown.name === \"string\" ? bodyUnknown.name.trim() : \"\"\n const subject =\n typeof bodyUnknown.subject === \"string\" ? bodyUnknown.subject.trim() : \"\"\n const templateIdRaw =\n typeof bodyUnknown.templateId === \"string\" ? bodyUnknown.templateId.trim() : \"\"\n\n const htmlProvided = typeof bodyUnknown.html === \"string\" ? bodyUnknown.html.trim() : \"\"\n const replyTo =\n typeof bodyUnknown.replyTo === \"string\" ? bodyUnknown.replyTo.trim() : undefined\n const locale =\n typeof bodyUnknown.locale === \"string\" ? bodyUnknown.locale : undefined\n\n if (!audienceIdRaw || !name || !subject) {\n return Response.json(\n { message: \"audienceId, name, and subject are required\" },\n { status: 400 },\n )\n }\n\n const hasTpl = Boolean(templateIdRaw !== \"\")\n if (!hasTpl && !htmlProvided) {\n return Response.json(\n { message: \"Provide HTML body or a template id.\" },\n { status: 400 },\n )\n }\n\n let normalized: CreateBroadcastInput\n if (hasTpl && htmlProvided !== \"\") {\n return Response.json(\n { message: \"Use either HTML or template id, not both.\" },\n { status: 400 },\n )\n }\n if (hasTpl) {\n normalized = {\n audienceId: audienceIdRaw,\n locale,\n name,\n replyTo,\n subject,\n templateId: templateIdRaw,\n }\n } else {\n normalized = {\n audienceId: audienceIdRaw,\n html: htmlProvided,\n locale,\n name,\n replyTo,\n subject,\n }\n }\n\n await adapterFor(req).broadcasts.create(normalized)\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/broadcasts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const broadcastId =\n typeof req.routeParams?.broadcastId === \"string\" ? req.routeParams.broadcastId : \"\"\n if (!broadcastId) {\n return Response.json({ message: \"Missing broadcast id\" }, { status: 400 })\n }\n await adapterFor(req).broadcasts.delete({ broadcastId })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/broadcasts/:broadcastId\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const broadcastId =\n typeof req.routeParams?.broadcastId === \"string\" ? req.routeParams.broadcastId : \"\"\n if (!broadcastId) {\n return Response.json({ message: \"Missing broadcast id\" }, { status: 400 })\n }\n\n let scheduledAt: string | undefined\n try {\n const cloned = (req as unknown as Request).clone()\n const payloadBody: unknown = await cloned.json()\n if (isRecord(payloadBody) && typeof payloadBody.scheduledAt === \"string\") {\n scheduledAt = payloadBody.scheduledAt\n }\n } catch {\n scheduledAt = undefined\n }\n\n await adapterFor(req).broadcasts.send({ broadcastId, scheduledAt })\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/broadcasts/:broadcastId/send\",\n },\n ]\n}\n","import { createMarketingEndpoints } from \"./endpoints/marketing-endpoints\"\nimport { mutateFormBuilderCollections } from \"./form-builder/mutate-collections\"\nimport {\n MARKETING_CUSTOM_CONFIG_KEY,\n type MarketingIntegrationState,\n} from \"./marketing-integration\"\n\nimport type { PayloadMarketingPlugin, PayloadPluginMarketingOptions } from \"./types\"\nimport type { Config } from \"payload\"\n\nfunction mergeMarketingCustom(\n config: Config,\n integration: MarketingIntegrationState,\n): Record<string, unknown> {\n const prev = config.custom\n const base =\n typeof prev === \"object\" && prev !== null && !Array.isArray(prev)\n ? { ...(prev as Record<string, unknown>) }\n : {}\n base[MARKETING_CUSTOM_CONFIG_KEY] = integration\n return base\n}\n\nfunction component(exportName: string, clientProps?: Record<string, unknown>) {\n return {\n path: \"payload-plugin-marketing/admin\",\n exportName,\n ...(clientProps ? { clientProps } : {}),\n }\n}\n\nfunction adminViewPath(basePath: string, ...segments: string[]): `/${string}` {\n const trimmed = basePath.replace(/^\\/+|\\/+$/g, \"\")\n const body = [trimmed, ...segments].filter(Boolean).join(\"/\")\n return `/${body}`\n}\n\nfunction withMarketingAdmin(config: Config, options: PayloadPluginMarketingOptions): Config {\n if (options.admin?.enabled === false) {\n return config\n }\n const basePath = options.admin?.basePath ?? \"\"\n const components = options.admin?.components ?? {}\n const menuComponent = components.marketingMenu ?? component(\"MarketingMenu\", { basePath })\n const viewClientProps: Record<string, unknown> = { basePath }\n\n const marketingIntegrationState: MarketingIntegrationState = {\n adapter: options.adapter,\n adminBasePath: basePath,\n permissions: options.permissions,\n }\n\n return {\n ...config,\n custom: mergeMarketingCustom(config, marketingIntegrationState),\n endpoints: [...(config.endpoints ?? []), ...createMarketingEndpoints()],\n admin: {\n ...(config.admin ?? {}),\n components: {\n ...(config.admin?.components ?? {}),\n afterNavLinks: [\n ...((config.admin?.components?.afterNavLinks as unknown[]) ?? []),\n menuComponent,\n ],\n views: {\n ...((config.admin?.components?.views as Record<string, unknown> | undefined) ?? {}),\n audienceList: {\n Component: components.audienceList ?? component(\"AudienceList\", viewClientProps),\n path: adminViewPath(basePath, \"audience\"),\n },\n audienceDetail: {\n Component: components.audienceDetail ?? component(\"AudienceDetail\", viewClientProps),\n path: adminViewPath(basePath, \"audience\", \":id\"),\n },\n broadcastList: {\n Component: components.broadcastList ?? component(\"BroadcastList\", viewClientProps),\n path: adminViewPath(basePath, \"broadcast\"),\n },\n },\n },\n },\n } as Config\n}\n\nexport function marketingPlugin(\n options: PayloadPluginMarketingOptions,\n): PayloadMarketingPlugin {\n const plugin: PayloadMarketingPlugin = (config) =>\n withMarketingAdmin(\n {\n ...config,\n collections: mutateFormBuilderCollections(config.collections, options),\n },\n options,\n )\n plugin.slug = \"marketing\"\n plugin.order = 10\n plugin.options = options as unknown as Record<string, unknown>\n return plugin\n}\n"],"mappings":"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","names":["index_exports","__export","MARKETING_CUSTOM_CONFIG_KEY","createAcceptanceBlock","createMarketingFormFields","marketingPlugin","getMarketingIntegration","getMarketingIntegrationFromRequest","marketingMetaAllowed","resolveMarketingPermissions","tryGetMarketingIntegration","__toCommonJS","mergeField","base","override","overrides","direct","row","fields","textLikeBlock","slug","labels","options","createAcceptanceBlock","createMarketingFormFields","FORM_HONEYPOT_FIELD","FORM_STARTED_AT_FIELD","MAX_LENGTH_BY_BLOCK","isControlField","fieldName","FORM_HONEYPOT_FIELD","FORM_STARTED_AT_FIELD","extractControlFields","submissionData","honeypot","entry","startedAt","stringifySubmissionValue","value","isValidFieldValue","field","option","requiredValueIsPresent","validateSubmissionInput","input","controlFields","supportedFields","formFieldMap","normalized","seenFields","formField","submissionDataToPlainRecord","substituteSubmissionPlaceholders","template","values","_","resolveCommaSeparatedSubmissionTags","tags","tag","getStringField","data","field","value","row","resolveMarketingForm","req","formsSlug","createValidateFormSubmissionHook","options","operation","form","result","validateSubmissionInput","createCreateLeadHook","adapter","formRecord","submission","email","fieldValues","submissionDataToPlainRecord","tags","resolveCommaSeparatedSubmissionTags","isNamedField","field","name","hasSlug","item","isRecord","value","upsertField","fields","existing","createMarketingConfigFields","options","audienceSelect","_data","siblingData","mutateFormsCollection","collection","fieldsIndex","fieldsField","existingBlocks","blockOverrides","overriddenExistingBlocks","block","override","existingSlugs","marketingBlocks","createMarketingFormFields","mutateSubmissionsCollection","hooks","createValidateFormSubmissionHook","createCreateLeadHook","mutateFormBuilderCollections","collections","formsSlug","submissionsSlug","strict","list","hasForms","hasSubmissions","MARKETING_CUSTOM_CONFIG_KEY","effectiveResource","slice","resolveMarketingPermissions","permissions","marketingMetaAllowed","effective","readIntegration","payload","custom","getMarketingIntegration","state","tryGetMarketingIntegration","getMarketingIntegrationFromRequest","req","unauthorized","forbidden","assertAuthenticated","req","effectiveForRequest","permissions","getMarketingIntegrationFromRequest","resolveMarketingPermissions","assertMarketingPermission","resource","action","auth","isRecord","value","parseRequestJson","adapterFor","createMarketingEndpoints","marketingMetaAllowed","adapter","denied","bodyUnknown","name","id","audience","audienceId","contactId","email","payloadUpsert","enriched","b","audienceIdRaw","subject","templateIdRaw","htmlProvided","replyTo","locale","hasTpl","normalized","broadcastId","scheduledAt","payloadBody","mergeMarketingCustom","config","integration","prev","base","MARKETING_CUSTOM_CONFIG_KEY","component","exportName","clientProps","adminViewPath","basePath","segments","withMarketingAdmin","options","components","menuComponent","viewClientProps","marketingIntegrationState","createMarketingEndpoints","marketingPlugin","plugin","mutateFormBuilderCollections"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { createMarketingActions } from "./actions";
2
1
  export { createAcceptanceBlock, createMarketingFormFields } from "./form-builder";
2
+ export { getMarketingIntegration, getMarketingIntegrationFromRequest, marketingMetaAllowed, MARKETING_CUSTOM_CONFIG_KEY, resolveMarketingPermissions, tryGetMarketingIntegration, } from "./marketing-integration";
3
+ export type { MarketingIntegrationState } from "./marketing-integration";
3
4
  export { marketingPlugin } from "./plugin";
4
- export type { CreateAudienceInput, CreateBroadcastInput, DeleteAudienceInput, DeleteBroadcastInput, DeleteContactInput, ListContactsInput, MarketingAdapter, MarketingAudience, MarketingBroadcast, MarketingContact, MarketingFormFieldOverrides, PayloadComponentOverride, PayloadPluginMarketingOptions, SendBroadcastInput, UpsertContactInput, } from "./types";
5
+ export type { CreateAudienceInput, CreateBroadcastInput, DeleteAudienceInput, DeleteBroadcastInput, DeleteContactInput, ListContactsInput, MarketingAdapter, MarketingAudience, MarketingBroadcast, MarketingContact, MarketingEffectivePermissions, MarketingFormFieldOverrides, MarketingPluginPermissions, MarketingResourcePermissions, PayloadComponentOverride, PayloadPluginMarketingOptions, SendBroadcastInput, UpsertContactInput, } from "./types";
5
6
  export { marketingPlugin as default } from "./plugin";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,EAC7B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AACjF,OAAO,EACL,uBAAuB,EACvB,kCAAkC,EAClC,oBAAoB,EACpB,2BAA2B,EAC3B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,yBAAyB,CAAA;AAChC,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAA;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,6BAA6B,EAC7B,2BAA2B,EAC3B,0BAA0B,EAC1B,4BAA4B,EAC5B,wBAAwB,EACxB,6BAA6B,EAC7B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as u}from"./chunk-RBBHOL35.js";import{a as c,b as m,l as r}from"./chunk-4RBNCG5Q.js";function i(n,e){return{path:"payload-plugin-marketing/admin",exportName:n,...e?{clientProps:e}:{}}}function o(n,...e){return`/${[n.replace(/^\/+|\/+$/g,""),...e].filter(Boolean).join("/")}`}function p(n,e){if(e.admin?.enabled===!1)return n;let t=e.admin?.basePath??"",a=e.admin?.components??{},s=a.marketingMenu??i("MarketingMenu",{basePath:t});return{...n,admin:{...n.admin??{},components:{...n.admin?.components??{},afterNavLinks:[...n.admin?.components?.afterNavLinks??[],s],views:{...n.admin?.components?.views??{},audienceList:{Component:a.audienceList??i("AudienceList"),path:o(t,"audience")},audienceDetail:{Component:a.audienceDetail??i("AudienceDetail"),path:o(t,"audience",":id")},broadcastList:{Component:a.broadcastList??i("BroadcastList"),path:o(t,"broadcast")}}}}}}function d(n){let e=t=>p({...t,collections:r(t.collections,n)},n);return e.slug="marketing",e.order=10,e.options=n,e}export{c as createAcceptanceBlock,u as createMarketingActions,m as createMarketingFormFields,d as default,d as marketingPlugin};
1
+ import{a as x,b as B,l as R}from"./chunk-4RBNCG5Q.js";var u="payloadPluginMarketing";function k(e){return{read:e?.read??!0,write:e?.write??!0}}function y(e){return e?{audiences:k(e.audiences),contacts:k(e.contacts),broadcasts:k(e.broadcasts)}:{audiences:{read:!0,write:!0},broadcasts:{read:!0,write:!0},contacts:{read:!0,write:!0}}}function I(e){return e.audiences.read||e.contacts.read||e.broadcasts.read}function w(e){let n=e.config.custom;if(!n||typeof n!="object")return;let t=n[u];if(t?.adapter)return t}function j(e){let n=w(e);if(!n)throw new Error(`${u}: adapter missing on Payload config. Is marketingPlugin() registered?`);return n}function E(e){return w(e)}function i(e){return j(e.payload)}function F(){return Response.json({message:"Unauthorized"},{status:401})}function C(){return Response.json({message:"Forbidden"},{status:403})}function A(e){return e.user?null:F()}function v(e){let{permissions:n}=i(e);return y(n)}function o(e,n,t){let a=A(e);return a||(v(e)[n][t]?null:C())}function p(e){return!!(e&&typeof e=="object")}async function P(e){return await e.json()}function d(e){return i(e).adapter}function N(){return[{handler:e=>{let n=A(e);if(n)return n;if(!I(v(e)))return C();let{adapter:t}=i(e);return Response.json({label:t.label,provider:t.provider,urls:{audience:t.urls?.audiences,broadcasts:t.urls?.broadcasts}})},method:"get",path:"/marketing/meta"},{handler:async e=>{let n=o(e,"audiences","read");if(n)return n;let t=i(e).adapter;return Response.json(await t.audiences.list())},method:"get",path:"/marketing/audiences"},{handler:async e=>{let n=o(e,"audiences","write");if(n)return n;let t=await P(e),a=typeof t?.name=="string"?t.name.trim():"";return a?(await d(e).audiences.create({name:a}),Response.json({ok:!0})):Response.json({message:"name is required"},{status:400})},method:"post",path:"/marketing/audiences"},{handler:async e=>{let n=o(e,"audiences","read");if(n)return n;let t=typeof e.routeParams?.id=="string"?e.routeParams.id:"";if(!t)return Response.json({message:"Missing audience id"},{status:400});let r=await i(e).adapter.audiences.get(t);return r?Response.json(r):Response.json({message:"Not found"},{status:404})},method:"get",path:"/marketing/audiences/:id"},{handler:async e=>{let n=o(e,"audiences","write");if(n)return n;let t=typeof e.routeParams?.id=="string"?e.routeParams.id:"";return t?(await d(e).audiences.delete({audienceId:t}),Response.json({ok:!0})):Response.json({message:"Missing audience id"},{status:400})},method:"delete",path:"/marketing/audiences/:id"},{handler:async e=>{let n=o(e,"contacts","read");if(n)return n;let t=typeof e.routeParams?.audienceId=="string"?e.routeParams.audienceId:"";if(!t)return Response.json({message:"Missing audience id"},{status:400});let a=i(e).adapter;return Response.json(await a.contacts.list({audienceId:t}))},method:"get",path:"/marketing/audiences/:audienceId/contacts"},{handler:async e=>{let n=o(e,"contacts","write");if(n)return n;let t=typeof e.routeParams?.audienceId=="string"?e.routeParams.audienceId:"",a=typeof e.routeParams?.contactId=="string"?e.routeParams.contactId:"";return!t||!a?Response.json({message:"Missing audienceId or contactId"},{status:400}):(await d(e).contacts.delete({audienceId:t,contactId:a}),Response.json({ok:!0}))},method:"delete",path:"/marketing/audiences/:audienceId/contacts/:contactId"},{handler:async e=>{let n=o(e,"contacts","write");if(n)return n;let t=await P(e);if(!p(t))return Response.json({message:"Invalid JSON"},{status:400});let a=typeof t.email=="string"?t.email.trim():void 0,r=typeof t.audienceId=="string"?t.audienceId:void 0;if(!r||!a)return Response.json({message:"audienceId and email are required"},{status:400});let s={audienceId:r,email:a,subscribed:typeof t.subscribed=="boolean"?t.subscribed:!0};return typeof t.id=="string"&&t.id&&(s.id=t.id),typeof t.firstName=="string"&&(s.firstName=t.firstName),typeof t.lastName=="string"&&(s.lastName=t.lastName),p(t.properties)&&(s.properties=t.properties),await d(e).contacts.upsert(s),Response.json({ok:!0})},method:"post",path:"/marketing/contacts"},{handler:async e=>{let n=o(e,"broadcasts","read");if(n)return n;let t=i(e).adapter,r=(await t.broadcasts.list()).map(s=>({...s,externalDashboardUrl:t.urls?.broadcast?.(s.id)}));return Response.json(r)},method:"get",path:"/marketing/broadcasts"},{handler:async e=>{let n=o(e,"broadcasts","write");if(n)return n;let t=await P(e);if(!p(t))return Response.json({message:"Invalid JSON"},{status:400});let a=typeof t.audienceId=="string"?t.audienceId.trim():"",r=typeof t.name=="string"?t.name.trim():"",s=typeof t.subject=="string"?t.subject.trim():"",c=typeof t.templateId=="string"?t.templateId.trim():"",g=typeof t.html=="string"?t.html.trim():"",b=typeof t.replyTo=="string"?t.replyTo.trim():void 0,h=typeof t.locale=="string"?t.locale:void 0;if(!a||!r||!s)return Response.json({message:"audienceId, name, and subject are required"},{status:400});let l=c!=="";if(!l&&!g)return Response.json({message:"Provide HTML body or a template id."},{status:400});let f;return l&&g!==""?Response.json({message:"Use either HTML or template id, not both."},{status:400}):(l?f={audienceId:a,locale:h,name:r,replyTo:b,subject:s,templateId:c}:f={audienceId:a,html:g,locale:h,name:r,replyTo:b,subject:s},await d(e).broadcasts.create(f),Response.json({ok:!0}))},method:"post",path:"/marketing/broadcasts"},{handler:async e=>{let n=o(e,"broadcasts","write");if(n)return n;let t=typeof e.routeParams?.broadcastId=="string"?e.routeParams.broadcastId:"";return t?(await d(e).broadcasts.delete({broadcastId:t}),Response.json({ok:!0})):Response.json({message:"Missing broadcast id"},{status:400})},method:"delete",path:"/marketing/broadcasts/:broadcastId"},{handler:async e=>{let n=o(e,"broadcasts","write");if(n)return n;let t=typeof e.routeParams?.broadcastId=="string"?e.routeParams.broadcastId:"";if(!t)return Response.json({message:"Missing broadcast id"},{status:400});let a;try{let s=await e.clone().json();p(s)&&typeof s.scheduledAt=="string"&&(a=s.scheduledAt)}catch{a=void 0}return await d(e).broadcasts.send({broadcastId:t,scheduledAt:a}),Response.json({ok:!0})},method:"post",path:"/marketing/broadcasts/:broadcastId/send"}]}function O(e,n){let t=e.custom,a=typeof t=="object"&&t!==null&&!Array.isArray(t)?{...t}:{};return a[u]=n,a}function m(e,n){return{path:"payload-plugin-marketing/admin",exportName:e,...n?{clientProps:n}:{}}}function M(e,...n){return`/${[e.replace(/^\/+|\/+$/g,""),...n].filter(Boolean).join("/")}`}function U(e,n){if(n.admin?.enabled===!1)return e;let t=n.admin?.basePath??"",a=n.admin?.components??{},r=a.marketingMenu??m("MarketingMenu",{basePath:t}),s={basePath:t},c={adapter:n.adapter,adminBasePath:t,permissions:n.permissions};return{...e,custom:O(e,c),endpoints:[...e.endpoints??[],...N()],admin:{...e.admin??{},components:{...e.admin?.components??{},afterNavLinks:[...e.admin?.components?.afterNavLinks??[],r],views:{...e.admin?.components?.views??{},audienceList:{Component:a.audienceList??m("AudienceList",s),path:M(t,"audience")},audienceDetail:{Component:a.audienceDetail??m("AudienceDetail",s),path:M(t,"audience",":id")},broadcastList:{Component:a.broadcastList??m("BroadcastList",s),path:M(t,"broadcast")}}}}}}function S(e){let n=t=>U({...t,collections:R(t.collections,e)},e);return n.slug="marketing",n.order=10,n.options=e,n}export{u as MARKETING_CUSTOM_CONFIG_KEY,x as createAcceptanceBlock,B as createMarketingFormFields,S as default,j as getMarketingIntegration,i as getMarketingIntegrationFromRequest,I as marketingMetaAllowed,S as marketingPlugin,y as resolveMarketingPermissions,E as tryGetMarketingIntegration};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["import { mutateFormBuilderCollections } from \"./form-builder/mutate-collections\"\n\nimport type { PayloadMarketingPlugin, PayloadPluginMarketingOptions } from \"./types\"\nimport type { Config } from \"payload\"\n\nfunction component(exportName: string, clientProps?: Record<string, unknown>) {\n return {\n path: \"payload-plugin-marketing/admin\",\n exportName,\n ...(clientProps ? { clientProps } : {}),\n }\n}\n\nfunction adminViewPath(basePath: string, ...segments: string[]): `/${string}` {\n const trimmed = basePath.replace(/^\\/+|\\/+$/g, \"\")\n const body = [trimmed, ...segments].filter(Boolean).join(\"/\")\n return `/${body}`\n}\n\nfunction withMarketingAdmin(config: Config, options: PayloadPluginMarketingOptions): Config {\n if (options.admin?.enabled === false) {\n return config\n }\n const basePath = options.admin?.basePath ?? \"\"\n const components = options.admin?.components ?? {}\n const menuComponent = components.marketingMenu ?? component(\"MarketingMenu\", { basePath })\n return {\n ...config,\n admin: {\n ...(config.admin ?? {}),\n components: {\n ...(config.admin?.components ?? {}),\n afterNavLinks: [\n ...((config.admin?.components?.afterNavLinks as unknown[]) ?? []),\n menuComponent,\n ],\n views: {\n ...((config.admin?.components?.views as Record<string, unknown> | undefined) ?? {}),\n audienceList: {\n Component: components.audienceList ?? component(\"AudienceList\"),\n path: adminViewPath(basePath, \"audience\"),\n },\n audienceDetail: {\n Component: components.audienceDetail ?? component(\"AudienceDetail\"),\n path: adminViewPath(basePath, \"audience\", \":id\"),\n },\n broadcastList: {\n Component: components.broadcastList ?? component(\"BroadcastList\"),\n path: adminViewPath(basePath, \"broadcast\"),\n },\n },\n },\n },\n } as Config\n}\n\nexport function marketingPlugin(\n options: PayloadPluginMarketingOptions,\n): PayloadMarketingPlugin {\n const plugin: PayloadMarketingPlugin = (config) =>\n withMarketingAdmin(\n {\n ...config,\n collections: mutateFormBuilderCollections(config.collections, options),\n },\n options,\n )\n plugin.slug = \"marketing\"\n plugin.order = 10\n plugin.options = options as unknown as Record<string, unknown>\n return plugin\n}\n"],"mappings":"8FAKA,SAASA,EAAUC,EAAoBC,EAAuC,CAC5E,MAAO,CACL,KAAM,iCACN,WAAAD,EACA,GAAIC,EAAc,CAAE,YAAAA,CAAY,EAAI,CAAC,CACvC,CACF,CAEA,SAASC,EAAcC,KAAqBC,EAAkC,CAG5E,MAAO,IADM,CADGD,EAAS,QAAQ,aAAc,EAAE,EAC1B,GAAGC,CAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAC7C,EACjB,CAEA,SAASC,EAAmBC,EAAgBC,EAAgD,CAC1F,GAAIA,EAAQ,OAAO,UAAY,GAC7B,OAAOD,EAET,IAAMH,EAAWI,EAAQ,OAAO,UAAY,GACtCC,EAAaD,EAAQ,OAAO,YAAc,CAAC,EAC3CE,EAAgBD,EAAW,eAAiBT,EAAU,gBAAiB,CAAE,SAAAI,CAAS,CAAC,EACzF,MAAO,CACL,GAAGG,EACH,MAAO,CACL,GAAIA,EAAO,OAAS,CAAC,EACrB,WAAY,CACV,GAAIA,EAAO,OAAO,YAAc,CAAC,EACjC,cAAe,CACb,GAAKA,EAAO,OAAO,YAAY,eAA+B,CAAC,EAC/DG,CACF,EACA,MAAO,CACL,GAAKH,EAAO,OAAO,YAAY,OAAiD,CAAC,EACjF,aAAc,CACZ,UAAWE,EAAW,cAAgBT,EAAU,cAAc,EAC9D,KAAMG,EAAcC,EAAU,UAAU,CAC1C,EACA,eAAgB,CACd,UAAWK,EAAW,gBAAkBT,EAAU,gBAAgB,EAClE,KAAMG,EAAcC,EAAU,WAAY,KAAK,CACjD,EACA,cAAe,CACb,UAAWK,EAAW,eAAiBT,EAAU,eAAe,EAChE,KAAMG,EAAcC,EAAU,WAAW,CAC3C,CACF,CACF,CACF,CACF,CACF,CAEO,SAASO,EACdH,EACwB,CACxB,IAAMI,EAAkCL,GACtCD,EACE,CACE,GAAGC,EACH,YAAaM,EAA6BN,EAAO,YAAaC,CAAO,CACvE,EACAA,CACF,EACF,OAAAI,EAAO,KAAO,YACdA,EAAO,MAAQ,GACfA,EAAO,QAAUJ,EACVI,CACT","names":["component","exportName","clientProps","adminViewPath","basePath","segments","withMarketingAdmin","config","options","components","menuComponent","marketingPlugin","plugin","mutateFormBuilderCollections"]}
1
+ {"version":3,"sources":["../src/marketing-integration.ts","../src/endpoints/marketing-endpoints.ts","../src/plugin.ts"],"sourcesContent":["import type {\n MarketingAdapter,\n MarketingEffectivePermissions,\n MarketingPluginPermissions,\n} from \"./types\"\nimport type { Payload, PayloadRequest } from \"payload\"\n\nexport const MARKETING_CUSTOM_CONFIG_KEY = \"payloadPluginMarketing\"\n\nexport interface MarketingIntegrationState {\n adapter: MarketingAdapter\n adminBasePath: string\n permissions?: MarketingPluginPermissions\n}\n\nfunction effectiveResource(slice: { read?: boolean; write?: boolean } | undefined): {\n read: boolean\n write: boolean\n} {\n return {\n read: slice?.read ?? true,\n write: slice?.write ?? true,\n }\n}\n\n/** Resolves endpoint access flags. If `permissions` is absent (plugin option omitted), all actions are allowed for authenticated users. */\nexport function resolveMarketingPermissions(\n permissions: MarketingPluginPermissions | undefined,\n): MarketingEffectivePermissions {\n if (!permissions) {\n return {\n audiences: { read: true, write: true },\n broadcasts: { read: true, write: true },\n contacts: { read: true, write: true },\n }\n }\n return {\n audiences: effectiveResource(permissions.audiences),\n contacts: effectiveResource(permissions.contacts),\n broadcasts: effectiveResource(permissions.broadcasts),\n }\n}\n\nexport function marketingMetaAllowed(effective: MarketingEffectivePermissions): boolean {\n return effective.audiences.read || effective.contacts.read || effective.broadcasts.read\n}\n\nfunction readIntegration(payload: Payload): MarketingIntegrationState | undefined {\n const custom = payload.config.custom as Record<string, unknown> | undefined\n if (!custom || typeof custom !== \"object\") {\n return undefined\n }\n const slice = custom[MARKETING_CUSTOM_CONFIG_KEY] as MarketingIntegrationState | undefined\n if (!slice?.adapter) {\n return undefined\n }\n return slice\n}\n\nexport function getMarketingIntegration(payload: Payload): MarketingIntegrationState {\n const state = readIntegration(payload)\n if (!state) {\n throw new Error(\n `${MARKETING_CUSTOM_CONFIG_KEY}: adapter missing on Payload config. Is marketingPlugin() registered?`,\n )\n }\n return state\n}\n\nexport function tryGetMarketingIntegration(payload: Payload): MarketingIntegrationState | undefined {\n return readIntegration(payload)\n}\n\nexport function getMarketingIntegrationFromRequest(req: PayloadRequest): MarketingIntegrationState {\n return getMarketingIntegration(req.payload)\n}\n","import {\n getMarketingIntegrationFromRequest,\n marketingMetaAllowed,\n resolveMarketingPermissions,\n} from \"../marketing-integration\"\n\nimport type { CreateBroadcastInput, UpsertContactInput } from \"../types\"\nimport type { Endpoint, PayloadRequest } from \"payload\"\n\ntype MarketingPermissionResource = \"audiences\" | \"broadcasts\" | \"contacts\"\n\nfunction unauthorized() {\n return Response.json({ message: \"Unauthorized\" }, { status: 401 })\n}\n\nfunction forbidden() {\n return Response.json({ message: \"Forbidden\" }, { status: 403 })\n}\n\nfunction assertAuthenticated(req: PayloadRequest): Response | null {\n if (!req.user) return unauthorized()\n return null\n}\n\nfunction effectiveForRequest(req: PayloadRequest) {\n const { permissions } = getMarketingIntegrationFromRequest(req)\n return resolveMarketingPermissions(permissions)\n}\n\nfunction assertMarketingPermission(\n req: PayloadRequest,\n resource: MarketingPermissionResource,\n action: \"read\" | \"write\",\n): Response | null {\n const auth = assertAuthenticated(req)\n if (auth) return auth\n const eff = effectiveForRequest(req)\n if (!eff[resource][action]) return forbidden()\n return null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\")\n}\n\nasync function parseRequestJson(req: PayloadRequest): Promise<unknown> {\n return (await (req as unknown as Request).json()) as unknown\n}\n\nfunction adapterFor(req: PayloadRequest) {\n return getMarketingIntegrationFromRequest(req).adapter\n}\n\nexport function createMarketingEndpoints(): Endpoint[] {\n return [\n {\n handler: (req) => {\n const auth = assertAuthenticated(req)\n if (auth) return auth\n if (!marketingMetaAllowed(effectiveForRequest(req))) return forbidden()\n const { adapter } = getMarketingIntegrationFromRequest(req)\n return Response.json({\n label: adapter.label,\n provider: adapter.provider,\n urls: {\n audience: adapter.urls?.audiences,\n broadcasts: adapter.urls?.broadcasts,\n },\n })\n },\n method: \"get\",\n path: \"/marketing/meta\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"read\")\n if (denied) return denied\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n return Response.json(await adapter.audiences.list())\n },\n method: \"get\",\n path: \"/marketing/audiences\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n const name =\n typeof (bodyUnknown as { name?: unknown })?.name === \"string\"\n ? (bodyUnknown as { name: string }).name.trim()\n : \"\"\n if (!name) {\n return Response.json({ message: \"name is required\" }, { status: 400 })\n }\n await adapterFor(req).audiences.create({ name })\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/audiences\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"read\")\n if (denied) return denied\n const id = typeof req.routeParams?.id === \"string\" ? req.routeParams.id : \"\"\n if (!id) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n const audience = await adapter.audiences.get(id)\n if (!audience) {\n return Response.json({ message: \"Not found\" }, { status: 404 })\n }\n return Response.json(audience)\n },\n method: \"get\",\n path: \"/marketing/audiences/:id\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"audiences\", \"write\")\n if (denied) return denied\n const id = typeof req.routeParams?.id === \"string\" ? req.routeParams.id : \"\"\n if (!id) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n await adapterFor(req).audiences.delete({ audienceId: id })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/audiences/:id\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"read\")\n if (denied) return denied\n const audienceId =\n typeof req.routeParams?.audienceId === \"string\" ? req.routeParams.audienceId : \"\"\n if (!audienceId) {\n return Response.json({ message: \"Missing audience id\" }, { status: 400 })\n }\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n return Response.json(await adapter.contacts.list({ audienceId }))\n },\n method: \"get\",\n path: \"/marketing/audiences/:audienceId/contacts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"write\")\n if (denied) return denied\n const audienceId =\n typeof req.routeParams?.audienceId === \"string\" ? req.routeParams.audienceId : \"\"\n const contactId =\n typeof req.routeParams?.contactId === \"string\" ? req.routeParams.contactId : \"\"\n if (!audienceId || !contactId) {\n return Response.json({ message: \"Missing audienceId or contactId\" }, { status: 400 })\n }\n await adapterFor(req).contacts.delete({ audienceId, contactId })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/audiences/:audienceId/contacts/:contactId\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"contacts\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n if (!isRecord(bodyUnknown)) {\n return Response.json({ message: \"Invalid JSON\" }, { status: 400 })\n }\n\n const email =\n typeof bodyUnknown.email === \"string\" ? bodyUnknown.email.trim() : undefined\n const audienceId =\n typeof bodyUnknown.audienceId === \"string\" ? bodyUnknown.audienceId : undefined\n\n if (!audienceId || !email) {\n return Response.json(\n { message: \"audienceId and email are required\" },\n { status: 400 },\n )\n }\n\n const payloadUpsert: UpsertContactInput = {\n audienceId,\n email,\n subscribed:\n typeof bodyUnknown.subscribed === \"boolean\" ? bodyUnknown.subscribed : true,\n }\n\n if (typeof bodyUnknown.id === \"string\" && bodyUnknown.id) {\n payloadUpsert.id = bodyUnknown.id\n }\n if (typeof bodyUnknown.firstName === \"string\") {\n payloadUpsert.firstName = bodyUnknown.firstName\n }\n if (typeof bodyUnknown.lastName === \"string\") {\n payloadUpsert.lastName = bodyUnknown.lastName\n }\n if (isRecord(bodyUnknown.properties)) {\n payloadUpsert.properties = bodyUnknown.properties as Record<\n string,\n string | number | null\n >\n }\n\n await adapterFor(req).contacts.upsert(payloadUpsert)\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/contacts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"read\")\n if (denied) return denied\n const adapter = getMarketingIntegrationFromRequest(req).adapter\n const broadcasts = await adapter.broadcasts.list()\n const enriched = broadcasts.map((b) => ({\n ...b,\n externalDashboardUrl: adapter.urls?.broadcast?.(b.id),\n }))\n return Response.json(enriched)\n },\n method: \"get\",\n path: \"/marketing/broadcasts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const bodyUnknown = await parseRequestJson(req)\n if (!isRecord(bodyUnknown)) {\n return Response.json({ message: \"Invalid JSON\" }, { status: 400 })\n }\n\n const audienceIdRaw =\n typeof bodyUnknown.audienceId === \"string\" ? bodyUnknown.audienceId.trim() : \"\"\n const name = typeof bodyUnknown.name === \"string\" ? bodyUnknown.name.trim() : \"\"\n const subject =\n typeof bodyUnknown.subject === \"string\" ? bodyUnknown.subject.trim() : \"\"\n const templateIdRaw =\n typeof bodyUnknown.templateId === \"string\" ? bodyUnknown.templateId.trim() : \"\"\n\n const htmlProvided = typeof bodyUnknown.html === \"string\" ? bodyUnknown.html.trim() : \"\"\n const replyTo =\n typeof bodyUnknown.replyTo === \"string\" ? bodyUnknown.replyTo.trim() : undefined\n const locale =\n typeof bodyUnknown.locale === \"string\" ? bodyUnknown.locale : undefined\n\n if (!audienceIdRaw || !name || !subject) {\n return Response.json(\n { message: \"audienceId, name, and subject are required\" },\n { status: 400 },\n )\n }\n\n const hasTpl = Boolean(templateIdRaw !== \"\")\n if (!hasTpl && !htmlProvided) {\n return Response.json(\n { message: \"Provide HTML body or a template id.\" },\n { status: 400 },\n )\n }\n\n let normalized: CreateBroadcastInput\n if (hasTpl && htmlProvided !== \"\") {\n return Response.json(\n { message: \"Use either HTML or template id, not both.\" },\n { status: 400 },\n )\n }\n if (hasTpl) {\n normalized = {\n audienceId: audienceIdRaw,\n locale,\n name,\n replyTo,\n subject,\n templateId: templateIdRaw,\n }\n } else {\n normalized = {\n audienceId: audienceIdRaw,\n html: htmlProvided,\n locale,\n name,\n replyTo,\n subject,\n }\n }\n\n await adapterFor(req).broadcasts.create(normalized)\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/broadcasts\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const broadcastId =\n typeof req.routeParams?.broadcastId === \"string\" ? req.routeParams.broadcastId : \"\"\n if (!broadcastId) {\n return Response.json({ message: \"Missing broadcast id\" }, { status: 400 })\n }\n await adapterFor(req).broadcasts.delete({ broadcastId })\n return Response.json({ ok: true })\n },\n method: \"delete\",\n path: \"/marketing/broadcasts/:broadcastId\",\n },\n\n {\n handler: async (req) => {\n const denied = assertMarketingPermission(req, \"broadcasts\", \"write\")\n if (denied) return denied\n const broadcastId =\n typeof req.routeParams?.broadcastId === \"string\" ? req.routeParams.broadcastId : \"\"\n if (!broadcastId) {\n return Response.json({ message: \"Missing broadcast id\" }, { status: 400 })\n }\n\n let scheduledAt: string | undefined\n try {\n const cloned = (req as unknown as Request).clone()\n const payloadBody: unknown = await cloned.json()\n if (isRecord(payloadBody) && typeof payloadBody.scheduledAt === \"string\") {\n scheduledAt = payloadBody.scheduledAt\n }\n } catch {\n scheduledAt = undefined\n }\n\n await adapterFor(req).broadcasts.send({ broadcastId, scheduledAt })\n return Response.json({ ok: true })\n },\n method: \"post\",\n path: \"/marketing/broadcasts/:broadcastId/send\",\n },\n ]\n}\n","import { createMarketingEndpoints } from \"./endpoints/marketing-endpoints\"\nimport { mutateFormBuilderCollections } from \"./form-builder/mutate-collections\"\nimport {\n MARKETING_CUSTOM_CONFIG_KEY,\n type MarketingIntegrationState,\n} from \"./marketing-integration\"\n\nimport type { PayloadMarketingPlugin, PayloadPluginMarketingOptions } from \"./types\"\nimport type { Config } from \"payload\"\n\nfunction mergeMarketingCustom(\n config: Config,\n integration: MarketingIntegrationState,\n): Record<string, unknown> {\n const prev = config.custom\n const base =\n typeof prev === \"object\" && prev !== null && !Array.isArray(prev)\n ? { ...(prev as Record<string, unknown>) }\n : {}\n base[MARKETING_CUSTOM_CONFIG_KEY] = integration\n return base\n}\n\nfunction component(exportName: string, clientProps?: Record<string, unknown>) {\n return {\n path: \"payload-plugin-marketing/admin\",\n exportName,\n ...(clientProps ? { clientProps } : {}),\n }\n}\n\nfunction adminViewPath(basePath: string, ...segments: string[]): `/${string}` {\n const trimmed = basePath.replace(/^\\/+|\\/+$/g, \"\")\n const body = [trimmed, ...segments].filter(Boolean).join(\"/\")\n return `/${body}`\n}\n\nfunction withMarketingAdmin(config: Config, options: PayloadPluginMarketingOptions): Config {\n if (options.admin?.enabled === false) {\n return config\n }\n const basePath = options.admin?.basePath ?? \"\"\n const components = options.admin?.components ?? {}\n const menuComponent = components.marketingMenu ?? component(\"MarketingMenu\", { basePath })\n const viewClientProps: Record<string, unknown> = { basePath }\n\n const marketingIntegrationState: MarketingIntegrationState = {\n adapter: options.adapter,\n adminBasePath: basePath,\n permissions: options.permissions,\n }\n\n return {\n ...config,\n custom: mergeMarketingCustom(config, marketingIntegrationState),\n endpoints: [...(config.endpoints ?? []), ...createMarketingEndpoints()],\n admin: {\n ...(config.admin ?? {}),\n components: {\n ...(config.admin?.components ?? {}),\n afterNavLinks: [\n ...((config.admin?.components?.afterNavLinks as unknown[]) ?? []),\n menuComponent,\n ],\n views: {\n ...((config.admin?.components?.views as Record<string, unknown> | undefined) ?? {}),\n audienceList: {\n Component: components.audienceList ?? component(\"AudienceList\", viewClientProps),\n path: adminViewPath(basePath, \"audience\"),\n },\n audienceDetail: {\n Component: components.audienceDetail ?? component(\"AudienceDetail\", viewClientProps),\n path: adminViewPath(basePath, \"audience\", \":id\"),\n },\n broadcastList: {\n Component: components.broadcastList ?? component(\"BroadcastList\", viewClientProps),\n path: adminViewPath(basePath, \"broadcast\"),\n },\n },\n },\n },\n } as Config\n}\n\nexport function marketingPlugin(\n options: PayloadPluginMarketingOptions,\n): PayloadMarketingPlugin {\n const plugin: PayloadMarketingPlugin = (config) =>\n withMarketingAdmin(\n {\n ...config,\n collections: mutateFormBuilderCollections(config.collections, options),\n },\n options,\n )\n plugin.slug = \"marketing\"\n plugin.order = 10\n plugin.options = options as unknown as Record<string, unknown>\n return plugin\n}\n"],"mappings":"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","names":["MARKETING_CUSTOM_CONFIG_KEY","effectiveResource","slice","resolveMarketingPermissions","permissions","marketingMetaAllowed","effective","readIntegration","payload","custom","getMarketingIntegration","state","tryGetMarketingIntegration","getMarketingIntegrationFromRequest","req","unauthorized","forbidden","assertAuthenticated","req","effectiveForRequest","permissions","getMarketingIntegrationFromRequest","resolveMarketingPermissions","assertMarketingPermission","resource","action","auth","isRecord","value","parseRequestJson","adapterFor","createMarketingEndpoints","marketingMetaAllowed","adapter","denied","bodyUnknown","name","id","audience","audienceId","contactId","email","payloadUpsert","enriched","b","audienceIdRaw","subject","templateIdRaw","htmlProvided","replyTo","locale","hasTpl","normalized","broadcastId","scheduledAt","payloadBody","mergeMarketingCustom","config","integration","prev","base","MARKETING_CUSTOM_CONFIG_KEY","component","exportName","clientProps","adminViewPath","basePath","segments","withMarketingAdmin","options","components","menuComponent","viewClientProps","marketingIntegrationState","createMarketingEndpoints","marketingPlugin","plugin","mutateFormBuilderCollections"]}
@@ -0,0 +1,15 @@
1
+ import type { MarketingAdapter, MarketingEffectivePermissions, MarketingPluginPermissions } from "./types";
2
+ import type { Payload, PayloadRequest } from "payload";
3
+ export declare const MARKETING_CUSTOM_CONFIG_KEY = "payloadPluginMarketing";
4
+ export interface MarketingIntegrationState {
5
+ adapter: MarketingAdapter;
6
+ adminBasePath: string;
7
+ permissions?: MarketingPluginPermissions;
8
+ }
9
+ /** Resolves endpoint access flags. If `permissions` is absent (plugin option omitted), all actions are allowed for authenticated users. */
10
+ export declare function resolveMarketingPermissions(permissions: MarketingPluginPermissions | undefined): MarketingEffectivePermissions;
11
+ export declare function marketingMetaAllowed(effective: MarketingEffectivePermissions): boolean;
12
+ export declare function getMarketingIntegration(payload: Payload): MarketingIntegrationState;
13
+ export declare function tryGetMarketingIntegration(payload: Payload): MarketingIntegrationState | undefined;
14
+ export declare function getMarketingIntegrationFromRequest(req: PayloadRequest): MarketingIntegrationState;
15
+ //# sourceMappingURL=marketing-integration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketing-integration.d.ts","sourceRoot":"","sources":["../src/marketing-integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,6BAA6B,EAC7B,0BAA0B,EAC3B,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAEtD,eAAO,MAAM,2BAA2B,2BAA2B,CAAA;AAEnE,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,gBAAgB,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,0BAA0B,CAAA;CACzC;AAYD,2IAA2I;AAC3I,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,0BAA0B,GAAG,SAAS,GAClD,6BAA6B,CAa/B;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,6BAA6B,GAAG,OAAO,CAEtF;AAcD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,yBAAyB,CAQnF;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,yBAAyB,GAAG,SAAS,CAElG;AAED,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB,CAEjG"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAA;AAsDpF,wBAAgB,eAAe,CAC7B,OAAO,EAAE,6BAA6B,GACrC,sBAAsB,CAaxB"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAA;AA6EpF,wBAAgB,eAAe,CAC7B,OAAO,EAAE,6BAA6B,GACrC,sBAAsB,CAaxB"}
package/dist/types.d.ts CHANGED
@@ -116,8 +116,35 @@ export interface MarketingFormFieldOverrides {
116
116
  upload?: MarketingBlockOptions;
117
117
  url?: MarketingBlockOptions;
118
118
  }
119
+ /** Per-resource flags for plugin HTTP endpoints (`/api/.../marketing/*`). Omitted flags default to `true` when `permissions` is set. If `permissions` is omitted entirely, all operations stay allowed for authenticated users. */
120
+ export interface MarketingResourcePermissions {
121
+ read?: boolean;
122
+ write?: boolean;
123
+ }
124
+ export interface MarketingPluginPermissions {
125
+ audiences?: MarketingResourcePermissions;
126
+ broadcasts?: MarketingResourcePermissions;
127
+ contacts?: MarketingResourcePermissions;
128
+ }
129
+ /** Resolved read/write flags for marketing HTTP endpoints. */
130
+ export interface MarketingEffectivePermissions {
131
+ audiences: {
132
+ read: boolean;
133
+ write: boolean;
134
+ };
135
+ broadcasts: {
136
+ read: boolean;
137
+ write: boolean;
138
+ };
139
+ contacts: {
140
+ read: boolean;
141
+ write: boolean;
142
+ };
143
+ }
119
144
  export interface PayloadPluginMarketingOptions {
120
145
  adapter: MarketingAdapter;
146
+ /** Restrict marketing REST endpoints by resource. See `MarketingPluginPermissions`. */
147
+ permissions?: MarketingPluginPermissions;
121
148
  admin?: {
122
149
  basePath?: string;
123
150
  components?: {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-plugin-marketing",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Payload CMS plugin for marketing forms, audiences, contacts, and broadcasts.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -39,11 +39,6 @@
39
39
  "import": "./dist/adapters/mailchimp.js",
40
40
  "require": "./dist/adapters/mailchimp.cjs"
41
41
  },
42
- "./actions": {
43
- "types": "./dist/actions/index.d.ts",
44
- "import": "./dist/actions/index.js",
45
- "require": "./dist/actions/index.cjs"
46
- },
47
42
  "./admin": {
48
43
  "types": "./dist/admin/index.d.ts",
49
44
  "import": "./dist/admin/index.js",
@@ -1,18 +0,0 @@
1
- import type { CreateAudienceInput, CreateBroadcastInput, DeleteAudienceInput, DeleteBroadcastInput, DeleteContactInput, MarketingAdapter, SendBroadcastInput, UpsertContactInput } from "../types";
2
- export interface CreateMarketingActionsOptions {
3
- adapter: MarketingAdapter;
4
- }
5
- export declare function createMarketingActions({ adapter }: CreateMarketingActionsOptions): {
6
- createAudience(input: CreateAudienceInput): Promise<boolean>;
7
- createBroadcast(input: CreateBroadcastInput): Promise<boolean>;
8
- deleteAudience(input: DeleteAudienceInput): Promise<boolean>;
9
- deleteBroadcast(input: DeleteBroadcastInput): Promise<boolean>;
10
- deleteContact(input: DeleteContactInput): Promise<boolean>;
11
- newsletterSubscribe(input: {
12
- audienceId?: string;
13
- email: string;
14
- }): Promise<boolean>;
15
- sendBroadcast(input: SendBroadcastInput): Promise<boolean>;
16
- updateContact(input: UpsertContactInput): Promise<boolean>;
17
- };
18
- //# sourceMappingURL=factories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../src/actions/factories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,gBAAgB,CAAA;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,EAAE,OAAO,EAAE,EAAE,6BAA6B;0BAEjD,mBAAmB;2BAIlB,oBAAoB;0BAIrB,mBAAmB;2BAIlB,oBAAoB;yBAItB,kBAAkB;+BAIZ;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;yBAQ5C,kBAAkB;yBAIlB,kBAAkB;EAKhD"}
@@ -1,2 +0,0 @@
1
- "use strict";var r=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var o=Object.prototype.hasOwnProperty;var d=(t,e)=>{for(var n in e)r(t,n,{get:e[n],enumerable:!0})},p=(t,e,n,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of u(e))!o.call(t,a)&&a!==n&&r(t,a,{get:()=>e[a],enumerable:!(c=i(e,a))||c.enumerable});return t};var l=t=>p(r({},"__esModule",{value:!0}),t);var I={};d(I,{createMarketingActions:()=>s});module.exports=l(I);function s({adapter:t}){return{async createAudience(e){return await t.audiences.create(e),!0},async createBroadcast(e){return await t.broadcasts.create(e),!0},async deleteAudience(e){return await t.audiences.delete(e),!0},async deleteBroadcast(e){return await t.broadcasts.delete(e),!0},async deleteContact(e){return await t.contacts.delete(e),!0},async newsletterSubscribe(e){let n=e.audienceId??(await t.audiences.list())[0]?.id;if(!n)throw new Error("No audience found. Create one in the admin first.");return await t.contacts.upsert({audienceId:n,email:e.email,subscribed:!0}),!0},async sendBroadcast(e){return await t.broadcasts.send(e),!0},async updateContact(e){return await t.contacts.upsert(e),!0}}}0&&(module.exports={createMarketingActions});
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/actions/index.ts","../../src/actions/factories.ts"],"sourcesContent":["export { createMarketingActions, type CreateMarketingActionsOptions } from \"./factories\"\n","import type {\n CreateAudienceInput,\n CreateBroadcastInput,\n DeleteAudienceInput,\n DeleteBroadcastInput,\n DeleteContactInput,\n MarketingAdapter,\n SendBroadcastInput,\n UpsertContactInput,\n} from \"../types\"\n\nexport interface CreateMarketingActionsOptions {\n adapter: MarketingAdapter\n}\n\nexport function createMarketingActions({ adapter }: CreateMarketingActionsOptions) {\n return {\n async createAudience(input: CreateAudienceInput) {\n await adapter.audiences.create(input)\n return true\n },\n async createBroadcast(input: CreateBroadcastInput) {\n await adapter.broadcasts.create(input)\n return true\n },\n async deleteAudience(input: DeleteAudienceInput) {\n await adapter.audiences.delete(input)\n return true\n },\n async deleteBroadcast(input: DeleteBroadcastInput) {\n await adapter.broadcasts.delete(input)\n return true\n },\n async deleteContact(input: DeleteContactInput) {\n await adapter.contacts.delete(input)\n return true\n },\n async newsletterSubscribe(input: { audienceId?: string; email: string }) {\n const audienceId = input.audienceId ?? (await adapter.audiences.list())[0]?.id\n if (!audienceId) {\n throw new Error(\"No audience found. Create one in the admin first.\")\n }\n await adapter.contacts.upsert({ audienceId, email: input.email, subscribed: true })\n return true\n },\n async sendBroadcast(input: SendBroadcastInput) {\n await adapter.broadcasts.send(input)\n return true\n },\n async updateContact(input: UpsertContactInput) {\n await adapter.contacts.upsert(input)\n return true\n },\n }\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,4BAAAE,IAAA,eAAAC,EAAAH,GCeO,SAASI,EAAuB,CAAE,QAAAC,CAAQ,EAAkC,CACjF,MAAO,CACL,MAAM,eAAeC,EAA4B,CAC/C,aAAMD,EAAQ,UAAU,OAAOC,CAAK,EAC7B,EACT,EACA,MAAM,gBAAgBA,EAA6B,CACjD,aAAMD,EAAQ,WAAW,OAAOC,CAAK,EAC9B,EACT,EACA,MAAM,eAAeA,EAA4B,CAC/C,aAAMD,EAAQ,UAAU,OAAOC,CAAK,EAC7B,EACT,EACA,MAAM,gBAAgBA,EAA6B,CACjD,aAAMD,EAAQ,WAAW,OAAOC,CAAK,EAC9B,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,SAAS,OAAOC,CAAK,EAC5B,EACT,EACA,MAAM,oBAAoBA,EAA+C,CACvE,IAAMC,EAAaD,EAAM,aAAe,MAAMD,EAAQ,UAAU,KAAK,GAAG,CAAC,GAAG,GAC5E,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,mDAAmD,EAErE,aAAMF,EAAQ,SAAS,OAAO,CAAE,WAAAE,EAAY,MAAOD,EAAM,MAAO,WAAY,EAAK,CAAC,EAC3E,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,WAAW,KAAKC,CAAK,EAC5B,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,SAAS,OAAOC,CAAK,EAC5B,EACT,CACF,CACF","names":["actions_exports","__export","createMarketingActions","__toCommonJS","createMarketingActions","adapter","input","audienceId"]}
@@ -1,2 +0,0 @@
1
- export { createMarketingActions, type CreateMarketingActionsOptions } from "./factories";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,KAAK,6BAA6B,EAAE,MAAM,aAAa,CAAA"}
@@ -1,2 +0,0 @@
1
- import{a}from"../chunk-RBBHOL35.js";export{a as createMarketingActions};
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,2 +0,0 @@
1
- function a({adapter:t}){return{async createAudience(e){return await t.audiences.create(e),!0},async createBroadcast(e){return await t.broadcasts.create(e),!0},async deleteAudience(e){return await t.audiences.delete(e),!0},async deleteBroadcast(e){return await t.broadcasts.delete(e),!0},async deleteContact(e){return await t.contacts.delete(e),!0},async newsletterSubscribe(e){let n=e.audienceId??(await t.audiences.list())[0]?.id;if(!n)throw new Error("No audience found. Create one in the admin first.");return await t.contacts.upsert({audienceId:n,email:e.email,subscribed:!0}),!0},async sendBroadcast(e){return await t.broadcasts.send(e),!0},async updateContact(e){return await t.contacts.upsert(e),!0}}}export{a};
2
- //# sourceMappingURL=chunk-RBBHOL35.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/actions/factories.ts"],"sourcesContent":["import type {\n CreateAudienceInput,\n CreateBroadcastInput,\n DeleteAudienceInput,\n DeleteBroadcastInput,\n DeleteContactInput,\n MarketingAdapter,\n SendBroadcastInput,\n UpsertContactInput,\n} from \"../types\"\n\nexport interface CreateMarketingActionsOptions {\n adapter: MarketingAdapter\n}\n\nexport function createMarketingActions({ adapter }: CreateMarketingActionsOptions) {\n return {\n async createAudience(input: CreateAudienceInput) {\n await adapter.audiences.create(input)\n return true\n },\n async createBroadcast(input: CreateBroadcastInput) {\n await adapter.broadcasts.create(input)\n return true\n },\n async deleteAudience(input: DeleteAudienceInput) {\n await adapter.audiences.delete(input)\n return true\n },\n async deleteBroadcast(input: DeleteBroadcastInput) {\n await adapter.broadcasts.delete(input)\n return true\n },\n async deleteContact(input: DeleteContactInput) {\n await adapter.contacts.delete(input)\n return true\n },\n async newsletterSubscribe(input: { audienceId?: string; email: string }) {\n const audienceId = input.audienceId ?? (await adapter.audiences.list())[0]?.id\n if (!audienceId) {\n throw new Error(\"No audience found. Create one in the admin first.\")\n }\n await adapter.contacts.upsert({ audienceId, email: input.email, subscribed: true })\n return true\n },\n async sendBroadcast(input: SendBroadcastInput) {\n await adapter.broadcasts.send(input)\n return true\n },\n async updateContact(input: UpsertContactInput) {\n await adapter.contacts.upsert(input)\n return true\n },\n }\n}\n"],"mappings":"AAeO,SAASA,EAAuB,CAAE,QAAAC,CAAQ,EAAkC,CACjF,MAAO,CACL,MAAM,eAAeC,EAA4B,CAC/C,aAAMD,EAAQ,UAAU,OAAOC,CAAK,EAC7B,EACT,EACA,MAAM,gBAAgBA,EAA6B,CACjD,aAAMD,EAAQ,WAAW,OAAOC,CAAK,EAC9B,EACT,EACA,MAAM,eAAeA,EAA4B,CAC/C,aAAMD,EAAQ,UAAU,OAAOC,CAAK,EAC7B,EACT,EACA,MAAM,gBAAgBA,EAA6B,CACjD,aAAMD,EAAQ,WAAW,OAAOC,CAAK,EAC9B,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,SAAS,OAAOC,CAAK,EAC5B,EACT,EACA,MAAM,oBAAoBA,EAA+C,CACvE,IAAMC,EAAaD,EAAM,aAAe,MAAMD,EAAQ,UAAU,KAAK,GAAG,CAAC,GAAG,GAC5E,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,mDAAmD,EAErE,aAAMF,EAAQ,SAAS,OAAO,CAAE,WAAAE,EAAY,MAAOD,EAAM,MAAO,WAAY,EAAK,CAAC,EAC3E,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,WAAW,KAAKC,CAAK,EAC5B,EACT,EACA,MAAM,cAAcA,EAA2B,CAC7C,aAAMD,EAAQ,SAAS,OAAOC,CAAK,EAC5B,EACT,CACF,CACF","names":["createMarketingActions","adapter","input","audienceId"]}