@aglyn/plugins-workflows 1.0.0-beta.221 → 1.0.0-beta.223

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 (101) hide show
  1. package/README.md +22 -14
  2. package/package.json +12 -12
  3. package/src/lib/components/automation-step-fields.component.d.ts +16 -16
  4. package/src/lib/components/automation-step-fields.component.js +146 -12
  5. package/src/lib/components/automation-step-fields.component.js.map +1 -1
  6. package/src/lib/components/automation-trigger-conditions.component.d.ts +25 -3
  7. package/src/lib/components/automation-trigger-conditions.component.js +89 -10
  8. package/src/lib/components/automation-trigger-conditions.component.js.map +1 -1
  9. package/src/lib/components/host-actions-card.component.js +126 -84
  10. package/src/lib/components/host-actions-card.component.js.map +1 -1
  11. package/src/lib/components/host-webhooks-card.component.js +2 -1
  12. package/src/lib/components/host-webhooks-card.component.js.map +1 -1
  13. package/src/lib/components/host-workflows-card.component.js +31 -10
  14. package/src/lib/components/host-workflows-card.component.js.map +1 -1
  15. package/src/lib/components/org-automation-editor.component.d.ts +2 -1
  16. package/src/lib/components/org-automation-editor.component.js +20 -11
  17. package/src/lib/components/org-automation-editor.component.js.map +1 -1
  18. package/src/lib/components/org-automations-card.component.js +2 -1
  19. package/src/lib/components/org-automations-card.component.js.map +1 -1
  20. package/src/lib/components/run-quota-line.component.d.ts +17 -4
  21. package/src/lib/components/run-quota-line.component.js +16 -7
  22. package/src/lib/components/run-quota-line.component.js.map +1 -1
  23. package/src/lib/components/site-org-automations-panel.component.js +2 -1
  24. package/src/lib/components/site-org-automations-panel.component.js.map +1 -1
  25. package/src/lib/components/workflows-console-page.js +18 -7
  26. package/src/lib/components/workflows-console-page.js.map +1 -1
  27. package/src/lib/declarations.d.ts +28 -0
  28. package/src/lib/declarations.js +37 -0
  29. package/src/lib/declarations.js.map +1 -0
  30. package/src/lib/declarations.server.js +17 -0
  31. package/src/lib/declarations.server.js.map +1 -1
  32. package/src/lib/engine/email-merge.d.ts +69 -0
  33. package/src/lib/engine/email-merge.js +98 -0
  34. package/src/lib/engine/email-merge.js.map +1 -0
  35. package/src/lib/engine/run-event-actions.d.ts +35 -10
  36. package/src/lib/engine/run-event-actions.js +256 -369
  37. package/src/lib/engine/run-event-actions.js.map +1 -1
  38. package/src/lib/engine/run-event-automations.d.ts +1 -1
  39. package/src/lib/engine/run-event-automations.js.map +1 -1
  40. package/src/lib/engine/run-event-workflows.d.ts +2 -1
  41. package/src/lib/engine/run-event-workflows.js +71 -30
  42. package/src/lib/engine/run-event-workflows.js.map +1 -1
  43. package/src/lib/engine/run-meter.d.ts +98 -0
  44. package/src/lib/engine/run-meter.js +121 -0
  45. package/src/lib/engine/run-meter.js.map +1 -0
  46. package/src/lib/engine/run-org-automations.d.ts +3 -2
  47. package/src/lib/engine/run-org-automations.js +17 -12
  48. package/src/lib/engine/run-org-automations.js.map +1 -1
  49. package/src/lib/engine/triggered-docs.d.ts +39 -0
  50. package/src/lib/engine/triggered-docs.js +47 -0
  51. package/src/lib/engine/triggered-docs.js.map +1 -0
  52. package/src/lib/engine/workflow-steps.d.ts +1 -1
  53. package/src/lib/engine/workflow-steps.js +3 -2
  54. package/src/lib/engine/workflow-steps.js.map +1 -1
  55. package/src/lib/model/host-actions.d.ts +284 -0
  56. package/src/lib/model/host-actions.js +316 -0
  57. package/src/lib/model/host-actions.js.map +1 -0
  58. package/src/lib/model/org-automations.d.ts +8 -5
  59. package/src/lib/model/org-automations.js +14 -8
  60. package/src/lib/model/org-automations.js.map +1 -1
  61. package/src/lib/model/step-outcomes.d.ts +2 -2
  62. package/src/lib/model/step-outcomes.js +1 -1
  63. package/src/lib/model/step-outcomes.js.map +1 -1
  64. package/src/lib/plugin.js +10 -0
  65. package/src/lib/plugin.js.map +1 -1
  66. package/src/lib/server/action-test-run-route.d.ts +3 -2
  67. package/src/lib/server/action-test-run-route.js +3 -2
  68. package/src/lib/server/action-test-run-route.js.map +1 -1
  69. package/src/lib/server/org-automations-routes.d.ts +42 -1
  70. package/src/lib/server/org-automations-routes.js +120 -72
  71. package/src/lib/server/org-automations-routes.js.map +1 -1
  72. package/src/lib/server-automation-drafts.d.ts +2 -2
  73. package/src/lib/server-automation-drafts.js +11 -7
  74. package/src/lib/server-automation-drafts.js.map +1 -1
  75. package/src/lib/server.js +19 -13
  76. package/src/lib/server.js.map +1 -1
  77. package/src/lib/testing/stand-in-crm-steps.d.ts +45 -0
  78. package/src/lib/testing/stand-in-crm-steps.js +97 -0
  79. package/src/lib/testing/stand-in-crm-steps.js.map +1 -0
  80. package/src/lib/testing/stand-in-dataset-list.js +11 -3
  81. package/src/lib/testing/stand-in-dataset-list.js.map +1 -1
  82. package/src/lib/testing/stand-in-dataset-steps.d.ts +43 -0
  83. package/src/lib/testing/stand-in-dataset-steps.js +65 -0
  84. package/src/lib/testing/stand-in-dataset-steps.js.map +1 -0
  85. package/src/lib/testing/stand-in-person-records.d.ts +35 -0
  86. package/src/lib/testing/stand-in-person-records.js +54 -0
  87. package/src/lib/testing/stand-in-person-records.js.map +1 -0
  88. package/src/lib/testing/stand-in-recipes.d.ts +36 -0
  89. package/src/lib/testing/stand-in-recipes.js +206 -0
  90. package/src/lib/testing/stand-in-recipes.js.map +1 -0
  91. package/src/lib/transfer/org-automations-package.d.ts +54 -0
  92. package/src/lib/transfer/org-automations-package.js +167 -0
  93. package/src/lib/transfer/org-automations-package.js.map +1 -0
  94. package/src/lib/transfer/org-automations-package.server.d.ts +38 -0
  95. package/src/lib/transfer/org-automations-package.server.js +296 -0
  96. package/src/lib/transfer/org-automations-package.server.js.map +1 -0
  97. package/src/lib/usage-axes.js +5 -1
  98. package/src/lib/usage-axes.js.map +1 -1
  99. package/src/lib/engine/crm-action-steps.d.ts +0 -142
  100. package/src/lib/engine/crm-action-steps.js +0 -452
  101. package/src/lib/engine/crm-action-steps.js.map +0 -1
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { registerInteractionRecipes } from "@aglyn/aglyn/plugin-manager/interaction-recipes";
17
+ import { registerPluginRecordListSource } from "@aglyn/aglyn/plugin-manager/plugin-record-lists";
18
+ import { collection, documentId, limit, orderBy, query } from "firebase/firestore";
19
+ /**
20
+ * The CRM's four recipes (AGL-2626), stood in for this plugin's specs — this
21
+ * plugin may not load the CRM, which writes them and registers them through
22
+ * the platform's recipe seam (AGL-3080). Built as the CRM builds them, so the
23
+ * editor is driven with the automations it is really handed; what the CRM's
24
+ * recipes ARE is held in the CRM's own spec, and that each is an automation
25
+ * this plugin accepts in `apps/console/specs/interaction-recipes.spec.ts`.
26
+ */ export const STAND_IN_RECIPES = [
27
+ {
28
+ id: 'welcomeNewLead',
29
+ title: 'Welcome a new lead',
30
+ description: 'When a form makes a new lead: rotate in an owner, book a call for ' + 'tomorrow, send a thank-you, and tag them website.',
31
+ build: ()=>({
32
+ recipe: 'welcomeNewLead',
33
+ name: 'Welcome a new lead',
34
+ trigger: {
35
+ event: 'lead',
36
+ conditions: [
37
+ {
38
+ field: 'formId',
39
+ op: 'notEmpty'
40
+ }
41
+ ],
42
+ combinator: 'and'
43
+ },
44
+ steps: [
45
+ {
46
+ type: 'assignContactOwner',
47
+ roundRobin: true
48
+ },
49
+ {
50
+ type: 'createCrmTask',
51
+ title: 'Call the new lead',
52
+ kind: 'call',
53
+ dueInDays: 1
54
+ },
55
+ {
56
+ type: 'sendEmail',
57
+ subject: 'Thanks for getting in touch',
58
+ body: 'Hi {{firstName|there}},\n\nThanks for reaching out. We have your ' + 'message and will reply to this email address.'
59
+ },
60
+ {
61
+ type: 'addContactTag',
62
+ tag: 'website'
63
+ }
64
+ ],
65
+ enabled: true
66
+ })
67
+ },
68
+ {
69
+ id: 'followUpWonDeal',
70
+ title: 'Follow up a won deal',
71
+ description: 'When a deal is won — which makes the contact a Customer on its own — ' + 'book a check-in call a week out.',
72
+ build: ()=>({
73
+ recipe: 'followUpWonDeal',
74
+ name: 'Follow up a won deal',
75
+ trigger: {
76
+ event: 'dealWon'
77
+ },
78
+ steps: [
79
+ {
80
+ type: 'createCrmTask',
81
+ title: 'Check in with the new customer',
82
+ kind: 'call',
83
+ dueInDays: 7
84
+ }
85
+ ],
86
+ enabled: true
87
+ })
88
+ },
89
+ {
90
+ id: 'reengageStaleLead',
91
+ title: 'Re-engage a stale lead',
92
+ description: 'When a contact becomes a lead: wait a week, and if their stage has ' + 'not moved, book a call to bring them back.',
93
+ build: ()=>({
94
+ recipe: 'reengageStaleLead',
95
+ name: 'Re-engage a stale lead',
96
+ trigger: {
97
+ event: 'contactStageChanged',
98
+ conditions: [
99
+ {
100
+ field: 'lifecycleStage',
101
+ op: 'equals',
102
+ value: 'lead'
103
+ }
104
+ ],
105
+ combinator: 'and'
106
+ },
107
+ steps: [
108
+ {
109
+ type: 'waitForEvent',
110
+ eventName: 'contactStageChanged',
111
+ timeoutMinutes: 7 * 24 * 60
112
+ },
113
+ {
114
+ type: 'createCrmTask',
115
+ title: 'Re-engage a lead that has gone quiet',
116
+ kind: 'call',
117
+ dueInDays: 1,
118
+ when: {
119
+ conditions: [
120
+ {
121
+ field: '_waitTimedOut',
122
+ op: 'notEmpty'
123
+ }
124
+ ]
125
+ }
126
+ }
127
+ ],
128
+ enabled: true
129
+ })
130
+ },
131
+ {
132
+ id: 'tagByForm',
133
+ title: 'Tag by form',
134
+ description: 'When a form you pick makes a new lead or contact: tag them with the form’s name.',
135
+ picks: {
136
+ kind: 'form',
137
+ label: 'Form',
138
+ plural: 'forms',
139
+ prompt: 'Pick the form whose new leads or contacts get the tag.',
140
+ none: 'This site has no forms yet. Add one in the besigner, then come back.'
141
+ },
142
+ build: (input)=>{
143
+ var _ref;
144
+ var _form_facts;
145
+ const form = input == null ? void 0 : input.picked;
146
+ return {
147
+ recipe: 'tagByForm',
148
+ name: form ? `Tag ${form.name.trim()} submissions` : 'Tag by form',
149
+ trigger: {
150
+ // A lead-routed form makes a lead and no contact (AGL-3458).
151
+ event: (form == null ? void 0 : (_form_facts = form.facts) == null ? void 0 : _form_facts['routesLeads']) === true ? 'lead' : 'contactCreated',
152
+ conditions: [
153
+ {
154
+ field: 'formId',
155
+ op: 'equals',
156
+ value: (_ref = form == null ? void 0 : form.id) != null ? _ref : ''
157
+ }
158
+ ],
159
+ combinator: 'and'
160
+ },
161
+ steps: [
162
+ {
163
+ type: 'addContactTag',
164
+ tag: form ? form.name.trim().slice(0, 60) : ''
165
+ }
166
+ ],
167
+ enabled: true
168
+ };
169
+ }
170
+ }
171
+ ];
172
+ /** Registers the stood-in recipes as the CRM's declarations would. */ export function standInRecipes() {
173
+ registerInteractionRecipes(STAND_IN_RECIPES, {
174
+ pluginId: 'crm'
175
+ });
176
+ }
177
+ /**
178
+ * The `form` list source the Forms plugin publishes (AGL-3080), stood in: a
179
+ * site's forms by document id, an archived one left out, a form named by its
180
+ * display name or its id, and whether it files leads shared as its
181
+ * `routesLeads` fact. What the Forms plugin itself answers is held in its own
182
+ * spec.
183
+ */ export function standInFormList() {
184
+ registerPluginRecordListSource('form', {
185
+ query (firestore, request) {
186
+ if (!request.hostId) return null;
187
+ return query(collection(firestore, 'hosts', request.hostId, 'forms'), orderBy(documentId()), limit(request.limit));
188
+ },
189
+ record (id, data) {
190
+ var _data_displayName;
191
+ if (data['archivedAt'] != null) return null;
192
+ const routing = data['routing'];
193
+ return {
194
+ id,
195
+ name: String((_data_displayName = data['displayName']) != null ? _data_displayName : '').trim() || id,
196
+ facts: {
197
+ routesLeads: (routing == null ? void 0 : routing.lead) === true
198
+ }
199
+ };
200
+ }
201
+ }, {
202
+ pluginId: 'forms'
203
+ });
204
+ }
205
+
206
+ //# sourceMappingURL=stand-in-recipes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-recipes.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 InteractionRecipe,\n registerInteractionRecipes,\n} from '@aglyn/aglyn/plugin-manager/interaction-recipes'\nimport { registerPluginRecordListSource } from '@aglyn/aglyn/plugin-manager/plugin-record-lists'\nimport { collection, documentId, limit, orderBy, query } from 'firebase/firestore'\n\n/**\n * The CRM's four recipes (AGL-2626), stood in for this plugin's specs — this\n * plugin may not load the CRM, which writes them and registers them through\n * the platform's recipe seam (AGL-3080). Built as the CRM builds them, so the\n * editor is driven with the automations it is really handed; what the CRM's\n * recipes ARE is held in the CRM's own spec, and that each is an automation\n * this plugin accepts in `apps/console/specs/interaction-recipes.spec.ts`.\n */\nexport const STAND_IN_RECIPES: readonly InteractionRecipe[] = [\n {\n id: 'welcomeNewLead',\n title: 'Welcome a new lead',\n description:\n 'When a form makes a new lead: rotate in an owner, book a call for ' +\n 'tomorrow, send a thank-you, and tag them website.',\n build: () => ({\n recipe: 'welcomeNewLead',\n name: 'Welcome a new lead',\n trigger: {\n event: 'lead',\n conditions: [{ field: 'formId', op: 'notEmpty' }],\n combinator: 'and',\n },\n steps: [\n { type: 'assignContactOwner', roundRobin: true },\n { type: 'createCrmTask', title: 'Call the new lead', kind: 'call', dueInDays: 1 },\n {\n type: 'sendEmail',\n subject: 'Thanks for getting in touch',\n body:\n 'Hi {{firstName|there}},\\n\\nThanks for reaching out. We have your ' +\n 'message and will reply 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 build: () => ({\n recipe: 'followUpWonDeal',\n name: 'Follow up a won deal',\n trigger: { event: 'dealWon' },\n steps: [\n { type: 'createCrmTask', title: 'Check in with the new customer', kind: 'call', dueInDays: 7 },\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 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 { type: 'waitForEvent', eventName: 'contactStageChanged', timeoutMinutes: 7 * 24 * 60 },\n {\n type: 'createCrmTask',\n title: 'Re-engage a lead that has gone quiet',\n kind: 'call',\n dueInDays: 1,\n when: { conditions: [{ field: '_waitTimedOut', op: 'notEmpty' }] },\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 lead or contact: tag them with the form’s name.',\n picks: {\n kind: 'form',\n label: 'Form',\n plural: 'forms',\n prompt: 'Pick the form whose new leads or contacts get the tag.',\n none: 'This site has no forms yet. Add one in the besigner, then come back.',\n },\n build: (input) => {\n const form = input?.picked\n return {\n recipe: 'tagByForm',\n name: form ? `Tag ${form.name.trim()} submissions` : 'Tag by form',\n trigger: {\n // A lead-routed form makes a lead and no contact (AGL-3458).\n event: form?.facts?.['routesLeads'] === true ? 'lead' : 'contactCreated',\n conditions: [{ field: 'formId', op: 'equals', value: form?.id ?? '' }],\n combinator: 'and',\n },\n steps: [{ type: 'addContactTag', tag: form ? form.name.trim().slice(0, 60) : '' }],\n enabled: true,\n }\n },\n },\n]\n\n/** Registers the stood-in recipes as the CRM's declarations would. */\nexport function standInRecipes(): void {\n registerInteractionRecipes(STAND_IN_RECIPES, { pluginId: 'crm' })\n}\n\n/**\n * The `form` list source the Forms plugin publishes (AGL-3080), stood in: a\n * site's forms by document id, an archived one left out, a form named by its\n * display name or its id, and whether it files leads shared as its\n * `routesLeads` fact. What the Forms plugin itself answers is held in its own\n * spec.\n */\nexport function standInFormList(): void {\n registerPluginRecordListSource(\n 'form',\n {\n query(firestore, request) {\n if (!request.hostId) return null\n return query(\n collection(firestore, 'hosts', request.hostId, 'forms'),\n orderBy(documentId()),\n limit(request.limit),\n )\n },\n record(id, data) {\n if (data['archivedAt'] != null) return null\n const routing = data['routing'] as { lead?: unknown } | null | undefined\n return {\n id,\n name: String(data['displayName'] ?? '').trim() || id,\n facts: { routesLeads: routing?.lead === true },\n }\n },\n },\n { pluginId: 'forms' },\n )\n}\n"],"names":["registerInteractionRecipes","registerPluginRecordListSource","collection","documentId","limit","orderBy","query","STAND_IN_RECIPES","id","title","description","build","recipe","name","trigger","event","conditions","field","op","combinator","steps","type","roundRobin","kind","dueInDays","subject","body","tag","enabled","value","eventName","timeoutMinutes","when","picks","label","plural","prompt","none","input","form","picked","trim","facts","slice","standInRecipes","pluginId","standInFormList","firestore","request","hostId","record","data","routing","String","routesLeads","lead"],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { PackageDependency } from '@aglyn/aglyn/data-transfer/package';
18
+ import { type OrgAutomationFields } from '../model/org-automations';
19
+ /** The resource key, and so the kind every automation item carries. */
20
+ export declare const ORG_AUTOMATIONS_TRANSFER_KEY = "workflows.org-automations";
21
+ /** The kinds a step's references are named under. */
22
+ export declare const ORG_AUTOMATION_REFERENCE_KINDS: {
23
+ readonly list: "email.lists";
24
+ readonly campaign: "marketing.campaigns";
25
+ readonly dataset: "data.datasets";
26
+ readonly topic: "email.topics";
27
+ readonly member: "member";
28
+ };
29
+ /** An org automation as a package carries it. */
30
+ export type OrgAutomationPackageContent = Omit<OrgAutomationFields, 'enabled'>;
31
+ /**
32
+ * The package content of a stored automation, or of an incoming item, read
33
+ * by the save route's own reader — so an item the reader refuses is `null`
34
+ * here and a problem at the dry run.
35
+ */
36
+ export declare function orgAutomationPackageContent(source: unknown): OrgAutomationPackageContent | null;
37
+ /** The incoming content as stored, before it is judged: whatever the file holds, shaped like an automation. */
38
+ export declare function rawOrgAutomationContent(source: unknown): OrgAutomationPackageContent;
39
+ export declare function orgAutomationDependencies(content: OrgAutomationPackageContent): PackageDependency[];
40
+ /**
41
+ * The automation with every reference moved through `idMap`. A dropped site
42
+ * leaves the placement; a dropped step reference clears its id and keeps
43
+ * its name (see the block header).
44
+ */
45
+ export declare function remapOrgAutomationIds(content: OrgAutomationPackageContent, idMap: ReadonlyMap<string, string>): OrgAutomationPackageContent;
46
+ export declare const ORG_AUTOMATION_PACKAGE_RULES: readonly [{
47
+ readonly id: "off";
48
+ readonly label: "An imported automation arrives switched off";
49
+ readonly reason: "An automation acts on every site it runs on the moment it is on, so an import never switches one on. One you replace keeps whether it was on.";
50
+ }, {
51
+ readonly id: "pauses";
52
+ readonly label: "Each site’s own pause stays";
53
+ readonly reason: "Pausing an automation is a site’s own decision, so a replace keeps the sites that paused it, and nothing about pausing travels in a package.";
54
+ }];
@@ -0,0 +1,167 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /*==========================================
17
+ * ORG AUTOMATIONS AS PACKAGE ITEMS (AGL-3535).
18
+ *
19
+ * An item is what an org automation does: its name, trigger, steps and
20
+ * the sites it runs on. Never whether it is switched on, which sites
21
+ * paused it, or who wrote it — so one exported and imported back is
22
+ * `identical`, and an import never switches anything on.
23
+ *
24
+ * What it names: its sites (`site`), and what its steps reach — an email
25
+ * list, a campaign, a dataset, a subscription topic, a member who owns or
26
+ * is assigned. A step names a list, a campaign and a dataset by id AND by
27
+ * name, and the engine finds one by its name when the id is empty — so a
28
+ * dropped reference clears the id and keeps the name, and the step finds
29
+ * the workspace's own list of that name when it runs.
30
+ *
31
+ * Pure: the server half (`org-automations-package.server.ts`) reads and
32
+ * writes.
33
+ *=========================================*/ import { _ as _extends } from "@swc/helpers/_/_extends";
34
+ import { remapPackageReference, TRANSFER_SITE_KIND } from "@aglyn/aglyn/data-transfer/package-plan";
35
+ import { hostIdsFromScope, hostScopeToken, ORG_SCOPE_TOKEN } from "@aglyn/aglyn/app-utils/scope-tokens";
36
+ import { readOrgAutomation } from "../model/org-automations.js";
37
+ /** The resource key, and so the kind every automation item carries. */ export const ORG_AUTOMATIONS_TRANSFER_KEY = 'workflows.org-automations';
38
+ /** The kinds a step's references are named under. */ export const ORG_AUTOMATION_REFERENCE_KINDS = {
39
+ list: 'email.lists',
40
+ campaign: 'marketing.campaigns',
41
+ dataset: 'data.datasets',
42
+ topic: 'email.topics',
43
+ member: 'member'
44
+ };
45
+ /** Each step field that names something, with the kind it names. */ const STEP_REFERENCES = [
46
+ {
47
+ field: 'listId',
48
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.list
49
+ },
50
+ {
51
+ field: 'campaignId',
52
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.campaign
53
+ },
54
+ {
55
+ field: 'datasetId',
56
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.dataset
57
+ },
58
+ {
59
+ field: 'topicId',
60
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.topic
61
+ },
62
+ {
63
+ field: 'ownerUid',
64
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.member
65
+ },
66
+ {
67
+ field: 'assigneeUid',
68
+ kind: ORG_AUTOMATION_REFERENCE_KINDS.member
69
+ }
70
+ ];
71
+ /**
72
+ * The package content of a stored automation, or of an incoming item, read
73
+ * by the save route's own reader — so an item the reader refuses is `null`
74
+ * here and a problem at the dry run.
75
+ */ export function orgAutomationPackageContent(source) {
76
+ const read = readOrgAutomation(source);
77
+ if (read.ok === false) return null;
78
+ const { name, trigger, steps, visibleTo } = read.value;
79
+ return {
80
+ name,
81
+ trigger,
82
+ steps,
83
+ visibleTo
84
+ };
85
+ }
86
+ /** The incoming content as stored, before it is judged: whatever the file holds, shaped like an automation. */ export function rawOrgAutomationContent(source) {
87
+ var _raw_name, _raw_trigger;
88
+ const raw = source && typeof source === 'object' ? source : {};
89
+ return {
90
+ name: String((_raw_name = raw.name) != null ? _raw_name : ''),
91
+ trigger: (_raw_trigger = raw.trigger) != null ? _raw_trigger : {
92
+ event: '',
93
+ conditions: null,
94
+ combinator: null
95
+ },
96
+ steps: Array.isArray(raw.steps) ? raw.steps : [],
97
+ visibleTo: Array.isArray(raw.visibleTo) ? raw.visibleTo : []
98
+ };
99
+ }
100
+ export function orgAutomationDependencies(content) {
101
+ var _content_steps;
102
+ const deps = [];
103
+ const seen = new Set();
104
+ const add = (kind, id)=>{
105
+ if (typeof id !== 'string' || !id.trim() || seen.has(`${kind}/${id}`)) return;
106
+ seen.add(`${kind}/${id}`);
107
+ deps.push({
108
+ kind,
109
+ id
110
+ });
111
+ };
112
+ for (const hostId of hostIdsFromScope(content.visibleTo))add(TRANSFER_SITE_KIND, hostId);
113
+ for (const step of (_content_steps = content.steps) != null ? _content_steps : []){
114
+ for (const { field, kind } of STEP_REFERENCES)add(kind, step[field]);
115
+ }
116
+ return deps;
117
+ }
118
+ /**
119
+ * The automation with every reference moved through `idMap`. A dropped site
120
+ * leaves the placement; a dropped step reference clears its id and keeps
121
+ * its name (see the block header).
122
+ */ export function remapOrgAutomationIds(content, idMap) {
123
+ var _content_steps;
124
+ const visibleTo = content.visibleTo.flatMap((token)=>{
125
+ if (token === ORG_SCOPE_TOKEN) return [
126
+ token
127
+ ];
128
+ const [hostId] = hostIdsFromScope([
129
+ token
130
+ ]);
131
+ if (!hostId) return [
132
+ token
133
+ ];
134
+ const mapped = remapPackageReference(idMap, TRANSFER_SITE_KIND, hostId);
135
+ return mapped ? [
136
+ hostScopeToken(mapped)
137
+ ] : [];
138
+ });
139
+ const steps = ((_content_steps = content.steps) != null ? _content_steps : []).map((step)=>{
140
+ const record = _extends({}, step);
141
+ for (const { field, kind } of STEP_REFERENCES){
142
+ var _remapPackageReference;
143
+ const id = record[field];
144
+ if (typeof id !== 'string' || !id) continue;
145
+ record[field] = (_remapPackageReference = remapPackageReference(idMap, kind, id)) != null ? _remapPackageReference : '';
146
+ }
147
+ return record;
148
+ });
149
+ return _extends({}, content, {
150
+ visibleTo: visibleTo,
151
+ steps
152
+ });
153
+ }
154
+ export const ORG_AUTOMATION_PACKAGE_RULES = [
155
+ {
156
+ id: 'off',
157
+ label: 'An imported automation arrives switched off',
158
+ reason: 'An automation acts on every site it runs on the moment it is on, so an import never switches one on. One you replace keeps whether it was on.'
159
+ },
160
+ {
161
+ id: 'pauses',
162
+ label: 'Each site’s own pause stays',
163
+ reason: 'Pausing an automation is a site’s own decision, so a replace keeps the sites that paused it, and nothing about pausing travels in a package.'
164
+ }
165
+ ];
166
+
167
+ //# sourceMappingURL=org-automations-package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/transfer/org-automations-package.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\n/*==========================================\n * ORG AUTOMATIONS AS PACKAGE ITEMS (AGL-3535).\n *\n * An item is what an org automation does: its name, trigger, steps and\n * the sites it runs on. Never whether it is switched on, which sites\n * paused it, or who wrote it — so one exported and imported back is\n * `identical`, and an import never switches anything on.\n *\n * What it names: its sites (`site`), and what its steps reach — an email\n * list, a campaign, a dataset, a subscription topic, a member who owns or\n * is assigned. A step names a list, a campaign and a dataset by id AND by\n * name, and the engine finds one by its name when the id is empty — so a\n * dropped reference clears the id and keeps the name, and the step finds\n * the workspace's own list of that name when it runs.\n *\n * Pure: the server half (`org-automations-package.server.ts`) reads and\n * writes.\n *=========================================*/\n\nimport type { PackageDependency } from '@aglyn/aglyn/data-transfer/package'\nimport { remapPackageReference, TRANSFER_SITE_KIND } from '@aglyn/aglyn/data-transfer/package-plan'\nimport { hostIdsFromScope, hostScopeToken, ORG_SCOPE_TOKEN } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport { readOrgAutomation, type OrgAutomationFields } from '../model/org-automations'\n\n/** The resource key, and so the kind every automation item carries. */\nexport const ORG_AUTOMATIONS_TRANSFER_KEY = 'workflows.org-automations'\n\n/** The kinds a step's references are named under. */\nexport const ORG_AUTOMATION_REFERENCE_KINDS = {\n list: 'email.lists',\n campaign: 'marketing.campaigns',\n dataset: 'data.datasets',\n topic: 'email.topics',\n member: 'member',\n} as const\n\n/** An org automation as a package carries it. */\nexport type OrgAutomationPackageContent = Omit<OrgAutomationFields, 'enabled'>\n\ntype StepRecord = Record<string, unknown>\n\n/** Each step field that names something, with the kind it names. */\nconst STEP_REFERENCES: ReadonlyArray<{ field: string; kind: string }> = [\n { field: 'listId', kind: ORG_AUTOMATION_REFERENCE_KINDS.list },\n { field: 'campaignId', kind: ORG_AUTOMATION_REFERENCE_KINDS.campaign },\n { field: 'datasetId', kind: ORG_AUTOMATION_REFERENCE_KINDS.dataset },\n { field: 'topicId', kind: ORG_AUTOMATION_REFERENCE_KINDS.topic },\n { field: 'ownerUid', kind: ORG_AUTOMATION_REFERENCE_KINDS.member },\n { field: 'assigneeUid', kind: ORG_AUTOMATION_REFERENCE_KINDS.member },\n]\n\n/**\n * The package content of a stored automation, or of an incoming item, read\n * by the save route's own reader — so an item the reader refuses is `null`\n * here and a problem at the dry run.\n */\nexport function orgAutomationPackageContent(source: unknown): OrgAutomationPackageContent | null {\n const read = readOrgAutomation(source)\n if (read.ok === false) return null\n const { name, trigger, steps, visibleTo } = read.value\n return { name, trigger, steps, visibleTo }\n}\n\n/** The incoming content as stored, before it is judged: whatever the file holds, shaped like an automation. */\nexport function rawOrgAutomationContent(source: unknown): OrgAutomationPackageContent {\n const raw = (source && typeof source === 'object' ? source : {}) as Partial<OrgAutomationPackageContent>\n return {\n name: String(raw.name ?? ''),\n trigger: (raw.trigger ?? { event: '', conditions: null, combinator: null }) as OrgAutomationPackageContent['trigger'],\n steps: Array.isArray(raw.steps) ? raw.steps : [],\n visibleTo: Array.isArray(raw.visibleTo) ? raw.visibleTo : [],\n }\n}\n\nexport function orgAutomationDependencies(content: OrgAutomationPackageContent): PackageDependency[] {\n const deps: PackageDependency[] = []\n const seen = new Set<string>()\n const add = (kind: string, id: unknown) => {\n if (typeof id !== 'string' || !id.trim() || seen.has(`${kind}/${id}`)) return\n seen.add(`${kind}/${id}`)\n deps.push({ kind, id })\n }\n for (const hostId of hostIdsFromScope(content.visibleTo)) add(TRANSFER_SITE_KIND, hostId)\n for (const step of content.steps ?? []) {\n for (const { field, kind } of STEP_REFERENCES) add(kind, (step as unknown as StepRecord)[field])\n }\n return deps\n}\n\n/**\n * The automation with every reference moved through `idMap`. A dropped site\n * leaves the placement; a dropped step reference clears its id and keeps\n * its name (see the block header).\n */\nexport function remapOrgAutomationIds(\n content: OrgAutomationPackageContent,\n idMap: ReadonlyMap<string, string>,\n): OrgAutomationPackageContent {\n const visibleTo = content.visibleTo.flatMap((token) => {\n if (token === ORG_SCOPE_TOKEN) return [token]\n const [hostId] = hostIdsFromScope([token])\n if (!hostId) return [token]\n const mapped = remapPackageReference(idMap, TRANSFER_SITE_KIND, hostId)\n return mapped ? [hostScopeToken(mapped)] : []\n })\n const steps = (content.steps ?? []).map((step) => {\n const record = { ...(step as unknown as StepRecord) }\n for (const { field, kind } of STEP_REFERENCES) {\n const id = record[field]\n if (typeof id !== 'string' || !id) continue\n record[field] = remapPackageReference(idMap, kind, id) ?? ''\n }\n return record as unknown as OrgAutomationPackageContent['steps'][number]\n })\n return { ...content, visibleTo: visibleTo as OrgAutomationPackageContent['visibleTo'], steps }\n}\n\nexport const ORG_AUTOMATION_PACKAGE_RULES = [\n {\n id: 'off',\n label: 'An imported automation arrives switched off',\n reason:\n 'An automation acts on every site it runs on the moment it is on, so an import never switches one on. One you replace keeps whether it was on.',\n },\n {\n id: 'pauses',\n label: 'Each site’s own pause stays',\n reason: 'Pausing an automation is a site’s own decision, so a replace keeps the sites that paused it, and nothing about pausing travels in a package.',\n },\n] as const\n"],"names":["remapPackageReference","TRANSFER_SITE_KIND","hostIdsFromScope","hostScopeToken","ORG_SCOPE_TOKEN","readOrgAutomation","ORG_AUTOMATIONS_TRANSFER_KEY","ORG_AUTOMATION_REFERENCE_KINDS","list","campaign","dataset","topic","member","STEP_REFERENCES","field","kind","orgAutomationPackageContent","source","read","ok","name","trigger","steps","visibleTo","value","rawOrgAutomationContent","raw","String","event","conditions","combinator","Array","isArray","orgAutomationDependencies","content","deps","seen","Set","add","id","trim","has","push","hostId","step","remapOrgAutomationIds","idMap","flatMap","token","mapped","map","record","ORG_AUTOMATION_PACKAGE_RULES","label","reason"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type ExistingPackageItem, type TransferReferenceKind } from '@aglyn/aglyn/data-transfer';
18
+ import type { TransferApplyResult, TransferApplyWriter, TransferPackageItemContent, TransferPackageItemWrite, TransferPackageRevertResult, TransferPackageRevertStep, TransferResourceContext } from '@aglyn/aglyn/plugin-manager/plugin-transfer-resources';
19
+ import { type OrgAutomationPackageContent } from './org-automations-package';
20
+ type Firestore = FirebaseFirestore.Firestore;
21
+ export interface OrgAutomationsPackageDeps {
22
+ firestore(): Firestore;
23
+ readOrg(orgId: string): Promise<Record<string, unknown> | null>;
24
+ memberOf(uid: string, orgId: string): Promise<Record<string, unknown> | null>;
25
+ logOrgActivity(orgId: string, uid: string, action: string, target: {
26
+ id: string;
27
+ name: string;
28
+ }): Promise<void>;
29
+ }
30
+ export declare function createOrgAutomationsPackage(deps?: OrgAutomationsPackageDeps): {
31
+ items(ctx: TransferResourceContext): Promise<ExistingPackageItem[]>;
32
+ readItems(ctx: TransferResourceContext, ids: readonly string[]): Promise<TransferPackageItemContent<OrgAutomationPackageContent>[]>;
33
+ problems(ctx: TransferResourceContext, write: TransferPackageItemWrite<OrgAutomationPackageContent>): Promise<string[]>;
34
+ referenceTargets(ctx: TransferResourceContext, kinds: readonly string[]): Promise<TransferReferenceKind[]>;
35
+ writeItems(ctx: TransferResourceContext, items: ReadonlyArray<TransferPackageItemWrite<OrgAutomationPackageContent>>, writer: TransferApplyWriter): Promise<TransferApplyResult>;
36
+ revertItems(ctx: TransferResourceContext, steps: ReadonlyArray<TransferPackageRevertStep<OrgAutomationPackageContent>>): Promise<TransferPackageRevertResult>;
37
+ };
38
+ export {};