@headless-lms/core 0.1.0
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/LICENSE +21 -0
- package/dist/assets/events.d.ts +81 -0
- package/dist/assets/events.js +24 -0
- package/dist/assets/events.js.map +1 -0
- package/dist/assets/index.d.ts +7 -0
- package/dist/assets/index.js +3 -0
- package/dist/assets/model.d.ts +4 -0
- package/dist/assets/model.js +1 -0
- package/dist/assets/ports.d.ts +34 -0
- package/dist/assets/ports.js +1 -0
- package/dist/assets/service.d.ts +29 -0
- package/dist/assets/service.js +130 -0
- package/dist/assets/service.js.map +1 -0
- package/dist/automations/actions.d.ts +24 -0
- package/dist/automations/actions.js +59 -0
- package/dist/automations/actions.js.map +1 -0
- package/dist/automations/catalog.d.ts +12 -0
- package/dist/automations/catalog.js +224 -0
- package/dist/automations/catalog.js.map +1 -0
- package/dist/automations/events.d.ts +264 -0
- package/dist/automations/events.js +54 -0
- package/dist/automations/events.js.map +1 -0
- package/dist/automations/index.d.ts +9 -0
- package/dist/automations/index.js +4 -0
- package/dist/automations/model.d.ts +12 -0
- package/dist/automations/model.js +14 -0
- package/dist/automations/model.js.map +1 -0
- package/dist/automations/ports.d.ts +56 -0
- package/dist/automations/ports.js +1 -0
- package/dist/automations/service.d.ts +53 -0
- package/dist/automations/service.js +225 -0
- package/dist/automations/service.js.map +1 -0
- package/dist/automations/types.d.ts +3 -0
- package/dist/automations/types.js +1 -0
- package/dist/content/events.d.ts +410 -0
- package/dist/content/events.js +105 -0
- package/dist/content/events.js.map +1 -0
- package/dist/content/index.d.ts +8 -0
- package/dist/content/index.js +3 -0
- package/dist/content/model.d.ts +3 -0
- package/dist/content/model.js +1 -0
- package/dist/content/ports.d.ts +85 -0
- package/dist/content/ports.js +1 -0
- package/dist/content/service.d.ts +54 -0
- package/dist/content/service.js +479 -0
- package/dist/content/service.js.map +1 -0
- package/dist/content/types.d.ts +4 -0
- package/dist/content/types.js +1 -0
- package/dist/discussion/events.d.ts +101 -0
- package/dist/discussion/events.js +29 -0
- package/dist/discussion/events.js.map +1 -0
- package/dist/discussion/index.d.ts +8 -0
- package/dist/discussion/index.js +3 -0
- package/dist/discussion/model.d.ts +5 -0
- package/dist/discussion/model.js +1 -0
- package/dist/discussion/ports.d.ts +112 -0
- package/dist/discussion/ports.js +1 -0
- package/dist/discussion/service.d.ts +67 -0
- package/dist/discussion/service.js +343 -0
- package/dist/discussion/service.js.map +1 -0
- package/dist/discussion/types.d.ts +4 -0
- package/dist/discussion/types.js +1 -0
- package/dist/entitlements/events.d.ts +89 -0
- package/dist/entitlements/events.js +29 -0
- package/dist/entitlements/events.js.map +1 -0
- package/dist/entitlements/index.d.ts +7 -0
- package/dist/entitlements/index.js +3 -0
- package/dist/entitlements/model.d.ts +4 -0
- package/dist/entitlements/model.js +1 -0
- package/dist/entitlements/ports.d.ts +34 -0
- package/dist/entitlements/ports.js +1 -0
- package/dist/entitlements/service.d.ts +27 -0
- package/dist/entitlements/service.js +60 -0
- package/dist/entitlements/service.js.map +1 -0
- package/dist/identity/events.d.ts +63 -0
- package/dist/identity/events.js +24 -0
- package/dist/identity/events.js.map +1 -0
- package/dist/identity/index.d.ts +8 -0
- package/dist/identity/index.js +3 -0
- package/dist/identity/model.d.ts +3 -0
- package/dist/identity/model.js +1 -0
- package/dist/identity/ports.d.ts +58 -0
- package/dist/identity/ports.js +1 -0
- package/dist/identity/service.d.ts +38 -0
- package/dist/identity/service.js +79 -0
- package/dist/identity/service.js.map +1 -0
- package/dist/identity/types.d.ts +4 -0
- package/dist/identity/types.js +1 -0
- package/dist/integrations/events.d.ts +70 -0
- package/dist/integrations/events.js +24 -0
- package/dist/integrations/events.js.map +1 -0
- package/dist/integrations/index.d.ts +9 -0
- package/dist/integrations/index.js +6 -0
- package/dist/integrations/model.d.ts +28 -0
- package/dist/integrations/model.js +45 -0
- package/dist/integrations/model.js.map +1 -0
- package/dist/integrations/ports.d.ts +62 -0
- package/dist/integrations/ports.js +1 -0
- package/dist/integrations/registry.d.ts +7 -0
- package/dist/integrations/registry.js +16 -0
- package/dist/integrations/registry.js.map +1 -0
- package/dist/integrations/service.d.ts +47 -0
- package/dist/integrations/service.js +184 -0
- package/dist/integrations/service.js.map +1 -0
- package/dist/integrations/zod.d.ts +29 -0
- package/dist/integrations/zod.js +40 -0
- package/dist/integrations/zod.js.map +1 -0
- package/dist/organizations/events.d.ts +197 -0
- package/dist/organizations/events.js +59 -0
- package/dist/organizations/events.js.map +1 -0
- package/dist/organizations/index.d.ts +11 -0
- package/dist/organizations/index.js +5 -0
- package/dist/organizations/members.d.ts +32 -0
- package/dist/organizations/members.js +12 -0
- package/dist/organizations/members.js.map +1 -0
- package/dist/organizations/model.d.ts +3 -0
- package/dist/organizations/model.js +1 -0
- package/dist/organizations/ports.d.ts +127 -0
- package/dist/organizations/ports.js +1 -0
- package/dist/organizations/roles.d.ts +23 -0
- package/dist/organizations/roles.js +70 -0
- package/dist/organizations/roles.js.map +1 -0
- package/dist/organizations/service.d.ts +58 -0
- package/dist/organizations/service.js +359 -0
- package/dist/organizations/service.js.map +1 -0
- package/dist/organizations/types.d.ts +39 -0
- package/dist/organizations/types.js +1 -0
- package/dist/progress/events.d.ts +55 -0
- package/dist/progress/events.js +19 -0
- package/dist/progress/events.js.map +1 -0
- package/dist/progress/index.d.ts +8 -0
- package/dist/progress/index.js +3 -0
- package/dist/progress/model.d.ts +3 -0
- package/dist/progress/model.js +1 -0
- package/dist/progress/ports.d.ts +37 -0
- package/dist/progress/ports.js +1 -0
- package/dist/progress/service.d.ts +33 -0
- package/dist/progress/service.js +181 -0
- package/dist/progress/service.js.map +1 -0
- package/dist/progress/types.d.ts +4 -0
- package/dist/progress/types.js +1 -0
- package/dist/reporting/dashboard/index.d.ts +4 -0
- package/dist/reporting/dashboard/index.js +2 -0
- package/dist/reporting/dashboard/model.d.ts +14 -0
- package/dist/reporting/dashboard/model.js +1 -0
- package/dist/reporting/dashboard/ports.d.ts +13 -0
- package/dist/reporting/dashboard/ports.js +1 -0
- package/dist/reporting/dashboard/service.d.ts +19 -0
- package/dist/reporting/dashboard/service.js +20 -0
- package/dist/reporting/dashboard/service.js.map +1 -0
- package/dist/reporting/learn/index.d.ts +5 -0
- package/dist/reporting/learn/index.js +2 -0
- package/dist/reporting/learn/model.d.ts +23 -0
- package/dist/reporting/learn/model.js +1 -0
- package/dist/reporting/learn/ports.d.ts +42 -0
- package/dist/reporting/learn/ports.js +1 -0
- package/dist/reporting/learn/service.d.ts +48 -0
- package/dist/reporting/learn/service.js +111 -0
- package/dist/reporting/learn/service.js.map +1 -0
- package/dist/reporting/students/index.d.ts +4 -0
- package/dist/reporting/students/index.js +2 -0
- package/dist/reporting/students/model.d.ts +31 -0
- package/dist/reporting/students/model.js +1 -0
- package/dist/reporting/students/ports.d.ts +13 -0
- package/dist/reporting/students/ports.js +1 -0
- package/dist/reporting/students/service.d.ts +19 -0
- package/dist/reporting/students/service.js +20 -0
- package/dist/reporting/students/service.js.map +1 -0
- package/dist/shared/errors.d.ts +22 -0
- package/dist/shared/errors.js +34 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/events.d.ts +31 -0
- package/dist/shared/events.js +75 -0
- package/dist/shared/events.js.map +1 -0
- package/dist/shared/id.d.ts +44 -0
- package/dist/shared/id.js +53 -0
- package/dist/shared/id.js.map +1 -0
- package/dist/shared/invite-token.d.ts +9 -0
- package/dist/shared/invite-token.js +16 -0
- package/dist/shared/invite-token.js.map +1 -0
- package/dist/shared/logger.d.ts +19 -0
- package/dist/shared/logger.js +44 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/mailer.d.ts +23 -0
- package/dist/shared/mailer.js +27 -0
- package/dist/shared/mailer.js.map +1 -0
- package/dist/shared/ports.d.ts +62 -0
- package/dist/shared/ports.js +2 -0
- package/dist/shared/settings.d.ts +25 -0
- package/dist/shared/settings.js +21 -0
- package/dist/shared/settings.js.map +1 -0
- package/dist/types/assets.d.ts +2 -0
- package/dist/types/assets.js +1 -0
- package/dist/types/automations.d.ts +23 -0
- package/dist/types/automations.js +1 -0
- package/dist/types/content.d.ts +2 -0
- package/dist/types/content.js +1 -0
- package/dist/types/discussion.d.ts +36 -0
- package/dist/types/discussion.js +1 -0
- package/dist/types/email-templates.d.ts +57 -0
- package/dist/types/email-templates.js +1 -0
- package/dist/types/entitlements.d.ts +3 -0
- package/dist/types/entitlements.js +1 -0
- package/dist/types/events.d.ts +25 -0
- package/dist/types/events.js +1 -0
- package/dist/types/identity.d.ts +37 -0
- package/dist/types/identity.js +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.js +1 -0
- package/dist/types/integrations.d.ts +45 -0
- package/dist/types/integrations.js +1 -0
- package/dist/types/organizations.d.ts +15 -0
- package/dist/types/organizations.js +1 -0
- package/dist/types/ports.d.ts +57 -0
- package/dist/types/ports.js +1 -0
- package/dist/types/progress.d.ts +6 -0
- package/dist/types/progress.js +1 -0
- package/dist/types/schemas/assets.d.ts +109 -0
- package/dist/types/schemas/assets.js +49 -0
- package/dist/types/schemas/assets.js.map +1 -0
- package/dist/types/schemas/automations.d.ts +118 -0
- package/dist/types/schemas/automations.js +73 -0
- package/dist/types/schemas/automations.js.map +1 -0
- package/dist/types/schemas/content.d.ts +216 -0
- package/dist/types/schemas/content.js +138 -0
- package/dist/types/schemas/content.js.map +1 -0
- package/dist/types/schemas/credentials.d.ts +15 -0
- package/dist/types/schemas/credentials.js +15 -0
- package/dist/types/schemas/credentials.js.map +1 -0
- package/dist/types/schemas/discussion.d.ts +192 -0
- package/dist/types/schemas/discussion.js +100 -0
- package/dist/types/schemas/discussion.js.map +1 -0
- package/dist/types/schemas/entitlements.d.ts +50 -0
- package/dist/types/schemas/entitlements.js +38 -0
- package/dist/types/schemas/entitlements.js.map +1 -0
- package/dist/types/schemas/identity.d.ts +37 -0
- package/dist/types/schemas/identity.js +34 -0
- package/dist/types/schemas/identity.js.map +1 -0
- package/dist/types/schemas/index.d.ts +14 -0
- package/dist/types/schemas/index.js +14 -0
- package/dist/types/schemas/integrations.d.ts +36 -0
- package/dist/types/schemas/integrations.js +30 -0
- package/dist/types/schemas/integrations.js.map +1 -0
- package/dist/types/schemas/organizations.d.ts +135 -0
- package/dist/types/schemas/organizations.js +90 -0
- package/dist/types/schemas/organizations.js.map +1 -0
- package/dist/types/schemas/outbox.d.ts +19 -0
- package/dist/types/schemas/outbox.js +18 -0
- package/dist/types/schemas/outbox.js.map +1 -0
- package/dist/types/schemas/progress.d.ts +53 -0
- package/dist/types/schemas/progress.js +37 -0
- package/dist/types/schemas/progress.js.map +1 -0
- package/dist/types/schemas/settings.d.ts +16 -0
- package/dist/types/schemas/settings.js +15 -0
- package/dist/types/schemas/settings.js.map +1 -0
- package/dist/types/schemas/shared.d.ts +13 -0
- package/dist/types/schemas/shared.js +28 -0
- package/dist/types/schemas/shared.js.map +1 -0
- package/dist/types/shared.d.ts +25 -0
- package/dist/types/shared.js +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DomainEvent, Page } from "../types/shared.js";
|
|
2
|
+
import { Logger } from "../types/ports.js";
|
|
3
|
+
import { Automation, AutomationActionResult, AutomationRun, AutomationRunsQuery, AvailableActions, AvailableTriggers, CreateAutomationInput, UpdateAutomationInput } from "../types/schemas/automations.js";
|
|
4
|
+
import { AutomationDispatch, AutomationEngine, AutomationExecutor } from "../types/automations.js";
|
|
5
|
+
import "../shared/ports.js";
|
|
6
|
+
import { Mailer, MailerLookups } from "../shared/mailer.js";
|
|
7
|
+
import "./model.js";
|
|
8
|
+
import "./types.js";
|
|
9
|
+
import { AutomationRunsRepository, AutomationsRepository, AutomationsService, AutomationsUnitOfWork } from "./ports.js";
|
|
10
|
+
import { IntegrationsService } from "../integrations/ports.js";
|
|
11
|
+
import "../integrations/index.js";
|
|
12
|
+
//#region src/automations/service.d.ts
|
|
13
|
+
type AutomationsServiceParams = {
|
|
14
|
+
/** Read-only access (list/get/available) — runs outside any transaction. */
|
|
15
|
+
repo: AutomationsRepository;
|
|
16
|
+
runsRepo: AutomationRunsRepository;
|
|
17
|
+
/** Atomic write scope: tx-bound repos + outbox appender. */
|
|
18
|
+
uow: AutomationsUnitOfWork;
|
|
19
|
+
engine: AutomationEngine;
|
|
20
|
+
mailer: Pick<Mailer, 'send'>;
|
|
21
|
+
lookups: MailerLookups;
|
|
22
|
+
integrations: Pick<IntegrationsService, 'available'>;
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
};
|
|
25
|
+
declare class AutomationsServiceImpl implements AutomationsService, AutomationExecutor {
|
|
26
|
+
private readonly repo;
|
|
27
|
+
private readonly runsRepo;
|
|
28
|
+
private readonly uow;
|
|
29
|
+
private readonly engine;
|
|
30
|
+
private readonly mailer;
|
|
31
|
+
private readonly lookups;
|
|
32
|
+
private readonly integrations;
|
|
33
|
+
private readonly logger;
|
|
34
|
+
constructor(params: AutomationsServiceParams);
|
|
35
|
+
handle(event: DomainEvent): Promise<void>;
|
|
36
|
+
private safeListByTrigger;
|
|
37
|
+
private dispatchOne;
|
|
38
|
+
/** Best-effort: logs and never rethrows — `handle` must never throw. */
|
|
39
|
+
private recordFailure;
|
|
40
|
+
runAction(d: AutomationDispatch, index: number): Promise<AutomationActionResult>;
|
|
41
|
+
finalize(d: AutomationDispatch, results: AutomationActionResult[]): Promise<void>;
|
|
42
|
+
create(orgId: string, input: CreateAutomationInput): Promise<Automation>;
|
|
43
|
+
update(orgId: string, id: string, input: UpdateAutomationInput): Promise<Automation | null>;
|
|
44
|
+
delete(orgId: string, id: string): Promise<boolean>;
|
|
45
|
+
list(orgId: string): Promise<Automation[]>;
|
|
46
|
+
get(orgId: string, id: string): Promise<Automation | null>;
|
|
47
|
+
listRuns(orgId: string, automationId: string, query: AutomationRunsQuery): Promise<Page<AutomationRun>>;
|
|
48
|
+
availableActions(): AvailableActions;
|
|
49
|
+
availableTriggers(): AvailableTriggers;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { AutomationsServiceImpl, AutomationsServiceParams };
|
|
53
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { noopLogger } from "../shared/logger.js";
|
|
2
|
+
import { catalogActions, catalogTriggers } from "./catalog.js";
|
|
3
|
+
import { executeAction } from "./actions.js";
|
|
4
|
+
import { automationEvents } from "./events.js";
|
|
5
|
+
import { InvalidTriggerError } from "./model.js";
|
|
6
|
+
//#region src/automations/service.ts
|
|
7
|
+
/** True only when `input` sets `enabled` and nothing else — emits automation.enabled|disabled instead of automation.updated. */
|
|
8
|
+
function isEnabledOnlyUpdate(input) {
|
|
9
|
+
if (input.enabled === void 0) return false;
|
|
10
|
+
const { enabled: _enabled, ...rest } = input;
|
|
11
|
+
return Object.values(rest).every((v) => v === void 0);
|
|
12
|
+
}
|
|
13
|
+
var AutomationsServiceImpl = class {
|
|
14
|
+
repo;
|
|
15
|
+
runsRepo;
|
|
16
|
+
uow;
|
|
17
|
+
engine;
|
|
18
|
+
mailer;
|
|
19
|
+
lookups;
|
|
20
|
+
integrations;
|
|
21
|
+
logger;
|
|
22
|
+
constructor(params) {
|
|
23
|
+
this.repo = params.repo;
|
|
24
|
+
this.runsRepo = params.runsRepo;
|
|
25
|
+
this.uow = params.uow;
|
|
26
|
+
this.engine = params.engine;
|
|
27
|
+
this.mailer = params.mailer;
|
|
28
|
+
this.lookups = params.lookups;
|
|
29
|
+
this.integrations = params.integrations;
|
|
30
|
+
this.logger = params.logger ?? noopLogger;
|
|
31
|
+
}
|
|
32
|
+
async handle(event) {
|
|
33
|
+
if (event.type.startsWith("automation.")) return;
|
|
34
|
+
const automations = await this.safeListByTrigger(event);
|
|
35
|
+
for (const automation of automations.filter((a) => a.enabled)) await this.dispatchOne(automation, event);
|
|
36
|
+
}
|
|
37
|
+
async safeListByTrigger(event) {
|
|
38
|
+
try {
|
|
39
|
+
return await this.repo.listByTrigger(event.orgId, event.type);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
this.logger.error("automations: failed to load trigger matches", {
|
|
42
|
+
orgId: event.orgId,
|
|
43
|
+
trigger: event.type,
|
|
44
|
+
error: err instanceof Error ? err.message : String(err)
|
|
45
|
+
});
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async dispatchOne(automation, event) {
|
|
50
|
+
let run;
|
|
51
|
+
try {
|
|
52
|
+
run = await this.uow.run(async ({ runs, outbox }) => {
|
|
53
|
+
const inserted = await runs.insert(event.orgId, {
|
|
54
|
+
orgId: event.orgId,
|
|
55
|
+
automationId: automation.id,
|
|
56
|
+
trigger: automation.trigger,
|
|
57
|
+
event,
|
|
58
|
+
status: "running",
|
|
59
|
+
actionResults: [],
|
|
60
|
+
startedAt: /* @__PURE__ */ new Date(),
|
|
61
|
+
finishedAt: null
|
|
62
|
+
});
|
|
63
|
+
if (!inserted) return null;
|
|
64
|
+
await outbox.append([automationEvents.runStarted.make({
|
|
65
|
+
orgId: event.orgId,
|
|
66
|
+
data: inserted
|
|
67
|
+
})]);
|
|
68
|
+
return inserted;
|
|
69
|
+
});
|
|
70
|
+
if (!run) return;
|
|
71
|
+
await this.engine.dispatch({
|
|
72
|
+
runId: run.id,
|
|
73
|
+
orgId: event.orgId,
|
|
74
|
+
automationId: automation.id,
|
|
75
|
+
actions: automation.actions,
|
|
76
|
+
event
|
|
77
|
+
});
|
|
78
|
+
} catch (err) {
|
|
79
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
80
|
+
this.logger.error("automation run failed", {
|
|
81
|
+
orgId: event.orgId,
|
|
82
|
+
automationId: automation.id,
|
|
83
|
+
runId: run?.id,
|
|
84
|
+
error: message
|
|
85
|
+
});
|
|
86
|
+
if (run) await this.recordFailure(run, message);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Best-effort: logs and never rethrows — `handle` must never throw. */
|
|
90
|
+
async recordFailure(run, error) {
|
|
91
|
+
try {
|
|
92
|
+
await this.uow.run(async ({ runs, outbox }) => {
|
|
93
|
+
const failed = await runs.recordOutcome(run.orgId, run.id, {
|
|
94
|
+
status: "failed",
|
|
95
|
+
actionResults: run.actionResults,
|
|
96
|
+
finishedAt: /* @__PURE__ */ new Date()
|
|
97
|
+
});
|
|
98
|
+
if (failed) await outbox.append([automationEvents.runFailed.make({
|
|
99
|
+
orgId: run.orgId,
|
|
100
|
+
data: failed
|
|
101
|
+
})]);
|
|
102
|
+
});
|
|
103
|
+
} catch (err) {
|
|
104
|
+
this.logger.error("failed to record automation run failure", {
|
|
105
|
+
orgId: run.orgId,
|
|
106
|
+
runId: run.id,
|
|
107
|
+
error: err instanceof Error ? err.message : String(err),
|
|
108
|
+
originalError: error
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async runAction(d, index) {
|
|
113
|
+
const action = d.actions[index];
|
|
114
|
+
if (!action) throw new Error(`automation ${d.automationId} run ${d.runId}: no action at index ${index}`);
|
|
115
|
+
await executeAction(action, d.event, this.mailer, this.lookups);
|
|
116
|
+
return {
|
|
117
|
+
index,
|
|
118
|
+
type: action.type,
|
|
119
|
+
status: "completed"
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async finalize(d, results) {
|
|
123
|
+
const status = results.length === d.actions.length && results.every((r) => r.status === "completed") ? "completed" : "failed";
|
|
124
|
+
await this.uow.run(async ({ runs, outbox }) => {
|
|
125
|
+
const run = await runs.recordOutcome(d.orgId, d.runId, {
|
|
126
|
+
status,
|
|
127
|
+
actionResults: results,
|
|
128
|
+
finishedAt: /* @__PURE__ */ new Date()
|
|
129
|
+
});
|
|
130
|
+
if (!run) return;
|
|
131
|
+
const runEvent = status === "completed" ? automationEvents.runCompleted.make({
|
|
132
|
+
orgId: d.orgId,
|
|
133
|
+
data: run
|
|
134
|
+
}) : automationEvents.runFailed.make({
|
|
135
|
+
orgId: d.orgId,
|
|
136
|
+
data: run
|
|
137
|
+
});
|
|
138
|
+
const actionFailedEvents = results.filter((r) => r.status === "failed").map((result) => ({ ...automationEvents.actionFailed.make({
|
|
139
|
+
orgId: d.orgId,
|
|
140
|
+
data: result
|
|
141
|
+
}) }));
|
|
142
|
+
await outbox.append([runEvent, ...actionFailedEvents]);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async create(orgId, input) {
|
|
146
|
+
if (input.trigger.startsWith("automation.")) throw new InvalidTriggerError(input.trigger);
|
|
147
|
+
const automation = await this.uow.run(async ({ automations, outbox }) => {
|
|
148
|
+
const created = await automations.insert(orgId, input);
|
|
149
|
+
await outbox.append([automationEvents.automationCreated.make({
|
|
150
|
+
orgId,
|
|
151
|
+
data: created
|
|
152
|
+
})]);
|
|
153
|
+
return created;
|
|
154
|
+
});
|
|
155
|
+
this.logger.info("automation created", {
|
|
156
|
+
orgId,
|
|
157
|
+
automationId: automation.id
|
|
158
|
+
});
|
|
159
|
+
return automation;
|
|
160
|
+
}
|
|
161
|
+
async update(orgId, id, input) {
|
|
162
|
+
if (input.trigger !== void 0 && input.trigger.startsWith("automation.")) throw new InvalidTriggerError(input.trigger);
|
|
163
|
+
const automation = await this.uow.run(async ({ automations, outbox }) => {
|
|
164
|
+
const updated = await automations.update(orgId, id, input);
|
|
165
|
+
if (!updated) return null;
|
|
166
|
+
if (isEnabledOnlyUpdate(input)) await outbox.append([input.enabled ? automationEvents.automationEnabled.make({
|
|
167
|
+
orgId,
|
|
168
|
+
data: updated
|
|
169
|
+
}) : automationEvents.automationDisabled.make({
|
|
170
|
+
orgId,
|
|
171
|
+
data: updated
|
|
172
|
+
})]);
|
|
173
|
+
else await outbox.append([automationEvents.automationUpdated.make({
|
|
174
|
+
orgId,
|
|
175
|
+
data: updated
|
|
176
|
+
})]);
|
|
177
|
+
return updated;
|
|
178
|
+
});
|
|
179
|
+
if (automation) this.logger.info("automation updated", {
|
|
180
|
+
orgId,
|
|
181
|
+
automationId: id
|
|
182
|
+
});
|
|
183
|
+
return automation;
|
|
184
|
+
}
|
|
185
|
+
async delete(orgId, id) {
|
|
186
|
+
const deleted = await this.uow.run(async ({ automations, outbox }) => {
|
|
187
|
+
const removed = await automations.delete(orgId, id);
|
|
188
|
+
if (!removed) return null;
|
|
189
|
+
await outbox.append([automationEvents.automationDeleted.make({
|
|
190
|
+
orgId,
|
|
191
|
+
data: removed
|
|
192
|
+
})]);
|
|
193
|
+
return removed;
|
|
194
|
+
});
|
|
195
|
+
if (deleted) this.logger.info("automation deleted", {
|
|
196
|
+
orgId,
|
|
197
|
+
automationId: id
|
|
198
|
+
});
|
|
199
|
+
return deleted !== null;
|
|
200
|
+
}
|
|
201
|
+
list(orgId) {
|
|
202
|
+
return this.repo.listByOrg(orgId);
|
|
203
|
+
}
|
|
204
|
+
get(orgId, id) {
|
|
205
|
+
return this.repo.findById(orgId, id);
|
|
206
|
+
}
|
|
207
|
+
listRuns(orgId, automationId, query) {
|
|
208
|
+
return this.runsRepo.list(orgId, automationId, query);
|
|
209
|
+
}
|
|
210
|
+
availableActions() {
|
|
211
|
+
return [...catalogActions(), ...this.integrations.available().flatMap((integration) => integration.actions.map((action) => ({
|
|
212
|
+
type: `${integration.id}.${action.id}`,
|
|
213
|
+
description: action.description,
|
|
214
|
+
inputSchema: action.inputSchema,
|
|
215
|
+
source: integration.id
|
|
216
|
+
})))];
|
|
217
|
+
}
|
|
218
|
+
availableTriggers() {
|
|
219
|
+
return { triggers: catalogTriggers() };
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
//#endregion
|
|
223
|
+
export { AutomationsServiceImpl };
|
|
224
|
+
|
|
225
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../../src/automations/service.ts"],"sourcesContent":["// automations context — service implementation (inbound port) and the\n// AutomationExecutor the engine drives.\n//\n// `handle` is subscribed to all events on the EventBus: it matches an event\n// against enabled automations for its trigger, opens one run per match, and\n// hands it to the injected AutomationEngine, which calls back into\n// `runAction`/`finalize`.\nimport { catalogActions, catalogTriggers } from './catalog.js';\nimport { executeAction } from './actions.js';\nimport {\n InvalidTriggerError,\n type Automation,\n type AutomationActionResult,\n type AutomationRun,\n type Page,\n} from './model.js';\nimport type {\n AutomationRunsQuery,\n AvailableActions,\n AvailableTriggers,\n CreateAutomationInput,\n UpdateAutomationInput,\n} from './types.js';\nimport type {\n AutomationDispatch,\n AutomationEngine,\n AutomationExecutor,\n AutomationRunsRepository,\n AutomationsRepository,\n AutomationsService,\n AutomationsUnitOfWork,\n} from './ports.js';\nimport type { DomainEvent, Logger } from '../shared/ports.js';\nimport type { JsonValue } from '../types/index.js';\nimport { noopLogger } from '../shared/logger.js';\nimport type { Mailer, MailerLookups } from '../shared/mailer.js';\nimport type { IntegrationsService } from '../integrations/index.js';\nimport { automationEvents } from './events.js';\n\n/** True only when `input` sets `enabled` and nothing else — emits automation.enabled|disabled instead of automation.updated. */\nfunction isEnabledOnlyUpdate(input: UpdateAutomationInput): input is { enabled: boolean } {\n if (input.enabled === undefined) {\n return false;\n }\n const { enabled: _enabled, ...rest } = input;\n return Object.values(rest).every((v) => v === undefined);\n}\n\nexport type AutomationsServiceParams = {\n /** Read-only access (list/get/available) — runs outside any transaction. */\n repo: AutomationsRepository;\n runsRepo: AutomationRunsRepository;\n /** Atomic write scope: tx-bound repos + outbox appender. */\n uow: AutomationsUnitOfWork;\n engine: AutomationEngine;\n mailer: Pick<Mailer, 'send'>;\n lookups: MailerLookups;\n integrations: Pick<IntegrationsService, 'available'>;\n logger?: Logger;\n};\n\nexport class AutomationsServiceImpl implements AutomationsService, AutomationExecutor {\n private readonly repo: AutomationsRepository;\n private readonly runsRepo: AutomationRunsRepository;\n private readonly uow: AutomationsUnitOfWork;\n private readonly engine: AutomationEngine;\n private readonly mailer: Pick<Mailer, 'send'>;\n private readonly lookups: MailerLookups;\n private readonly integrations: Pick<IntegrationsService, 'available'>;\n private readonly logger: Logger;\n\n constructor(params: AutomationsServiceParams) {\n this.repo = params.repo;\n this.runsRepo = params.runsRepo;\n this.uow = params.uow;\n this.engine = params.engine;\n this.mailer = params.mailer;\n this.lookups = params.lookups;\n this.integrations = params.integrations;\n this.logger = params.logger ?? noopLogger;\n }\n\n async handle(event: DomainEvent): Promise<void> {\n // automation.* events are this service's own output — matching one as a trigger would self-loop.\n if (event.type.startsWith('automation.')) {\n return;\n }\n const automations = await this.safeListByTrigger(event);\n for (const automation of automations.filter((a) => a.enabled)) {\n await this.dispatchOne(automation, event);\n }\n }\n\n private async safeListByTrigger(event: DomainEvent): Promise<Automation[]> {\n try {\n return await this.repo.listByTrigger(event.orgId, event.type);\n } catch (err) {\n this.logger.error('automations: failed to load trigger matches', {\n orgId: event.orgId,\n trigger: event.type,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n }\n\n private async dispatchOne(automation: Automation, event: DomainEvent): Promise<void> {\n let run: AutomationRun | null | undefined;\n try {\n run = await this.uow.run(async ({ runs, outbox }) => {\n const inserted = await runs.insert(event.orgId, {\n orgId: event.orgId,\n automationId: automation.id,\n trigger: automation.trigger,\n event,\n status: 'running',\n actionResults: [],\n startedAt: new Date(),\n finishedAt: null,\n });\n if (!inserted) {\n // At-least-once redelivery of a trigger event already run for this automation — no-op.\n return null;\n }\n await outbox.append([\n automationEvents.runStarted.make({\n orgId: event.orgId,\n data: inserted,\n }),\n ]);\n return inserted;\n });\n if (!run) {\n return;\n }\n await this.engine.dispatch({\n runId: run.id,\n orgId: event.orgId,\n automationId: automation.id,\n actions: automation.actions,\n event,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.logger.error('automation run failed', {\n orgId: event.orgId,\n automationId: automation.id,\n runId: run?.id,\n error: message,\n });\n if (run) {\n await this.recordFailure(run, message);\n }\n }\n }\n\n /** Best-effort: logs and never rethrows — `handle` must never throw. */\n private async recordFailure(run: AutomationRun, error: string): Promise<void> {\n try {\n await this.uow.run(async ({ runs, outbox }) => {\n const failed = await runs.recordOutcome(run.orgId, run.id, {\n status: 'failed',\n actionResults: run.actionResults,\n finishedAt: new Date(),\n });\n if (failed) {\n await outbox.append([\n automationEvents.runFailed.make({\n orgId: run.orgId,\n data: failed,\n }),\n ]);\n }\n });\n } catch (err) {\n this.logger.error('failed to record automation run failure', {\n orgId: run.orgId,\n runId: run.id,\n error: err instanceof Error ? err.message : String(err),\n originalError: error,\n });\n }\n }\n\n async runAction(d: AutomationDispatch, index: number): Promise<AutomationActionResult> {\n const action = d.actions[index];\n if (!action) {\n throw new Error(`automation ${d.automationId} run ${d.runId}: no action at index ${index}`);\n }\n await executeAction(action, d.event, this.mailer, this.lookups);\n return { index, type: action.type, status: 'completed' };\n }\n\n async finalize(d: AutomationDispatch, results: AutomationActionResult[]): Promise<void> {\n const status: 'completed' | 'failed' =\n results.length === d.actions.length && results.every((r) => r.status === 'completed')\n ? 'completed'\n : 'failed';\n await this.uow.run(async ({ runs, outbox }) => {\n const run = await runs.recordOutcome(d.orgId, d.runId, {\n status,\n actionResults: results,\n finishedAt: new Date(),\n });\n if (!run) {\n return;\n }\n const runEvent =\n status === 'completed'\n ? automationEvents.runCompleted.make({ orgId: d.orgId, data: run })\n : automationEvents.runFailed.make({ orgId: d.orgId, data: run });\n const actionFailedEvents = results\n .filter((r) => r.status === 'failed')\n .map((result) => ({\n ...automationEvents.actionFailed.make({\n orgId: d.orgId,\n data: result,\n }),\n }));\n await outbox.append([runEvent, ...actionFailedEvents]);\n });\n }\n\n async create(orgId: string, input: CreateAutomationInput): Promise<Automation> {\n if (input.trigger.startsWith('automation.')) {\n throw new InvalidTriggerError(input.trigger);\n }\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const created = await automations.insert(orgId, input);\n await outbox.append([\n automationEvents.automationCreated.make({ orgId, data: created }),\n ]);\n return created;\n });\n this.logger.info('automation created', { orgId, automationId: automation.id });\n return automation;\n }\n\n async update(\n orgId: string,\n id: string,\n input: UpdateAutomationInput,\n ): Promise<Automation | null> {\n if (input.trigger !== undefined && input.trigger.startsWith('automation.')) {\n throw new InvalidTriggerError(input.trigger);\n }\n const automation = await this.uow.run(async ({ automations, outbox }) => {\n const updated = await automations.update(orgId, id, input);\n if (!updated) {\n return null;\n }\n if (isEnabledOnlyUpdate(input)) {\n await outbox.append([\n input.enabled\n ? automationEvents.automationEnabled.make({\n orgId,\n data: updated,\n })\n : automationEvents.automationDisabled.make({\n orgId,\n data: updated,\n }),\n ]);\n } else {\n await outbox.append([\n automationEvents.automationUpdated.make({ orgId, data: updated }),\n ]);\n }\n return updated;\n });\n if (automation) {\n this.logger.info('automation updated', { orgId, automationId: id });\n }\n return automation;\n }\n\n async delete(orgId: string, id: string): Promise<boolean> {\n const deleted = await this.uow.run(async ({ automations, outbox }) => {\n const removed = await automations.delete(orgId, id);\n if (!removed) {\n return null;\n }\n await outbox.append([\n automationEvents.automationDeleted.make({ orgId, data: removed }),\n ]);\n return removed;\n });\n if (deleted) {\n this.logger.info('automation deleted', { orgId, automationId: id });\n }\n return deleted !== null;\n }\n\n list(orgId: string): Promise<Automation[]> {\n return this.repo.listByOrg(orgId);\n }\n\n get(orgId: string, id: string): Promise<Automation | null> {\n return this.repo.findById(orgId, id);\n }\n\n listRuns(\n orgId: string,\n automationId: string,\n query: AutomationRunsQuery,\n ): Promise<Page<AutomationRun>> {\n return this.runsRepo.list(orgId, automationId, query);\n }\n\n availableActions(): AvailableActions {\n return [\n ...catalogActions(),\n ...this.integrations.available().flatMap((integration) =>\n integration.actions.map((action) => ({\n type: `${integration.id}.${action.id}`,\n description: action.description,\n inputSchema: action.inputSchema as Record<string, JsonValue>,\n source: integration.id,\n })),\n ),\n ];\n }\n\n availableTriggers(): AvailableTriggers {\n return { triggers: catalogTriggers() };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { AutomationRunsQuery, AvailableAction, AvailableActions, AvailableTriggers, CreateAutomationInput, UpdateAutomationInput } from "../types/schemas/automations.js";
|
|
2
|
+
import "../types/index.js";
|
|
3
|
+
export type { AutomationRunsQuery, AvailableAction, AvailableActions, AvailableTriggers, CreateAutomationInput, UpdateAutomationInput };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|