@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,45 @@
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 ServerStepRequest } from '@aglyn/aglyn/plugin-manager/plugin-server-steps';
18
+ /** The contact an event names, as the spec's own Firestore double holds it. */
19
+ export interface CrmContactDouble {
20
+ id: string;
21
+ update(patch: Record<string, unknown>): Promise<unknown>;
22
+ }
23
+ /** Where the stand-in finds the person and which site facet it writes. */
24
+ export interface CrmStepsDouble {
25
+ /** The contact the event names, or `null` for nobody the site can see. */
26
+ contact(request: ServerStepRequest): Promise<CrmContactDouble | null>;
27
+ /** The consent group whose facet the site writes. */
28
+ groupId: string;
29
+ }
30
+ /** The step types the CRM declares under `serverSteps`. */
31
+ export declare const STAND_IN_CRM_STEP_TYPES: readonly ["setContactStage", "addContactTag", "assignContactOwner", "createCrmTask", "logCrmActivity"];
32
+ /**
33
+ * The CRM steps the CRM runs for this engine (AGL-3080), stood in for this
34
+ * plugin's specs — this plugin may not load the CRM. Over the spec's own
35
+ * Firestore double it does what the owner's executor does for the shapes these
36
+ * specs store: it finds the contact the event names, writes a stage or a tag
37
+ * inside the site's facet, answers the run history's detail, and answers a
38
+ * stage that moved as the `contactStageChanged` event for the engine to raise.
39
+ * An owner, a task and an activity are answered by their detail alone.
40
+ *
41
+ * Owners, tasks, scopes, the plan gate and the activity ceiling are the CRM's
42
+ * own spec's (`automation-steps.spec.ts`), and the real pair runs together in
43
+ * `apps/console/specs/crm-automation-steps.spec.ts`.
44
+ */
45
+ export declare function standInCrmSteps(double: CrmStepsDouble): () => void;
@@ -0,0 +1,97 @@
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 { registerServerStepExecutor } from "@aglyn/aglyn/plugin-manager/plugin-server-steps";
17
+ import { FieldValue } from "firebase-admin/firestore";
18
+ /** The step types the CRM declares under `serverSteps`. */ export const STAND_IN_CRM_STEP_TYPES = [
19
+ 'setContactStage',
20
+ 'addContactTag',
21
+ 'assignContactOwner',
22
+ 'createCrmTask',
23
+ 'logCrmActivity'
24
+ ];
25
+ const capitalized = (word)=>word.charAt(0).toUpperCase() + word.slice(1);
26
+ /**
27
+ * The CRM steps the CRM runs for this engine (AGL-3080), stood in for this
28
+ * plugin's specs — this plugin may not load the CRM. Over the spec's own
29
+ * Firestore double it does what the owner's executor does for the shapes these
30
+ * specs store: it finds the contact the event names, writes a stage or a tag
31
+ * inside the site's facet, answers the run history's detail, and answers a
32
+ * stage that moved as the `contactStageChanged` event for the engine to raise.
33
+ * An owner, a task and an activity are answered by their detail alone.
34
+ *
35
+ * Owners, tasks, scopes, the plan gate and the activity ceiling are the CRM's
36
+ * own spec's (`automation-steps.spec.ts`), and the real pair runs together in
37
+ * `apps/console/specs/crm-automation-steps.spec.ts`.
38
+ */ export function standInCrmSteps(double) {
39
+ return registerServerStepExecutor(STAND_IN_CRM_STEP_TYPES, async (request)=>{
40
+ var _step_title, _step_kind;
41
+ const step = request.step;
42
+ const contact = await double.contact(request);
43
+ if (!contact) {
44
+ var _ref, _request_payload_contactId;
45
+ const named = String((_ref = (_request_payload_contactId = request.payload['contactId']) != null ? _request_payload_contactId : request.payload['email']) != null ? _ref : '');
46
+ return {
47
+ error: `no contact or lead this site can see for ${named}`
48
+ };
49
+ }
50
+ const facet = (field)=>`facets.${double.groupId}.${field}`;
51
+ if (step.type === 'setContactStage') {
52
+ var _step_lifecycleStage;
53
+ const stage = String((_step_lifecycleStage = step['lifecycleStage']) != null ? _step_lifecycleStage : '');
54
+ await contact.update({
55
+ [facet('lifecycleStage')]: stage,
56
+ updatedAt: FieldValue.serverTimestamp()
57
+ });
58
+ return {
59
+ detail: capitalized(stage),
60
+ emit: {
61
+ event: 'contactStageChanged',
62
+ payload: {
63
+ contactId: contact.id,
64
+ lifecycleStage: stage
65
+ }
66
+ }
67
+ };
68
+ }
69
+ if (step.type === 'addContactTag') {
70
+ var _step_tag;
71
+ const tag = String((_step_tag = step['tag']) != null ? _step_tag : '').trim();
72
+ await contact.update({
73
+ [facet('tags')]: FieldValue.arrayUnion(tag),
74
+ updatedAt: FieldValue.serverTimestamp()
75
+ });
76
+ return {
77
+ detail: tag
78
+ };
79
+ }
80
+ if (step.type === 'assignContactOwner') {
81
+ var _ref1, _step_ownerEmail;
82
+ return {
83
+ detail: step['roundRobin'] === true ? 'round robin' : String((_ref1 = (_step_ownerEmail = step['ownerEmail']) != null ? _step_ownerEmail : step['ownerUid']) != null ? _ref1 : '')
84
+ };
85
+ }
86
+ if (step.type === 'createCrmTask') return {
87
+ detail: String((_step_title = step['title']) != null ? _step_title : '').slice(0, 60)
88
+ };
89
+ return {
90
+ detail: String((_step_kind = step['kind']) != null ? _step_kind : '')
91
+ };
92
+ }, {
93
+ pluginId: 'crm'
94
+ });
95
+ }
96
+
97
+ //# sourceMappingURL=stand-in-crm-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-crm-steps.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 registerServerStepExecutor,\n type ServerStepRequest,\n} from '@aglyn/aglyn/plugin-manager/plugin-server-steps'\nimport { FieldValue } from 'firebase-admin/firestore'\n\n/** The contact an event names, as the spec's own Firestore double holds it. */\nexport interface CrmContactDouble {\n id: string\n update(patch: Record<string, unknown>): Promise<unknown>\n}\n\n/** Where the stand-in finds the person and which site facet it writes. */\nexport interface CrmStepsDouble {\n /** The contact the event names, or `null` for nobody the site can see. */\n contact(request: ServerStepRequest): Promise<CrmContactDouble | null>\n /** The consent group whose facet the site writes. */\n groupId: string\n}\n\n/** The step types the CRM declares under `serverSteps`. */\nexport const STAND_IN_CRM_STEP_TYPES = [\n 'setContactStage',\n 'addContactTag',\n 'assignContactOwner',\n 'createCrmTask',\n 'logCrmActivity',\n] as const\n\nconst capitalized = (word: string) => word.charAt(0).toUpperCase() + word.slice(1)\n\n/**\n * The CRM steps the CRM runs for this engine (AGL-3080), stood in for this\n * plugin's specs — this plugin may not load the CRM. Over the spec's own\n * Firestore double it does what the owner's executor does for the shapes these\n * specs store: it finds the contact the event names, writes a stage or a tag\n * inside the site's facet, answers the run history's detail, and answers a\n * stage that moved as the `contactStageChanged` event for the engine to raise.\n * An owner, a task and an activity are answered by their detail alone.\n *\n * Owners, tasks, scopes, the plan gate and the activity ceiling are the CRM's\n * own spec's (`automation-steps.spec.ts`), and the real pair runs together in\n * `apps/console/specs/crm-automation-steps.spec.ts`.\n */\nexport function standInCrmSteps(double: CrmStepsDouble): () => void {\n return registerServerStepExecutor(\n STAND_IN_CRM_STEP_TYPES,\n async (request) => {\n const step = request.step as Record<string, unknown> & { type: string }\n const contact = await double.contact(request)\n if (!contact) {\n const named = String(request.payload['contactId'] ?? request.payload['email'] ?? '')\n return { error: `no contact or lead this site can see for ${named}` }\n }\n const facet = (field: string) => `facets.${double.groupId}.${field}`\n if (step.type === 'setContactStage') {\n const stage = String(step['lifecycleStage'] ?? '')\n await contact.update({\n [facet('lifecycleStage')]: stage,\n updatedAt: FieldValue.serverTimestamp(),\n })\n return {\n detail: capitalized(stage),\n emit: {\n event: 'contactStageChanged',\n payload: { contactId: contact.id, lifecycleStage: stage },\n },\n }\n }\n if (step.type === 'addContactTag') {\n const tag = String(step['tag'] ?? '').trim()\n await contact.update({\n [facet('tags')]: FieldValue.arrayUnion(tag),\n updatedAt: FieldValue.serverTimestamp(),\n })\n return { detail: tag }\n }\n if (step.type === 'assignContactOwner') {\n return { detail: step['roundRobin'] === true ? 'round robin' : String(step['ownerEmail'] ?? step['ownerUid'] ?? '') }\n }\n if (step.type === 'createCrmTask') return { detail: String(step['title'] ?? '').slice(0, 60) }\n return { detail: String(step['kind'] ?? '') }\n },\n { pluginId: 'crm' },\n )\n}\n"],"names":["registerServerStepExecutor","FieldValue","STAND_IN_CRM_STEP_TYPES","capitalized","word","charAt","toUpperCase","slice","standInCrmSteps","double","request","step","contact","named","String","payload","error","facet","field","groupId","type","stage","update","updatedAt","serverTimestamp","detail","emit","event","contactId","id","lifecycleStage","tag","trim","arrayUnion","pluginId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,0BAA0B,QAErB,kDAAiD;AACxD,SAASC,UAAU,QAAQ,2BAA0B;AAgBrD,yDAAyD,GACzD,OAAO,MAAMC,0BAA0B;IACrC;IACA;IACA;IACA;IACA;CACD,CAAS;AAEV,MAAMC,cAAc,CAACC,OAAiBA,KAAKC,MAAM,CAAC,GAAGC,WAAW,KAAKF,KAAKG,KAAK,CAAC;AAEhF;;;;;;;;;;;;CAYC,GACD,OAAO,SAASC,gBAAgBC,MAAsB;IACpD,OAAOT,2BACLE,yBACA,OAAOQ;YAiCsDC,aACnCA;QAjCxB,MAAMA,OAAOD,QAAQC,IAAI;QACzB,MAAMC,UAAU,MAAMH,OAAOG,OAAO,CAACF;QACrC,IAAI,CAACE,SAAS;gBACSF,MAAAA;YAArB,MAAMG,QAAQC,QAAOJ,QAAAA,6BAAAA,QAAQK,OAAO,CAAC,YAAY,YAA5BL,6BAAgCA,QAAQK,OAAO,CAAC,QAAQ,YAAxDL,OAA4D;YACjF,OAAO;gBAAEM,OAAO,CAAC,yCAAyC,EAAEH,OAAO;YAAC;QACtE;QACA,MAAMI,QAAQ,CAACC,QAAkB,CAAC,OAAO,EAAET,OAAOU,OAAO,CAAC,CAAC,EAAED,OAAO;QACpE,IAAIP,KAAKS,IAAI,KAAK,mBAAmB;gBACdT;YAArB,MAAMU,QAAQP,QAAOH,uBAAAA,IAAI,CAAC,iBAAiB,YAAtBA,uBAA0B;YAC/C,MAAMC,QAAQU,MAAM,CAAC;gBACnB,CAACL,MAAM,kBAAkB,EAAEI;gBAC3BE,WAAWtB,WAAWuB,eAAe;YACvC;YACA,OAAO;gBACLC,QAAQtB,YAAYkB;gBACpBK,MAAM;oBACJC,OAAO;oBACPZ,SAAS;wBAAEa,WAAWhB,QAAQiB,EAAE;wBAAEC,gBAAgBT;oBAAM;gBAC1D;YACF;QACF;QACA,IAAIV,KAAKS,IAAI,KAAK,iBAAiB;gBACdT;YAAnB,MAAMoB,MAAMjB,QAAOH,YAAAA,IAAI,CAAC,MAAM,YAAXA,YAAe,IAAIqB,IAAI;YAC1C,MAAMpB,QAAQU,MAAM,CAAC;gBACnB,CAACL,MAAM,QAAQ,EAAEhB,WAAWgC,UAAU,CAACF;gBACvCR,WAAWtB,WAAWuB,eAAe;YACvC;YACA,OAAO;gBAAEC,QAAQM;YAAI;QACvB;QACA,IAAIpB,KAAKS,IAAI,KAAK,sBAAsB;gBACgCT,OAAAA;YAAtE,OAAO;gBAAEc,QAAQd,IAAI,CAAC,aAAa,KAAK,OAAO,gBAAgBG,QAAOH,SAAAA,mBAAAA,IAAI,CAAC,aAAa,YAAlBA,mBAAsBA,IAAI,CAAC,WAAW,YAAtCA,QAA0C;YAAI;QACtH;QACA,IAAIA,KAAKS,IAAI,KAAK,iBAAiB,OAAO;YAAEK,QAAQX,QAAOH,cAAAA,IAAI,CAAC,QAAQ,YAAbA,cAAiB,IAAIJ,KAAK,CAAC,GAAG;QAAI;QAC7F,OAAO;YAAEkB,QAAQX,QAAOH,aAAAA,IAAI,CAAC,OAAO,YAAZA,aAAgB;QAAI;IAC9C,GACA;QAAEuB,UAAU;IAAM;AAEtB"}
@@ -13,11 +13,19 @@
13
13
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
- */ import { datasetDisplayName } from "@aglyn/aglyn/app-utils/datasets";
17
- import { scopeTokensForHost } from "@aglyn/aglyn/app-utils/scope-tokens";
16
+ */ import { scopeTokensForHost } from "@aglyn/aglyn/app-utils/scope-tokens";
18
17
  import { registerPluginRecordListSource } from "@aglyn/aglyn/plugin-manager/plugin-record-lists";
19
18
  import { unregisterPluginServices } from "@aglyn/aglyn/plugin-manager/plugin-services";
20
19
  import { collection, documentId, limit, orderBy, query, where } from "firebase/firestore";
20
+ /** A dataset's name as the Data page shows it: its display name, else its legacy name. */ function datasetName(data) {
21
+ for (const candidate of [
22
+ data['displayName'],
23
+ data['name']
24
+ ]){
25
+ if (typeof candidate === 'string' && candidate.trim()) return candidate.trim();
26
+ }
27
+ return '';
28
+ }
21
29
  /**
22
30
  * The `dataset` list source the plugin that keeps the workspace's datasets
23
31
  * publishes (AGL-3080), stood in for this plugin's specs — this plugin may
@@ -37,7 +45,7 @@ import { collection, documentId, limit, orderBy, query, where } from "firebase/f
37
45
  if (!data || data['deletedAt'] != null) return null;
38
46
  return {
39
47
  id,
40
- name: datasetDisplayName(data) || id,
48
+ name: datasetName(data) || id,
41
49
  facts: {
42
50
  fields: [],
43
51
  visibleTo: Array.isArray(data['visibleTo']) ? data['visibleTo'] : []
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-dataset-list.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 { datasetDisplayName } from '@aglyn/aglyn/app-utils/datasets'\nimport { scopeTokensForHost } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport { registerPluginRecordListSource } from '@aglyn/aglyn/plugin-manager/plugin-record-lists'\nimport { unregisterPluginServices } from '@aglyn/aglyn/plugin-manager/plugin-services'\nimport { collection, documentId, limit, orderBy, query, where } from 'firebase/firestore'\n\n/**\n * The `dataset` list source the plugin that keeps the workspace's datasets\n * publishes (AGL-3080), stood in for this plugin's specs — this plugin may\n * not load the data plugin. It builds the query that plugin's\n * `dataset-record-list.ts` builds (a site's answer narrowed by its scope\n * tokens, ordered by document id) from whatever `firebase/firestore` the spec\n * stages, and reads a row as a live dataset named as the Data page names it.\n * What the data plugin itself answers is held in its own spec.\n */\nexport function standInDatasetList(): void {\n registerPluginRecordListSource(\n 'dataset',\n {\n query(firestore, request) {\n if (!request.orgId) return null\n const datasets = collection(firestore, 'orgs', request.orgId, 'datasets')\n return request.hostId\n ? query(\n datasets,\n where('visibleTo', 'array-contains-any', scopeTokensForHost(request.hostId)),\n orderBy(documentId()),\n limit(request.limit),\n )\n : query(datasets, orderBy(documentId()), limit(request.limit))\n },\n record(id, data) {\n if (!data || data['deletedAt'] != null) return null\n return {\n id,\n name: datasetDisplayName(data) || id,\n facts: { fields: [], visibleTo: Array.isArray(data['visibleTo']) ? data['visibleTo'] : [] },\n }\n },\n },\n { pluginId: 'data' },\n )\n}\n\n/** Forgets it, so a spec can ask what happens where no plugin keeps datasets. */\nexport function removeStandInDatasetList(): void {\n unregisterPluginServices('data')\n}\n"],"names":["datasetDisplayName","scopeTokensForHost","registerPluginRecordListSource","unregisterPluginServices","collection","documentId","limit","orderBy","query","where","standInDatasetList","firestore","request","orgId","datasets","hostId","record","id","data","name","facts","fields","visibleTo","Array","isArray","pluginId","removeStandInDatasetList"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,kBAAkB,QAAQ,kCAAiC;AACpE,SAASC,kBAAkB,QAAQ,sCAAqC;AACxE,SAASC,8BAA8B,QAAQ,kDAAiD;AAChG,SAASC,wBAAwB,QAAQ,8CAA6C;AACtF,SAASC,UAAU,EAAEC,UAAU,EAAEC,KAAK,EAAEC,OAAO,EAAEC,KAAK,EAAEC,KAAK,QAAQ,qBAAoB;AAEzF;;;;;;;;CAQC,GACD,OAAO,SAASC;IACdR,+BACE,WACA;QACEM,OAAMG,SAAS,EAAEC,OAAO;YACtB,IAAI,CAACA,QAAQC,KAAK,EAAE,OAAO;YAC3B,MAAMC,WAAWV,WAAWO,WAAW,QAAQC,QAAQC,KAAK,EAAE;YAC9D,OAAOD,QAAQG,MAAM,GACjBP,MACEM,UACAL,MAAM,aAAa,sBAAsBR,mBAAmBW,QAAQG,MAAM,IAC1ER,QAAQF,eACRC,MAAMM,QAAQN,KAAK,KAErBE,MAAMM,UAAUP,QAAQF,eAAeC,MAAMM,QAAQN,KAAK;QAChE;QACAU,QAAOC,EAAE,EAAEC,IAAI;YACb,IAAI,CAACA,QAAQA,IAAI,CAAC,YAAY,IAAI,MAAM,OAAO;YAC/C,OAAO;gBACLD;gBACAE,MAAMnB,mBAAmBkB,SAASD;gBAClCG,OAAO;oBAAEC,QAAQ,EAAE;oBAAEC,WAAWC,MAAMC,OAAO,CAACN,IAAI,CAAC,YAAY,IAAIA,IAAI,CAAC,YAAY,GAAG,EAAE;gBAAC;YAC5F;QACF;IACF,GACA;QAAEO,UAAU;IAAO;AAEvB;AAEA,+EAA+E,GAC/E,OAAO,SAASC;IACdvB,yBAAyB;AAC3B"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-dataset-list.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 { scopeTokensForHost } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport { registerPluginRecordListSource } from '@aglyn/aglyn/plugin-manager/plugin-record-lists'\nimport { unregisterPluginServices } from '@aglyn/aglyn/plugin-manager/plugin-services'\nimport { collection, documentId, limit, orderBy, query, where } from 'firebase/firestore'\n\n/** A dataset's name as the Data page shows it: its display name, else its legacy name. */\nfunction datasetName(data: Readonly<Record<string, unknown>>): string {\n for (const candidate of [data['displayName'], data['name']]) {\n if (typeof candidate === 'string' && candidate.trim()) return candidate.trim()\n }\n return ''\n}\n\n/**\n * The `dataset` list source the plugin that keeps the workspace's datasets\n * publishes (AGL-3080), stood in for this plugin's specs — this plugin may\n * not load the data plugin. It builds the query that plugin's\n * `dataset-record-list.ts` builds (a site's answer narrowed by its scope\n * tokens, ordered by document id) from whatever `firebase/firestore` the spec\n * stages, and reads a row as a live dataset named as the Data page names it.\n * What the data plugin itself answers is held in its own spec.\n */\nexport function standInDatasetList(): void {\n registerPluginRecordListSource(\n 'dataset',\n {\n query(firestore, request) {\n if (!request.orgId) return null\n const datasets = collection(firestore, 'orgs', request.orgId, 'datasets')\n return request.hostId\n ? query(\n datasets,\n where('visibleTo', 'array-contains-any', scopeTokensForHost(request.hostId)),\n orderBy(documentId()),\n limit(request.limit),\n )\n : query(datasets, orderBy(documentId()), limit(request.limit))\n },\n record(id, data) {\n if (!data || data['deletedAt'] != null) return null\n return {\n id,\n name: datasetName(data) || id,\n facts: { fields: [], visibleTo: Array.isArray(data['visibleTo']) ? data['visibleTo'] : [] },\n }\n },\n },\n { pluginId: 'data' },\n )\n}\n\n/** Forgets it, so a spec can ask what happens where no plugin keeps datasets. */\nexport function removeStandInDatasetList(): void {\n unregisterPluginServices('data')\n}\n"],"names":["scopeTokensForHost","registerPluginRecordListSource","unregisterPluginServices","collection","documentId","limit","orderBy","query","where","datasetName","data","candidate","trim","standInDatasetList","firestore","request","orgId","datasets","hostId","record","id","name","facts","fields","visibleTo","Array","isArray","pluginId","removeStandInDatasetList"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,kBAAkB,QAAQ,sCAAqC;AACxE,SAASC,8BAA8B,QAAQ,kDAAiD;AAChG,SAASC,wBAAwB,QAAQ,8CAA6C;AACtF,SAASC,UAAU,EAAEC,UAAU,EAAEC,KAAK,EAAEC,OAAO,EAAEC,KAAK,EAAEC,KAAK,QAAQ,qBAAoB;AAEzF,wFAAwF,GACxF,SAASC,YAAYC,IAAuC;IAC1D,KAAK,MAAMC,aAAa;QAACD,IAAI,CAAC,cAAc;QAAEA,IAAI,CAAC,OAAO;KAAC,CAAE;QAC3D,IAAI,OAAOC,cAAc,YAAYA,UAAUC,IAAI,IAAI,OAAOD,UAAUC,IAAI;IAC9E;IACA,OAAO;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASC;IACdZ,+BACE,WACA;QACEM,OAAMO,SAAS,EAAEC,OAAO;YACtB,IAAI,CAACA,QAAQC,KAAK,EAAE,OAAO;YAC3B,MAAMC,WAAWd,WAAWW,WAAW,QAAQC,QAAQC,KAAK,EAAE;YAC9D,OAAOD,QAAQG,MAAM,GACjBX,MACEU,UACAT,MAAM,aAAa,sBAAsBR,mBAAmBe,QAAQG,MAAM,IAC1EZ,QAAQF,eACRC,MAAMU,QAAQV,KAAK,KAErBE,MAAMU,UAAUX,QAAQF,eAAeC,MAAMU,QAAQV,KAAK;QAChE;QACAc,QAAOC,EAAE,EAAEV,IAAI;YACb,IAAI,CAACA,QAAQA,IAAI,CAAC,YAAY,IAAI,MAAM,OAAO;YAC/C,OAAO;gBACLU;gBACAC,MAAMZ,YAAYC,SAASU;gBAC3BE,OAAO;oBAAEC,QAAQ,EAAE;oBAAEC,WAAWC,MAAMC,OAAO,CAAChB,IAAI,CAAC,YAAY,IAAIA,IAAI,CAAC,YAAY,GAAG,EAAE;gBAAC;YAC5F;QACF;IACF,GACA;QAAEiB,UAAU;IAAO;AAEvB;AAEA,+EAA+E,GAC/E,OAAO,SAASC;IACd1B,yBAAyB;AAC3B"}
@@ -0,0 +1,43 @@
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 ServerStepRequest } from '@aglyn/aglyn/plugin-manager/plugin-server-steps';
18
+ /** The dataset a step names, as the spec's own Firestore double holds it. */
19
+ interface DatasetDouble {
20
+ exists: boolean;
21
+ get(field: string): unknown;
22
+ }
23
+ /** Where the stand-in reads a dataset and writes its records: the spec's own double. */
24
+ export interface DatasetStepsDouble {
25
+ dataset(request: ServerStepRequest, datasetId: string): Promise<DatasetDouble>;
26
+ append(request: ServerStepRequest, datasetId: string, record: {
27
+ values: Record<string, string>;
28
+ }): Promise<unknown>;
29
+ }
30
+ /**
31
+ * The dataset steps the data plugin runs for this engine (AGL-3080), stood in
32
+ * for this plugin's specs — this plugin may not load the data plugin. Over the
33
+ * spec's own Firestore double it does what the owner's executor does for the
34
+ * shapes these specs store: it finds the dataset the step names by id, writes
35
+ * the event's fields the dataset has as text, and answers the dataset's name
36
+ * as the run's detail — or the owner's words for a dataset it cannot find, or
37
+ * for an event with no field the dataset has. Models, caps, merges and the
38
+ * live-page refresh are the data plugin's own spec's
39
+ * (`dataset-steps.server.spec.ts`), and the real pair runs together in
40
+ * `apps/console/specs/dataset-automation-steps.spec.ts`.
41
+ */
42
+ export declare function standInDatasetSteps(double: DatasetStepsDouble): () => void;
43
+ export {};
@@ -0,0 +1,65 @@
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 { registerServerStepExecutor } from "@aglyn/aglyn/plugin-manager/plugin-server-steps";
17
+ /**
18
+ * The dataset steps the data plugin runs for this engine (AGL-3080), stood in
19
+ * for this plugin's specs — this plugin may not load the data plugin. Over the
20
+ * spec's own Firestore double it does what the owner's executor does for the
21
+ * shapes these specs store: it finds the dataset the step names by id, writes
22
+ * the event's fields the dataset has as text, and answers the dataset's name
23
+ * as the run's detail — or the owner's words for a dataset it cannot find, or
24
+ * for an event with no field the dataset has. Models, caps, merges and the
25
+ * live-page refresh are the data plugin's own spec's
26
+ * (`dataset-steps.server.spec.ts`), and the real pair runs together in
27
+ * `apps/console/specs/dataset-automation-steps.spec.ts`.
28
+ */ export function standInDatasetSteps(double) {
29
+ return registerServerStepExecutor([
30
+ 'datasetAppend',
31
+ 'updateDataset'
32
+ ], async (request)=>{
33
+ var _step_datasetId, _ref, _dataset_get, _dataset_get1;
34
+ const step = request.step;
35
+ const datasetId = String((_step_datasetId = step.datasetId) != null ? _step_datasetId : '');
36
+ const dataset = await double.dataset(request, datasetId);
37
+ if (!dataset.exists || dataset.get('deletedAt')) {
38
+ return {
39
+ error: `unknown dataset "${step.datasetName || step.datasetId}"`
40
+ };
41
+ }
42
+ const label = String((_ref = (_dataset_get = dataset.get('displayName')) != null ? _dataset_get : step.datasetName) != null ? _ref : '');
43
+ const fields = (_dataset_get1 = dataset.get('fields')) != null ? _dataset_get1 : [];
44
+ const values = {};
45
+ for (const field of fields){
46
+ const value = request.payload[field];
47
+ if (value != null && String(value) !== '') values[field] = String(value);
48
+ }
49
+ if (!Object.keys(values).length) {
50
+ return {
51
+ error: `no event field matches a field in dataset "${label}"`
52
+ };
53
+ }
54
+ await double.append(request, datasetId, {
55
+ values
56
+ });
57
+ return step.type === 'datasetAppend' ? {
58
+ detail: label
59
+ } : {};
60
+ }, {
61
+ pluginId: 'data'
62
+ });
63
+ }
64
+
65
+ //# sourceMappingURL=stand-in-dataset-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-dataset-steps.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 registerServerStepExecutor,\n type ServerStepRequest,\n} from '@aglyn/aglyn/plugin-manager/plugin-server-steps'\n\n/** The dataset a step names, as the spec's own Firestore double holds it. */\ninterface DatasetDouble {\n exists: boolean\n get(field: string): unknown\n}\n\n/** Where the stand-in reads a dataset and writes its records: the spec's own double. */\nexport interface DatasetStepsDouble {\n dataset(request: ServerStepRequest, datasetId: string): Promise<DatasetDouble>\n append(request: ServerStepRequest, datasetId: string, record: { values: Record<string, string> }): Promise<unknown>\n}\n\n/**\n * The dataset steps the data plugin runs for this engine (AGL-3080), stood in\n * for this plugin's specs — this plugin may not load the data plugin. Over the\n * spec's own Firestore double it does what the owner's executor does for the\n * shapes these specs store: it finds the dataset the step names by id, writes\n * the event's fields the dataset has as text, and answers the dataset's name\n * as the run's detail — or the owner's words for a dataset it cannot find, or\n * for an event with no field the dataset has. Models, caps, merges and the\n * live-page refresh are the data plugin's own spec's\n * (`dataset-steps.server.spec.ts`), and the real pair runs together in\n * `apps/console/specs/dataset-automation-steps.spec.ts`.\n */\nexport function standInDatasetSteps(double: DatasetStepsDouble): () => void {\n return registerServerStepExecutor(\n ['datasetAppend', 'updateDataset'],\n async (request) => {\n const step = request.step as { type: string; datasetId?: string; datasetName?: string }\n const datasetId = String(step.datasetId ?? '')\n const dataset = await double.dataset(request, datasetId)\n if (!dataset.exists || dataset.get('deletedAt')) {\n return { error: `unknown dataset \"${step.datasetName || step.datasetId}\"` }\n }\n const label = String(dataset.get('displayName') ?? step.datasetName ?? '')\n const fields = (dataset.get('fields') as string[] | undefined) ?? []\n const values: Record<string, string> = {}\n for (const field of fields) {\n const value = request.payload[field]\n if (value != null && String(value) !== '') values[field] = String(value)\n }\n if (!Object.keys(values).length) {\n return { error: `no event field matches a field in dataset \"${label}\"` }\n }\n await double.append(request, datasetId, { values })\n return step.type === 'datasetAppend' ? { detail: label } : {}\n },\n { pluginId: 'data' },\n )\n}\n"],"names":["registerServerStepExecutor","standInDatasetSteps","double","request","step","dataset","datasetId","String","exists","get","error","datasetName","label","fields","values","field","value","payload","Object","keys","length","append","type","detail","pluginId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,0BAA0B,QAErB,kDAAiD;AAcxD;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,oBAAoBC,MAA0B;IAC5D,OAAOF,2BACL;QAAC;QAAiB;KAAgB,EAClC,OAAOG;YAEoBC,iBAKJC,MAAAA,cACLA;QAPhB,MAAMD,OAAOD,QAAQC,IAAI;QACzB,MAAME,YAAYC,QAAOH,kBAAAA,KAAKE,SAAS,YAAdF,kBAAkB;QAC3C,MAAMC,UAAU,MAAMH,OAAOG,OAAO,CAACF,SAASG;QAC9C,IAAI,CAACD,QAAQG,MAAM,IAAIH,QAAQI,GAAG,CAAC,cAAc;YAC/C,OAAO;gBAAEC,OAAO,CAAC,iBAAiB,EAAEN,KAAKO,WAAW,IAAIP,KAAKE,SAAS,CAAC,CAAC,CAAC;YAAC;QAC5E;QACA,MAAMM,QAAQL,QAAOF,QAAAA,eAAAA,QAAQI,GAAG,CAAC,0BAAZJ,eAA8BD,KAAKO,WAAW,YAA9CN,OAAkD;QACvE,MAAMQ,UAAUR,gBAAAA,QAAQI,GAAG,CAAC,qBAAZJ,gBAAkD,EAAE;QACpE,MAAMS,SAAiC,CAAC;QACxC,KAAK,MAAMC,SAASF,OAAQ;YAC1B,MAAMG,QAAQb,QAAQc,OAAO,CAACF,MAAM;YACpC,IAAIC,SAAS,QAAQT,OAAOS,WAAW,IAAIF,MAAM,CAACC,MAAM,GAAGR,OAAOS;QACpE;QACA,IAAI,CAACE,OAAOC,IAAI,CAACL,QAAQM,MAAM,EAAE;YAC/B,OAAO;gBAAEV,OAAO,CAAC,2CAA2C,EAAEE,MAAM,CAAC,CAAC;YAAC;QACzE;QACA,MAAMV,OAAOmB,MAAM,CAAClB,SAASG,WAAW;YAAEQ;QAAO;QACjD,OAAOV,KAAKkB,IAAI,KAAK,kBAAkB;YAAEC,QAAQX;QAAM,IAAI,CAAC;IAC9D,GACA;QAAEY,UAAU;IAAO;AAEvB"}
@@ -0,0 +1,35 @@
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 PluginPersonFileRequest, type PluginPersonFindRequest, type PluginPersonRecord } from '@aglyn/aglyn/plugin-manager/plugin-person-records';
18
+ /**
19
+ * A plugin that keeps people, standing in for the one that does (AGL-3080).
20
+ *
21
+ * An automation asks for the person an event names, and files them under a
22
+ * campaign, through `plugin-person-records` and imports no record system, so
23
+ * its specs stand an owner up the way the loader would. One plugin may not
24
+ * import another, which is why this is here rather than borrowed from the CRM.
25
+ *
26
+ * `find` is the spec's: it answers from the spec's own fixture. Every filing
27
+ * is recorded as asked, so a spec asserts what the step REPORTED; what a
28
+ * filing writes on the person is held by the CRM's `person-records.spec.ts`.
29
+ */
30
+ export declare function standInPersonRecords(options: {
31
+ find: (request: PluginPersonFindRequest) => PluginPersonRecord | null;
32
+ }): {
33
+ asked: PluginPersonFindRequest[];
34
+ filings: PluginPersonFileRequest[];
35
+ };
@@ -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
+ */ import { registerPluginPersonRecords } from "@aglyn/aglyn/plugin-manager/plugin-person-records";
17
+ /**
18
+ * A plugin that keeps people, standing in for the one that does (AGL-3080).
19
+ *
20
+ * An automation asks for the person an event names, and files them under a
21
+ * campaign, through `plugin-person-records` and imports no record system, so
22
+ * its specs stand an owner up the way the loader would. One plugin may not
23
+ * import another, which is why this is here rather than borrowed from the CRM.
24
+ *
25
+ * `find` is the spec's: it answers from the spec's own fixture. Every filing
26
+ * is recorded as asked, so a spec asserts what the step REPORTED; what a
27
+ * filing writes on the person is held by the CRM's `person-records.spec.ts`.
28
+ */ export function standInPersonRecords(options) {
29
+ const asked = [];
30
+ const filings = [];
31
+ registerPluginPersonRecords({
32
+ async find (request) {
33
+ asked.push(request);
34
+ return options.find(request);
35
+ },
36
+ async read (request) {
37
+ return request.records.map(()=>null);
38
+ },
39
+ async fileUnder (request) {
40
+ filings.push(request);
41
+ return {
42
+ filed: true
43
+ };
44
+ }
45
+ }, {
46
+ pluginId: 'record-system'
47
+ });
48
+ return {
49
+ asked,
50
+ filings
51
+ };
52
+ }
53
+
54
+ //# sourceMappingURL=stand-in-person-records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/workflows/src/lib/testing/stand-in-person-records.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 registerPluginPersonRecords,\n type PluginPersonFileRequest,\n type PluginPersonFindRequest,\n type PluginPersonRecord,\n} from '@aglyn/aglyn/plugin-manager/plugin-person-records'\n\n/**\n * A plugin that keeps people, standing in for the one that does (AGL-3080).\n *\n * An automation asks for the person an event names, and files them under a\n * campaign, through `plugin-person-records` and imports no record system, so\n * its specs stand an owner up the way the loader would. One plugin may not\n * import another, which is why this is here rather than borrowed from the CRM.\n *\n * `find` is the spec's: it answers from the spec's own fixture. Every filing\n * is recorded as asked, so a spec asserts what the step REPORTED; what a\n * filing writes on the person is held by the CRM's `person-records.spec.ts`.\n */\nexport function standInPersonRecords(options: {\n find: (request: PluginPersonFindRequest) => PluginPersonRecord | null\n}): { asked: PluginPersonFindRequest[]; filings: PluginPersonFileRequest[] } {\n const asked: PluginPersonFindRequest[] = []\n const filings: PluginPersonFileRequest[] = []\n registerPluginPersonRecords(\n {\n async find(request) {\n asked.push(request)\n return options.find(request)\n },\n async read(request) {\n return request.records.map(() => null)\n },\n async fileUnder(request) {\n filings.push(request)\n return { filed: true }\n },\n },\n { pluginId: 'record-system' },\n )\n return { asked, filings }\n}\n"],"names":["registerPluginPersonRecords","standInPersonRecords","options","asked","filings","find","request","push","read","records","map","fileUnder","filed","pluginId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,2BAA2B,QAItB,oDAAmD;AAE1D;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,qBAAqBC,OAEpC;IACC,MAAMC,QAAmC,EAAE;IAC3C,MAAMC,UAAqC,EAAE;IAC7CJ,4BACE;QACE,MAAMK,MAAKC,OAAO;YAChBH,MAAMI,IAAI,CAACD;YACX,OAAOJ,QAAQG,IAAI,CAACC;QACtB;QACA,MAAME,MAAKF,OAAO;YAChB,OAAOA,QAAQG,OAAO,CAACC,GAAG,CAAC,IAAM;QACnC;QACA,MAAMC,WAAUL,OAAO;YACrBF,QAAQG,IAAI,CAACD;YACb,OAAO;gBAAEM,OAAO;YAAK;QACvB;IACF,GACA;QAAEC,UAAU;IAAgB;IAE9B,OAAO;QAAEV;QAAOC;IAAQ;AAC1B"}
@@ -0,0 +1,36 @@
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 InteractionRecipe } from '@aglyn/aglyn/plugin-manager/interaction-recipes';
18
+ /**
19
+ * The CRM's four recipes (AGL-2626), stood in for this plugin's specs — this
20
+ * plugin may not load the CRM, which writes them and registers them through
21
+ * the platform's recipe seam (AGL-3080). Built as the CRM builds them, so the
22
+ * editor is driven with the automations it is really handed; what the CRM's
23
+ * recipes ARE is held in the CRM's own spec, and that each is an automation
24
+ * this plugin accepts in `apps/console/specs/interaction-recipes.spec.ts`.
25
+ */
26
+ export declare const STAND_IN_RECIPES: readonly InteractionRecipe[];
27
+ /** Registers the stood-in recipes as the CRM's declarations would. */
28
+ export declare function standInRecipes(): void;
29
+ /**
30
+ * The `form` list source the Forms plugin publishes (AGL-3080), stood in: a
31
+ * site's forms by document id, an archived one left out, a form named by its
32
+ * display name or its id, and whether it files leads shared as its
33
+ * `routesLeads` fact. What the Forms plugin itself answers is held in its own
34
+ * spec.
35
+ */
36
+ export declare function standInFormList(): void;