@headless-lms/adapter-defaults 0.5.1 → 0.5.3

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.
@@ -3,8 +3,14 @@ var InMemoryEventBus = class {
3
3
  handlers = /* @__PURE__ */ new Map();
4
4
  allHandlers = [];
5
5
  async publish(event) {
6
- for (const handler of this.handlers.get(event.type) ?? []) await handler(event);
7
- for (const handler of this.allHandlers) await handler(event);
6
+ const errors = [];
7
+ for (const handler of [...this.handlers.get(event.type) ?? [], ...this.allHandlers]) try {
8
+ await handler(event);
9
+ } catch (err) {
10
+ errors.push(err);
11
+ }
12
+ if (errors.length === 1) throw errors[0];
13
+ if (errors.length > 1) throw new AggregateError(errors, `${errors.length} handlers failed for ${event.type}`);
8
14
  }
9
15
  subscribe(typeOrDefinition, handler) {
10
16
  const type = typeof typeOrDefinition === "string" ? typeOrDefinition : typeOrDefinition.type;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["// In-process event bus. Implements the shared EventBus port: publish invokes\n// every handler subscribed to the event's type, sequentially, awaiting each,\n// then every all-events handler (subscribeAll), also sequentially awaited.\nimport type { DomainEvent, EventBus, EventDefinition } from \"@headless-lms/core/shared/ports\";\n\nexport class InMemoryEventBus implements EventBus {\n private readonly handlers = new Map<string, Array<(e: DomainEvent) => Promise<void>>>();\n private readonly allHandlers: Array<(e: DomainEvent) => Promise<void>> = [];\n\n async publish(event: DomainEvent): Promise<void> {\n for (const handler of this.handlers.get(event.type) ?? []) {\n await handler(event);\n }\n for (const handler of this.allHandlers) {\n await handler(event);\n }\n }\n\n subscribe<E extends DomainEvent>(\n definition: EventDefinition<E>,\n handler: (e: E) => Promise<void>,\n ): void;\n subscribe(type: string, handler: (e: DomainEvent) => Promise<void>): void;\n subscribe(\n typeOrDefinition: string | EventDefinition<DomainEvent>,\n handler: (e: DomainEvent) => Promise<void>,\n ): void {\n const type = typeof typeOrDefinition === \"string\" ? typeOrDefinition : typeOrDefinition.type;\n const parsedHandler =\n typeof typeOrDefinition === \"string\"\n ? handler\n : async (event: DomainEvent) => handler(typeOrDefinition.parse(event));\n const list = this.handlers.get(type) ?? [];\n list.push(parsedHandler);\n this.handlers.set(type, list);\n }\n\n subscribeAll(handler: (e: DomainEvent) => Promise<void>): void {\n this.allHandlers.push(handler);\n }\n}\n"],"mappings":";AAKA,IAAa,mBAAb,MAAkD;CAChD,2BAA4B,IAAI,IAAsD;CACtF,cAAyE,CAAC;CAE1E,MAAM,QAAQ,OAAmC;EAC/C,KAAK,MAAM,WAAW,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,CAAC,GACtD,MAAM,QAAQ,KAAK;EAErB,KAAK,MAAM,WAAW,KAAK,aACzB,MAAM,QAAQ,KAAK;CAEvB;CAOA,UACE,kBACA,SACM;EACN,MAAM,OAAO,OAAO,qBAAqB,WAAW,mBAAmB,iBAAiB;EACxF,MAAM,gBACJ,OAAO,qBAAqB,WACxB,UACA,OAAO,UAAuB,QAAQ,iBAAiB,MAAM,KAAK,CAAC;EACzE,MAAM,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,CAAC;EACzC,KAAK,KAAK,aAAa;EACvB,KAAK,SAAS,IAAI,MAAM,IAAI;CAC9B;CAEA,aAAa,SAAkD;EAC7D,KAAK,YAAY,KAAK,OAAO;CAC/B;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["// In-process event bus. Implements the shared EventBus port: publish invokes\n// every handler subscribed to the event's type, sequentially, awaiting each,\n// then every all-events handler (subscribeAll), also sequentially awaited.\n// A failing handler does not stop the others; publish then rejects so the\n// event is redelivered.\nimport type { DomainEvent, EventBus, EventDefinition } from \"@headless-lms/core/shared/ports\";\n\nexport class InMemoryEventBus implements EventBus {\n private readonly handlers = new Map<string, Array<(e: DomainEvent) => Promise<void>>>();\n private readonly allHandlers: Array<(e: DomainEvent) => Promise<void>> = [];\n\n async publish(event: DomainEvent): Promise<void> {\n const errors: unknown[] = [];\n for (const handler of [...(this.handlers.get(event.type) ?? []), ...this.allHandlers]) {\n try {\n await handler(event);\n } catch (err) {\n errors.push(err);\n }\n }\n if (errors.length === 1) {\n throw errors[0];\n }\n if (errors.length > 1) {\n throw new AggregateError(errors, `${errors.length} handlers failed for ${event.type}`);\n }\n }\n\n subscribe<E extends DomainEvent>(\n definition: EventDefinition<E>,\n handler: (e: E) => Promise<void>,\n ): void;\n subscribe(type: string, handler: (e: DomainEvent) => Promise<void>): void;\n subscribe(\n typeOrDefinition: string | EventDefinition<DomainEvent>,\n handler: (e: DomainEvent) => Promise<void>,\n ): void {\n const type = typeof typeOrDefinition === \"string\" ? typeOrDefinition : typeOrDefinition.type;\n const parsedHandler =\n typeof typeOrDefinition === \"string\"\n ? handler\n : async (event: DomainEvent) => handler(typeOrDefinition.parse(event));\n const list = this.handlers.get(type) ?? [];\n list.push(parsedHandler);\n this.handlers.set(type, list);\n }\n\n subscribeAll(handler: (e: DomainEvent) => Promise<void>): void {\n this.allHandlers.push(handler);\n }\n}\n"],"mappings":";AAOA,IAAa,mBAAb,MAAkD;CAChD,2BAA4B,IAAI,IAAsD;CACtF,cAAyE,CAAC;CAE1E,MAAM,QAAQ,OAAmC;EAC/C,MAAM,SAAoB,CAAC;EAC3B,KAAK,MAAM,WAAW,CAAC,GAAI,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,CAAC,GAAI,GAAG,KAAK,WAAW,GAClF,IAAI;GACF,MAAM,QAAQ,KAAK;EACrB,SAAS,KAAK;GACZ,OAAO,KAAK,GAAG;EACjB;EAEF,IAAI,OAAO,WAAW,GACpB,MAAM,OAAO;EAEf,IAAI,OAAO,SAAS,GAClB,MAAM,IAAI,eAAe,QAAQ,GAAG,OAAO,OAAO,uBAAuB,MAAM,MAAM;CAEzF;CAOA,UACE,kBACA,SACM;EACN,MAAM,OAAO,OAAO,qBAAqB,WAAW,mBAAmB,iBAAiB;EACxF,MAAM,gBACJ,OAAO,qBAAqB,WACxB,UACA,OAAO,UAAuB,QAAQ,iBAAiB,MAAM,KAAK,CAAC;EACzE,MAAM,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,CAAC;EACzC,KAAK,KAAK,aAAa;EACvB,KAAK,SAAS,IAAI,MAAM,IAAI;CAC9B;CAEA,aAAa,SAAkD;EAC7D,KAAK,YAAY,KAAK,OAAO;CAC/B;AACF"}
@@ -1,14 +1,16 @@
1
1
  import { startScheduleLoop } from "./schedule.js";
2
2
  import { RecurringJob, ScheduledJob, Scheduler } from "@headless-lms/core/shared/ports";
3
- import { AutomationDispatch, AutomationEngine, AutomationExecutor, DeliveryDispatch, JsonValue, Logger as Logger$1 } from "@headless-lms/core/types";
3
+ import { AutomationDispatch, AutomationEngine, AutomationExecutor, DeliveryDispatch, DeliveryExecutor, JsonValue, Logger as Logger$1 } from "@headless-lms/core/types";
4
4
  //#region src/workflows/index.d.ts
5
5
  declare class InlineAutomationEngine implements AutomationEngine, Scheduler {
6
6
  private readonly logger?;
7
7
  private executor;
8
+ private deliveries;
8
9
  private schedule;
9
10
  private readonly jobs;
10
11
  constructor(logger?: Logger$1 | undefined);
11
12
  register(executor: AutomationExecutor): void;
13
+ registerDeliveries(executor: DeliveryExecutor): void;
12
14
  registerJobs(handlers: ScheduledJob[], recurring: RecurringJob[]): void;
13
15
  at(job: string, runAt: Date, key: string, payload: JsonValue): Promise<void>;
14
16
  cancel(job: string, key: string): Promise<void>;
@@ -5,6 +5,7 @@ import { ActionFailedError, actionFailureMessage } from "@headless-lms/core/auto
5
5
  var InlineAutomationEngine = class {
6
6
  logger;
7
7
  executor;
8
+ deliveries;
8
9
  schedule;
9
10
  jobs;
10
11
  constructor(logger) {
@@ -14,6 +15,9 @@ var InlineAutomationEngine = class {
14
15
  register(executor) {
15
16
  this.executor = executor;
16
17
  }
18
+ registerDeliveries(executor) {
19
+ this.deliveries = executor;
20
+ }
17
21
  registerJobs(handlers, recurring) {
18
22
  this.jobs.register(handlers, recurring);
19
23
  }
@@ -48,8 +52,8 @@ var InlineAutomationEngine = class {
48
52
  await executor.finalize(d, results);
49
53
  }
50
54
  async deliver(d) {
51
- if (!this.executor) throw new Error("InlineAutomationEngine.deliver called before register()");
52
- await this.executor.runDelivery(d, true);
55
+ if (!this.deliveries) throw new Error("InlineAutomationEngine.deliver called before registerDeliveries()");
56
+ await this.deliveries.runDelivery(d, true);
53
57
  }
54
58
  async start() {
55
59
  this.schedule?.stop();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/workflows/index.ts"],"sourcesContent":["// Default in-process engine — runs a dispatched automation immediately, one\n// attempt per action; durable engines (Hatchet, …) are installation adapters.\nimport type {\n AutomationActionResult,\n AutomationDispatch,\n AutomationEngine,\n AutomationExecutor,\n DeliveryDispatch,\n JsonValue,\n Logger,\n} from \"@headless-lms/core/types\";\nimport type { RecurringJob, ScheduledJob, Scheduler } from \"@headless-lms/core/shared/ports\";\nimport { ActionFailedError, actionFailureMessage } from \"@headless-lms/core/automations\";\nimport { startScheduleLoop } from \"./schedule.js\";\nimport { InlineJobs } from \"./jobs.js\";\n\nexport { startScheduleLoop };\n\nexport class InlineAutomationEngine implements AutomationEngine, Scheduler {\n private executor: AutomationExecutor | undefined;\n private schedule: { stop(): void } | undefined;\n private readonly jobs: InlineJobs;\n\n constructor(private readonly logger?: Logger) {\n this.jobs = new InlineJobs(logger);\n }\n\n register(executor: AutomationExecutor): void {\n this.executor = executor;\n }\n\n registerJobs(handlers: ScheduledJob[], recurring: RecurringJob[]): void {\n this.jobs.register(handlers, recurring);\n }\n\n async at(job: string, runAt: Date, key: string, payload: JsonValue): Promise<void> {\n this.jobs.at(job, runAt, key, payload);\n }\n\n async cancel(job: string, key: string): Promise<void> {\n this.jobs.cancel(job, key);\n }\n\n async dispatch(d: AutomationDispatch): Promise<void> {\n if (!this.executor) {\n throw new Error(\"InlineAutomationEngine.dispatch called before register()\");\n }\n const executor = this.executor;\n\n const results: AutomationActionResult[] = [];\n for (let index = 0; index < d.actions.length; index++) {\n try {\n results.push(await executor.runAction(d, index));\n } catch (err) {\n if (!(err instanceof ActionFailedError)) {\n this.logger?.error(\"automation action failed\", {\n orgId: d.orgId,\n automationId: d.automationId,\n runId: d.runId,\n index,\n err,\n });\n }\n results.push({\n index,\n type: d.actions[index]!.type,\n status: \"failed\",\n error: actionFailureMessage(err),\n });\n break;\n }\n }\n\n await executor.finalize(d, results);\n }\n\n async deliver(d: DeliveryDispatch): Promise<void> {\n if (!this.executor) {\n throw new Error(\"InlineAutomationEngine.deliver called before register()\");\n }\n await this.executor.runDelivery(d, true);\n }\n\n async start(): Promise<void> {\n this.schedule?.stop();\n this.schedule = startScheduleLoop(() => this.executor, this.logger);\n this.jobs.start();\n }\n\n async stop(): Promise<void> {\n this.schedule?.stop();\n this.schedule = undefined;\n this.jobs.stop();\n }\n}\n"],"mappings":";;;;AAkBA,IAAa,yBAAb,MAA2E;CAK5C;CAJ7B;CACA;CACA;CAEA,YAAY,QAAkC;EAAjB,KAAA,SAAA;EAC3B,KAAK,OAAO,IAAI,WAAW,MAAM;CACnC;CAEA,SAAS,UAAoC;EAC3C,KAAK,WAAW;CAClB;CAEA,aAAa,UAA0B,WAAiC;EACtE,KAAK,KAAK,SAAS,UAAU,SAAS;CACxC;CAEA,MAAM,GAAG,KAAa,OAAa,KAAa,SAAmC;EACjF,KAAK,KAAK,GAAG,KAAK,OAAO,KAAK,OAAO;CACvC;CAEA,MAAM,OAAO,KAAa,KAA4B;EACpD,KAAK,KAAK,OAAO,KAAK,GAAG;CAC3B;CAEA,MAAM,SAAS,GAAsC;EACnD,IAAI,CAAC,KAAK,UACR,MAAM,IAAI,MAAM,0DAA0D;EAE5E,MAAM,WAAW,KAAK;EAEtB,MAAM,UAAoC,CAAC;EAC3C,KAAK,IAAI,QAAQ,GAAG,QAAQ,EAAE,QAAQ,QAAQ,SAC5C,IAAI;GACF,QAAQ,KAAK,MAAM,SAAS,UAAU,GAAG,KAAK,CAAC;EACjD,SAAS,KAAK;GACZ,IAAI,EAAE,eAAe,oBACnB,KAAK,QAAQ,MAAM,4BAA4B;IAC7C,OAAO,EAAE;IACT,cAAc,EAAE;IAChB,OAAO,EAAE;IACT;IACA;GACF,CAAC;GAEH,QAAQ,KAAK;IACX;IACA,MAAM,EAAE,QAAQ,MAAM,CAAE;IACxB,QAAQ;IACR,OAAO,qBAAqB,GAAG;GACjC,CAAC;GACD;EACF;EAGF,MAAM,SAAS,SAAS,GAAG,OAAO;CACpC;CAEA,MAAM,QAAQ,GAAoC;EAChD,IAAI,CAAC,KAAK,UACR,MAAM,IAAI,MAAM,yDAAyD;EAE3E,MAAM,KAAK,SAAS,YAAY,GAAG,IAAI;CACzC;CAEA,MAAM,QAAuB;EAC3B,KAAK,UAAU,KAAK;EACpB,KAAK,WAAW,wBAAwB,KAAK,UAAU,KAAK,MAAM;EAClE,KAAK,KAAK,MAAM;CAClB;CAEA,MAAM,OAAsB;EAC1B,KAAK,UAAU,KAAK;EACpB,KAAK,WAAW,KAAA;EAChB,KAAK,KAAK,KAAK;CACjB;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/workflows/index.ts"],"sourcesContent":["// Default in-process engine — runs a dispatched automation immediately, one\n// attempt per action; durable engines (Hatchet, …) are installation adapters.\nimport type {\n AutomationActionResult,\n AutomationDispatch,\n AutomationEngine,\n AutomationExecutor,\n DeliveryDispatch,\n DeliveryExecutor,\n JsonValue,\n Logger,\n} from \"@headless-lms/core/types\";\nimport type { RecurringJob, ScheduledJob, Scheduler } from \"@headless-lms/core/shared/ports\";\nimport { ActionFailedError, actionFailureMessage } from \"@headless-lms/core/automations\";\nimport { startScheduleLoop } from \"./schedule.js\";\nimport { InlineJobs } from \"./jobs.js\";\n\nexport { startScheduleLoop };\n\nexport class InlineAutomationEngine implements AutomationEngine, Scheduler {\n private executor: AutomationExecutor | undefined;\n private deliveries: DeliveryExecutor | undefined;\n private schedule: { stop(): void } | undefined;\n private readonly jobs: InlineJobs;\n\n constructor(private readonly logger?: Logger) {\n this.jobs = new InlineJobs(logger);\n }\n\n register(executor: AutomationExecutor): void {\n this.executor = executor;\n }\n\n registerDeliveries(executor: DeliveryExecutor): void {\n this.deliveries = executor;\n }\n\n registerJobs(handlers: ScheduledJob[], recurring: RecurringJob[]): void {\n this.jobs.register(handlers, recurring);\n }\n\n async at(job: string, runAt: Date, key: string, payload: JsonValue): Promise<void> {\n this.jobs.at(job, runAt, key, payload);\n }\n\n async cancel(job: string, key: string): Promise<void> {\n this.jobs.cancel(job, key);\n }\n\n async dispatch(d: AutomationDispatch): Promise<void> {\n if (!this.executor) {\n throw new Error(\"InlineAutomationEngine.dispatch called before register()\");\n }\n const executor = this.executor;\n\n const results: AutomationActionResult[] = [];\n for (let index = 0; index < d.actions.length; index++) {\n try {\n results.push(await executor.runAction(d, index));\n } catch (err) {\n if (!(err instanceof ActionFailedError)) {\n this.logger?.error(\"automation action failed\", {\n orgId: d.orgId,\n automationId: d.automationId,\n runId: d.runId,\n index,\n err,\n });\n }\n results.push({\n index,\n type: d.actions[index]!.type,\n status: \"failed\",\n error: actionFailureMessage(err),\n });\n break;\n }\n }\n\n await executor.finalize(d, results);\n }\n\n async deliver(d: DeliveryDispatch): Promise<void> {\n if (!this.deliveries) {\n throw new Error(\"InlineAutomationEngine.deliver called before registerDeliveries()\");\n }\n await this.deliveries.runDelivery(d, true);\n }\n\n async start(): Promise<void> {\n this.schedule?.stop();\n this.schedule = startScheduleLoop(() => this.executor, this.logger);\n this.jobs.start();\n }\n\n async stop(): Promise<void> {\n this.schedule?.stop();\n this.schedule = undefined;\n this.jobs.stop();\n }\n}\n"],"mappings":";;;;AAmBA,IAAa,yBAAb,MAA2E;CAM5C;CAL7B;CACA;CACA;CACA;CAEA,YAAY,QAAkC;EAAjB,KAAA,SAAA;EAC3B,KAAK,OAAO,IAAI,WAAW,MAAM;CACnC;CAEA,SAAS,UAAoC;EAC3C,KAAK,WAAW;CAClB;CAEA,mBAAmB,UAAkC;EACnD,KAAK,aAAa;CACpB;CAEA,aAAa,UAA0B,WAAiC;EACtE,KAAK,KAAK,SAAS,UAAU,SAAS;CACxC;CAEA,MAAM,GAAG,KAAa,OAAa,KAAa,SAAmC;EACjF,KAAK,KAAK,GAAG,KAAK,OAAO,KAAK,OAAO;CACvC;CAEA,MAAM,OAAO,KAAa,KAA4B;EACpD,KAAK,KAAK,OAAO,KAAK,GAAG;CAC3B;CAEA,MAAM,SAAS,GAAsC;EACnD,IAAI,CAAC,KAAK,UACR,MAAM,IAAI,MAAM,0DAA0D;EAE5E,MAAM,WAAW,KAAK;EAEtB,MAAM,UAAoC,CAAC;EAC3C,KAAK,IAAI,QAAQ,GAAG,QAAQ,EAAE,QAAQ,QAAQ,SAC5C,IAAI;GACF,QAAQ,KAAK,MAAM,SAAS,UAAU,GAAG,KAAK,CAAC;EACjD,SAAS,KAAK;GACZ,IAAI,EAAE,eAAe,oBACnB,KAAK,QAAQ,MAAM,4BAA4B;IAC7C,OAAO,EAAE;IACT,cAAc,EAAE;IAChB,OAAO,EAAE;IACT;IACA;GACF,CAAC;GAEH,QAAQ,KAAK;IACX;IACA,MAAM,EAAE,QAAQ,MAAM,CAAE;IACxB,QAAQ;IACR,OAAO,qBAAqB,GAAG;GACjC,CAAC;GACD;EACF;EAGF,MAAM,SAAS,SAAS,GAAG,OAAO;CACpC;CAEA,MAAM,QAAQ,GAAoC;EAChD,IAAI,CAAC,KAAK,YACR,MAAM,IAAI,MAAM,mEAAmE;EAErF,MAAM,KAAK,WAAW,YAAY,GAAG,IAAI;CAC3C;CAEA,MAAM,QAAuB;EAC3B,KAAK,UAAU,KAAK;EACpB,KAAK,WAAW,wBAAwB,KAAK,UAAU,KAAK,MAAM;EAClE,KAAK,KAAK,MAAM;CAClB;CAEA,MAAM,OAAsB;EAC1B,KAAK,UAAU,KAAK;EACpB,KAAK,WAAW,KAAA;EAChB,KAAK,KAAK,KAAK;CACjB;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-lms/adapter-defaults",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./email": {
@@ -45,8 +45,8 @@
45
45
  ],
46
46
  "dependencies": {
47
47
  "pino": "^10.3.1",
48
- "@headless-lms/adapter-db": "0.6.0",
49
- "@headless-lms/core": "0.6.0"
48
+ "@headless-lms/adapter-db": "0.6.2",
49
+ "@headless-lms/core": "0.8.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "^22.10.2",