@nestjs/workflows 0.0.1

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 (265) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +50 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +8 -0
  5. package/dist/core/codecs/aes-gcm-payload.codec.d.ts +42 -0
  6. package/dist/core/codecs/aes-gcm-payload.codec.js +119 -0
  7. package/dist/core/codecs/index.d.ts +2 -0
  8. package/dist/core/codecs/index.js +2 -0
  9. package/dist/core/codecs/payload-codecs.d.ts +59 -0
  10. package/dist/core/codecs/payload-codecs.js +130 -0
  11. package/dist/core/index.d.ts +16 -0
  12. package/dist/core/index.js +21 -0
  13. package/dist/core/interfaces/clock.interface.d.ts +18 -0
  14. package/dist/core/interfaces/clock.interface.js +1 -0
  15. package/dist/core/interfaces/index.d.ts +9 -0
  16. package/dist/core/interfaces/index.js +9 -0
  17. package/dist/core/interfaces/leased-worker-options.interface.d.ts +94 -0
  18. package/dist/core/interfaces/leased-worker-options.interface.js +1 -0
  19. package/dist/core/interfaces/limits.interface.d.ts +92 -0
  20. package/dist/core/interfaces/limits.interface.js +1 -0
  21. package/dist/core/interfaces/payload-codec.interface.d.ts +64 -0
  22. package/dist/core/interfaces/payload-codec.interface.js +1 -0
  23. package/dist/core/interfaces/result-waiter-options.interface.d.ts +52 -0
  24. package/dist/core/interfaces/result-waiter-options.interface.js +1 -0
  25. package/dist/core/interfaces/retry-settings.interface.d.ts +71 -0
  26. package/dist/core/interfaces/retry-settings.interface.js +1 -0
  27. package/dist/core/interfaces/schedule-store.interface.d.ts +143 -0
  28. package/dist/core/interfaces/schedule-store.interface.js +1 -0
  29. package/dist/core/interfaces/schedule.interface.d.ts +106 -0
  30. package/dist/core/interfaces/schedule.interface.js +1 -0
  31. package/dist/core/interfaces/scheduler-options.interface.d.ts +152 -0
  32. package/dist/core/interfaces/scheduler-options.interface.js +1 -0
  33. package/dist/core/limits/index.d.ts +1 -0
  34. package/dist/core/limits/index.js +1 -0
  35. package/dist/core/limits/limits.d.ts +61 -0
  36. package/dist/core/limits/limits.js +130 -0
  37. package/dist/core/results/index.d.ts +1 -0
  38. package/dist/core/results/index.js +1 -0
  39. package/dist/core/results/result-waiter.d.ts +54 -0
  40. package/dist/core/results/result-waiter.js +140 -0
  41. package/dist/core/retries/index.d.ts +1 -0
  42. package/dist/core/retries/index.js +1 -0
  43. package/dist/core/retries/retry.d.ts +60 -0
  44. package/dist/core/retries/retry.js +107 -0
  45. package/dist/core/scheduling/cron.util.d.ts +52 -0
  46. package/dist/core/scheduling/cron.util.js +262 -0
  47. package/dist/core/scheduling/encoded-schedule.store.d.ts +26 -0
  48. package/dist/core/scheduling/encoded-schedule.store.js +54 -0
  49. package/dist/core/scheduling/in-memory-schedule.store.d.ts +20 -0
  50. package/dist/core/scheduling/in-memory-schedule.store.js +90 -0
  51. package/dist/core/scheduling/index.d.ts +3 -0
  52. package/dist/core/scheduling/index.js +3 -0
  53. package/dist/core/scheduling/rrule.util.d.ts +55 -0
  54. package/dist/core/scheduling/rrule.util.js +371 -0
  55. package/dist/core/scheduling/schedule-spec.d.ts +57 -0
  56. package/dist/core/scheduling/schedule-spec.js +233 -0
  57. package/dist/core/scheduling/scheduler.d.ts +134 -0
  58. package/dist/core/scheduling/scheduler.js +450 -0
  59. package/dist/core/scheduling/time-zone.util.d.ts +18 -0
  60. package/dist/core/scheduling/time-zone.util.js +88 -0
  61. package/dist/core/time/clock.d.ts +28 -0
  62. package/dist/core/time/clock.js +35 -0
  63. package/dist/core/time/duration.d.ts +21 -0
  64. package/dist/core/time/duration.js +30 -0
  65. package/dist/core/time/index.d.ts +2 -0
  66. package/dist/core/time/index.js +2 -0
  67. package/dist/core/utils/canonical.util.d.ts +2 -0
  68. package/dist/core/utils/canonical.util.js +4 -0
  69. package/dist/core/utils/maybe.util.d.ts +8 -0
  70. package/dist/core/utils/maybe.util.js +14 -0
  71. package/dist/core/utils/payload-place.util.d.ts +10 -0
  72. package/dist/core/utils/payload-place.util.js +32 -0
  73. package/dist/core/workers/index.d.ts +1 -0
  74. package/dist/core/workers/index.js +1 -0
  75. package/dist/core/workers/leased-worker.d.ts +86 -0
  76. package/dist/core/workers/leased-worker.js +280 -0
  77. package/dist/cqrs/decorators/index.d.ts +2 -0
  78. package/dist/cqrs/decorators/index.js +2 -0
  79. package/dist/cqrs/decorators/signal-on.decorator.d.ts +18 -0
  80. package/dist/cqrs/decorators/signal-on.decorator.js +34 -0
  81. package/dist/cqrs/decorators/start-on.decorator.d.ts +18 -0
  82. package/dist/cqrs/decorators/start-on.decorator.js +49 -0
  83. package/dist/cqrs/index.d.ts +3 -0
  84. package/dist/cqrs/index.js +5 -0
  85. package/dist/cqrs/interfaces/index.d.ts +4 -0
  86. package/dist/cqrs/interfaces/index.js +4 -0
  87. package/dist/cqrs/interfaces/signal-on-options.interface.d.ts +22 -0
  88. package/dist/cqrs/interfaces/signal-on-options.interface.js +1 -0
  89. package/dist/cqrs/interfaces/start-on-options.interface.d.ts +23 -0
  90. package/dist/cqrs/interfaces/start-on-options.interface.js +1 -0
  91. package/dist/cqrs/interfaces/workflow-dispatcher-context.interface.d.ts +10 -0
  92. package/dist/cqrs/interfaces/workflow-dispatcher-context.interface.js +1 -0
  93. package/dist/cqrs/interfaces/workflow-event-route.interface.d.ts +20 -0
  94. package/dist/cqrs/interfaces/workflow-event-route.interface.js +1 -0
  95. package/dist/cqrs/utils/event-routes.util.d.ts +7 -0
  96. package/dist/cqrs/utils/event-routes.util.js +22 -0
  97. package/dist/cqrs/workflow-event.publisher.d.ts +52 -0
  98. package/dist/cqrs/workflow-event.publisher.js +257 -0
  99. package/dist/cqrs/workflow-events.explorer.d.ts +27 -0
  100. package/dist/cqrs/workflow-events.explorer.js +92 -0
  101. package/dist/cqrs/workflows-cqrs.module.d.ts +10 -0
  102. package/dist/cqrs/workflows-cqrs.module.js +27 -0
  103. package/dist/decorators/index.d.ts +1 -0
  104. package/dist/decorators/index.js +1 -0
  105. package/dist/decorators/workflow.decorator.d.ts +7 -0
  106. package/dist/decorators/workflow.decorator.js +52 -0
  107. package/dist/errors/child-workflow-failed.error.d.ts +13 -0
  108. package/dist/errors/child-workflow-failed.error.js +14 -0
  109. package/dist/errors/index.d.ts +13 -0
  110. package/dist/errors/index.js +13 -0
  111. package/dist/errors/non-retryable-step.error.d.ts +4 -0
  112. package/dist/errors/non-retryable-step.error.js +7 -0
  113. package/dist/errors/step-failed.error.d.ts +15 -0
  114. package/dist/errors/step-failed.error.js +16 -0
  115. package/dist/errors/step-timeout.error.d.ts +5 -0
  116. package/dist/errors/step-timeout.error.js +8 -0
  117. package/dist/errors/workflow-definition.error.d.ts +10 -0
  118. package/dist/errors/workflow-definition.error.js +13 -0
  119. package/dist/errors/workflow-failed.error.d.ts +20 -0
  120. package/dist/errors/workflow-failed.error.js +17 -0
  121. package/dist/errors/workflow-id-conflict.error.d.ts +6 -0
  122. package/dist/errors/workflow-id-conflict.error.js +9 -0
  123. package/dist/errors/workflow-interrupt.error.d.ts +32 -0
  124. package/dist/errors/workflow-interrupt.error.js +19 -0
  125. package/dist/errors/workflow-non-determinism.error.d.ts +4 -0
  126. package/dist/errors/workflow-non-determinism.error.js +7 -0
  127. package/dist/errors/workflow-not-found.error.d.ts +10 -0
  128. package/dist/errors/workflow-not-found.error.js +13 -0
  129. package/dist/errors/workflow-result-timeout.error.d.ts +11 -0
  130. package/dist/errors/workflow-result-timeout.error.js +13 -0
  131. package/dist/errors/workflow-state.error.d.ts +11 -0
  132. package/dist/errors/workflow-state.error.js +14 -0
  133. package/dist/errors/workflow.error.d.ts +7 -0
  134. package/dist/errors/workflow.error.js +7 -0
  135. package/dist/events/index.d.ts +3 -0
  136. package/dist/events/index.js +3 -0
  137. package/dist/events/workflow-events.interface.d.ts +145 -0
  138. package/dist/events/workflow-events.interface.js +1 -0
  139. package/dist/events/workflow-events.service.d.ts +17 -0
  140. package/dist/events/workflow-events.service.js +38 -0
  141. package/dist/events/workflows.channels.d.ts +3 -0
  142. package/dist/events/workflows.channels.js +9 -0
  143. package/dist/index.d.ts +20 -0
  144. package/dist/index.js +23 -0
  145. package/dist/interfaces/index.d.ts +13 -0
  146. package/dist/interfaces/index.js +13 -0
  147. package/dist/interfaces/serialized-workflow-error.interface.d.ts +6 -0
  148. package/dist/interfaces/serialized-workflow-error.interface.js +1 -0
  149. package/dist/interfaces/workflow-client.interface.d.ts +156 -0
  150. package/dist/interfaces/workflow-client.interface.js +1 -0
  151. package/dist/interfaces/workflow-clock.interface.d.ts +7 -0
  152. package/dist/interfaces/workflow-clock.interface.js +1 -0
  153. package/dist/interfaces/workflow-context.interface.d.ts +241 -0
  154. package/dist/interfaces/workflow-context.interface.js +1 -0
  155. package/dist/interfaces/workflow-decorator-options.interface.d.ts +101 -0
  156. package/dist/interfaces/workflow-decorator-options.interface.js +1 -0
  157. package/dist/interfaces/workflow-instance.interface.d.ts +83 -0
  158. package/dist/interfaces/workflow-instance.interface.js +1 -0
  159. package/dist/interfaces/workflow-payload-codec.interface.d.ts +32 -0
  160. package/dist/interfaces/workflow-payload-codec.interface.js +1 -0
  161. package/dist/interfaces/workflow-retry-options.interface.d.ts +9 -0
  162. package/dist/interfaces/workflow-retry-options.interface.js +1 -0
  163. package/dist/interfaces/workflow-runner.interface.d.ts +11 -0
  164. package/dist/interfaces/workflow-runner.interface.js +1 -0
  165. package/dist/interfaces/workflow-schedule.interface.d.ts +104 -0
  166. package/dist/interfaces/workflow-schedule.interface.js +1 -0
  167. package/dist/interfaces/workflow-storage.interface.d.ts +4 -0
  168. package/dist/interfaces/workflow-storage.interface.js +1 -0
  169. package/dist/interfaces/workflow-store.interface.d.ts +488 -0
  170. package/dist/interfaces/workflow-store.interface.js +1 -0
  171. package/dist/interfaces/workflows-module-options.interface.d.ts +80 -0
  172. package/dist/interfaces/workflows-module-options.interface.js +1 -0
  173. package/dist/mysql/index.d.ts +5 -0
  174. package/dist/mysql/index.js +8 -0
  175. package/dist/mysql/interfaces/index.d.ts +1 -0
  176. package/dist/mysql/interfaces/index.js +1 -0
  177. package/dist/mysql/interfaces/mysql-workflow-store-options.interface.d.ts +25 -0
  178. package/dist/mysql/interfaces/mysql-workflow-store-options.interface.js +1 -0
  179. package/dist/mysql/key-limits.d.ts +30 -0
  180. package/dist/mysql/key-limits.js +41 -0
  181. package/dist/mysql/migrations/index.d.ts +7 -0
  182. package/dist/mysql/migrations/index.js +16 -0
  183. package/dist/mysql/migrations/initial.migration.d.ts +9 -0
  184. package/dist/mysql/migrations/initial.migration.js +104 -0
  185. package/dist/mysql/mysql-workflow.store.d.ts +197 -0
  186. package/dist/mysql/mysql-workflow.store.js +828 -0
  187. package/dist/postgres/errors/index.d.ts +1 -0
  188. package/dist/postgres/errors/index.js +2 -0
  189. package/dist/postgres/index.d.ts +5 -0
  190. package/dist/postgres/index.js +8 -0
  191. package/dist/postgres/interfaces/index.d.ts +1 -0
  192. package/dist/postgres/interfaces/index.js +1 -0
  193. package/dist/postgres/interfaces/postgres-workflow-store-options.interface.d.ts +22 -0
  194. package/dist/postgres/interfaces/postgres-workflow-store-options.interface.js +1 -0
  195. package/dist/postgres/migrations/index.d.ts +6 -0
  196. package/dist/postgres/migrations/index.js +15 -0
  197. package/dist/postgres/migrations/initial.migration.d.ts +6 -0
  198. package/dist/postgres/migrations/initial.migration.js +106 -0
  199. package/dist/postgres/postgres-workflow.store.d.ts +132 -0
  200. package/dist/postgres/postgres-workflow.store.js +586 -0
  201. package/dist/services/index.d.ts +6 -0
  202. package/dist/services/index.js +6 -0
  203. package/dist/services/workflow-client.service.d.ts +146 -0
  204. package/dist/services/workflow-client.service.js +436 -0
  205. package/dist/services/workflow-execution.service.d.ts +267 -0
  206. package/dist/services/workflow-execution.service.js +1076 -0
  207. package/dist/services/workflow-registry.service.d.ts +56 -0
  208. package/dist/services/workflow-registry.service.js +172 -0
  209. package/dist/services/workflow-scheduler.service.d.ts +54 -0
  210. package/dist/services/workflow-scheduler.service.js +173 -0
  211. package/dist/services/workflow-schedules.service.d.ts +60 -0
  212. package/dist/services/workflow-schedules.service.js +193 -0
  213. package/dist/services/workflow-worker.service.d.ts +92 -0
  214. package/dist/services/workflow-worker.service.js +468 -0
  215. package/dist/signals/index.d.ts +1 -0
  216. package/dist/signals/index.js +1 -0
  217. package/dist/signals/workflow.signal.d.ts +17 -0
  218. package/dist/signals/workflow.signal.js +28 -0
  219. package/dist/sql/rate-windows.d.ts +41 -0
  220. package/dist/sql/rate-windows.js +53 -0
  221. package/dist/sql/workflow-rows.d.ts +16 -0
  222. package/dist/sql/workflow-rows.js +102 -0
  223. package/dist/sql/workflow-schema.error.d.ts +21 -0
  224. package/dist/sql/workflow-schema.error.js +15 -0
  225. package/dist/storage/encoded-workflow.store.d.ts +71 -0
  226. package/dist/storage/encoded-workflow.store.js +201 -0
  227. package/dist/storage/index.d.ts +1 -0
  228. package/dist/storage/index.js +1 -0
  229. package/dist/storage/workflow.storage.d.ts +55 -0
  230. package/dist/storage/workflow.storage.js +159 -0
  231. package/dist/stores/in-memory-workflow.store.d.ts +75 -0
  232. package/dist/stores/in-memory-workflow.store.js +380 -0
  233. package/dist/stores/index.d.ts +1 -0
  234. package/dist/stores/index.js +1 -0
  235. package/dist/testing/assertions.d.ts +10 -0
  236. package/dist/testing/assertions.js +72 -0
  237. package/dist/testing/index.d.ts +38 -0
  238. package/dist/testing/index.js +1089 -0
  239. package/dist/testing/schedule-store.contract.d.ts +33 -0
  240. package/dist/testing/schedule-store.contract.js +161 -0
  241. package/dist/utils/index.d.ts +7 -0
  242. package/dist/utils/index.js +7 -0
  243. package/dist/utils/journal-limits.util.d.ts +6 -0
  244. package/dist/utils/journal-limits.util.js +25 -0
  245. package/dist/utils/new-instance.util.d.ts +26 -0
  246. package/dist/utils/new-instance.util.js +87 -0
  247. package/dist/utils/normalize.util.d.ts +5 -0
  248. package/dist/utils/normalize.util.js +11 -0
  249. package/dist/utils/run-timeout.util.d.ts +3 -0
  250. package/dist/utils/run-timeout.util.js +15 -0
  251. package/dist/utils/schedule-spec.util.d.ts +16 -0
  252. package/dist/utils/schedule-spec.util.js +9 -0
  253. package/dist/utils/schedule-store.util.d.ts +15 -0
  254. package/dist/utils/schedule-store.util.js +44 -0
  255. package/dist/utils/serialize-error.util.d.ts +7 -0
  256. package/dist/utils/serialize-error.util.js +22 -0
  257. package/dist/utils/step-scope.util.d.ts +16 -0
  258. package/dist/utils/step-scope.util.js +38 -0
  259. package/dist/workflows.constants.d.ts +10 -0
  260. package/dist/workflows.constants.js +10 -0
  261. package/dist/workflows.module-definition.d.ts +4 -0
  262. package/dist/workflows.module-definition.js +6 -0
  263. package/dist/workflows.module.d.ts +24 -0
  264. package/dist/workflows.module.js +68 -0
  265. package/package.json +123 -0
@@ -0,0 +1,52 @@
1
+ import { applyDecorators, Injectable, SetMetadata } from '@nestjs/common';
2
+ import { resolveConcurrency, resolveRateLimit } from '../core/limits/limits.js';
3
+ import { runTimeoutMs } from '../utils/run-timeout.util.js';
4
+ import { normalize } from '../utils/normalize.util.js';
5
+ import { assertScheduleId } from '../core/scheduling/schedule-spec.js';
6
+ import { scheduleSpec } from '../utils/schedule-spec.util.js';
7
+ import { WORKFLOW_METADATA } from '../workflows.constants.js';
8
+ /**
9
+ * Marks an injectable class with a `run(ctx, input)` method as a durable
10
+ * workflow. Register it as a provider in any module; constructor injection
11
+ * works as usual. Workflows must be singletons (default scope).
12
+ */
13
+ export function Workflow(name, options = {}) {
14
+ if (!/^[\w.:-]+$/.test(name)) {
15
+ throw new TypeError(`Invalid workflow name "${name}". Use letters, digits, ".", ":", "_" or "-".`);
16
+ }
17
+ const version = options.version ?? 1;
18
+ if (!Number.isInteger(version) || version < 1) {
19
+ throw new TypeError(`Invalid version ${version} for workflow "${name}". Use a positive integer.`);
20
+ }
21
+ const timeout = options.timeout === undefined ? undefined : runTimeoutMs(options.timeout, `workflow "${name}"`);
22
+ const concurrency = options.concurrency === undefined ? null : resolveConcurrency(`workflow "${name}"`, options.concurrency);
23
+ const rateLimit = options.rateLimit === undefined ? null : resolveRateLimit(`workflow "${name}"`, options.rateLimit);
24
+ const schedules = options.schedules === undefined ? [] : schedulesOf(name, options.schedules);
25
+ return applyDecorators(Injectable(), SetMetadata(WORKFLOW_METADATA, { name, version, timeout, concurrency, rateLimit, schedules }));
26
+ }
27
+ function schedulesOf(name, schedules) {
28
+ if (!Array.isArray(schedules)) {
29
+ throw new TypeError(`Workflow "${name}": schedules must be an array, such as [{ id: 'weekly-digest', cron: '0 8 * * MON' }].`);
30
+ }
31
+ const ids = new Set();
32
+ return schedules.map((declaration) => {
33
+ const id = declaration?.id;
34
+ assertScheduleId(id, `workflow "${name}"`);
35
+ if (ids.has(id)) {
36
+ throw new TypeError(`Workflow "${name}" declares schedule "${id}" twice.`);
37
+ }
38
+ ids.add(id);
39
+ const owner = `Schedule "${id}" of workflow "${name}"`;
40
+ const inputFn = typeof declaration.input === 'function';
41
+ let input = declaration.input;
42
+ if (!inputFn) {
43
+ try {
44
+ input = normalize(declaration.input);
45
+ }
46
+ catch (error) {
47
+ throw new TypeError(`${owner}: its input is not JSON-serializable: ${error.message}`);
48
+ }
49
+ }
50
+ return { id, spec: scheduleSpec(owner, declaration, { version: null, inputFn }), input };
51
+ });
52
+ }
@@ -0,0 +1,13 @@
1
+ import type { SerializedWorkflowError } from '../interfaces/serialized-workflow-error.interface.js';
2
+ import { WorkflowFailedError, type WorkflowFailureStatus } from './workflow-failed.error.js';
3
+ /**
4
+ * A child workflow (`ctx.startChild()`) ended without completing: what its handle's `result()`
5
+ * and `ctx.executeChild()` throw in the parent. `status` says how it ended, `cause` is its error.
6
+ * Built from the journal on every replay, like `StepFailedError`, so a parent that catches it
7
+ * and branches sees the same error each time.
8
+ */
9
+ export declare class ChildWorkflowFailedError extends WorkflowFailedError {
10
+ readonly workflow: string;
11
+ name: string;
12
+ constructor(workflow: string, instanceId: string, status: WorkflowFailureStatus, cause: SerializedWorkflowError);
13
+ }
@@ -0,0 +1,14 @@
1
+ import { WorkflowFailedError } from './workflow-failed.error.js';
2
+ /**
3
+ * A child workflow (`ctx.startChild()`) ended without completing: what its handle's `result()`
4
+ * and `ctx.executeChild()` throw in the parent. `status` says how it ended, `cause` is its error.
5
+ * Built from the journal on every replay, like `StepFailedError`, so a parent that catches it
6
+ * and branches sees the same error each time.
7
+ */
8
+ export class ChildWorkflowFailedError extends WorkflowFailedError {
9
+ constructor(workflow, instanceId, status, cause) {
10
+ super(`Child workflow "${workflow}" ("${instanceId}") ${status.replace('_', ' ')}: ${cause.name}: ${cause.message}`, { instanceId, status, cause });
11
+ this.workflow = workflow;
12
+ this.name = 'ChildWorkflowFailedError';
13
+ }
14
+ }
@@ -0,0 +1,13 @@
1
+ export * from './child-workflow-failed.error.js';
2
+ export * from './non-retryable-step.error.js';
3
+ export * from './step-failed.error.js';
4
+ export * from './step-timeout.error.js';
5
+ export * from './workflow-definition.error.js';
6
+ export * from './workflow-failed.error.js';
7
+ export * from './workflow-id-conflict.error.js';
8
+ export * from './workflow-interrupt.error.js';
9
+ export * from './workflow-non-determinism.error.js';
10
+ export * from './workflow-result-timeout.error.js';
11
+ export * from './workflow-state.error.js';
12
+ export * from './workflow-not-found.error.js';
13
+ export * from './workflow.error.js';
@@ -0,0 +1,13 @@
1
+ export * from './child-workflow-failed.error.js';
2
+ export * from './non-retryable-step.error.js';
3
+ export * from './step-failed.error.js';
4
+ export * from './step-timeout.error.js';
5
+ export * from './workflow-definition.error.js';
6
+ export * from './workflow-failed.error.js';
7
+ export * from './workflow-id-conflict.error.js';
8
+ export * from './workflow-interrupt.error.js';
9
+ export * from './workflow-non-determinism.error.js';
10
+ export * from './workflow-result-timeout.error.js';
11
+ export * from './workflow-state.error.js';
12
+ export * from './workflow-not-found.error.js';
13
+ export * from './workflow.error.js';
@@ -0,0 +1,4 @@
1
+ /** Throw from a step to fail it without retrying (a declined card, a 4xx). */
2
+ export declare class NonRetryableStepError extends Error {
3
+ name: string;
4
+ }
@@ -0,0 +1,7 @@
1
+ /** Throw from a step to fail it without retrying (a declined card, a 4xx). */
2
+ export class NonRetryableStepError extends Error {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.name = 'NonRetryableStepError';
6
+ }
7
+ }
@@ -0,0 +1,15 @@
1
+ import type { SerializedWorkflowError } from '../interfaces/serialized-workflow-error.interface.js';
2
+ import { WorkflowError } from './workflow.error.js';
3
+ /**
4
+ * A step gave up (retries exhausted, or a `NonRetryableStepError`). Built from the
5
+ * journal on both the first run and every replay, so a workflow that catches it
6
+ * and branches sees exactly the same error each time. The original class is not
7
+ * preserved; `cause` carries its name and message.
8
+ */
9
+ export declare class StepFailedError extends WorkflowError {
10
+ readonly step: string;
11
+ readonly attempts: number;
12
+ readonly cause: SerializedWorkflowError;
13
+ name: string;
14
+ constructor(step: string, attempts: number, cause: SerializedWorkflowError);
15
+ }
@@ -0,0 +1,16 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * A step gave up (retries exhausted, or a `NonRetryableStepError`). Built from the
4
+ * journal on both the first run and every replay, so a workflow that catches it
5
+ * and branches sees exactly the same error each time. The original class is not
6
+ * preserved; `cause` carries its name and message.
7
+ */
8
+ export class StepFailedError extends WorkflowError {
9
+ constructor(step, attempts, cause) {
10
+ super(`Step "${step}" failed after ${attempts} attempt(s): ${cause.name}: ${cause.message}`);
11
+ this.step = step;
12
+ this.attempts = attempts;
13
+ this.cause = cause;
14
+ this.name = 'StepFailedError';
15
+ }
16
+ }
@@ -0,0 +1,5 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /** A step attempt ran past its `timeout` or `heartbeatTimeout`. Retryable. */
3
+ export declare class StepTimeoutError extends WorkflowError {
4
+ name: string;
5
+ }
@@ -0,0 +1,8 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /** A step attempt ran past its `timeout` or `heartbeatTimeout`. Retryable. */
3
+ export class StepTimeoutError extends WorkflowError {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.name = 'StepTimeoutError';
7
+ }
8
+ }
@@ -0,0 +1,10 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * The workflow code cannot run against this instance's journal: a name is used
4
+ * twice, a `ctx` method is called inside a step, or a deployed change renamed,
5
+ * removed or reordered steps. The instance fails without compensation, because
6
+ * the compensations are defined by the same code that no longer matches.
7
+ */
8
+ export declare class WorkflowDefinitionError extends WorkflowError {
9
+ name: string;
10
+ }
@@ -0,0 +1,13 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * The workflow code cannot run against this instance's journal: a name is used
4
+ * twice, a `ctx` method is called inside a step, or a deployed change renamed,
5
+ * removed or reordered steps. The instance fails without compensation, because
6
+ * the compensations are defined by the same code that no longer matches.
7
+ */
8
+ export class WorkflowDefinitionError extends WorkflowError {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.name = 'WorkflowDefinitionError';
12
+ }
13
+ }
@@ -0,0 +1,20 @@
1
+ import type { SerializedWorkflowError } from '../interfaces/serialized-workflow-error.interface.js';
2
+ import { WorkflowError } from './workflow.error.js';
3
+ /** How an instance ended when it didn't complete. */
4
+ export type WorkflowFailureStatus = 'failed' | 'cancelled' | 'compensation_failed';
5
+ /**
6
+ * Thrown by `ctx.fail()`: fails the instance and runs its compensations. Also what
7
+ * `WorkflowClient.result()` and `startAndWait()` reject with when the instance ended without
8
+ * completing: then `instanceId`, `status` and `cause` (the instance's error) are set.
9
+ */
10
+ export declare class WorkflowFailedError extends WorkflowError {
11
+ name: string;
12
+ readonly instanceId?: string;
13
+ readonly status?: WorkflowFailureStatus;
14
+ readonly cause?: SerializedWorkflowError;
15
+ constructor(message: string, details?: {
16
+ instanceId: string;
17
+ status: WorkflowFailureStatus;
18
+ cause: SerializedWorkflowError;
19
+ });
20
+ }
@@ -0,0 +1,17 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * Thrown by `ctx.fail()`: fails the instance and runs its compensations. Also what
4
+ * `WorkflowClient.result()` and `startAndWait()` reject with when the instance ended without
5
+ * completing: then `instanceId`, `status` and `cause` (the instance's error) are set.
6
+ */
7
+ export class WorkflowFailedError extends WorkflowError {
8
+ constructor(message, details) {
9
+ super(message);
10
+ this.name = 'WorkflowFailedError';
11
+ if (details) {
12
+ this.instanceId = details.instanceId;
13
+ this.status = details.status;
14
+ this.cause = details.cause;
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,6 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /** `start()` with an existing id but a different workflow or input. `status` 409. */
3
+ export declare class WorkflowIdConflictError extends WorkflowError {
4
+ name: string;
5
+ readonly status = 409;
6
+ }
@@ -0,0 +1,9 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /** `start()` with an existing id but a different workflow or input. `status` 409. */
3
+ export class WorkflowIdConflictError extends WorkflowError {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.name = 'WorkflowIdConflictError';
7
+ this.status = 409;
8
+ }
9
+ }
@@ -0,0 +1,32 @@
1
+ export type InterruptReason =
2
+ /** A sleep, wait or retry backoff is pending: the run is parked until later. */
3
+ 'suspend'
4
+ /** A replay for compensation reached code that has not run yet. */
5
+ | 'halt'
6
+ /** `WorkflowClient.cancel()` was accepted while the run was executing. */
7
+ | 'cancel'
8
+ /** The instance's run timeout passed. */
9
+ | 'timeout'
10
+ /** The instance's journal reached the module's `journal.maxEntries` or `journal.maxBytes`. */
11
+ | 'journal-limit'
12
+ /** Another worker took over the instance; nothing this run does is recorded. */
13
+ | 'lease-lost'
14
+ /** The application is shutting down; the instance is handed back. */
15
+ | 'shutdown'
16
+ /** The store failed; the instance is retried once the lease expires. */
17
+ | 'store-error';
18
+ /**
19
+ * Thrown by `ctx` operations to unwind the workflow function. It is control
20
+ * flow, not a failure: code that catches errors inside `run()` must rethrow it
21
+ * (`if (isWorkflowInterrupt(e)) throw e`). The engine does not depend on seeing
22
+ * it, though. Once an execution is parking, no step starts and nothing passes a
23
+ * `commit()`; a cancel, shutdown, lost lease or store failure decides the
24
+ * outcome however `run()` ends. A swallowed interrupt only wastes the code that
25
+ * runs after it.
26
+ */
27
+ export declare class WorkflowInterrupt extends Error {
28
+ readonly reason: InterruptReason;
29
+ name: string;
30
+ constructor(reason: InterruptReason);
31
+ }
32
+ export declare function isWorkflowInterrupt(error: unknown): error is WorkflowInterrupt;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Thrown by `ctx` operations to unwind the workflow function. It is control
3
+ * flow, not a failure: code that catches errors inside `run()` must rethrow it
4
+ * (`if (isWorkflowInterrupt(e)) throw e`). The engine does not depend on seeing
5
+ * it, though. Once an execution is parking, no step starts and nothing passes a
6
+ * `commit()`; a cancel, shutdown, lost lease or store failure decides the
7
+ * outcome however `run()` ends. A swallowed interrupt only wastes the code that
8
+ * runs after it.
9
+ */
10
+ export class WorkflowInterrupt extends Error {
11
+ constructor(reason) {
12
+ super(`Workflow execution interrupted (${reason}). Rethrow this error if you catch it.`);
13
+ this.reason = reason;
14
+ this.name = 'WorkflowInterrupt';
15
+ }
16
+ }
17
+ export function isWorkflowInterrupt(error) {
18
+ return error instanceof WorkflowInterrupt;
19
+ }
@@ -0,0 +1,4 @@
1
+ import { WorkflowDefinitionError } from './workflow-definition.error.js';
2
+ export declare class WorkflowNonDeterminismError extends WorkflowDefinitionError {
3
+ name: string;
4
+ }
@@ -0,0 +1,7 @@
1
+ import { WorkflowDefinitionError } from './workflow-definition.error.js';
2
+ export class WorkflowNonDeterminismError extends WorkflowDefinitionError {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.name = 'WorkflowNonDeterminismError';
6
+ }
7
+ }
@@ -0,0 +1,10 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * `cancel()` of an unknown instance id, or `start()` of a workflow this
4
+ * application cannot resolve. `status` 404: the caller asked for something
5
+ * that doesn't exist, so retrying won't help.
6
+ */
7
+ export declare class WorkflowNotFoundError extends WorkflowError {
8
+ name: string;
9
+ readonly status = 404;
10
+ }
@@ -0,0 +1,13 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * `cancel()` of an unknown instance id, or `start()` of a workflow this
4
+ * application cannot resolve. `status` 404: the caller asked for something
5
+ * that doesn't exist, so retrying won't help.
6
+ */
7
+ export class WorkflowNotFoundError extends WorkflowError {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.name = 'WorkflowNotFoundError';
11
+ this.status = 404;
12
+ }
13
+ }
@@ -0,0 +1,11 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * `WorkflowClient.result()` (or `startAndWait()`) waited for its `timeout` and the instance
4
+ * hadn't ended. The instance keeps running: wait again, or read it with `getStatus()`.
5
+ */
6
+ export declare class WorkflowResultTimeoutError extends WorkflowError {
7
+ readonly instanceId: string;
8
+ readonly timeoutMs: number;
9
+ name: string;
10
+ constructor(instanceId: string, timeoutMs: number);
11
+ }
@@ -0,0 +1,13 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * `WorkflowClient.result()` (or `startAndWait()`) waited for its `timeout` and the instance
4
+ * hadn't ended. The instance keeps running: wait again, or read it with `getStatus()`.
5
+ */
6
+ export class WorkflowResultTimeoutError extends WorkflowError {
7
+ constructor(instanceId, timeoutMs) {
8
+ super(`Instance "${instanceId}" didn't end within ${timeoutMs}ms. It keeps running; wait for it again or read it with getStatus().`);
9
+ this.instanceId = instanceId;
10
+ this.timeoutMs = timeoutMs;
11
+ this.name = 'WorkflowResultTimeoutError';
12
+ }
13
+ }
@@ -0,0 +1,11 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * An operator action that the instance's status rules out: `retry()` of an instance that isn't
4
+ * `failed` or `compensation_failed` (or whose compensations already undid its steps),
5
+ * `delete()` of an unfinished one without `force`, or either racing another change to the same
6
+ * instance. `status` 409.
7
+ */
8
+ export declare class WorkflowStateError extends WorkflowError {
9
+ name: string;
10
+ readonly status = 409;
11
+ }
@@ -0,0 +1,14 @@
1
+ import { WorkflowError } from './workflow.error.js';
2
+ /**
3
+ * An operator action that the instance's status rules out: `retry()` of an instance that isn't
4
+ * `failed` or `compensation_failed` (or whose compensations already undid its steps),
5
+ * `delete()` of an unfinished one without `force`, or either racing another change to the same
6
+ * instance. `status` 409.
7
+ */
8
+ export class WorkflowStateError extends WorkflowError {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.name = 'WorkflowStateError';
12
+ this.status = 409;
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Base class of the errors the package throws for an app to catch or inspect.
3
+ * Not of `WorkflowInterrupt` (control flow, never to be kept) or
4
+ * `NonRetryableStepError` (thrown by the app).
5
+ */
6
+ export declare abstract class WorkflowError extends Error {
7
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Base class of the errors the package throws for an app to catch or inspect.
3
+ * Not of `WorkflowInterrupt` (control flow, never to be kept) or
4
+ * `NonRetryableStepError` (thrown by the app).
5
+ */
6
+ export class WorkflowError extends Error {
7
+ }
@@ -0,0 +1,3 @@
1
+ export * from './workflow-events.interface.js';
2
+ export * from './workflow-events.service.js';
3
+ export * from './workflows.channels.js';
@@ -0,0 +1,3 @@
1
+ export * from './workflow-events.interface.js';
2
+ export * from './workflow-events.service.js';
3
+ export * from './workflows.channels.js';
@@ -0,0 +1,145 @@
1
+ import type { SerializedWorkflowError } from '../interfaces/serialized-workflow-error.interface.js';
2
+ import type { WorkflowStatus, WorkflowWait } from '../interfaces/workflow-instance.interface.js';
3
+ /** Fields every lifecycle event carries. */
4
+ export interface WorkflowEventBase {
5
+ /** Instance id (a schedule's id for `schedule-skipped`). */
6
+ id: string;
7
+ workflow: string;
8
+ version: number;
9
+ /** Engine clock time (ms). */
10
+ at: number;
11
+ }
12
+ /** Channel `nestjs:workflows:workflow-started`: the first execution of an instance began. */
13
+ export interface WorkflowStartedEvent extends WorkflowEventBase {
14
+ type: 'workflow-started';
15
+ }
16
+ /** Channel `nestjs:workflows:workflow-resumed`: a later execution began (after a wait, a sleep, a retry or a crash). */
17
+ export interface WorkflowResumedEvent extends WorkflowEventBase {
18
+ type: 'workflow-resumed';
19
+ /** The execution's number, 2 or more. */
20
+ run: number;
21
+ }
22
+ /** Channel `nestjs:workflows:workflow-suspended`: an execution parked the instance. */
23
+ export interface WorkflowSuspendedEvent extends WorkflowEventBase {
24
+ type: 'workflow-suspended';
25
+ wakeAt: number | null;
26
+ waits: WorkflowWait[];
27
+ }
28
+ /** Channel `nestjs:workflows:workflow-compensating`: the instance failed or was cancelled, and starts undoing. */
29
+ export interface WorkflowCompensatingEvent extends WorkflowEventBase {
30
+ type: 'workflow-compensating';
31
+ error: SerializedWorkflowError;
32
+ }
33
+ /** Channel `nestjs:workflows:workflow-completed`. */
34
+ export interface WorkflowCompletedEvent extends WorkflowEventBase {
35
+ type: 'workflow-completed';
36
+ output: unknown;
37
+ }
38
+ /** Channel `nestjs:workflows:workflow-failed`: failed, after its compensations ran (none for a definition error). */
39
+ export interface WorkflowFailedEvent extends WorkflowEventBase {
40
+ type: 'workflow-failed';
41
+ error: SerializedWorkflowError;
42
+ }
43
+ /** Channel `nestjs:workflows:workflow-cancelled`: cancelled, after its compensations ran. `error.message` is the reason. */
44
+ export interface WorkflowCancelledEvent extends WorkflowEventBase {
45
+ type: 'workflow-cancelled';
46
+ error: SerializedWorkflowError;
47
+ }
48
+ /** Channel `nestjs:workflows:workflow-compensation-failed`: an undo gave up halfway. Needs a person. */
49
+ export interface WorkflowCompensationFailedEvent extends WorkflowEventBase {
50
+ type: 'workflow-compensation-failed';
51
+ /** The original failure, with the compensation's own error as `compensation`. */
52
+ error: SerializedWorkflowError;
53
+ }
54
+ /** Channel `nestjs:workflows:step-completed`. */
55
+ export interface WorkflowStepCompletedEvent extends WorkflowEventBase {
56
+ type: 'step-completed';
57
+ step: string;
58
+ attempt: number;
59
+ durationMs: number;
60
+ }
61
+ /** Channel `nestjs:workflows:step-failed`: an attempt failed. `retryAt` is `null` when the step gave up. */
62
+ export interface WorkflowStepFailedEvent extends WorkflowEventBase {
63
+ type: 'step-failed';
64
+ step: string;
65
+ /** The attempt that failed (1-based). */
66
+ attempt: number;
67
+ error: SerializedWorkflowError;
68
+ retryAt: number | null;
69
+ }
70
+ /** Channel `nestjs:workflows:step-compensated`: a step's compensation completed. */
71
+ export interface WorkflowStepCompensatedEvent extends WorkflowEventBase {
72
+ type: 'step-compensated';
73
+ step: string;
74
+ attempt: number;
75
+ }
76
+ /** Channel `nestjs:workflows:child-started`: the instance started a child (`ctx.startChild()`). */
77
+ export interface WorkflowChildStartedEvent extends WorkflowEventBase {
78
+ type: 'child-started';
79
+ /** The child's id. */
80
+ child: string;
81
+ childWorkflow: string;
82
+ childVersion: number;
83
+ }
84
+ /** Channel `nestjs:workflows:signal-received`: a wait took a signal. */
85
+ export interface WorkflowSignalReceivedEvent extends WorkflowEventBase {
86
+ type: 'signal-received';
87
+ /** The wait's name. */
88
+ wait: string;
89
+ signal: string;
90
+ signalId: number;
91
+ }
92
+ /** Channel `nestjs:workflows:signal-timed-out`: a wait's deadline passed without a matching signal. */
93
+ export interface WorkflowSignalTimedOutEvent extends WorkflowEventBase {
94
+ type: 'signal-timed-out';
95
+ wait: string;
96
+ signal: string;
97
+ }
98
+ /**
99
+ * Channel `nestjs:workflows:journal-large`: the instance's journal reached the module's
100
+ * `journal.warnEntries` or `journal.warnBytes`. Emitted once, when it crosses the line.
101
+ */
102
+ export interface WorkflowJournalLargeEvent extends WorkflowEventBase {
103
+ type: 'journal-large';
104
+ entries: number;
105
+ bytes: number;
106
+ }
107
+ /**
108
+ * Channel `nestjs:workflows:custom-status`: the instance's custom status (`ctx.setStatus()`)
109
+ * changed, and was written.
110
+ */
111
+ export interface WorkflowCustomStatusEvent extends WorkflowEventBase {
112
+ type: 'custom-status';
113
+ status: unknown;
114
+ }
115
+ /**
116
+ * Channel `nestjs:workflows:workflow-retried`: an operator's `WorkflowClient.retry()` reopened a
117
+ * `failed` instance (it runs again from its journal) or a `compensation_failed` one (its
118
+ * compensations run again).
119
+ */
120
+ export interface WorkflowRetriedEvent extends WorkflowEventBase {
121
+ type: 'workflow-retried';
122
+ from: 'failed' | 'compensation_failed';
123
+ /** The error the instance had. */
124
+ error: SerializedWorkflowError | null;
125
+ }
126
+ /** Channel `nestjs:workflows:workflow-deleted`: `WorkflowClient.delete()` removed an instance. */
127
+ export interface WorkflowDeletedEvent extends WorkflowEventBase {
128
+ type: 'workflow-deleted';
129
+ /** The status it had. */
130
+ status: WorkflowStatus;
131
+ }
132
+ /**
133
+ * Channel `nestjs:workflows:schedule-skipped`: a schedule passed over occurrences, missed while no worker was up
134
+ * (`reason: 'missed'`, see its `missed` option) or due while an instance it started still ran (`'overlap'`). `id`
135
+ * is the schedule's id, `workflow` and `version` what it starts.
136
+ */
137
+ export interface WorkflowScheduleSkippedEvent extends WorkflowEventBase {
138
+ type: 'schedule-skipped';
139
+ reason: 'missed' | 'overlap';
140
+ /** The first occurrence it passed over (epoch milliseconds). */
141
+ from: number;
142
+ /** The last one. */
143
+ to: number;
144
+ }
145
+ export type WorkflowEvent = WorkflowStartedEvent | WorkflowResumedEvent | WorkflowSuspendedEvent | WorkflowCompensatingEvent | WorkflowCompletedEvent | WorkflowFailedEvent | WorkflowCancelledEvent | WorkflowCompensationFailedEvent | WorkflowStepCompletedEvent | WorkflowStepFailedEvent | WorkflowStepCompensatedEvent | WorkflowChildStartedEvent | WorkflowSignalReceivedEvent | WorkflowSignalTimedOutEvent | WorkflowJournalLargeEvent | WorkflowCustomStatusEvent | WorkflowRetriedEvent | WorkflowDeletedEvent | WorkflowScheduleSkippedEvent;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import { type OnApplicationShutdown } from '@nestjs/common';
2
+ import { type Observable } from 'rxjs';
3
+ import type { WorkflowEvent } from './workflow-events.interface.js';
4
+ /**
5
+ * This application's lifecycle events, for logs, metrics and alerts. Every event
6
+ * is also published on its `node:diagnostics_channel` channel
7
+ * (`nestjs:workflows:<type>`), process-wide, where tracing tools (NestJS Observe,
8
+ * OpenTelemetry) subscribe without Nest. An instance maps onto one trace: the
9
+ * instance is the root span, each execution a child span, each step attempt a
10
+ * span inside it (https://docs.nestjs.com/reliability/workflows#events).
11
+ */
12
+ export declare class WorkflowEvents implements OnApplicationShutdown {
13
+ private readonly subject;
14
+ readonly events$: Observable<WorkflowEvent>;
15
+ emit(event: WorkflowEvent): void;
16
+ onApplicationShutdown(): void;
17
+ }