@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.
- package/README.md +22 -14
- package/package.json +12 -12
- package/src/lib/components/automation-step-fields.component.d.ts +16 -16
- package/src/lib/components/automation-step-fields.component.js +146 -12
- package/src/lib/components/automation-step-fields.component.js.map +1 -1
- package/src/lib/components/automation-trigger-conditions.component.d.ts +25 -3
- package/src/lib/components/automation-trigger-conditions.component.js +89 -10
- package/src/lib/components/automation-trigger-conditions.component.js.map +1 -1
- package/src/lib/components/host-actions-card.component.js +126 -84
- package/src/lib/components/host-actions-card.component.js.map +1 -1
- package/src/lib/components/host-webhooks-card.component.js +2 -1
- package/src/lib/components/host-webhooks-card.component.js.map +1 -1
- package/src/lib/components/host-workflows-card.component.js +31 -10
- package/src/lib/components/host-workflows-card.component.js.map +1 -1
- package/src/lib/components/org-automation-editor.component.d.ts +2 -1
- package/src/lib/components/org-automation-editor.component.js +20 -11
- package/src/lib/components/org-automation-editor.component.js.map +1 -1
- package/src/lib/components/org-automations-card.component.js +2 -1
- package/src/lib/components/org-automations-card.component.js.map +1 -1
- package/src/lib/components/run-quota-line.component.d.ts +17 -4
- package/src/lib/components/run-quota-line.component.js +16 -7
- package/src/lib/components/run-quota-line.component.js.map +1 -1
- package/src/lib/components/site-org-automations-panel.component.js +2 -1
- package/src/lib/components/site-org-automations-panel.component.js.map +1 -1
- package/src/lib/components/workflows-console-page.js +18 -7
- package/src/lib/components/workflows-console-page.js.map +1 -1
- package/src/lib/declarations.d.ts +28 -0
- package/src/lib/declarations.js +37 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/declarations.server.js +17 -0
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/engine/email-merge.d.ts +69 -0
- package/src/lib/engine/email-merge.js +98 -0
- package/src/lib/engine/email-merge.js.map +1 -0
- package/src/lib/engine/run-event-actions.d.ts +35 -10
- package/src/lib/engine/run-event-actions.js +256 -369
- package/src/lib/engine/run-event-actions.js.map +1 -1
- package/src/lib/engine/run-event-automations.d.ts +1 -1
- package/src/lib/engine/run-event-automations.js.map +1 -1
- package/src/lib/engine/run-event-workflows.d.ts +2 -1
- package/src/lib/engine/run-event-workflows.js +71 -30
- package/src/lib/engine/run-event-workflows.js.map +1 -1
- package/src/lib/engine/run-meter.d.ts +98 -0
- package/src/lib/engine/run-meter.js +121 -0
- package/src/lib/engine/run-meter.js.map +1 -0
- package/src/lib/engine/run-org-automations.d.ts +3 -2
- package/src/lib/engine/run-org-automations.js +17 -12
- package/src/lib/engine/run-org-automations.js.map +1 -1
- package/src/lib/engine/triggered-docs.d.ts +39 -0
- package/src/lib/engine/triggered-docs.js +47 -0
- package/src/lib/engine/triggered-docs.js.map +1 -0
- package/src/lib/engine/workflow-steps.d.ts +1 -1
- package/src/lib/engine/workflow-steps.js +3 -2
- package/src/lib/engine/workflow-steps.js.map +1 -1
- package/src/lib/model/host-actions.d.ts +284 -0
- package/src/lib/model/host-actions.js +316 -0
- package/src/lib/model/host-actions.js.map +1 -0
- package/src/lib/model/org-automations.d.ts +8 -5
- package/src/lib/model/org-automations.js +14 -8
- package/src/lib/model/org-automations.js.map +1 -1
- package/src/lib/model/step-outcomes.d.ts +2 -2
- package/src/lib/model/step-outcomes.js +1 -1
- package/src/lib/model/step-outcomes.js.map +1 -1
- package/src/lib/plugin.js +10 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/action-test-run-route.d.ts +3 -2
- package/src/lib/server/action-test-run-route.js +3 -2
- package/src/lib/server/action-test-run-route.js.map +1 -1
- package/src/lib/server/org-automations-routes.d.ts +42 -1
- package/src/lib/server/org-automations-routes.js +120 -72
- package/src/lib/server/org-automations-routes.js.map +1 -1
- package/src/lib/server-automation-drafts.d.ts +2 -2
- package/src/lib/server-automation-drafts.js +11 -7
- package/src/lib/server-automation-drafts.js.map +1 -1
- package/src/lib/server.js +19 -13
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/stand-in-crm-steps.d.ts +45 -0
- package/src/lib/testing/stand-in-crm-steps.js +97 -0
- package/src/lib/testing/stand-in-crm-steps.js.map +1 -0
- package/src/lib/testing/stand-in-dataset-list.js +11 -3
- package/src/lib/testing/stand-in-dataset-list.js.map +1 -1
- package/src/lib/testing/stand-in-dataset-steps.d.ts +43 -0
- package/src/lib/testing/stand-in-dataset-steps.js +65 -0
- package/src/lib/testing/stand-in-dataset-steps.js.map +1 -0
- package/src/lib/testing/stand-in-person-records.d.ts +35 -0
- package/src/lib/testing/stand-in-person-records.js +54 -0
- package/src/lib/testing/stand-in-person-records.js.map +1 -0
- package/src/lib/testing/stand-in-recipes.d.ts +36 -0
- package/src/lib/testing/stand-in-recipes.js +206 -0
- package/src/lib/testing/stand-in-recipes.js.map +1 -0
- package/src/lib/transfer/org-automations-package.d.ts +54 -0
- package/src/lib/transfer/org-automations-package.js +167 -0
- package/src/lib/transfer/org-automations-package.js.map +1 -0
- package/src/lib/transfer/org-automations-package.server.d.ts +38 -0
- package/src/lib/transfer/org-automations-package.server.js +296 -0
- package/src/lib/transfer/org-automations-package.server.js.map +1 -0
- package/src/lib/usage-axes.js +5 -1
- package/src/lib/usage-axes.js.map +1 -1
- package/src/lib/engine/crm-action-steps.d.ts +0 -142
- package/src/lib/engine/crm-action-steps.js +0 -452
- 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 {};
|