@aglyn/aglyn 1.0.0-beta.221 → 1.0.0-beta.222

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 (346) hide show
  1. package/package.json +15 -11
  2. package/src/lib/app-utils/agent-openapi.js +1 -1
  3. package/src/lib/app-utils/agent-openapi.js.map +1 -1
  4. package/src/lib/app-utils/analytics-events.d.ts +3 -2
  5. package/src/lib/app-utils/analytics-events.js +3 -2
  6. package/src/lib/app-utils/analytics-events.js.map +1 -1
  7. package/src/lib/app-utils/api-plugins.d.ts +30 -0
  8. package/src/lib/app-utils/api-plugins.js +24 -1
  9. package/src/lib/app-utils/api-plugins.js.map +1 -1
  10. package/src/lib/app-utils/author-html.d.ts +1 -1
  11. package/src/lib/app-utils/author-html.js.map +1 -1
  12. package/src/lib/app-utils/bandwidth-cap.d.ts +12 -1
  13. package/src/lib/app-utils/bandwidth-cap.js +17 -1
  14. package/src/lib/app-utils/bandwidth-cap.js.map +1 -1
  15. package/src/lib/app-utils/compose-reusable-components.d.ts +19 -0
  16. package/src/lib/app-utils/compose-reusable-components.js +116 -26
  17. package/src/lib/app-utils/compose-reusable-components.js.map +1 -1
  18. package/src/lib/app-utils/console-routes.d.ts +4 -0
  19. package/src/lib/app-utils/console-routes.js +3 -0
  20. package/src/lib/app-utils/console-routes.js.map +1 -1
  21. package/src/lib/app-utils/contacts.d.ts +71 -0
  22. package/src/lib/app-utils/contacts.js +55 -0
  23. package/src/lib/app-utils/contacts.js.map +1 -1
  24. package/src/lib/app-utils/contexts.d.ts +1 -0
  25. package/src/lib/app-utils/contexts.js +1 -0
  26. package/src/lib/app-utils/contexts.js.map +1 -1
  27. package/src/lib/app-utils/crm-email-templates.js +21 -4
  28. package/src/lib/app-utils/crm-email-templates.js.map +1 -1
  29. package/src/lib/app-utils/crm-kinds.d.ts +2 -0
  30. package/src/lib/app-utils/crm-kinds.js +1 -0
  31. package/src/lib/app-utils/crm-kinds.js.map +1 -1
  32. package/src/lib/app-utils/crm.d.ts +1199 -67
  33. package/src/lib/app-utils/crm.js +1951 -310
  34. package/src/lib/app-utils/crm.js.map +1 -1
  35. package/src/lib/app-utils/csv-import.d.ts +10 -38
  36. package/src/lib/app-utils/csv-import.js +17 -42
  37. package/src/lib/app-utils/csv-import.js.map +1 -1
  38. package/src/lib/app-utils/csv.d.ts +32 -11
  39. package/src/lib/app-utils/csv.js +43 -5
  40. package/src/lib/app-utils/csv.js.map +1 -1
  41. package/src/lib/app-utils/default-site.d.ts +116 -0
  42. package/src/lib/app-utils/default-site.js +1024 -0
  43. package/src/lib/app-utils/default-site.js.map +1 -0
  44. package/src/lib/app-utils/docs-help.generated.d.ts +22 -22
  45. package/src/lib/app-utils/docs-help.generated.js +44 -10
  46. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  47. package/src/lib/app-utils/docs-index.generated.js +738 -150
  48. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  49. package/src/lib/app-utils/draft-placeholders.d.ts +76 -0
  50. package/src/lib/app-utils/draft-placeholders.js +115 -0
  51. package/src/lib/app-utils/draft-placeholders.js.map +1 -0
  52. package/src/lib/app-utils/entity-picker-context.d.ts +19 -15
  53. package/src/lib/app-utils/entity-picker-context.js +4 -4
  54. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  55. package/src/lib/app-utils/expand-repeatables.d.ts +66 -10
  56. package/src/lib/app-utils/expand-repeatables.js +88 -14
  57. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  58. package/src/lib/app-utils/forms.d.ts +33 -22
  59. package/src/lib/app-utils/forms.js +47 -28
  60. package/src/lib/app-utils/forms.js.map +1 -1
  61. package/src/lib/app-utils/full-use-cost.d.ts +277 -0
  62. package/src/lib/app-utils/full-use-cost.js +421 -0
  63. package/src/lib/app-utils/full-use-cost.js.map +1 -0
  64. package/src/lib/app-utils/health-report.js +11 -0
  65. package/src/lib/app-utils/health-report.js.map +1 -1
  66. package/src/lib/app-utils/llms-txt.d.ts +20 -0
  67. package/src/lib/app-utils/llms-txt.js +7 -1
  68. package/src/lib/app-utils/llms-txt.js.map +1 -1
  69. package/src/lib/app-utils/media-asset-facts.d.ts +16 -1
  70. package/src/lib/app-utils/media-asset-facts.js +40 -13
  71. package/src/lib/app-utils/media-asset-facts.js.map +1 -1
  72. package/src/lib/app-utils/media-bandwidth.d.ts +52 -0
  73. package/src/lib/app-utils/media-bandwidth.js +94 -0
  74. package/src/lib/app-utils/media-bandwidth.js.map +1 -0
  75. package/src/lib/app-utils/media-ref.d.ts +241 -33
  76. package/src/lib/app-utils/media-ref.js +324 -43
  77. package/src/lib/app-utils/media-ref.js.map +1 -1
  78. package/src/lib/app-utils/media-src.d.ts +8 -8
  79. package/src/lib/app-utils/media-src.js +27 -11
  80. package/src/lib/app-utils/media-src.js.map +1 -1
  81. package/src/lib/app-utils/media-takedown-reach.d.ts +4 -1
  82. package/src/lib/app-utils/media-takedown-reach.js +6 -3
  83. package/src/lib/app-utils/media-takedown-reach.js.map +1 -1
  84. package/src/lib/app-utils/notifications.d.ts +1 -1
  85. package/src/lib/app-utils/notifications.js +2 -0
  86. package/src/lib/app-utils/notifications.js.map +1 -1
  87. package/src/lib/app-utils/organizations.d.ts +51 -2
  88. package/src/lib/app-utils/organizations.js +56 -3
  89. package/src/lib/app-utils/organizations.js.map +1 -1
  90. package/src/lib/app-utils/page-record-sources.d.ts +87 -0
  91. package/src/lib/app-utils/page-record-sources.js +53 -0
  92. package/src/lib/app-utils/page-record-sources.js.map +1 -0
  93. package/src/lib/app-utils/paid-media-source.d.ts +3 -7
  94. package/src/lib/app-utils/paid-media-source.js +5 -19
  95. package/src/lib/app-utils/paid-media-source.js.map +1 -1
  96. package/src/lib/app-utils/person-erasure.d.ts +5 -2
  97. package/src/lib/app-utils/person-erasure.js.map +1 -1
  98. package/src/lib/app-utils/picklists.d.ts +187 -0
  99. package/src/lib/app-utils/picklists.js +320 -0
  100. package/src/lib/app-utils/picklists.js.map +1 -0
  101. package/src/lib/app-utils/plan-entitlements.d.ts +220 -50
  102. package/src/lib/app-utils/plan-entitlements.js +309 -115
  103. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  104. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  105. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  106. package/src/lib/app-utils/release-flags.d.ts +1 -1
  107. package/src/lib/app-utils/release-flags.js +11 -0
  108. package/src/lib/app-utils/release-flags.js.map +1 -1
  109. package/src/lib/app-utils/rendered-widths.d.ts +121 -0
  110. package/src/lib/app-utils/rendered-widths.js +211 -0
  111. package/src/lib/app-utils/rendered-widths.js.map +1 -0
  112. package/src/lib/app-utils/repeat-sources.d.ts +2 -1
  113. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  114. package/src/lib/app-utils/screen-route.d.ts +154 -36
  115. package/src/lib/app-utils/screen-route.js +185 -40
  116. package/src/lib/app-utils/screen-route.js.map +1 -1
  117. package/src/lib/app-utils/seo-audit.d.ts +11 -1
  118. package/src/lib/app-utils/seo-audit.js +33 -13
  119. package/src/lib/app-utils/seo-audit.js.map +1 -1
  120. package/src/lib/app-utils/seo-keywords.d.ts +11 -0
  121. package/src/lib/app-utils/seo-keywords.js +19 -5
  122. package/src/lib/app-utils/seo-keywords.js.map +1 -1
  123. package/src/lib/app-utils/seo-page-facts.d.ts +47 -4
  124. package/src/lib/app-utils/seo-page-facts.js +136 -31
  125. package/src/lib/app-utils/seo-page-facts.js.map +1 -1
  126. package/src/lib/app-utils/seo-site-scan.d.ts +42 -4
  127. package/src/lib/app-utils/seo-site-scan.js +113 -12
  128. package/src/lib/app-utils/seo-site-scan.js.map +1 -1
  129. package/src/lib/app-utils/server.d.ts +5 -4
  130. package/src/lib/app-utils/server.js +14 -5
  131. package/src/lib/app-utils/server.js.map +1 -1
  132. package/src/lib/app-utils/site-icon-set.d.ts +195 -0
  133. package/src/lib/app-utils/site-icon-set.js +351 -0
  134. package/src/lib/app-utils/site-icon-set.js.map +1 -0
  135. package/src/lib/app-utils/site-interactions.d.ts +101 -4
  136. package/src/lib/app-utils/site-interactions.js +120 -4
  137. package/src/lib/app-utils/site-interactions.js.map +1 -1
  138. package/src/lib/app-utils/starter-template-nodes.d.ts +7 -0
  139. package/src/lib/app-utils/starter-template-nodes.js +3 -0
  140. package/src/lib/app-utils/starter-template-nodes.js.map +1 -1
  141. package/src/lib/app-utils/starter-templates.d.ts +5 -19
  142. package/src/lib/app-utils/starter-templates.js +5 -49
  143. package/src/lib/app-utils/starter-templates.js.map +1 -1
  144. package/src/lib/app-utils/transfer-launcher-context.d.ts +136 -0
  145. package/src/lib/app-utils/transfer-launcher-context.js +23 -0
  146. package/src/lib/app-utils/transfer-launcher-context.js.map +1 -0
  147. package/src/lib/app-utils/transfer-resume-import.d.ts +39 -0
  148. package/src/lib/app-utils/transfer-resume-import.js +128 -0
  149. package/src/lib/app-utils/transfer-resume-import.js.map +1 -0
  150. package/src/lib/app-utils/upgrade-proposal.d.ts +66 -0
  151. package/src/lib/app-utils/upgrade-proposal.js +95 -0
  152. package/src/lib/app-utils/upgrade-proposal.js.map +1 -0
  153. package/src/lib/app-utils/utc-month.d.ts +33 -0
  154. package/src/lib/app-utils/utc-month.js +35 -0
  155. package/src/lib/app-utils/utc-month.js.map +1 -0
  156. package/src/lib/app-utils/visitor-record-ceiling.d.ts +4 -4
  157. package/src/lib/app-utils/visitor-record-ceiling.js +4 -4
  158. package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
  159. package/src/lib/app-utils/wire-nodes.d.ts +39 -19
  160. package/src/lib/app-utils/wire-nodes.js +120 -34
  161. package/src/lib/app-utils/wire-nodes.js.map +1 -1
  162. package/src/lib/data-transfer/access.d.ts +74 -0
  163. package/src/lib/data-transfer/access.js +93 -0
  164. package/src/lib/data-transfer/access.js.map +1 -0
  165. package/src/lib/data-transfer/derive.d.ts +246 -0
  166. package/src/lib/data-transfer/derive.js +1007 -0
  167. package/src/lib/data-transfer/derive.js.map +1 -0
  168. package/src/lib/data-transfer/export-file.d.ts +46 -0
  169. package/src/lib/data-transfer/export-file.js +146 -0
  170. package/src/lib/data-transfer/export-file.js.map +1 -0
  171. package/src/lib/data-transfer/field-catalog.d.ts +134 -0
  172. package/src/lib/data-transfer/field-catalog.js +278 -0
  173. package/src/lib/data-transfer/field-catalog.js.map +1 -0
  174. package/src/lib/data-transfer/header-match.d.ts +129 -0
  175. package/src/lib/data-transfer/header-match.js +367 -0
  176. package/src/lib/data-transfer/header-match.js.map +1 -0
  177. package/src/lib/data-transfer/index.d.ts +34 -0
  178. package/src/lib/data-transfer/index.js +40 -0
  179. package/src/lib/data-transfer/index.js.map +1 -0
  180. package/src/lib/data-transfer/job.d.ts +190 -0
  181. package/src/lib/data-transfer/job.js +229 -0
  182. package/src/lib/data-transfer/job.js.map +1 -0
  183. package/src/lib/data-transfer/lookup.d.ts +45 -0
  184. package/src/lib/data-transfer/lookup.js +71 -0
  185. package/src/lib/data-transfer/lookup.js.map +1 -0
  186. package/src/lib/data-transfer/match.d.ts +99 -0
  187. package/src/lib/data-transfer/match.js +244 -0
  188. package/src/lib/data-transfer/match.js.map +1 -0
  189. package/src/lib/data-transfer/package-plan.d.ts +205 -0
  190. package/src/lib/data-transfer/package-plan.js +475 -0
  191. package/src/lib/data-transfer/package-plan.js.map +1 -0
  192. package/src/lib/data-transfer/package.d.ts +181 -0
  193. package/src/lib/data-transfer/package.js +426 -0
  194. package/src/lib/data-transfer/package.js.map +1 -0
  195. package/src/lib/data-transfer/picklist-map.d.ts +139 -0
  196. package/src/lib/data-transfer/picklist-map.js +271 -0
  197. package/src/lib/data-transfer/picklist-map.js.map +1 -0
  198. package/src/lib/data-transfer/plan.d.ts +176 -0
  199. package/src/lib/data-transfer/plan.js +451 -0
  200. package/src/lib/data-transfer/plan.js.map +1 -0
  201. package/src/lib/data-transfer/policy.d.ts +170 -0
  202. package/src/lib/data-transfer/policy.js +378 -0
  203. package/src/lib/data-transfer/policy.js.map +1 -0
  204. package/src/lib/data-transfer/resource.d.ts +211 -0
  205. package/src/lib/data-transfer/resource.js +241 -0
  206. package/src/lib/data-transfer/resource.js.map +1 -0
  207. package/src/lib/data-transfer/review.d.ts +70 -0
  208. package/src/lib/data-transfer/review.js +233 -0
  209. package/src/lib/data-transfer/review.js.map +1 -0
  210. package/src/lib/data-transfer/similarity.d.ts +40 -0
  211. package/src/lib/data-transfer/similarity.js +106 -0
  212. package/src/lib/data-transfer/similarity.js.map +1 -0
  213. package/src/lib/data-transfer/site-package.d.ts +365 -0
  214. package/src/lib/data-transfer/site-package.js +1077 -0
  215. package/src/lib/data-transfer/site-package.js.map +1 -0
  216. package/src/lib/data-transfer/source.d.ts +74 -0
  217. package/src/lib/data-transfer/source.js +293 -0
  218. package/src/lib/data-transfer/source.js.map +1 -0
  219. package/src/lib/data-transfer/transfer-api.d.ts +898 -0
  220. package/src/lib/data-transfer/transfer-api.js +107 -0
  221. package/src/lib/data-transfer/transfer-api.js.map +1 -0
  222. package/src/lib/foundation/definitions/org-billing.types.d.ts +31 -0
  223. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  224. package/src/lib/foundation/definitions/organization.types.d.ts +42 -1
  225. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  226. package/src/lib/foundation/definitions/platform.types.d.ts +6 -4
  227. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  228. package/src/lib/foundation/index.d.ts +1 -1
  229. package/src/lib/foundation/index.js.map +1 -1
  230. package/src/lib/plugin-manager/feature-plugins.d.ts +91 -2
  231. package/src/lib/plugin-manager/feature-plugins.js +48 -3
  232. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  233. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +50 -0
  234. package/src/lib/plugin-manager/first-party-plugins.generated.js +1129 -28
  235. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  236. package/src/lib/plugin-manager/index.d.ts +0 -1
  237. package/src/lib/plugin-manager/index.js +0 -1
  238. package/src/lib/plugin-manager/index.js.map +1 -1
  239. package/src/lib/plugin-manager/interaction-recipes.d.ts +142 -0
  240. package/src/lib/plugin-manager/interaction-recipes.js +104 -0
  241. package/src/lib/plugin-manager/interaction-recipes.js.map +1 -0
  242. package/src/lib/plugin-manager/interaction-step-checks.d.ts +66 -0
  243. package/src/lib/plugin-manager/interaction-step-checks.js +86 -0
  244. package/src/lib/plugin-manager/interaction-step-checks.js.map +1 -0
  245. package/src/lib/plugin-manager/plugin-artifact-types.d.ts +235 -0
  246. package/src/lib/plugin-manager/plugin-artifact-types.js +99 -0
  247. package/src/lib/plugin-manager/plugin-artifact-types.js.map +1 -0
  248. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +8 -0
  249. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  250. package/src/lib/plugin-manager/plugin-conversion-credit.d.ts +216 -0
  251. package/src/lib/plugin-manager/plugin-conversion-credit.js +91 -0
  252. package/src/lib/plugin-manager/plugin-conversion-credit.js.map +1 -0
  253. package/src/lib/plugin-manager/plugin-entity-pickers.d.ts +83 -0
  254. package/src/lib/plugin-manager/plugin-entity-pickers.js +87 -0
  255. package/src/lib/plugin-manager/plugin-entity-pickers.js.map +1 -0
  256. package/src/lib/plugin-manager/plugin-host-resources.d.ts +6 -0
  257. package/src/lib/plugin-manager/plugin-host-resources.js +6 -1
  258. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -1
  259. package/src/lib/plugin-manager/plugin-intake-gates.d.ts +75 -0
  260. package/src/lib/plugin-manager/plugin-intake-gates.js +49 -0
  261. package/src/lib/plugin-manager/plugin-intake-gates.js.map +1 -0
  262. package/src/lib/plugin-manager/plugin-jobs.d.ts +5 -5
  263. package/src/lib/plugin-manager/plugin-jobs.js +7 -7
  264. package/src/lib/plugin-manager/plugin-jobs.js.map +1 -1
  265. package/src/lib/plugin-manager/plugin-live-paths.d.ts +70 -0
  266. package/src/lib/plugin-manager/plugin-live-paths.js +66 -0
  267. package/src/lib/plugin-manager/plugin-live-paths.js.map +1 -0
  268. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +3 -2
  269. package/src/lib/plugin-manager/plugin-org-erasure.js +30 -5
  270. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  271. package/src/lib/plugin-manager/plugin-person-erasure.d.ts +68 -9
  272. package/src/lib/plugin-manager/plugin-person-erasure.js +196 -51
  273. package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -1
  274. package/src/lib/plugin-manager/plugin-person-records.d.ts +275 -0
  275. package/src/lib/plugin-manager/plugin-person-records.js +107 -0
  276. package/src/lib/plugin-manager/plugin-person-records.js.map +1 -0
  277. package/src/lib/plugin-manager/plugin-record-counts.d.ts +76 -0
  278. package/src/lib/plugin-manager/plugin-record-counts.js +49 -0
  279. package/src/lib/plugin-manager/plugin-record-counts.js.map +1 -0
  280. package/src/lib/plugin-manager/plugin-record-email-state.d.ts +26 -0
  281. package/src/lib/plugin-manager/plugin-record-email-state.js +16 -0
  282. package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
  283. package/src/lib/plugin-manager/plugin-record-index.d.ts +10 -0
  284. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -1
  285. package/src/lib/plugin-manager/plugin-record-lists.d.ts +86 -6
  286. package/src/lib/plugin-manager/plugin-record-lists.js +42 -5
  287. package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -1
  288. package/src/lib/plugin-manager/plugin-record-origin.d.ts +79 -0
  289. package/src/lib/plugin-manager/plugin-record-origin.js +46 -0
  290. package/src/lib/plugin-manager/plugin-record-origin.js.map +1 -0
  291. package/src/lib/plugin-manager/plugin-record-pages.d.ts +37 -0
  292. package/src/lib/plugin-manager/plugin-record-pages.js +52 -0
  293. package/src/lib/plugin-manager/plugin-record-pages.js.map +1 -0
  294. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +60 -0
  295. package/src/lib/plugin-manager/plugin-record-timeline.js +16 -0
  296. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  297. package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +5 -5
  298. package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -1
  299. package/src/lib/plugin-manager/plugin-revocations.d.ts +64 -0
  300. package/src/lib/plugin-manager/plugin-revocations.js +47 -0
  301. package/src/lib/plugin-manager/plugin-revocations.js.map +1 -0
  302. package/src/lib/plugin-manager/plugin-send-tallies.d.ts +69 -0
  303. package/src/lib/plugin-manager/plugin-send-tallies.js +45 -0
  304. package/src/lib/plugin-manager/plugin-send-tallies.js.map +1 -0
  305. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +40 -0
  306. package/src/lib/plugin-manager/plugin-site-bundle.js +4 -0
  307. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -1
  308. package/src/lib/plugin-manager/plugin-site-export.d.ts +57 -1
  309. package/src/lib/plugin-manager/plugin-site-export.js +23 -10
  310. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -1
  311. package/src/lib/plugin-manager/plugin-sitemap-readers.d.ts +146 -0
  312. package/src/lib/plugin-manager/plugin-sitemap-readers.js +110 -0
  313. package/src/lib/plugin-manager/plugin-sitemap-readers.js.map +1 -0
  314. package/src/lib/plugin-manager/plugin-transfer-resources.d.ts +714 -0
  315. package/src/lib/plugin-manager/plugin-transfer-resources.js +443 -0
  316. package/src/lib/plugin-manager/plugin-transfer-resources.js.map +1 -0
  317. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +54 -5
  318. package/src/lib/plugin-manager/plugin-usage-axes.js +11 -3
  319. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -1
  320. package/src/lib/plugin-manager/plugin-user-erasure.js +9 -1
  321. package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -1
  322. package/src/lib/plugin-manager/plugin-visitor-doors.d.ts +104 -0
  323. package/src/lib/plugin-manager/plugin-visitor-doors.js +108 -0
  324. package/src/lib/plugin-manager/plugin-visitor-doors.js.map +1 -0
  325. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  326. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  327. package/src/lib/plugin-manager/repeat-rows.d.ts +5 -6
  328. package/src/lib/plugin-manager/repeat-rows.js.map +1 -1
  329. package/src/lib/app-utils/actions.d.ts +0 -310
  330. package/src/lib/app-utils/actions.js +0 -506
  331. package/src/lib/app-utils/actions.js.map +0 -1
  332. package/src/lib/app-utils/automation-placeholders.d.ts +0 -72
  333. package/src/lib/app-utils/automation-placeholders.js +0 -207
  334. package/src/lib/app-utils/automation-placeholders.js.map +0 -1
  335. package/src/lib/app-utils/dataset-models.d.ts +0 -339
  336. package/src/lib/app-utils/dataset-models.js +0 -722
  337. package/src/lib/app-utils/dataset-models.js.map +0 -1
  338. package/src/lib/app-utils/datasets.d.ts +0 -171
  339. package/src/lib/app-utils/datasets.js +0 -227
  340. package/src/lib/app-utils/datasets.js.map +0 -1
  341. package/src/lib/app-utils/form-abuse-ceiling.d.ts +0 -146
  342. package/src/lib/app-utils/form-abuse-ceiling.js +0 -158
  343. package/src/lib/app-utils/form-abuse-ceiling.js.map +0 -1
  344. package/src/lib/plugin-manager/order-fulfilment.d.ts +0 -142
  345. package/src/lib/plugin-manager/order-fulfilment.js +0 -104
  346. package/src/lib/plugin-manager/order-fulfilment.js.map +0 -1
@@ -1,506 +0,0 @@
1
- import { _ as _extends } from "@swc/helpers/_/_extends";
2
- import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
- /**
4
- * @license
5
- * Copyright 2026 Aglyn LLC
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */ import { CRM_TASK_MAX_DUE_DAYS, isContactLifecycleStage, isCrmActivityKind, isCrmTaskKind } from "./crm-kinds.js";
19
- import { CUSTOM_EVENT_PATTERN, validateInteraction } from "./site-interactions.js";
20
- import { HOST_EVENT_TYPES } from "./host-events.js";
21
- /**
22
- * Actions builder (AGL-148): HubSpot-style event → action automation on
23
- * top of the AGL-128 event triggers. An action listens for a host event
24
- * (built-in or a custom name fired by another action), optionally filters
25
- * on the payload, and runs an ordered step list. Pure types + validation
26
- * here; the executor lives in the workflows plugin, where the I/O is.
27
- *
28
- * An action is a SITE INTERACTION (`site-interactions.ts`) with server steps
29
- * added: its trigger, its conditions, its client steps and its storage are
30
- * the platform's, and are re-exported here for the readers that take both
31
- * from this module. What is declared below is the automation's own — the
32
- * server steps, flows, recipes and webhooks.
33
- */ export * from "./site-interactions.js";
34
- /**
35
- * The scope key a resumed flow carries to say the wait ended on the CLOCK
36
- * rather than on the event it was watching for.
37
- *
38
- * This is how a `waitForEvent` gets its timeout branch without a nested step
39
- * list: the flow resumes either way, and the step after it carries a `when`
40
- * naming this field. Underscored because it shares a namespace with the
41
- * event payload's own fields, which are merchant-authored form field names.
42
- */ export const FLOW_TIMED_OUT_FIELD = '_waitTimedOut';
43
- /**
44
- * The steps that suspend a run and continue it later, from a job beat.
45
- *
46
- * Named as a set rather than checked inline because three surfaces have to
47
- * agree on it: the executor stops here and writes an enrollment, the client
48
- * payload is truncated here, and the validator refuses a flow that waits
49
- * without a person to wait for.
50
- */ export const FLOW_SUSPENDING_STEP_TYPES = new Set([
51
- 'wait',
52
- 'waitForEvent'
53
- ]);
54
- export function isFlowSuspendingStep(step) {
55
- return FLOW_SUSPENDING_STEP_TYPES.has(step.type);
56
- }
57
- /** Longest tag an automation may write — the console's own tag field cap. */ export const CONTACT_TAG_MAX_LENGTH = 60;
58
- /*
59
- * THE RECIPES (AGL-2626).
60
- *
61
- * A recipe is a ready-to-edit action — a trigger, its conditions and an
62
- * ordered step list — built from the vocabulary the editor already offers
63
- * and handed to the editor as a draft. Nothing is written until the person
64
- * saves, and every field is theirs to change first: the recipe decides
65
- * where the editor starts, not what the site runs.
66
- *
67
- * Defined here, beside the step catalog, rather than in the builder, so the
68
- * docs page that lists the recipes and the menu that offers them read ONE
69
- * list, and so a step the catalog renames or retires breaks a recipe at
70
- * compile time rather than in a menu nobody tests.
71
- *
72
- * Definitions only. Three of the four are complete as written. `tagByForm`
73
- * needs a form, and a form belongs to a site (`hosts/{hostId}/forms`), so
74
- * the picker that supplies it is the builder's business and host-scoped by
75
- * nature. That is the seam an org-level mount keeps: the recipes are the
76
- * same at either level, and only the form picker knows where it is.
77
- */ export const CRM_ACTION_RECIPE_IDS = [
78
- 'welcomeNewLead',
79
- 'followUpWonDeal',
80
- 'reengageStaleLead',
81
- 'tagByForm'
82
- ];
83
- /**
84
- * How long the stale-lead recipe holds before it decides a lead has gone
85
- * quiet. A week: long enough that a rep who is working the lead has had a
86
- * chance to move its stage, short enough that a lead nobody touched is
87
- * still warm when the reminder lands.
88
- */ export const STALE_LEAD_WAIT_MINUTES = 7 * 24 * 60;
89
- /**
90
- * The tag a form's captures get: the form's own name, cut to the tag cap.
91
- * The name is what the person calls the form, so it is the tag they would
92
- * have typed; the editor is open to change it before anything is saved.
93
- */ export function crmRecipeTagForForm(formName) {
94
- return formName.trim().slice(0, CONTACT_TAG_MAX_LENGTH);
95
- }
96
- export const CRM_ACTION_RECIPES = [
97
- {
98
- id: 'welcomeNewLead',
99
- title: 'Welcome a new lead',
100
- description: 'When a form makes a new contact: rotate in an owner, book a call for ' + 'tomorrow, send a thank-you, and tag them website.',
101
- /*
102
- * The owner first, because the task that follows names no assignee and
103
- * so goes to whoever owns the contact when it is created — the member
104
- * the rotation just chose. Round robin rather than a named member: a
105
- * recipe cannot know who is on the team, and the pool under CRM →
106
- * Settings is the one place that does. On a workspace with no pool the
107
- * step fails and the run continues, so the call, the email and the tag
108
- * still land and the run history says who was not assigned.
109
- *
110
- * The email comes before any wait, which makes it an immediate reply to
111
- * what the visitor just did — transactional, sent from the org's own
112
- * identity, to the address the event carries.
113
- *
114
- * Its words promise no response time. The org hub installs this recipe
115
- * into a site without its editor opening, so the business never reads
116
- * the sentence it is sending, and a "within a day" written here would be
117
- * a commitment made on its behalf that nothing in the run keeps.
118
- */ build: ()=>({
119
- recipe: 'welcomeNewLead',
120
- name: 'Welcome a new lead',
121
- trigger: {
122
- event: 'contactCreated',
123
- conditions: [
124
- {
125
- field: 'source',
126
- op: 'equals',
127
- value: 'form'
128
- }
129
- ],
130
- combinator: 'and'
131
- },
132
- steps: [
133
- {
134
- type: 'assignContactOwner',
135
- roundRobin: true
136
- },
137
- {
138
- type: 'createCrmTask',
139
- title: 'Call the new lead',
140
- kind: 'call',
141
- dueInDays: 1
142
- },
143
- {
144
- type: 'sendEmail',
145
- subject: 'Thanks for getting in touch',
146
- body: 'Thanks for reaching out. We have your message and will reply ' + 'to this email address.'
147
- },
148
- {
149
- type: 'addContactTag',
150
- tag: 'website'
151
- }
152
- ],
153
- enabled: true
154
- })
155
- },
156
- {
157
- id: 'followUpWonDeal',
158
- title: 'Follow up a won deal',
159
- description: 'When a deal is won — which makes the contact a Customer on its own — ' + 'book a check-in call a week out.',
160
- /*
161
- * No stage step (AGL-2641): the win itself floors the contact at
162
- * `customer` before `dealWon` is announced, so a step setting the stage
163
- * here would at best repeat the write and at worst move an evangelist
164
- * back to customer — a SET, which is what the step is, and not the
165
- * floor the win applies. The recipe books the follow-up and nothing
166
- * else.
167
- */ build: ()=>({
168
- recipe: 'followUpWonDeal',
169
- name: 'Follow up a won deal',
170
- trigger: {
171
- event: 'dealWon'
172
- },
173
- steps: [
174
- {
175
- type: 'createCrmTask',
176
- title: 'Check in with the new customer',
177
- kind: 'call',
178
- dueInDays: 7
179
- }
180
- ],
181
- enabled: true
182
- })
183
- },
184
- {
185
- id: 'reengageStaleLead',
186
- title: 'Re-engage a stale lead',
187
- description: 'When a contact becomes a lead: wait a week, and if their stage has ' + 'not moved, book a call to bring them back.',
188
- /*
189
- * "Unless the stage moved on" is the wait's own event: the flow watches
190
- * for the next stage change on this person and gives up after a week.
191
- * Resumed by the clock, the run carries `_waitTimedOut`, and the task
192
- * step's guard reads it; resumed by the event, the field is absent and
193
- * the task is skipped — the lead was worked, and nobody is told to
194
- * re-engage somebody who just moved to Sales qualified.
195
- */ build: ()=>({
196
- recipe: 'reengageStaleLead',
197
- name: 'Re-engage a stale lead',
198
- trigger: {
199
- event: 'contactStageChanged',
200
- conditions: [
201
- {
202
- field: 'lifecycleStage',
203
- op: 'equals',
204
- value: 'lead'
205
- }
206
- ],
207
- combinator: 'and'
208
- },
209
- steps: [
210
- {
211
- type: 'waitForEvent',
212
- eventName: 'contactStageChanged',
213
- timeoutMinutes: STALE_LEAD_WAIT_MINUTES
214
- },
215
- {
216
- type: 'createCrmTask',
217
- title: 'Re-engage a lead that has gone quiet',
218
- kind: 'call',
219
- dueInDays: 1,
220
- when: {
221
- conditions: [
222
- {
223
- field: FLOW_TIMED_OUT_FIELD,
224
- op: 'notEmpty'
225
- }
226
- ]
227
- }
228
- }
229
- ],
230
- enabled: true
231
- })
232
- },
233
- {
234
- id: 'tagByForm',
235
- title: 'Tag by form',
236
- description: 'When a form you pick makes a new contact: tag them with the form’s ' + 'name.',
237
- needs: 'form',
238
- build: (input)=>{
239
- var _ref;
240
- const form = input == null ? void 0 : input.form;
241
- return {
242
- recipe: 'tagByForm',
243
- name: form ? `Tag ${form.name.trim()} submissions` : 'Tag by form',
244
- trigger: {
245
- event: 'contactCreated',
246
- conditions: [
247
- {
248
- field: 'formId',
249
- op: 'equals',
250
- value: (_ref = form == null ? void 0 : form.id) != null ? _ref : ''
251
- }
252
- ],
253
- combinator: 'and'
254
- },
255
- steps: [
256
- {
257
- type: 'addContactTag',
258
- tag: form ? crmRecipeTagForForm(form.name) : ''
259
- }
260
- ],
261
- enabled: true
262
- };
263
- }
264
- }
265
- ];
266
- /** The recipe with this id, or null for a string that names none. */ export function crmActionRecipe(id) {
267
- var _CRM_ACTION_RECIPES_find;
268
- return (_CRM_ACTION_RECIPES_find = CRM_ACTION_RECIPES.find((recipe)=>recipe.id === id)) != null ? _CRM_ACTION_RECIPES_find : null;
269
- }
270
- /**
271
- * The recipe a STORED action came from, read off its document (AGL-2639).
272
- *
273
- * Three answers, and the third is the one that matters. A known id: the
274
- * action was installed from, or begun as, that recipe. `null`: the action
275
- * was begun blank, or from a recipe this build no longer knows — the
276
- * editor wrote the field and said "no recipe". `undefined`: the document
277
- * carries no `recipe` field at all, which is every action saved before the
278
- * stamp existed. Such an action may well have started from a recipe — the
279
- * menu opened the editor prefilled long before anything recorded it — so a
280
- * reader that needs to know whether a site has a recipe treats `undefined`
281
- * as UNKNOWN, never as absent, and never writes a `null` over it.
282
- */ export function hostActionRecipeId(action) {
283
- var _ref;
284
- var _crmActionRecipe;
285
- const stamp = action == null ? void 0 : action.recipe;
286
- if (stamp === undefined) return undefined;
287
- return (_ref = (_crmActionRecipe = crmActionRecipe(stamp)) == null ? void 0 : _crmActionRecipe.id) != null ? _ref : null;
288
- }
289
- export function hostActionDocument(action) {
290
- var _trigger_conditions, _trigger_combinator;
291
- const { recipe } = action, rest = _object_without_properties_loose(action, [
292
- "recipe"
293
- ]);
294
- const trigger = action.trigger;
295
- return _extends({}, rest, {
296
- trigger: _extends({}, trigger, {
297
- oncePerVisitor: trigger.oncePerVisitor === true,
298
- oncePerSession: trigger.oncePerSession === true,
299
- cooldownMinutes: Number(trigger.cooldownMinutes) >= 1 ? Number(trigger.cooldownMinutes) : null,
300
- everyTime: trigger.everyTime === true,
301
- condition: null,
302
- conditions: (_trigger_conditions = trigger.conditions) != null ? _trigger_conditions : null,
303
- combinator: (_trigger_combinator = trigger.combinator) != null ? _trigger_combinator : null
304
- }),
305
- enabled: action.enabled !== false
306
- }, recipe !== undefined ? {
307
- recipe
308
- } : {});
309
- }
310
- /**
311
- * The step list as the visitor's browser may see it.
312
- *
313
- * A client step AFTER a wait must never reach the page. The client engine
314
- * runs its slice of the list immediately, so shipping the whole list would
315
- * make "wait three days, then show the popup" show the popup at once — the
316
- * delay would appear to work on the server, be ignored in the browser, and
317
- * the two halves of one authored flow would disagree about when it happened.
318
- *
319
- * Truncating rather than filtering: everything past the first wait belongs to
320
- * a run that has not happened yet, whichever side would have executed it.
321
- */ export function hostActionStepsForClient(steps) {
322
- const list = steps != null ? steps : [];
323
- const suspendAt = list.findIndex(isFlowSuspendingStep);
324
- return [
325
- ...suspendAt < 0 ? list : list.slice(0, suspendAt)
326
- ];
327
- }
328
- /**
329
- * The shortest and longest a flow may wait.
330
- *
331
- * The floor is a minute because the resume beat runs on a minute, so anything
332
- * under one is a delay the scheduler cannot honor and would only read as
333
- * imprecision. The ceiling is ninety days: long enough for the win-back that
334
- * is the longest sequence anybody writes, and short enough that an enrollment
335
- * is not an unbounded lease on a document. A person waiting inside a flow is
336
- * storage the merchant is not looking at, and a wait measured in years is
337
- * indistinguishable from one nobody will ever collect.
338
- */ export const FLOW_WAIT_MIN_MINUTES = 1;
339
- export const FLOW_WAIT_MAX_MINUTES = 90 * 24 * 60;
340
- export const HOST_ACTION_STEP_LABELS = {
341
- runWorkflow: 'Run a workflow',
342
- siteAlert: 'Show a site alert',
343
- customEvent: 'Fire a custom event',
344
- datasetAppend: 'Write to a dataset',
345
- webhookPost: 'Send a webhook (Business)',
346
- showOverlay: 'Show a popup or bar',
347
- stickyNav: 'Make navigation sticky',
348
- addClass: 'Add a CSS class',
349
- toggleClass: 'Toggle a CSS class',
350
- removeClass: 'Remove a CSS class',
351
- showElement: 'Show an element',
352
- hideElement: 'Hide an element',
353
- toggleElement: 'Show/hide an element',
354
- openDrawer: 'Open a drawer',
355
- closeDrawer: 'Close a drawer',
356
- toggleDrawer: 'Open/close a drawer',
357
- openMenu: 'Open a menu',
358
- closeMenu: 'Close a menu',
359
- toggleMenu: 'Open/close a menu',
360
- setAttribute: 'Set an ARIA or data attribute',
361
- removeAttribute: 'Remove an ARIA or data attribute',
362
- scrollTo: 'Scroll to element',
363
- playVideo: 'Play a video',
364
- showHtml: 'Show custom HTML',
365
- runJs: 'Run custom JS (Business)',
366
- redirect: 'Redirect the visitor',
367
- trackGaEvent: 'Track an analytics event',
368
- sendEmail: 'Send an email',
369
- notifyAdmins: 'Notify site admins',
370
- enrollList: 'Enroll in a list',
371
- updateDataset: 'Update a dataset record',
372
- assignCampaign: 'Assign to a campaign',
373
- wait: 'Wait',
374
- waitForEvent: 'Wait for something to happen',
375
- exitFlow: 'End the flow here',
376
- setContactStage: 'Set the contact’s lifecycle stage',
377
- addContactTag: 'Tag the contact',
378
- assignContactOwner: 'Assign the contact an owner',
379
- createCrmTask: 'Create a CRM task',
380
- logCrmActivity: 'Log a CRM activity'
381
- };
382
- /** A whole number of minutes inside the wait band. */ export function isFlowWaitMinutes(value) {
383
- return Number.isInteger(value) && value >= FLOW_WAIT_MIN_MINUTES && value <= FLOW_WAIT_MAX_MINUTES;
384
- }
385
- /** True for a custom (non-built-in) event name an action may fire. */ export function isCustomEventName(event) {
386
- return !HOST_EVENT_TYPES.includes(event) && CUSTOM_EVENT_PATTERN.test(event);
387
- }
388
- /**
389
- * Validates an action doc shape; returns a human-readable error or null.
390
- * Server and console share this so bad steps never persist or run.
391
- */ export function validateHostAction(action) {
392
- var _action_name;
393
- if (!((_action_name = action.name) == null ? void 0 : _action_name.trim())) return 'Name the action';
394
- // A stamp is provenance, and provenance naming a recipe that does not
395
- // exist is a document nothing can read back; `null` and absent both pass.
396
- if (action.recipe != null && !crmActionRecipe(action.recipe)) {
397
- return 'Unknown recipe';
398
- }
399
- // The trigger, the step guards, the client steps and every declared step's
400
- // pick are the platform's to check; the server steps are this module's.
401
- return validateInteraction(action, {
402
- validateStep: (step, label)=>serverStepProblem(step, label)
403
- });
404
- }
405
- /**
406
- * A server step's own complaint, or null. A `runWorkflow` step's pick is
407
- * checked with every other declared step's (`interactionSteps` in
408
- * `plugins.config.json`), by `validateInteraction`.
409
- */ function serverStepProblem(step, label) {
410
- var _step_datasetId, _step_datasetName, _step_webhookId, _step_webhookName, _step_title, _step_listId, _step_listName, _step_datasetId1, _step_datasetName1, _step_campaignId, _step_campaignName;
411
- if (step.type === 'wait' && !isFlowWaitMinutes(step.delayMinutes)) {
412
- return `${label}: wait between ${FLOW_WAIT_MIN_MINUTES} minute and ${FLOW_WAIT_MAX_MINUTES} minutes`;
413
- }
414
- if (step.type === 'waitForEvent') {
415
- var _ref;
416
- var _step_eventName;
417
- const waited = (_ref = (_step_eventName = step.eventName) == null ? void 0 : _step_eventName.trim()) != null ? _ref : '';
418
- if (!waited || !HOST_EVENT_TYPES.includes(waited) && !isCustomEventName(waited)) {
419
- return `${label}: pick the event to wait for`;
420
- }
421
- if (!isFlowWaitMinutes(step.timeoutMinutes)) {
422
- return `${label}: give up after ${FLOW_WAIT_MIN_MINUTES}–${FLOW_WAIT_MAX_MINUTES} minutes`;
423
- }
424
- }
425
- if (step.type === 'customEvent') {
426
- var _ref1;
427
- var _step_eventName1;
428
- if (!isCustomEventName((_ref1 = (_step_eventName1 = step.eventName) == null ? void 0 : _step_eventName1.trim()) != null ? _ref1 : '')) {
429
- return `${label}: custom event names are 2–40 letters, digits, dashes`;
430
- }
431
- }
432
- if (step.type === 'datasetAppend' && !((_step_datasetId = step.datasetId) == null ? void 0 : _step_datasetId.trim()) && !((_step_datasetName = step.datasetName) == null ? void 0 : _step_datasetName.trim())) {
433
- return `${label}: pick a dataset`;
434
- }
435
- if (step.type === 'webhookPost' && !((_step_webhookId = step.webhookId) == null ? void 0 : _step_webhookId.trim()) && !((_step_webhookName = step.webhookName) == null ? void 0 : _step_webhookName.trim())) {
436
- return `${label}: pick a webhook`;
437
- }
438
- if (step.type === 'sendEmail') {
439
- var _step_subject, _step_body;
440
- if (!((_step_subject = step.subject) == null ? void 0 : _step_subject.trim())) return `${label}: enter the subject`;
441
- if (!((_step_body = step.body) == null ? void 0 : _step_body.trim())) return `${label}: enter the email body`;
442
- }
443
- if (step.type === 'notifyAdmins' && !((_step_title = step.title) == null ? void 0 : _step_title.trim())) {
444
- return `${label}: enter the notification title`;
445
- }
446
- if (step.type === 'enrollList' && !((_step_listId = step.listId) == null ? void 0 : _step_listId.trim()) && !((_step_listName = step.listName) == null ? void 0 : _step_listName.trim())) {
447
- return `${label}: pick a list`;
448
- }
449
- if (step.type === 'updateDataset' && !((_step_datasetId1 = step.datasetId) == null ? void 0 : _step_datasetId1.trim()) && !((_step_datasetName1 = step.datasetName) == null ? void 0 : _step_datasetName1.trim())) {
450
- return `${label}: pick a dataset`;
451
- }
452
- if (step.type === 'assignCampaign' && !((_step_campaignId = step.campaignId) == null ? void 0 : _step_campaignId.trim()) && !((_step_campaignName = step.campaignName) == null ? void 0 : _step_campaignName.trim())) {
453
- return `${label}: pick a campaign`;
454
- }
455
- // CRM steps (AGL-2605). A stage or a kind outside its vocabulary is
456
- // refused here rather than stored: the executor treats the value as
457
- // trusted and would write it into a facet every stage report counts.
458
- if (step.type === 'setContactStage' && !isContactLifecycleStage(step.lifecycleStage)) {
459
- return `${label}: pick a lifecycle stage`;
460
- }
461
- if (step.type === 'addContactTag') {
462
- var _ref2;
463
- var _step_tag;
464
- const tag = (_ref2 = (_step_tag = step.tag) == null ? void 0 : _step_tag.trim()) != null ? _ref2 : '';
465
- if (!tag) return `${label}: enter the tag`;
466
- if (tag.length > CONTACT_TAG_MAX_LENGTH) {
467
- return `${label}: tags are at most ${CONTACT_TAG_MAX_LENGTH} characters`;
468
- }
469
- }
470
- if (step.type === 'assignContactOwner') {
471
- var _step_ownerUid, _step_ownerEmail, _step_ownerUid1, _step_ownerEmail1;
472
- const named = Boolean(((_step_ownerUid = step.ownerUid) == null ? void 0 : _step_ownerUid.trim()) || ((_step_ownerEmail = step.ownerEmail) == null ? void 0 : _step_ownerEmail.trim()));
473
- if (step.roundRobin === true && named) {
474
- return `${label}: pick round robin or a member, not both`;
475
- }
476
- if (step.roundRobin !== true && !((_step_ownerUid1 = step.ownerUid) == null ? void 0 : _step_ownerUid1.trim()) && !((_step_ownerEmail1 = step.ownerEmail) == null ? void 0 : _step_ownerEmail1.trim().includes('@'))) {
477
- return `${label}: enter the owner’s email address`;
478
- }
479
- }
480
- if (step.type === 'createCrmTask') {
481
- var _ref3;
482
- var _step_title1, _step_assigneeEmail;
483
- if (!((_step_title1 = step.title) == null ? void 0 : _step_title1.trim())) return `${label}: give the task a title`;
484
- if (!isCrmTaskKind(step.kind)) return `${label}: pick the kind of task`;
485
- if (!Number.isInteger(step.dueInDays) || step.dueInDays < 0 || step.dueInDays > CRM_TASK_MAX_DUE_DAYS) {
486
- return `${label}: due in 0–${CRM_TASK_MAX_DUE_DAYS} days`;
487
- }
488
- // Optional — but an address that is not one would resolve to nobody at
489
- // run time, and the task would land unassigned with no word why.
490
- const assigneeEmail = (_ref3 = (_step_assigneeEmail = step.assigneeEmail) == null ? void 0 : _step_assigneeEmail.trim()) != null ? _ref3 : '';
491
- if (assigneeEmail && !assigneeEmail.includes('@')) {
492
- return `${label}: enter the assignee’s email address`;
493
- }
494
- }
495
- if (step.type === 'logCrmActivity') {
496
- var _step_body1;
497
- if (!isCrmActivityKind(step.kind)) {
498
- return `${label}: pick the kind of activity`;
499
- }
500
- if (!((_step_body1 = step.body) == null ? void 0 : _step_body1.trim())) return `${label}: write what happened`;
501
- }
502
- return null;
503
- }
504
- /** The most webhooks one site keeps; the site create route enforces it. */ export const WEBHOOK_MAX_PER_HOST = 5;
505
-
506
- //# sourceMappingURL=actions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/actions.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n type ContactLifecycleStage,\n CRM_TASK_MAX_DUE_DAYS,\n type CrmActivityKind,\n type CrmTaskKind,\n isContactLifecycleStage,\n isCrmActivityKind,\n isCrmTaskKind,\n} from './crm-kinds'\nimport {\n type ClientInteractionStep,\n CUSTOM_EVENT_PATTERN,\n type InteractionCondition,\n type InteractionStepGuard,\n type InteractionTrigger,\n type SiteAlert,\n type SiteInteraction,\n type TriggerCombinator,\n validateInteraction,\n} from './site-interactions'\nimport { HOST_EVENT_TYPES } from './host-events'\n\n/**\n * Actions builder (AGL-148): HubSpot-style event → action automation on\n * top of the AGL-128 event triggers. An action listens for a host event\n * (built-in or a custom name fired by another action), optionally filters\n * on the payload, and runs an ordered step list. Pure types + validation\n * here; the executor lives in the workflows plugin, where the I/O is.\n *\n * An action is a SITE INTERACTION (`site-interactions.ts`) with server steps\n * added: its trigger, its conditions, its client steps and its storage are\n * the platform's, and are re-exported here for the readers that take both\n * from this module. What is declared below is the automation's own — the\n * server steps, flows, recipes and webhooks.\n */\nexport * from './site-interactions'\n\n/** The automation's names for the platform's interaction shapes. */\nexport type HostActionTriggerCondition = InteractionCondition\nexport type HostActionTrigger = InteractionTrigger\nexport type HostActionStepGuard = InteractionStepGuard\n/** Alert produced by a `siteAlert` step, surfaced to the emitting client. */\nexport type HostActionAlert = SiteAlert\n\n/**\n * The scope key a resumed flow carries to say the wait ended on the CLOCK\n * rather than on the event it was watching for.\n *\n * This is how a `waitForEvent` gets its timeout branch without a nested step\n * list: the flow resumes either way, and the step after it carries a `when`\n * naming this field. Underscored because it shares a namespace with the\n * event payload's own fields, which are merchant-authored form field names.\n */\nexport const FLOW_TIMED_OUT_FIELD = '_waitTimedOut'\n\n/** The steps an automation adds to the platform's client steps: the server's, run by the workflows plugin. */\ntype ServerActionStep = (\n // Entity references carry a doc id (AGL-261, rename-safe) with the name\n // kept as a display hint; pre-AGL-261 docs have only the name and the\n // executor resolves either.\n | { type: 'runWorkflow'; workflowId?: string; workflowName?: string }\n | { type: 'customEvent'; eventName: string }\n | { type: 'datasetAppend'; datasetId?: string; datasetName?: string }\n | { type: 'webhookPost'; webhookId?: string; webhookName?: string }\n // Server-side steps (AGL-257).\n | {\n type: 'sendEmail'\n subject: string\n body: string\n toField?: string\n /**\n * The stream this message belongs to, so a recipient who left it is not\n * mailed. Absent on every step authored before topics reached the\n * actions editor, which the executor resolves to the default topic.\n */\n topicId?: string\n }\n | { type: 'notifyAdmins'; title: string; body?: string }\n | { type: 'enrollList'; listId?: string; listName?: string }\n | { type: 'updateDataset'; datasetId?: string; datasetName?: string }\n | { type: 'assignCampaign'; campaignId?: string; campaignName?: string }\n /*\n * THE THREE FLOW STEPS.\n *\n * `wait` is the one that matters: without a durable delay an automation is\n * always trigger → immediate actions, so no welcome series, win-back or\n * post-purchase follow-up can exist at all. The other two are what make a\n * delay useful — something to end the flow early, and a wait that ends on\n * an event instead of on the clock.\n *\n * All three are SERVER steps. A delay outlives the page view that started\n * it by days, so the browser that fired the trigger is long gone by the time\n * the flow continues; `hostActionStepsForClient` truncates the client's copy\n * of the step list at the first of these for that reason.\n */\n | {\n type: 'wait'\n /** Whole minutes to hold before the next step. */\n delayMinutes: number\n }\n | {\n type: 'waitForEvent'\n /** The host or custom event that resumes this person's flow. */\n eventName: string\n /**\n * Whole minutes after which the flow continues anyway, with\n * {@link FLOW_TIMED_OUT_FIELD} true in scope. There is always a\n * deadline: a wait with no timeout is an enrollment that lives forever.\n */\n timeoutMinutes: number\n }\n /** Ends the enrollment here. Paired with a `when`, this is the exit branch. */\n | { type: 'exitFlow' }\n /*\n * THE CRM STEPS (AGL-2605).\n *\n * Server steps, every one, because each writes a record only the Admin\n * SDK may write on a visitor's behalf. Each acts on ONE person — the\n * contact the event names, resolved by `contactId` when the payload\n * carries one and by `email` otherwise — and each writes inside the\n * site's own facet or stamps the site's own scope, for the reason\n * `assignCampaign` gives: a contact row is shared by every site in the\n * org, and a stage or a tag is one holder's business record. A step whose\n * event names nobody the site can see does nothing and says so in the run.\n *\n * None of them carries a doc-id reference for the reference audit to\n * check: a stage and a kind are fixed vocabularies, a tag is free text,\n * and an owner is a member who is resolved at run time.\n */\n | { type: 'setContactStage'; lifecycleStage: ContactLifecycleStage }\n | { type: 'addContactTag'; tag: string }\n /**\n * The owner by uid when a member id was typed or a picker wrote the step,\n * by email when an address was typed; the executor resolves either against\n * the org's roster, and only the roster (AGL-2614).\n * Or `roundRobin`, and the owner is the next member of the pool the CRM's\n * settings keep (AGL-2618) — a step that names nobody and hands the\n * choice to the rotation, so a stage change can spread its follow-ups\n * across a team rather than pile them on one rep. The two are exclusive:\n * a rotation step carries no member, and the validator refuses one that\n * names both.\n */\n | {\n type: 'assignContactOwner'\n ownerUid?: string\n ownerEmail?: string\n roundRobin?: boolean\n }\n | {\n type: 'createCrmTask'\n title: string\n kind: CrmTaskKind\n /** Days from the run to the due date; `0` is due today. */\n dueInDays: number\n /**\n * Who gets it — by uid or by an address, both resolved against the\n * roster the way the owner step's are. Neither named, the task goes\n * to the contact's owner, then to nobody.\n */\n assigneeUid?: string\n assigneeEmail?: string\n }\n | { type: 'logCrmActivity'; kind: CrmActivityKind; body: string }\n) & {\n /** See {@link InteractionStepGuard}. Absent means the step always runs. */\n when?: InteractionStepGuard | null\n}\n\n/** A step of an automation: one of the platform's client steps, or one of its server steps. */\nexport type HostActionStep = ClientInteractionStep | ServerActionStep\n\n/**\n * The steps that suspend a run and continue it later, from a job beat.\n *\n * Named as a set rather than checked inline because three surfaces have to\n * agree on it: the executor stops here and writes an enrollment, the client\n * payload is truncated here, and the validator refuses a flow that waits\n * without a person to wait for.\n */\nexport const FLOW_SUSPENDING_STEP_TYPES: ReadonlySet<HostActionStepType> =\n new Set(['wait', 'waitForEvent'] as const)\n\nexport function isFlowSuspendingStep(step: HostActionStep): boolean {\n return FLOW_SUSPENDING_STEP_TYPES.has(step.type)\n}\n\n/** Longest tag an automation may write — the console's own tag field cap. */\nexport const CONTACT_TAG_MAX_LENGTH = 60\n\n/*\n * THE RECIPES (AGL-2626).\n *\n * A recipe is a ready-to-edit action — a trigger, its conditions and an\n * ordered step list — built from the vocabulary the editor already offers\n * and handed to the editor as a draft. Nothing is written until the person\n * saves, and every field is theirs to change first: the recipe decides\n * where the editor starts, not what the site runs.\n *\n * Defined here, beside the step catalog, rather than in the builder, so the\n * docs page that lists the recipes and the menu that offers them read ONE\n * list, and so a step the catalog renames or retires breaks a recipe at\n * compile time rather than in a menu nobody tests.\n *\n * Definitions only. Three of the four are complete as written. `tagByForm`\n * needs a form, and a form belongs to a site (`hosts/{hostId}/forms`), so\n * the picker that supplies it is the builder's business and host-scoped by\n * nature. That is the seam an org-level mount keeps: the recipes are the\n * same at either level, and only the form picker knows where it is.\n */\nexport const CRM_ACTION_RECIPE_IDS = [\n 'welcomeNewLead',\n 'followUpWonDeal',\n 'reengageStaleLead',\n 'tagByForm',\n] as const\n\nexport type CrmActionRecipeId = (typeof CRM_ACTION_RECIPE_IDS)[number]\n\n/** What a recipe is handed before it builds — today only the form `tagByForm` reads. */\nexport interface CrmActionRecipeInput {\n form?: { id: string; name: string }\n}\n\nexport interface CrmActionRecipe {\n id: CrmActionRecipeId\n /** How the recipe reads in the menu; also the action's starting name. */\n title: string\n /** One sentence under the title. */\n description: string\n /**\n * What must be picked before the recipe can be built. A recipe that needs\n * nothing opens the editor at once; one that needs a form opens a picker\n * first. Built WITHOUT its pick, such a recipe yields an action the\n * validator refuses — a condition with no value — rather than one that\n * saves and then silently matches nothing.\n */\n needs?: 'form'\n /**\n * A fresh action each call, because the draft is edited in place. The\n * action carries `recipe: id` — the provenance is the builder's to stamp,\n * so a writer that saves what it was handed cannot forget it.\n */\n build: (input?: CrmActionRecipeInput) => HostAction\n}\n\n/**\n * How long the stale-lead recipe holds before it decides a lead has gone\n * quiet. A week: long enough that a rep who is working the lead has had a\n * chance to move its stage, short enough that a lead nobody touched is\n * still warm when the reminder lands.\n */\nexport const STALE_LEAD_WAIT_MINUTES = 7 * 24 * 60\n\n/**\n * The tag a form's captures get: the form's own name, cut to the tag cap.\n * The name is what the person calls the form, so it is the tag they would\n * have typed; the editor is open to change it before anything is saved.\n */\nexport function crmRecipeTagForForm(formName: string): string {\n return formName.trim().slice(0, CONTACT_TAG_MAX_LENGTH)\n}\n\nexport const CRM_ACTION_RECIPES: readonly CrmActionRecipe[] = [\n {\n id: 'welcomeNewLead',\n title: 'Welcome a new lead',\n description:\n 'When a form makes a new contact: rotate in an owner, book a call for ' +\n 'tomorrow, send a thank-you, and tag them website.',\n /*\n * The owner first, because the task that follows names no assignee and\n * so goes to whoever owns the contact when it is created — the member\n * the rotation just chose. Round robin rather than a named member: a\n * recipe cannot know who is on the team, and the pool under CRM →\n * Settings is the one place that does. On a workspace with no pool the\n * step fails and the run continues, so the call, the email and the tag\n * still land and the run history says who was not assigned.\n *\n * The email comes before any wait, which makes it an immediate reply to\n * what the visitor just did — transactional, sent from the org's own\n * identity, to the address the event carries.\n *\n * Its words promise no response time. The org hub installs this recipe\n * into a site without its editor opening, so the business never reads\n * the sentence it is sending, and a \"within a day\" written here would be\n * a commitment made on its behalf that nothing in the run keeps.\n */\n build: () => ({\n recipe: 'welcomeNewLead',\n name: 'Welcome a new lead',\n trigger: {\n event: 'contactCreated',\n conditions: [{ field: 'source', op: 'equals', value: 'form' }],\n combinator: 'and',\n },\n steps: [\n { type: 'assignContactOwner', roundRobin: true },\n {\n type: 'createCrmTask',\n title: 'Call the new lead',\n kind: 'call',\n dueInDays: 1,\n },\n {\n type: 'sendEmail',\n subject: 'Thanks for getting in touch',\n body:\n 'Thanks for reaching out. We have your message and will reply ' +\n 'to this email address.',\n },\n { type: 'addContactTag', tag: 'website' },\n ],\n enabled: true,\n }),\n },\n {\n id: 'followUpWonDeal',\n title: 'Follow up a won deal',\n description:\n 'When a deal is won — which makes the contact a Customer on its own — ' +\n 'book a check-in call a week out.',\n /*\n * No stage step (AGL-2641): the win itself floors the contact at\n * `customer` before `dealWon` is announced, so a step setting the stage\n * here would at best repeat the write and at worst move an evangelist\n * back to customer — a SET, which is what the step is, and not the\n * floor the win applies. The recipe books the follow-up and nothing\n * else.\n */\n build: () => ({\n recipe: 'followUpWonDeal',\n name: 'Follow up a won deal',\n trigger: { event: 'dealWon' },\n steps: [\n {\n type: 'createCrmTask',\n title: 'Check in with the new customer',\n kind: 'call',\n dueInDays: 7,\n },\n ],\n enabled: true,\n }),\n },\n {\n id: 'reengageStaleLead',\n title: 'Re-engage a stale lead',\n description:\n 'When a contact becomes a lead: wait a week, and if their stage has ' +\n 'not moved, book a call to bring them back.',\n /*\n * \"Unless the stage moved on\" is the wait's own event: the flow watches\n * for the next stage change on this person and gives up after a week.\n * Resumed by the clock, the run carries `_waitTimedOut`, and the task\n * step's guard reads it; resumed by the event, the field is absent and\n * the task is skipped — the lead was worked, and nobody is told to\n * re-engage somebody who just moved to Sales qualified.\n */\n build: () => ({\n recipe: 'reengageStaleLead',\n name: 'Re-engage a stale lead',\n trigger: {\n event: 'contactStageChanged',\n conditions: [{ field: 'lifecycleStage', op: 'equals', value: 'lead' }],\n combinator: 'and',\n },\n steps: [\n {\n type: 'waitForEvent',\n eventName: 'contactStageChanged',\n timeoutMinutes: STALE_LEAD_WAIT_MINUTES,\n },\n {\n type: 'createCrmTask',\n title: 'Re-engage a lead that has gone quiet',\n kind: 'call',\n dueInDays: 1,\n when: {\n conditions: [{ field: FLOW_TIMED_OUT_FIELD, op: 'notEmpty' }],\n },\n },\n ],\n enabled: true,\n }),\n },\n {\n id: 'tagByForm',\n title: 'Tag by form',\n description:\n 'When a form you pick makes a new contact: tag them with the form’s ' +\n 'name.',\n needs: 'form',\n build: (input) => {\n const form = input?.form\n return {\n recipe: 'tagByForm',\n name: form ? `Tag ${form.name.trim()} submissions` : 'Tag by form',\n trigger: {\n event: 'contactCreated',\n conditions: [{ field: 'formId', op: 'equals', value: form?.id ?? '' }],\n combinator: 'and',\n },\n steps: [\n { type: 'addContactTag', tag: form ? crmRecipeTagForForm(form.name) : '' },\n ],\n enabled: true,\n }\n },\n },\n]\n\n/** The recipe with this id, or null for a string that names none. */\nexport function crmActionRecipe(id: unknown): CrmActionRecipe | null {\n return CRM_ACTION_RECIPES.find((recipe) => recipe.id === id) ?? null\n}\n\n/**\n * The recipe a STORED action came from, read off its document (AGL-2639).\n *\n * Three answers, and the third is the one that matters. A known id: the\n * action was installed from, or begun as, that recipe. `null`: the action\n * was begun blank, or from a recipe this build no longer knows — the\n * editor wrote the field and said \"no recipe\". `undefined`: the document\n * carries no `recipe` field at all, which is every action saved before the\n * stamp existed. Such an action may well have started from a recipe — the\n * menu opened the editor prefilled long before anything recorded it — so a\n * reader that needs to know whether a site has a recipe treats `undefined`\n * as UNKNOWN, never as absent, and never writes a `null` over it.\n */\nexport function hostActionRecipeId(\n action: { recipe?: unknown } | null | undefined,\n): CrmActionRecipeId | null | undefined {\n const stamp = action?.recipe\n if (stamp === undefined) return undefined\n return crmActionRecipe(stamp)?.id ?? null\n}\n\n/**\n * A HostAction as the document at `hosts/{hostId}/actions/{id}` holds it.\n *\n * Every optional trigger key is written OUT — a boolean cap as `false`, a\n * cleared list as `null` — because the editor saves with a merge-set, and\n * a merge keeps whatever key the payload omits: a frequency cap switched\n * off, left out of the payload, would stay on. The legacy single\n * `condition` is always nulled; `conditions` has been canonical since the\n * list shape arrived and a document that carried both would have the\n * reader pick. Everything else is the action, unchanged.\n *\n * `recipe` rides along only when the action SAYS something about it: an\n * id or `null`. An action that carries no stamp (an older document, edited\n * and saved again) keeps carrying none — see {@link hostActionRecipeId}\n * for why an absent stamp must not become a `null` one.\n */\nexport interface HostActionDocument extends HostAction {\n trigger: HostActionTrigger & {\n oncePerVisitor: boolean\n oncePerSession: boolean\n cooldownMinutes: number | null\n everyTime: boolean\n condition: null\n conditions: HostActionTriggerCondition[] | null\n combinator: TriggerCombinator | null\n }\n enabled: boolean\n}\n\nexport function hostActionDocument(action: HostAction): HostActionDocument {\n const { recipe, ...rest } = action\n const trigger = action.trigger\n return {\n ...rest,\n trigger: {\n ...trigger,\n oncePerVisitor: trigger.oncePerVisitor === true,\n oncePerSession: trigger.oncePerSession === true,\n cooldownMinutes:\n Number(trigger.cooldownMinutes) >= 1 ? Number(trigger.cooldownMinutes) : null,\n everyTime: trigger.everyTime === true,\n condition: null,\n conditions: trigger.conditions ?? null,\n combinator: trigger.combinator ?? null,\n },\n enabled: action.enabled !== false,\n ...(recipe !== undefined ? { recipe } : {}),\n }\n}\n\n/**\n * The step list as the visitor's browser may see it.\n *\n * A client step AFTER a wait must never reach the page. The client engine\n * runs its slice of the list immediately, so shipping the whole list would\n * make \"wait three days, then show the popup\" show the popup at once — the\n * delay would appear to work on the server, be ignored in the browser, and\n * the two halves of one authored flow would disagree about when it happened.\n *\n * Truncating rather than filtering: everything past the first wait belongs to\n * a run that has not happened yet, whichever side would have executed it.\n */\nexport function hostActionStepsForClient(\n steps: readonly HostActionStep[] | undefined | null,\n): HostActionStep[] {\n const list = steps ?? []\n const suspendAt = list.findIndex(isFlowSuspendingStep)\n return [...(suspendAt < 0 ? list : list.slice(0, suspendAt))]\n}\n\nexport type HostActionStepType = HostActionStep['type']\n\n/**\n * `hosts/{hostId}/actions/{id}` doc: a site interaction whose steps may be\n * the automation's server steps as well as the platform's client steps.\n */\nexport interface HostAction extends SiteInteraction<HostActionStep> {\n /**\n * The recipe this action was installed from or begun as (AGL-2639), or\n * `null` for one begun blank. Absent on a document from before the stamp\n * existed — read it through {@link hostActionRecipeId}, which keeps the\n * three cases apart.\n */\n recipe?: CrmActionRecipeId | null\n}\n\n/**\n * The shortest and longest a flow may wait.\n *\n * The floor is a minute because the resume beat runs on a minute, so anything\n * under one is a delay the scheduler cannot honor and would only read as\n * imprecision. The ceiling is ninety days: long enough for the win-back that\n * is the longest sequence anybody writes, and short enough that an enrollment\n * is not an unbounded lease on a document. A person waiting inside a flow is\n * storage the merchant is not looking at, and a wait measured in years is\n * indistinguishable from one nobody will ever collect.\n */\nexport const FLOW_WAIT_MIN_MINUTES = 1\nexport const FLOW_WAIT_MAX_MINUTES = 90 * 24 * 60\n\nexport const HOST_ACTION_STEP_LABELS: Record<HostActionStepType, string> = {\n runWorkflow: 'Run a workflow',\n siteAlert: 'Show a site alert',\n customEvent: 'Fire a custom event',\n datasetAppend: 'Write to a dataset',\n webhookPost: 'Send a webhook (Business)',\n showOverlay: 'Show a popup or bar',\n stickyNav: 'Make navigation sticky',\n addClass: 'Add a CSS class',\n toggleClass: 'Toggle a CSS class',\n removeClass: 'Remove a CSS class',\n showElement: 'Show an element',\n hideElement: 'Hide an element',\n toggleElement: 'Show/hide an element',\n openDrawer: 'Open a drawer',\n closeDrawer: 'Close a drawer',\n toggleDrawer: 'Open/close a drawer',\n openMenu: 'Open a menu',\n closeMenu: 'Close a menu',\n toggleMenu: 'Open/close a menu',\n setAttribute: 'Set an ARIA or data attribute',\n removeAttribute: 'Remove an ARIA or data attribute',\n scrollTo: 'Scroll to element',\n playVideo: 'Play a video',\n showHtml: 'Show custom HTML',\n runJs: 'Run custom JS (Business)',\n redirect: 'Redirect the visitor',\n trackGaEvent: 'Track an analytics event',\n sendEmail: 'Send an email',\n notifyAdmins: 'Notify site admins',\n enrollList: 'Enroll in a list',\n updateDataset: 'Update a dataset record',\n assignCampaign: 'Assign to a campaign',\n wait: 'Wait',\n waitForEvent: 'Wait for something to happen',\n exitFlow: 'End the flow here',\n setContactStage: 'Set the contact’s lifecycle stage',\n addContactTag: 'Tag the contact',\n assignContactOwner: 'Assign the contact an owner',\n createCrmTask: 'Create a CRM task',\n logCrmActivity: 'Log a CRM activity',\n}\n\n/** A whole number of minutes inside the wait band. */\nexport function isFlowWaitMinutes(value: unknown): boolean {\n return (\n Number.isInteger(value) &&\n (value as number) >= FLOW_WAIT_MIN_MINUTES &&\n (value as number) <= FLOW_WAIT_MAX_MINUTES\n )\n}\n\n/** True for a custom (non-built-in) event name an action may fire. */\nexport function isCustomEventName(event: string): boolean {\n return (\n !HOST_EVENT_TYPES.includes(event as any) &&\n CUSTOM_EVENT_PATTERN.test(event)\n )\n}\n\n/**\n * Validates an action doc shape; returns a human-readable error or null.\n * Server and console share this so bad steps never persist or run.\n */\nexport function validateHostAction(action: HostAction): string | null {\n if (!action.name?.trim()) return 'Name the action'\n // A stamp is provenance, and provenance naming a recipe that does not\n // exist is a document nothing can read back; `null` and absent both pass.\n if (action.recipe != null && !crmActionRecipe(action.recipe)) {\n return 'Unknown recipe'\n }\n // The trigger, the step guards, the client steps and every declared step's\n // pick are the platform's to check; the server steps are this module's.\n return validateInteraction(action, {\n validateStep: (step, label) => serverStepProblem(step as HostActionStep, label),\n })\n}\n\n/**\n * A server step's own complaint, or null. A `runWorkflow` step's pick is\n * checked with every other declared step's (`interactionSteps` in\n * `plugins.config.json`), by `validateInteraction`.\n */\nfunction serverStepProblem(step: HostActionStep, label: string): string | null {\n if (step.type === 'wait' && !isFlowWaitMinutes(step.delayMinutes)) {\n return `${label}: wait between ${FLOW_WAIT_MIN_MINUTES} minute and ${FLOW_WAIT_MAX_MINUTES} minutes`\n }\n if (step.type === 'waitForEvent') {\n const waited = step.eventName?.trim() ?? ''\n if (\n !waited ||\n (!HOST_EVENT_TYPES.includes(waited as any) && !isCustomEventName(waited))\n ) {\n return `${label}: pick the event to wait for`\n }\n if (!isFlowWaitMinutes(step.timeoutMinutes)) {\n return `${label}: give up after ${FLOW_WAIT_MIN_MINUTES}–${FLOW_WAIT_MAX_MINUTES} minutes`\n }\n }\n if (step.type === 'customEvent') {\n if (!isCustomEventName(step.eventName?.trim() ?? '')) {\n return `${label}: custom event names are 2–40 letters, digits, dashes`\n }\n }\n if (\n step.type === 'datasetAppend' &&\n !step.datasetId?.trim() &&\n !step.datasetName?.trim()\n ) {\n return `${label}: pick a dataset`\n }\n if (\n step.type === 'webhookPost' &&\n !step.webhookId?.trim() &&\n !step.webhookName?.trim()\n ) {\n return `${label}: pick a webhook`\n }\n if (step.type === 'sendEmail') {\n if (!step.subject?.trim()) return `${label}: enter the subject`\n if (!step.body?.trim()) return `${label}: enter the email body`\n }\n if (step.type === 'notifyAdmins' && !step.title?.trim()) {\n return `${label}: enter the notification title`\n }\n if (\n step.type === 'enrollList' &&\n !step.listId?.trim() &&\n !step.listName?.trim()\n ) {\n return `${label}: pick a list`\n }\n if (\n step.type === 'updateDataset' &&\n !step.datasetId?.trim() &&\n !step.datasetName?.trim()\n ) {\n return `${label}: pick a dataset`\n }\n if (\n step.type === 'assignCampaign' &&\n !step.campaignId?.trim() &&\n !step.campaignName?.trim()\n ) {\n return `${label}: pick a campaign`\n }\n // CRM steps (AGL-2605). A stage or a kind outside its vocabulary is\n // refused here rather than stored: the executor treats the value as\n // trusted and would write it into a facet every stage report counts.\n if (\n step.type === 'setContactStage' &&\n !isContactLifecycleStage(step.lifecycleStage)\n ) {\n return `${label}: pick a lifecycle stage`\n }\n if (step.type === 'addContactTag') {\n const tag = step.tag?.trim() ?? ''\n if (!tag) return `${label}: enter the tag`\n if (tag.length > CONTACT_TAG_MAX_LENGTH) {\n return `${label}: tags are at most ${CONTACT_TAG_MAX_LENGTH} characters`\n }\n }\n if (step.type === 'assignContactOwner') {\n const named = Boolean(step.ownerUid?.trim() || step.ownerEmail?.trim())\n if (step.roundRobin === true && named) {\n return `${label}: pick round robin or a member, not both`\n }\n if (\n step.roundRobin !== true &&\n !step.ownerUid?.trim() &&\n !step.ownerEmail?.trim().includes('@')\n ) {\n return `${label}: enter the owner’s email address`\n }\n }\n if (step.type === 'createCrmTask') {\n if (!step.title?.trim()) return `${label}: give the task a title`\n if (!isCrmTaskKind(step.kind)) return `${label}: pick the kind of task`\n if (\n !Number.isInteger(step.dueInDays) ||\n step.dueInDays < 0 ||\n step.dueInDays > CRM_TASK_MAX_DUE_DAYS\n ) {\n return `${label}: due in 0–${CRM_TASK_MAX_DUE_DAYS} days`\n }\n // Optional — but an address that is not one would resolve to nobody at\n // run time, and the task would land unassigned with no word why.\n const assigneeEmail = step.assigneeEmail?.trim() ?? ''\n if (assigneeEmail && !assigneeEmail.includes('@')) {\n return `${label}: enter the assignee’s email address`\n }\n }\n if (step.type === 'logCrmActivity') {\n if (!isCrmActivityKind(step.kind)) {\n return `${label}: pick the kind of activity`\n }\n if (!step.body?.trim()) return `${label}: write what happened`\n }\n return null\n}\n\n/** The most webhooks one site keeps; the site create route enforces it. */\nexport const WEBHOOK_MAX_PER_HOST = 5\n"],"names":["CRM_TASK_MAX_DUE_DAYS","isContactLifecycleStage","isCrmActivityKind","isCrmTaskKind","CUSTOM_EVENT_PATTERN","validateInteraction","HOST_EVENT_TYPES","FLOW_TIMED_OUT_FIELD","FLOW_SUSPENDING_STEP_TYPES","Set","isFlowSuspendingStep","step","has","type","CONTACT_TAG_MAX_LENGTH","CRM_ACTION_RECIPE_IDS","STALE_LEAD_WAIT_MINUTES","crmRecipeTagForForm","formName","trim","slice","CRM_ACTION_RECIPES","id","title","description","build","recipe","name","trigger","event","conditions","field","op","value","combinator","steps","roundRobin","kind","dueInDays","subject","body","tag","enabled","eventName","timeoutMinutes","when","needs","input","form","crmActionRecipe","find","hostActionRecipeId","action","stamp","undefined","hostActionDocument","rest","oncePerVisitor","oncePerSession","cooldownMinutes","Number","everyTime","condition","hostActionStepsForClient","list","suspendAt","findIndex","FLOW_WAIT_MIN_MINUTES","FLOW_WAIT_MAX_MINUTES","HOST_ACTION_STEP_LABELS","runWorkflow","siteAlert","customEvent","datasetAppend","webhookPost","showOverlay","stickyNav","addClass","toggleClass","removeClass","showElement","hideElement","toggleElement","openDrawer","closeDrawer","toggleDrawer","openMenu","closeMenu","toggleMenu","setAttribute","removeAttribute","scrollTo","playVideo","showHtml","runJs","redirect","trackGaEvent","sendEmail","notifyAdmins","enrollList","updateDataset","assignCampaign","wait","waitForEvent","exitFlow","setContactStage","addContactTag","assignContactOwner","createCrmTask","logCrmActivity","isFlowWaitMinutes","isInteger","isCustomEventName","includes","test","validateHostAction","validateStep","label","serverStepProblem","delayMinutes","waited","datasetId","datasetName","webhookId","webhookName","listId","listName","campaignId","campaignName","lifecycleStage","length","named","Boolean","ownerUid","ownerEmail","assigneeEmail","WEBHOOK_MAX_PER_HOST"],"mappings":"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"}