@aglyn/plugins-workflows 1.0.0-beta.222 → 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/package.json +12 -12
- package/src/lib/components/automation-step-fields.component.d.ts +16 -2
- package/src/lib/components/automation-step-fields.component.js +53 -2
- package/src/lib/components/automation-step-fields.component.js.map +1 -1
- package/src/lib/components/automation-trigger-conditions.component.d.ts +23 -2
- 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 +64 -30
- package/src/lib/components/host-actions-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 +1 -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/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 +30 -0
- package/src/lib/engine/run-event-actions.js +158 -54
- package/src/lib/engine/run-event-actions.js.map +1 -1
- package/src/lib/engine/run-event-workflows.js +44 -8
- package/src/lib/engine/run-event-workflows.js.map +1 -1
- package/src/lib/engine/run-org-automations.js +3 -1
- 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/model/host-actions.d.ts +53 -0
- package/src/lib/model/host-actions.js +50 -2
- package/src/lib/model/host-actions.js.map +1 -1
- package/src/lib/model/org-automations.d.ts +6 -4
- package/src/lib/model/org-automations.js +8 -5
- package/src/lib/model/org-automations.js.map +1 -1
- package/src/lib/server-automation-drafts.js +2 -1
- package/src/lib/server-automation-drafts.js.map +1 -1
- package/src/lib/testing/stand-in-crm-steps.js +1 -1
- package/src/lib/testing/stand-in-crm-steps.js.map +1 -1
- package/src/lib/testing/stand-in-recipes.d.ts +3 -2
- package/src/lib/testing/stand-in-recipes.js +17 -12
- package/src/lib/testing/stand-in-recipes.js.map +1 -1
|
@@ -27,17 +27,16 @@ import { collection, documentId, limit, orderBy, query } from "firebase/firestor
|
|
|
27
27
|
{
|
|
28
28
|
id: 'welcomeNewLead',
|
|
29
29
|
title: 'Welcome a new lead',
|
|
30
|
-
description: 'When a form makes a new
|
|
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
31
|
build: ()=>({
|
|
32
32
|
recipe: 'welcomeNewLead',
|
|
33
33
|
name: 'Welcome a new lead',
|
|
34
34
|
trigger: {
|
|
35
|
-
event: '
|
|
35
|
+
event: 'lead',
|
|
36
36
|
conditions: [
|
|
37
37
|
{
|
|
38
|
-
field: '
|
|
39
|
-
op: '
|
|
40
|
-
value: 'form'
|
|
38
|
+
field: 'formId',
|
|
39
|
+
op: 'notEmpty'
|
|
41
40
|
}
|
|
42
41
|
],
|
|
43
42
|
combinator: 'and'
|
|
@@ -56,7 +55,7 @@ import { collection, documentId, limit, orderBy, query } from "firebase/firestor
|
|
|
56
55
|
{
|
|
57
56
|
type: 'sendEmail',
|
|
58
57
|
subject: 'Thanks for getting in touch',
|
|
59
|
-
body: '
|
|
58
|
+
body: 'Hi {{firstName|there}},\n\nThanks for reaching out. We have your ' + 'message and will reply to this email address.'
|
|
60
59
|
},
|
|
61
60
|
{
|
|
62
61
|
type: 'addContactTag',
|
|
@@ -132,22 +131,24 @@ import { collection, documentId, limit, orderBy, query } from "firebase/firestor
|
|
|
132
131
|
{
|
|
133
132
|
id: 'tagByForm',
|
|
134
133
|
title: 'Tag by form',
|
|
135
|
-
description: 'When a form you pick makes a new contact: tag them with the form’s name.',
|
|
134
|
+
description: 'When a form you pick makes a new lead or contact: tag them with the form’s name.',
|
|
136
135
|
picks: {
|
|
137
136
|
kind: 'form',
|
|
138
137
|
label: 'Form',
|
|
139
138
|
plural: 'forms',
|
|
140
|
-
prompt: 'Pick the form whose new contacts get the tag.',
|
|
139
|
+
prompt: 'Pick the form whose new leads or contacts get the tag.',
|
|
141
140
|
none: 'This site has no forms yet. Add one in the besigner, then come back.'
|
|
142
141
|
},
|
|
143
142
|
build: (input)=>{
|
|
144
143
|
var _ref;
|
|
144
|
+
var _form_facts;
|
|
145
145
|
const form = input == null ? void 0 : input.picked;
|
|
146
146
|
return {
|
|
147
147
|
recipe: 'tagByForm',
|
|
148
148
|
name: form ? `Tag ${form.name.trim()} submissions` : 'Tag by form',
|
|
149
149
|
trigger: {
|
|
150
|
-
|
|
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',
|
|
151
152
|
conditions: [
|
|
152
153
|
{
|
|
153
154
|
field: 'formId',
|
|
@@ -176,8 +177,9 @@ import { collection, documentId, limit, orderBy, query } from "firebase/firestor
|
|
|
176
177
|
/**
|
|
177
178
|
* The `form` list source the Forms plugin publishes (AGL-3080), stood in: a
|
|
178
179
|
* site's forms by document id, an archived one left out, a form named by its
|
|
179
|
-
* display name or its id
|
|
180
|
-
*
|
|
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.
|
|
181
183
|
*/ export function standInFormList() {
|
|
182
184
|
registerPluginRecordListSource('form', {
|
|
183
185
|
query (firestore, request) {
|
|
@@ -187,10 +189,13 @@ import { collection, documentId, limit, orderBy, query } from "firebase/firestor
|
|
|
187
189
|
record (id, data) {
|
|
188
190
|
var _data_displayName;
|
|
189
191
|
if (data['archivedAt'] != null) return null;
|
|
192
|
+
const routing = data['routing'];
|
|
190
193
|
return {
|
|
191
194
|
id,
|
|
192
195
|
name: String((_data_displayName = data['displayName']) != null ? _data_displayName : '').trim() || id,
|
|
193
|
-
facts: {
|
|
196
|
+
facts: {
|
|
197
|
+
routesLeads: (routing == null ? void 0 : routing.lead) === true
|
|
198
|
+
}
|
|
194
199
|
};
|
|
195
200
|
}
|
|
196
201
|
}, {
|
|
@@ -1 +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
|
|
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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"}
|