@nest-batch/core 0.2.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.
Files changed (476) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +368 -0
  3. package/dist/src/adapters/in-process.adapter.d.ts +140 -0
  4. package/dist/src/adapters/in-process.adapter.d.ts.map +1 -0
  5. package/dist/src/adapters/in-process.adapter.js +86 -0
  6. package/dist/src/adapters/in-process.adapter.js.map +1 -0
  7. package/dist/src/adapters/index.d.ts +18 -0
  8. package/dist/src/adapters/index.d.ts.map +1 -0
  9. package/dist/src/adapters/index.js +35 -0
  10. package/dist/src/adapters/index.js.map +1 -0
  11. package/dist/src/builder/batch-builder.d.ts +26 -0
  12. package/dist/src/builder/batch-builder.d.ts.map +1 -0
  13. package/dist/src/builder/batch-builder.js +25 -0
  14. package/dist/src/builder/batch-builder.js.map +1 -0
  15. package/dist/src/builder/flow-builder.d.ts +59 -0
  16. package/dist/src/builder/flow-builder.d.ts.map +1 -0
  17. package/dist/src/builder/flow-builder.js +115 -0
  18. package/dist/src/builder/flow-builder.js.map +1 -0
  19. package/dist/src/builder/index.d.ts +5 -0
  20. package/dist/src/builder/index.d.ts.map +1 -0
  21. package/dist/src/builder/index.js +23 -0
  22. package/dist/src/builder/index.js.map +1 -0
  23. package/dist/src/builder/job-builder.d.ts +76 -0
  24. package/dist/src/builder/job-builder.d.ts.map +1 -0
  25. package/dist/src/builder/job-builder.js +166 -0
  26. package/dist/src/builder/job-builder.js.map +1 -0
  27. package/dist/src/builder/step-builder.d.ts +74 -0
  28. package/dist/src/builder/step-builder.d.ts.map +1 -0
  29. package/dist/src/builder/step-builder.js +144 -0
  30. package/dist/src/builder/step-builder.js.map +1 -0
  31. package/dist/src/compiler/builder-types.d.ts +20 -0
  32. package/dist/src/compiler/builder-types.d.ts.map +1 -0
  33. package/dist/src/compiler/builder-types.js +6 -0
  34. package/dist/src/compiler/builder-types.js.map +1 -0
  35. package/dist/src/compiler/definition-compiler.d.ts +99 -0
  36. package/dist/src/compiler/definition-compiler.d.ts.map +1 -0
  37. package/dist/src/compiler/definition-compiler.js +257 -0
  38. package/dist/src/compiler/definition-compiler.js.map +1 -0
  39. package/dist/src/compiler/index.d.ts +3 -0
  40. package/dist/src/compiler/index.d.ts.map +1 -0
  41. package/dist/src/compiler/index.js +21 -0
  42. package/dist/src/compiler/index.js.map +1 -0
  43. package/dist/src/core/errors.d.ts +77 -0
  44. package/dist/src/core/errors.d.ts.map +1 -0
  45. package/dist/src/core/errors.js +170 -0
  46. package/dist/src/core/errors.js.map +1 -0
  47. package/dist/src/core/execution-context/index.d.ts +4 -0
  48. package/dist/src/core/execution-context/index.d.ts.map +1 -0
  49. package/dist/src/core/execution-context/index.js +22 -0
  50. package/dist/src/core/execution-context/index.js.map +1 -0
  51. package/dist/src/core/execution-context/json-value.d.ts +5 -0
  52. package/dist/src/core/execution-context/json-value.d.ts.map +1 -0
  53. package/dist/src/core/execution-context/json-value.js +6 -0
  54. package/dist/src/core/execution-context/json-value.js.map +1 -0
  55. package/dist/src/core/execution-context/serializer.d.ts +4 -0
  56. package/dist/src/core/execution-context/serializer.d.ts.map +1 -0
  57. package/dist/src/core/execution-context/serializer.js +34 -0
  58. package/dist/src/core/execution-context/serializer.js.map +1 -0
  59. package/dist/src/core/execution-context/validator.d.ts +18 -0
  60. package/dist/src/core/execution-context/validator.d.ts.map +1 -0
  61. package/dist/src/core/execution-context/validator.js +90 -0
  62. package/dist/src/core/execution-context/validator.js.map +1 -0
  63. package/dist/src/core/index.d.ts +8 -0
  64. package/dist/src/core/index.d.ts.map +1 -0
  65. package/dist/src/core/index.js +26 -0
  66. package/dist/src/core/index.js.map +1 -0
  67. package/dist/src/core/ir/decider-definition.d.ts +20 -0
  68. package/dist/src/core/ir/decider-definition.d.ts.map +1 -0
  69. package/dist/src/core/ir/decider-definition.js +6 -0
  70. package/dist/src/core/ir/decider-definition.js.map +1 -0
  71. package/dist/src/core/ir/index.d.ts +8 -0
  72. package/dist/src/core/ir/index.d.ts.map +1 -0
  73. package/dist/src/core/ir/index.js +26 -0
  74. package/dist/src/core/ir/index.js.map +1 -0
  75. package/dist/src/core/ir/job-definition.d.ts +15 -0
  76. package/dist/src/core/ir/job-definition.d.ts.map +1 -0
  77. package/dist/src/core/ir/job-definition.js +6 -0
  78. package/dist/src/core/ir/job-definition.js.map +1 -0
  79. package/dist/src/core/ir/listener-definition.d.ts +10 -0
  80. package/dist/src/core/ir/listener-definition.d.ts.map +1 -0
  81. package/dist/src/core/ir/listener-definition.js +6 -0
  82. package/dist/src/core/ir/listener-definition.js.map +1 -0
  83. package/dist/src/core/ir/policy-config.d.ts +24 -0
  84. package/dist/src/core/ir/policy-config.d.ts.map +1 -0
  85. package/dist/src/core/ir/policy-config.js +6 -0
  86. package/dist/src/core/ir/policy-config.js.map +1 -0
  87. package/dist/src/core/ir/refs.d.ts +42 -0
  88. package/dist/src/core/ir/refs.d.ts.map +1 -0
  89. package/dist/src/core/ir/refs.js +18 -0
  90. package/dist/src/core/ir/refs.js.map +1 -0
  91. package/dist/src/core/ir/step-definition.d.ts +59 -0
  92. package/dist/src/core/ir/step-definition.d.ts.map +1 -0
  93. package/dist/src/core/ir/step-definition.js +6 -0
  94. package/dist/src/core/ir/step-definition.js.map +1 -0
  95. package/dist/src/core/ir/transition-definition.d.ts +8 -0
  96. package/dist/src/core/ir/transition-definition.d.ts.map +1 -0
  97. package/dist/src/core/ir/transition-definition.js +6 -0
  98. package/dist/src/core/ir/transition-definition.js.map +1 -0
  99. package/dist/src/core/item/index.d.ts +2 -0
  100. package/dist/src/core/item/index.d.ts.map +1 -0
  101. package/dist/src/core/item/index.js +20 -0
  102. package/dist/src/core/item/index.js.map +1 -0
  103. package/dist/src/core/item/interfaces.d.ts +64 -0
  104. package/dist/src/core/item/interfaces.d.ts.map +1 -0
  105. package/dist/src/core/item/interfaces.js +6 -0
  106. package/dist/src/core/item/interfaces.js.map +1 -0
  107. package/dist/src/core/repository/index.d.ts +3 -0
  108. package/dist/src/core/repository/index.d.ts.map +1 -0
  109. package/dist/src/core/repository/index.js +21 -0
  110. package/dist/src/core/repository/index.js.map +1 -0
  111. package/dist/src/core/repository/job-repository.d.ts +60 -0
  112. package/dist/src/core/repository/job-repository.d.ts.map +1 -0
  113. package/dist/src/core/repository/job-repository.js +27 -0
  114. package/dist/src/core/repository/job-repository.js.map +1 -0
  115. package/dist/src/core/repository/types.d.ts +84 -0
  116. package/dist/src/core/repository/types.d.ts.map +1 -0
  117. package/dist/src/core/repository/types.js +6 -0
  118. package/dist/src/core/repository/types.js.map +1 -0
  119. package/dist/src/core/status.d.ts +29 -0
  120. package/dist/src/core/status.d.ts.map +1 -0
  121. package/dist/src/core/status.js +58 -0
  122. package/dist/src/core/status.js.map +1 -0
  123. package/dist/src/core/transaction/index.d.ts +2 -0
  124. package/dist/src/core/transaction/index.d.ts.map +1 -0
  125. package/dist/src/core/transaction/index.js +20 -0
  126. package/dist/src/core/transaction/index.js.map +1 -0
  127. package/dist/src/core/transaction/transaction-manager.d.ts +8 -0
  128. package/dist/src/core/transaction/transaction-manager.d.ts.map +1 -0
  129. package/dist/src/core/transaction/transaction-manager.js +14 -0
  130. package/dist/src/core/transaction/transaction-manager.js.map +1 -0
  131. package/dist/src/core/validation/definition-validator.d.ts +46 -0
  132. package/dist/src/core/validation/definition-validator.d.ts.map +1 -0
  133. package/dist/src/core/validation/definition-validator.js +177 -0
  134. package/dist/src/core/validation/definition-validator.js.map +1 -0
  135. package/dist/src/core/validation/index.d.ts +2 -0
  136. package/dist/src/core/validation/index.d.ts.map +1 -0
  137. package/dist/src/core/validation/index.js +20 -0
  138. package/dist/src/core/validation/index.js.map +1 -0
  139. package/dist/src/decorators/constants.d.ts +10 -0
  140. package/dist/src/decorators/constants.d.ts.map +1 -0
  141. package/dist/src/decorators/constants.js +50 -0
  142. package/dist/src/decorators/constants.js.map +1 -0
  143. package/dist/src/decorators/flow.decorator.d.ts +25 -0
  144. package/dist/src/decorators/flow.decorator.d.ts.map +1 -0
  145. package/dist/src/decorators/flow.decorator.js +19 -0
  146. package/dist/src/decorators/flow.decorator.js.map +1 -0
  147. package/dist/src/decorators/index.d.ts +8 -0
  148. package/dist/src/decorators/index.d.ts.map +1 -0
  149. package/dist/src/decorators/index.js +26 -0
  150. package/dist/src/decorators/index.js.map +1 -0
  151. package/dist/src/decorators/item.decorators.d.ts +32 -0
  152. package/dist/src/decorators/item.decorators.d.ts.map +1 -0
  153. package/dist/src/decorators/item.decorators.js +40 -0
  154. package/dist/src/decorators/item.decorators.js.map +1 -0
  155. package/dist/src/decorators/job.decorator.d.ts +11 -0
  156. package/dist/src/decorators/job.decorator.d.ts.map +1 -0
  157. package/dist/src/decorators/job.decorator.js +17 -0
  158. package/dist/src/decorators/job.decorator.js.map +1 -0
  159. package/dist/src/decorators/listener.decorators.d.ts +56 -0
  160. package/dist/src/decorators/listener.decorators.d.ts.map +1 -0
  161. package/dist/src/decorators/listener.decorators.js +157 -0
  162. package/dist/src/decorators/listener.decorators.js.map +1 -0
  163. package/dist/src/decorators/step.decorator.d.ts +25 -0
  164. package/dist/src/decorators/step.decorator.d.ts.map +1 -0
  165. package/dist/src/decorators/step.decorator.js +21 -0
  166. package/dist/src/decorators/step.decorator.js.map +1 -0
  167. package/dist/src/decorators/tasklet.decorator.d.ts +7 -0
  168. package/dist/src/decorators/tasklet.decorator.d.ts.map +1 -0
  169. package/dist/src/decorators/tasklet.decorator.js +21 -0
  170. package/dist/src/decorators/tasklet.decorator.js.map +1 -0
  171. package/dist/src/execution/batch-worker-runner.d.ts +27 -0
  172. package/dist/src/execution/batch-worker-runner.d.ts.map +1 -0
  173. package/dist/src/execution/batch-worker-runner.js +147 -0
  174. package/dist/src/execution/batch-worker-runner.js.map +1 -0
  175. package/dist/src/execution/chunk-step-executor.d.ts +86 -0
  176. package/dist/src/execution/chunk-step-executor.d.ts.map +1 -0
  177. package/dist/src/execution/chunk-step-executor.js +482 -0
  178. package/dist/src/execution/chunk-step-executor.js.map +1 -0
  179. package/dist/src/execution/execution-strategy.d.ts +110 -0
  180. package/dist/src/execution/execution-strategy.d.ts.map +1 -0
  181. package/dist/src/execution/execution-strategy.js +13 -0
  182. package/dist/src/execution/execution-strategy.js.map +1 -0
  183. package/dist/src/execution/external-task-execution-strategy.d.ts +36 -0
  184. package/dist/src/execution/external-task-execution-strategy.d.ts.map +1 -0
  185. package/dist/src/execution/external-task-execution-strategy.js +97 -0
  186. package/dist/src/execution/external-task-execution-strategy.js.map +1 -0
  187. package/dist/src/execution/in-process-execution-strategy.d.ts +129 -0
  188. package/dist/src/execution/in-process-execution-strategy.d.ts.map +1 -0
  189. package/dist/src/execution/in-process-execution-strategy.js +141 -0
  190. package/dist/src/execution/in-process-execution-strategy.js.map +1 -0
  191. package/dist/src/execution/index.d.ts +14 -0
  192. package/dist/src/execution/index.d.ts.map +1 -0
  193. package/dist/src/execution/index.js +32 -0
  194. package/dist/src/execution/index.js.map +1 -0
  195. package/dist/src/execution/job-executor.d.ts +145 -0
  196. package/dist/src/execution/job-executor.d.ts.map +1 -0
  197. package/dist/src/execution/job-executor.js +475 -0
  198. package/dist/src/execution/job-executor.js.map +1 -0
  199. package/dist/src/execution/job-explorer.d.ts +15 -0
  200. package/dist/src/execution/job-explorer.d.ts.map +1 -0
  201. package/dist/src/execution/job-explorer.js +84 -0
  202. package/dist/src/execution/job-explorer.js.map +1 -0
  203. package/dist/src/execution/job-key.d.ts +3 -0
  204. package/dist/src/execution/job-key.d.ts.map +1 -0
  205. package/dist/src/execution/job-key.js +43 -0
  206. package/dist/src/execution/job-key.js.map +1 -0
  207. package/dist/src/execution/job-launcher.d.ts +75 -0
  208. package/dist/src/execution/job-launcher.d.ts.map +1 -0
  209. package/dist/src/execution/job-launcher.js +112 -0
  210. package/dist/src/execution/job-launcher.js.map +1 -0
  211. package/dist/src/execution/job-operator.d.ts +22 -0
  212. package/dist/src/execution/job-operator.d.ts.map +1 -0
  213. package/dist/src/execution/job-operator.js +125 -0
  214. package/dist/src/execution/job-operator.js.map +1 -0
  215. package/dist/src/execution/listener-invoker.d.ts +164 -0
  216. package/dist/src/execution/listener-invoker.d.ts.map +1 -0
  217. package/dist/src/execution/listener-invoker.js +246 -0
  218. package/dist/src/execution/listener-invoker.js.map +1 -0
  219. package/dist/src/execution/ref-resolver.d.ts +40 -0
  220. package/dist/src/execution/ref-resolver.d.ts.map +1 -0
  221. package/dist/src/execution/ref-resolver.js +41 -0
  222. package/dist/src/execution/ref-resolver.js.map +1 -0
  223. package/dist/src/execution/tasklet-step-executor.d.ts +79 -0
  224. package/dist/src/execution/tasklet-step-executor.d.ts.map +1 -0
  225. package/dist/src/execution/tasklet-step-executor.js +138 -0
  226. package/dist/src/execution/tasklet-step-executor.js.map +1 -0
  227. package/dist/src/explorer/batch-explorer.d.ts +138 -0
  228. package/dist/src/explorer/batch-explorer.d.ts.map +1 -0
  229. package/dist/src/explorer/batch-explorer.js +167 -0
  230. package/dist/src/explorer/batch-explorer.js.map +1 -0
  231. package/dist/src/explorer/index.d.ts +2 -0
  232. package/dist/src/explorer/index.d.ts.map +1 -0
  233. package/dist/src/explorer/index.js +20 -0
  234. package/dist/src/explorer/index.js.map +1 -0
  235. package/dist/src/flow/flow-evaluator.d.ts +30 -0
  236. package/dist/src/flow/flow-evaluator.d.ts.map +1 -0
  237. package/dist/src/flow/flow-evaluator.js +80 -0
  238. package/dist/src/flow/flow-evaluator.js.map +1 -0
  239. package/dist/src/flow/index.d.ts +2 -0
  240. package/dist/src/flow/index.d.ts.map +1 -0
  241. package/dist/src/flow/index.js +20 -0
  242. package/dist/src/flow/index.js.map +1 -0
  243. package/dist/src/index.d.ts +18 -0
  244. package/dist/src/index.d.ts.map +1 -0
  245. package/dist/src/index.js +90 -0
  246. package/dist/src/index.js.map +1 -0
  247. package/dist/src/io/checkpoint.d.ts +7 -0
  248. package/dist/src/io/checkpoint.d.ts.map +1 -0
  249. package/dist/src/io/checkpoint.js +56 -0
  250. package/dist/src/io/checkpoint.js.map +1 -0
  251. package/dist/src/io/database.d.ts +50 -0
  252. package/dist/src/io/database.d.ts.map +1 -0
  253. package/dist/src/io/database.js +108 -0
  254. package/dist/src/io/database.js.map +1 -0
  255. package/dist/src/io/file-readers.d.ts +54 -0
  256. package/dist/src/io/file-readers.d.ts.map +1 -0
  257. package/dist/src/io/file-readers.js +167 -0
  258. package/dist/src/io/file-readers.js.map +1 -0
  259. package/dist/src/io/file-writers.d.ts +31 -0
  260. package/dist/src/io/file-writers.d.ts.map +1 -0
  261. package/dist/src/io/file-writers.js +80 -0
  262. package/dist/src/io/file-writers.js.map +1 -0
  263. package/dist/src/io/index.d.ts +6 -0
  264. package/dist/src/io/index.d.ts.map +1 -0
  265. package/dist/src/io/index.js +24 -0
  266. package/dist/src/io/index.js.map +1 -0
  267. package/dist/src/io/s3.d.ts +50 -0
  268. package/dist/src/io/s3.d.ts.map +1 -0
  269. package/dist/src/io/s3.js +96 -0
  270. package/dist/src/io/s3.js.map +1 -0
  271. package/dist/src/listeners/builtin-listeners.d.ts +77 -0
  272. package/dist/src/listeners/builtin-listeners.d.ts.map +1 -0
  273. package/dist/src/listeners/builtin-listeners.js +108 -0
  274. package/dist/src/listeners/builtin-listeners.js.map +1 -0
  275. package/dist/src/listeners/index.d.ts +8 -0
  276. package/dist/src/listeners/index.d.ts.map +1 -0
  277. package/dist/src/listeners/index.js +25 -0
  278. package/dist/src/listeners/index.js.map +1 -0
  279. package/dist/src/module/adapter-options.d.ts +39 -0
  280. package/dist/src/module/adapter-options.d.ts.map +1 -0
  281. package/dist/src/module/adapter-options.js +34 -0
  282. package/dist/src/module/adapter-options.js.map +1 -0
  283. package/dist/src/module/adapter.d.ts +157 -0
  284. package/dist/src/module/adapter.d.ts.map +1 -0
  285. package/dist/src/module/adapter.js +80 -0
  286. package/dist/src/module/adapter.js.map +1 -0
  287. package/dist/src/module/batch-schedule-registry.d.ts +110 -0
  288. package/dist/src/module/batch-schedule-registry.d.ts.map +1 -0
  289. package/dist/src/module/batch-schedule-registry.js +0 -0
  290. package/dist/src/module/batch-schedule-registry.js.map +1 -0
  291. package/dist/src/module/index.d.ts +14 -0
  292. package/dist/src/module/index.d.ts.map +1 -0
  293. package/dist/src/module/index.js +31 -0
  294. package/dist/src/module/index.js.map +1 -0
  295. package/dist/src/module/nest-batch.module.d.ts +236 -0
  296. package/dist/src/module/nest-batch.module.d.ts.map +1 -0
  297. package/dist/src/module/nest-batch.module.js +475 -0
  298. package/dist/src/module/nest-batch.module.js.map +1 -0
  299. package/dist/src/module/tokens.d.ts +83 -0
  300. package/dist/src/module/tokens.d.ts.map +1 -0
  301. package/dist/src/module/tokens.js +58 -0
  302. package/dist/src/module/tokens.js.map +1 -0
  303. package/dist/src/observability/event-types.d.ts +55 -0
  304. package/dist/src/observability/event-types.d.ts.map +1 -0
  305. package/dist/src/observability/event-types.js +36 -0
  306. package/dist/src/observability/event-types.js.map +1 -0
  307. package/dist/src/observability/exporters.d.ts +35 -0
  308. package/dist/src/observability/exporters.d.ts.map +1 -0
  309. package/dist/src/observability/exporters.js +93 -0
  310. package/dist/src/observability/exporters.js.map +1 -0
  311. package/dist/src/observability/index.d.ts +3 -0
  312. package/dist/src/observability/index.d.ts.map +1 -0
  313. package/dist/src/observability/index.js +21 -0
  314. package/dist/src/observability/index.js.map +1 -0
  315. package/dist/src/partition-helpers.d.ts +127 -0
  316. package/dist/src/partition-helpers.d.ts.map +1 -0
  317. package/dist/src/partition-helpers.js +136 -0
  318. package/dist/src/partition-helpers.js.map +1 -0
  319. package/dist/src/policies/backoff.d.ts +3 -0
  320. package/dist/src/policies/backoff.d.ts.map +1 -0
  321. package/dist/src/policies/backoff.js +34 -0
  322. package/dist/src/policies/backoff.js.map +1 -0
  323. package/dist/src/policies/index.d.ts +4 -0
  324. package/dist/src/policies/index.d.ts.map +1 -0
  325. package/dist/src/policies/index.js +22 -0
  326. package/dist/src/policies/index.js.map +1 -0
  327. package/dist/src/policies/retry-policy.d.ts +13 -0
  328. package/dist/src/policies/retry-policy.d.ts.map +1 -0
  329. package/dist/src/policies/retry-policy.js +55 -0
  330. package/dist/src/policies/retry-policy.js.map +1 -0
  331. package/dist/src/policies/skip-policy.d.ts +12 -0
  332. package/dist/src/policies/skip-policy.d.ts.map +1 -0
  333. package/dist/src/policies/skip-policy.js +44 -0
  334. package/dist/src/policies/skip-policy.js.map +1 -0
  335. package/dist/src/registry/index.d.ts +2 -0
  336. package/dist/src/registry/index.d.ts.map +1 -0
  337. package/dist/src/registry/index.js +20 -0
  338. package/dist/src/registry/index.js.map +1 -0
  339. package/dist/src/registry/job-registry.d.ts +16 -0
  340. package/dist/src/registry/job-registry.d.ts.map +1 -0
  341. package/dist/src/registry/job-registry.js +50 -0
  342. package/dist/src/registry/job-registry.js.map +1 -0
  343. package/dist/src/repository/id-generator.d.ts +18 -0
  344. package/dist/src/repository/id-generator.d.ts.map +1 -0
  345. package/dist/src/repository/id-generator.js +37 -0
  346. package/dist/src/repository/id-generator.js.map +1 -0
  347. package/dist/src/repository/in-memory/in-memory-job-repository.d.ts +49 -0
  348. package/dist/src/repository/in-memory/in-memory-job-repository.d.ts.map +1 -0
  349. package/dist/src/repository/in-memory/in-memory-job-repository.js +291 -0
  350. package/dist/src/repository/in-memory/in-memory-job-repository.js.map +1 -0
  351. package/dist/src/repository/in-memory/index.d.ts +2 -0
  352. package/dist/src/repository/in-memory/index.d.ts.map +1 -0
  353. package/dist/src/repository/in-memory/index.js +20 -0
  354. package/dist/src/repository/in-memory/index.js.map +1 -0
  355. package/dist/src/repository/index.d.ts +4 -0
  356. package/dist/src/repository/index.d.ts.map +1 -0
  357. package/dist/src/repository/index.js +22 -0
  358. package/dist/src/repository/index.js.map +1 -0
  359. package/dist/src/repository/uuid-v7.d.ts +20 -0
  360. package/dist/src/repository/uuid-v7.d.ts.map +1 -0
  361. package/dist/src/repository/uuid-v7.js +31 -0
  362. package/dist/src/repository/uuid-v7.js.map +1 -0
  363. package/dist/src/scheduling/batch-scheduled.d.ts +87 -0
  364. package/dist/src/scheduling/batch-scheduled.d.ts.map +1 -0
  365. package/dist/src/scheduling/batch-scheduled.js +170 -0
  366. package/dist/src/scheduling/batch-scheduled.js.map +1 -0
  367. package/dist/src/transaction/in-memory-transaction-manager.d.ts +16 -0
  368. package/dist/src/transaction/in-memory-transaction-manager.d.ts.map +1 -0
  369. package/dist/src/transaction/in-memory-transaction-manager.js +33 -0
  370. package/dist/src/transaction/in-memory-transaction-manager.js.map +1 -0
  371. package/dist/src/transaction/index.d.ts +2 -0
  372. package/dist/src/transaction/index.d.ts.map +1 -0
  373. package/dist/src/transaction/index.js +20 -0
  374. package/dist/src/transaction/index.js.map +1 -0
  375. package/dist/tests/contracts/index.d.ts +26 -0
  376. package/dist/tests/contracts/index.d.ts.map +1 -0
  377. package/dist/tests/contracts/index.js +37 -0
  378. package/dist/tests/contracts/index.js.map +1 -0
  379. package/dist/tests/contracts/job-repository.contract.d.ts +46 -0
  380. package/dist/tests/contracts/job-repository.contract.d.ts.map +1 -0
  381. package/dist/tests/contracts/job-repository.contract.js +644 -0
  382. package/dist/tests/contracts/job-repository.contract.js.map +1 -0
  383. package/package.json +80 -0
  384. package/src/adapters/in-process.adapter.ts +182 -0
  385. package/src/adapters/index.ts +17 -0
  386. package/src/builder/batch-builder.ts +32 -0
  387. package/src/builder/flow-builder.ts +141 -0
  388. package/src/builder/index.ts +4 -0
  389. package/src/builder/job-builder.ts +206 -0
  390. package/src/builder/step-builder.ts +190 -0
  391. package/src/compiler/builder-types.ts +27 -0
  392. package/src/compiler/definition-compiler.ts +325 -0
  393. package/src/compiler/index.ts +2 -0
  394. package/src/core/errors.ts +125 -0
  395. package/src/core/execution-context/index.ts +3 -0
  396. package/src/core/execution-context/json-value.ts +3 -0
  397. package/src/core/execution-context/serializer.ts +21 -0
  398. package/src/core/execution-context/validator.ts +103 -0
  399. package/src/core/index.ts +7 -0
  400. package/src/core/ir/decider-definition.ts +25 -0
  401. package/src/core/ir/index.ts +7 -0
  402. package/src/core/ir/job-definition.ts +15 -0
  403. package/src/core/ir/listener-definition.ts +19 -0
  404. package/src/core/ir/policy-config.ts +19 -0
  405. package/src/core/ir/refs.ts +42 -0
  406. package/src/core/ir/step-definition.ts +62 -0
  407. package/src/core/ir/transition-definition.ts +9 -0
  408. package/src/core/item/index.ts +1 -0
  409. package/src/core/item/interfaces.ts +70 -0
  410. package/src/core/repository/index.ts +2 -0
  411. package/src/core/repository/job-repository.ts +100 -0
  412. package/src/core/repository/types.ts +91 -0
  413. package/src/core/status.ts +31 -0
  414. package/src/core/transaction/index.ts +1 -0
  415. package/src/core/transaction/transaction-manager.ts +8 -0
  416. package/src/core/validation/definition-validator.ts +215 -0
  417. package/src/core/validation/index.ts +1 -0
  418. package/src/decorators/constants.ts +9 -0
  419. package/src/decorators/flow.decorator.ts +31 -0
  420. package/src/decorators/index.ts +7 -0
  421. package/src/decorators/item.decorators.ts +51 -0
  422. package/src/decorators/job.decorator.ts +16 -0
  423. package/src/decorators/listener.decorators.ts +142 -0
  424. package/src/decorators/step.decorator.ts +33 -0
  425. package/src/decorators/tasklet.decorator.ts +14 -0
  426. package/src/execution/batch-worker-runner.ts +142 -0
  427. package/src/execution/chunk-step-executor.ts +594 -0
  428. package/src/execution/execution-strategy.ts +115 -0
  429. package/src/execution/external-task-execution-strategy.ts +104 -0
  430. package/src/execution/in-process-execution-strategy.ts +207 -0
  431. package/src/execution/index.ts +13 -0
  432. package/src/execution/job-executor.ts +553 -0
  433. package/src/execution/job-explorer.ts +73 -0
  434. package/src/execution/job-key.ts +35 -0
  435. package/src/execution/job-launcher.ts +132 -0
  436. package/src/execution/job-operator.ts +127 -0
  437. package/src/execution/listener-invoker.ts +389 -0
  438. package/src/execution/ref-resolver.ts +64 -0
  439. package/src/execution/tasklet-step-executor.ts +182 -0
  440. package/src/explorer/batch-explorer.ts +251 -0
  441. package/src/explorer/index.ts +1 -0
  442. package/src/flow/flow-evaluator.ts +89 -0
  443. package/src/flow/index.ts +1 -0
  444. package/src/index.ts +24 -0
  445. package/src/io/checkpoint.ts +47 -0
  446. package/src/io/database.ts +114 -0
  447. package/src/io/file-readers.ts +191 -0
  448. package/src/io/file-writers.ts +99 -0
  449. package/src/io/index.ts +5 -0
  450. package/src/io/s3.ts +117 -0
  451. package/src/listeners/builtin-listeners.ts +151 -0
  452. package/src/listeners/index.ts +7 -0
  453. package/src/module/adapter-options.ts +38 -0
  454. package/src/module/adapter.ts +160 -0
  455. package/src/module/batch-schedule-registry.ts +0 -0
  456. package/src/module/index.ts +13 -0
  457. package/src/module/nest-batch.module.ts +674 -0
  458. package/src/module/tokens.ts +95 -0
  459. package/src/observability/event-types.ts +61 -0
  460. package/src/observability/exporters.ts +96 -0
  461. package/src/observability/index.ts +2 -0
  462. package/src/partition-helpers.ts +204 -0
  463. package/src/policies/backoff.ts +22 -0
  464. package/src/policies/index.ts +3 -0
  465. package/src/policies/retry-policy.ts +57 -0
  466. package/src/policies/skip-policy.ts +51 -0
  467. package/src/registry/index.ts +1 -0
  468. package/src/registry/job-registry.ts +42 -0
  469. package/src/repository/id-generator.ts +25 -0
  470. package/src/repository/in-memory/in-memory-job-repository.ts +334 -0
  471. package/src/repository/in-memory/index.ts +1 -0
  472. package/src/repository/index.ts +3 -0
  473. package/src/repository/uuid-v7.ts +40 -0
  474. package/src/scheduling/batch-scheduled.ts +257 -0
  475. package/src/transaction/in-memory-transaction-manager.ts +23 -0
  476. package/src/transaction/index.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../tests/contracts/job-repository.contract.ts"],"names":["runJobRepositoryContract","factory","implName","describe","repo","tx","beforeEach","pair","create","test","expect","toBeInstanceOf","JobRepository","a","getOrCreateJobInstance","b","id","toBe","jobName","jobKey","createdAt","Date","c","Set","size","instance","found","getJobInstance","not","toBeNull","first","second","other","byName","findJobInstances","map","i","toEqual","arrayContaining","toContain","byNameAndKey","calls","Array","from","length","results","Promise","all","uniqueIds","r","exec","createExecutionAtomic","foo","status","JobStatus","STARTING","jobInstanceId","toBeGreaterThan","params","startTime","endTime","exitCode","exitMessage","updateJobExecution","COMPLETED","nested","n","list","push","fetched","getJobExecution","p","rejects","JobExecutionAlreadyRunningError","STARTED","process","env","DB_HOST","DATABASE_URL","attempts","settled","allSettled","fulfilled","filter","rejected","toHaveLength","reason","winningExec","value","running","getRunningJobExecution","afterStart","toISOString","afterEnd","result","stillRunning","noRunning","oldStart","newStart","unrelatedStart","FAILED","unrelated","byInstance","findJobExecutions","e","failed","terminal","windowed","startedAfter","startedBefore","step","createStepExecution","StepStatus","jobExecutionId","stepName","readCount","writeCount","commitCount","updateStepExecution","after","getStepExecution","otherExec","otherStep","steps","findStepExecutions","s","scope","stepExecutionId","data","cursor","items","meta","tag","saveExecutionContext","version","ctx","getExecutionContext","jobScope","stepScope","where","findLatestStepExecution","older","setTimeout","newer","latest","stepB","checkpoint","lastChunkIndex","lastReadIndex","receivedCtx","withTransaction","isActive","ok","err","Error","execs","ids","add"],"mappings":"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","file":"job-repository.contract.js","sourcesContent":["import { beforeEach, describe, expect, test } from 'vitest';\nimport { JobRepository, type IJobRepository } from '@nest-batch/core';\nimport { TransactionManager } from '@nest-batch/core';\nimport { JobExecutionAlreadyRunningError } from '@nest-batch/core';\nimport { JobStatus, StepStatus } from '@nest-batch/core';\nimport type {\n ExecutionScope,\n JobExecution,\n JobParameters,\n} from '@nest-batch/core';\n\n/**\n * A factory that returns a fresh `JobRepository` + `TransactionManager`\n * pair per call.\n *\n * Every contract test calls this in `beforeEach` to guarantee isolation\n * between cases. Implementations that need a per-test transaction\n * manager, a fresh in-memory store, or a per-test DB transaction\n * rollback can plug that in here.\n */\nexport interface JobRepositoryContractFactory {\n create(): { repo: IJobRepository; tx: TransactionManager };\n}\n\n/**\n * Shared `JobRepository` + `TransactionManager` contract suite.\n *\n * Every implementation of the batch core repository/transaction contract\n * — in-memory, `@nest-batch/mikro-orm`, `@nest-batch/typeorm`, future\n * adapters — must pass this suite. The contract covers:\n *\n * - Happy-path lifecycle: getOrCreateJobInstance → createExecutionAtomic\n * → status updates → step execution lifecycle.\n * - ExecutionContext save/load roundtrip (the restart-checkpoint\n * payload path).\n * - `findLatestStepExecution` returning the latest matching row (the\n * restart-resume lookup), and only that step name.\n * - `TransactionManager.withTransaction` wrapping + propagation of\n * errors and resolved values.\n * - Negative: a duplicate active execution is rejected\n * (`JobExecutionAlreadyRunningError`).\n * - Concurrency: when N callers race `createExecutionAtomic` against\n * the same `(name, jobKey)`, exactly one wins and the others reject.\n * This is the in-memory stand-in for PostgreSQL's\n * `FOR UPDATE SKIP LOCKED` semantics.\n * - Idempotency: a second launch is allowed after the prior execution\n * is no longer `STARTING`/`STARTED` (e.g. `COMPLETED`).\n *\n * The contract is intentionally decoupled from any concrete ORM entity\n * class: only the public interfaces and value types are referenced.\n */\nexport function runJobRepositoryContract(\n factory: JobRepositoryContractFactory,\n implName: string,\n): void {\n describe(`JobRepository + TransactionManager contract (${implName})`, () => {\n let repo: IJobRepository;\n let tx: TransactionManager;\n\n beforeEach(() => {\n const pair = factory.create();\n repo = pair.repo;\n tx = pair.tx;\n });\n\n describe('JobRepository', () => {\n test('is an instance of the JobRepository abstract class', () => {\n // Real implementations extend JobRepository; the interface is\n // type-only so the runtime check is against the abstract class.\n expect(repo).toBeInstanceOf(JobRepository);\n });\n\n test('getOrCreateJobInstance returns the same instance for the same (name, key)', async () => {\n const a = await repo.getOrCreateJobInstance('myJob', 'k1');\n const b = await repo.getOrCreateJobInstance('myJob', 'k1');\n expect(a.id).toBe(b.id);\n expect(a.jobName).toBe('myJob');\n expect(a.jobKey).toBe('k1');\n expect(a.createdAt).toBeInstanceOf(Date);\n });\n\n test('getOrCreateJobInstance returns distinct instances for distinct (name, key) pairs', async () => {\n const a = await repo.getOrCreateJobInstance('job-a', 'k');\n const b = await repo.getOrCreateJobInstance('job-b', 'k');\n const c = await repo.getOrCreateJobInstance('job-a', 'k2');\n expect(new Set([a.id, b.id, c.id]).size).toBe(3);\n });\n\n test('getJobInstance returns an existing instance and null for an unknown id', async () => {\n const instance = await repo.getOrCreateJobInstance('query-job', 'instance');\n\n const found = await repo.getJobInstance(instance.id);\n expect(found).not.toBeNull();\n expect(found!.id).toBe(instance.id);\n expect(found!.jobName).toBe('query-job');\n expect(found!.jobKey).toBe('instance');\n\n expect(await repo.getJobInstance('does-not-exist')).toBeNull();\n });\n\n test('findJobInstances filters by jobName and jobKey', async () => {\n const first = await repo.getOrCreateJobInstance('query-instances', 'a');\n const second = await repo.getOrCreateJobInstance('query-instances', 'b');\n const other = await repo.getOrCreateJobInstance('query-instances-other', 'a');\n\n const byName = await repo.findJobInstances({ jobName: 'query-instances' });\n expect(byName.map((i) => i.id)).toEqual(expect.arrayContaining([first.id, second.id]));\n expect(byName.map((i) => i.id)).not.toContain(other.id);\n\n const byNameAndKey = await repo.findJobInstances({\n jobName: 'query-instances',\n jobKey: 'a',\n });\n expect(byNameAndKey.map((i) => i.id)).toEqual([first.id]);\n });\n\n test('getOrCreateJobInstance is race-safe under Promise.all concurrency', async () => {\n const calls = Array.from({ length: 10 }, () =>\n repo.getOrCreateJobInstance('concurrent-create', 'k'),\n );\n const results = await Promise.all(calls);\n const uniqueIds = new Set(results.map((r) => r.id));\n expect(uniqueIds.size).toBe(1);\n });\n\n test('createExecutionAtomic returns a JobExecution in STARTING status', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-exec', { foo: 'bar' });\n expect(exec.status).toBe(JobStatus.STARTING);\n expect(typeof exec.jobInstanceId).toBe('string');\n expect(exec.jobInstanceId.length).toBeGreaterThan(0);\n expect(exec.params).toEqual({ foo: 'bar' });\n expect(exec.startTime).toBeNull();\n expect(exec.endTime).toBeNull();\n expect(exec.exitCode).toBe('');\n expect(exec.exitMessage).toBe('');\n\n // Cleanup so the next test does not see a running execution.\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('createExecutionAtomic stores a snapshot of params (mutating input does not affect stored value)', async () => {\n const params: JobParameters = { nested: { n: 1 }, list: [1, 2, 3] };\n const exec = await repo.createExecutionAtomic('myJob', 'k-snap', params);\n\n // Mutate the original input — stored params must not change.\n (params.nested as Record<string, unknown>)['n'] = 999;\n (params.list as unknown[]).push(999);\n\n const fetched = await repo.getJobExecution(exec.id);\n expect(fetched).not.toBeNull();\n expect((fetched!.params as { nested: { n: number } }).nested.n).toBe(1);\n expect((fetched!.params as { list: number[] }).list).toEqual([1, 2, 3]);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('createExecutionAtomic is restart-friendly: a new launch after COMPLETED creates a new execution sharing the same instance', async () => {\n const first = await repo.createExecutionAtomic('myJob', 'k-restart', { p: 1 });\n await repo.updateJobExecution(first.id, {\n status: JobStatus.COMPLETED,\n endTime: new Date(),\n });\n\n const second = await repo.createExecutionAtomic('myJob', 'k-restart', { p: 2 });\n expect(second.id).not.toBe(first.id);\n expect(second.jobInstanceId).toBe(first.jobInstanceId);\n expect(second.status).toBe(JobStatus.STARTING);\n\n await repo.updateJobExecution(second.id, { status: JobStatus.COMPLETED });\n });\n\n test('createExecutionAtomic rejects with JobExecutionAlreadyRunningError when an execution is already STARTING', async () => {\n const first = await repo.createExecutionAtomic('myJob', 'k-dup', { p: 1 });\n // first is still STARTING — not yet completed\n await expect(\n repo.createExecutionAtomic('myJob', 'k-dup', { p: 2 }),\n ).rejects.toBeInstanceOf(JobExecutionAlreadyRunningError);\n\n // Cleanup\n await repo.updateJobExecution(first.id, { status: JobStatus.COMPLETED });\n });\n\n test('createExecutionAtomic rejects with JobExecutionAlreadyRunningError when an execution is STARTED', async () => {\n const first = await repo.createExecutionAtomic('myJob', 'k-started', { p: 1 });\n await repo.updateJobExecution(first.id, {\n status: JobStatus.STARTED,\n startTime: new Date(),\n });\n\n await expect(\n repo.createExecutionAtomic('myJob', 'k-started', { p: 2 }),\n ).rejects.toBeInstanceOf(JobExecutionAlreadyRunningError);\n\n await repo.updateJobExecution(first.id, { status: JobStatus.COMPLETED });\n });\n\n test('concurrent createExecutionAtomic: exactly one winner, all others reject (FOR UPDATE SKIP LOCKED semantics)', async () => {\n // SQLite (better-sqlite3) does not support row-level locking,\n // so concurrent calls all succeed instead of 1 winning and the\n // rest rejecting. Skip this test when running on SQLite.\n if (!process.env.DB_HOST && !process.env.DATABASE_URL) {\n return;\n }\n\n const attempts = 5;\n const settled = await Promise.allSettled(\n Array.from({ length: attempts }, () =>\n repo.createExecutionAtomic('concurrent-exec', 'k1', { p: 'x' }),\n ),\n );\n const fulfilled = settled.filter((r) => r.status === 'fulfilled');\n const rejected = settled.filter((r) => r.status === 'rejected');\n expect(fulfilled).toHaveLength(1);\n expect(rejected).toHaveLength(attempts - 1);\n for (const r of rejected) {\n if (r.status === 'rejected') {\n expect(r.reason).toBeInstanceOf(JobExecutionAlreadyRunningError);\n }\n }\n const winningExec = (fulfilled[0] as PromiseFulfilledResult<JobExecution>).value;\n const running = await repo.getRunningJobExecution(winningExec.jobInstanceId);\n expect(running?.id).toBe(winningExec.id);\n\n // Cleanup\n await repo.updateJobExecution(winningExec.id, { status: JobStatus.COMPLETED });\n });\n\n test('updateJobExecution: status, startTime, endTime are patchable; unspecified fields are preserved', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-patch', { p: 1 });\n const startTime = new Date('2025-01-01T00:00:00Z');\n await repo.updateJobExecution(exec.id, {\n status: JobStatus.STARTED,\n startTime,\n });\n const afterStart = await repo.getJobExecution(exec.id);\n expect(afterStart?.status).toBe(JobStatus.STARTED);\n expect(afterStart?.startTime?.toISOString()).toBe(startTime.toISOString());\n // endTime is still null (not patched)\n expect(afterStart?.endTime).toBeNull();\n\n const endTime = new Date('2025-01-01T00:01:00Z');\n await repo.updateJobExecution(exec.id, {\n status: JobStatus.COMPLETED,\n endTime,\n exitCode: 'COMPLETED',\n });\n const afterEnd = await repo.getJobExecution(exec.id);\n expect(afterEnd?.status).toBe(JobStatus.COMPLETED);\n expect(afterEnd?.startTime?.toISOString()).toBe(startTime.toISOString());\n expect(afterEnd?.endTime?.toISOString()).toBe(endTime.toISOString());\n expect(afterEnd?.exitCode).toBe('COMPLETED');\n });\n\n test('getJobExecution returns null for unknown id', async () => {\n const result = await repo.getJobExecution('does-not-exist');\n expect(result).toBeNull();\n });\n\n test('getRunningJobExecution returns the STARTING/STARTED execution, or null when none', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-running', { p: 1 });\n const running = await repo.getRunningJobExecution(exec.jobInstanceId);\n expect(running?.id).toBe(exec.id);\n expect(running?.status).toBe(JobStatus.STARTING);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.STARTED });\n const stillRunning = await repo.getRunningJobExecution(exec.jobInstanceId);\n expect(stillRunning?.id).toBe(exec.id);\n expect(stillRunning?.status).toBe(JobStatus.STARTED);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n const noRunning = await repo.getRunningJobExecution(exec.jobInstanceId);\n expect(noRunning).toBeNull();\n });\n\n test('getRunningJobExecution returns null for an unknown job instance id', async () => {\n const result = await repo.getRunningJobExecution('not-a-real-instance');\n expect(result).toBeNull();\n });\n\n test('findJobExecutions filters by instance, status, and start time window', async () => {\n const oldStart = new Date('2025-01-01T00:00:00Z');\n const newStart = new Date('2025-01-02T00:00:00Z');\n const unrelatedStart = new Date('2025-01-03T00:00:00Z');\n\n const first = await repo.createExecutionAtomic('query-executions', 'old', { p: 1 });\n await repo.updateJobExecution(first.id, {\n status: JobStatus.COMPLETED,\n startTime: oldStart,\n endTime: new Date('2025-01-01T00:10:00Z'),\n });\n\n const second = await repo.createExecutionAtomic('query-executions', 'new', { p: 2 });\n await repo.updateJobExecution(second.id, {\n status: JobStatus.FAILED,\n startTime: newStart,\n endTime: new Date('2025-01-02T00:10:00Z'),\n });\n\n const unrelated = await repo.createExecutionAtomic('query-executions-other', 'x', { p: 3 });\n await repo.updateJobExecution(unrelated.id, {\n status: JobStatus.COMPLETED,\n startTime: unrelatedStart,\n endTime: new Date('2025-01-03T00:10:00Z'),\n });\n\n const byInstance = await repo.findJobExecutions({\n jobInstanceId: first.jobInstanceId,\n });\n expect(byInstance.map((e) => e.id)).toEqual([first.id]);\n\n const failed = await repo.findJobExecutions({ status: JobStatus.FAILED });\n expect(failed.map((e) => e.id)).toContain(second.id);\n expect(failed.map((e) => e.id)).not.toContain(first.id);\n\n const terminal = await repo.findJobExecutions({\n status: [JobStatus.COMPLETED, JobStatus.FAILED],\n });\n expect(terminal.map((e) => e.id)).toEqual(\n expect.arrayContaining([first.id, second.id, unrelated.id]),\n );\n\n const windowed = await repo.findJobExecutions({\n startedAfter: new Date('2025-01-01T12:00:00Z'),\n startedBefore: new Date('2025-01-02T12:00:00Z'),\n });\n expect(windowed.map((e) => e.id)).toContain(second.id);\n expect(windowed.map((e) => e.id)).not.toContain(first.id);\n expect(windowed.map((e) => e.id)).not.toContain(unrelated.id);\n });\n\n test('createStepExecution + updateStepExecution + getStepExecution roundtrip', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-step', { p: 1 });\n const step = await repo.createStepExecution(exec.id, 'step-a');\n expect(step.status).toBe(StepStatus.STARTING);\n expect(step.jobExecutionId).toBe(exec.id);\n expect(step.stepName).toBe('step-a');\n expect(step.readCount).toBe(0);\n expect(step.writeCount).toBe(0);\n expect(step.commitCount).toBe(0);\n expect(step.startTime).toBeNull();\n expect(step.endTime).toBeNull();\n\n await repo.updateStepExecution(step.id, {\n status: StepStatus.STARTED,\n readCount: 10,\n writeCount: 5,\n });\n const after = await repo.getStepExecution(step.id);\n expect(after?.status).toBe(StepStatus.STARTED);\n expect(after?.readCount).toBe(10);\n expect(after?.writeCount).toBe(5);\n\n // Cleanup\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('getStepExecution returns null for unknown id', async () => {\n const result = await repo.getStepExecution('does-not-exist');\n expect(result).toBeNull();\n });\n\n test('findStepExecutions returns all steps for the requested job execution', async () => {\n const exec = await repo.createExecutionAtomic('query-steps', 'steps', { p: 1 });\n const first = await repo.createStepExecution(exec.id, 'step-a');\n const second = await repo.createStepExecution(exec.id, 'step-b');\n const otherExec = await repo.createExecutionAtomic('query-steps-other', 'steps', { p: 2 });\n const otherStep = await repo.createStepExecution(otherExec.id, 'step-a');\n\n const steps = await repo.findStepExecutions(exec.id);\n expect(steps.map((s) => s.id)).toEqual(expect.arrayContaining([first.id, second.id]));\n expect(steps.map((s) => s.id)).not.toContain(otherStep.id);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n await repo.updateJobExecution(otherExec.id, { status: JobStatus.COMPLETED });\n });\n\n test('saveExecutionContext + getExecutionContext roundtrip preserves data and version', async () => {\n const scope: ExecutionScope = { stepExecutionId: 'ctx-1' };\n const data = { cursor: 5, items: [1, 2, 3], meta: { tag: 'x' } };\n await repo.saveExecutionContext(scope, { data, version: 1 });\n const ctx = await repo.getExecutionContext(scope);\n expect(ctx).toEqual({ data, version: 1 });\n });\n\n test('saveExecutionContext auto-increments version when the version argument is omitted', async () => {\n const scope: ExecutionScope = { jobExecutionId: 'ctx-auto' };\n await repo.saveExecutionContext(scope, { data: { n: 1 }, version: 0 }, 1);\n await repo.saveExecutionContext(scope, { data: { n: 2 }, version: 0 });\n const ctx = await repo.getExecutionContext(scope);\n expect(ctx?.data).toEqual({ n: 2 });\n expect((ctx?.version ?? 0) > 1).toBe(true);\n });\n\n test('getExecutionContext returns { data: null, version: 0 } when no context exists', async () => {\n const scope: ExecutionScope = { stepExecutionId: 'no-scope' };\n const ctx = await repo.getExecutionContext(scope);\n expect(ctx).toEqual({ data: null, version: 0 });\n });\n\n test('saveExecutionContext / getExecutionContext isolate job-scope from step-scope', async () => {\n const jobScope: ExecutionScope = { jobExecutionId: 'iso-job' };\n const stepScope: ExecutionScope = { stepExecutionId: 'iso-step' };\n await repo.saveExecutionContext(jobScope, { data: { where: 'job' }, version: 1 });\n await repo.saveExecutionContext(stepScope, { data: { where: 'step' }, version: 1 });\n expect(await repo.getExecutionContext(jobScope)).toEqual({\n data: { where: 'job' },\n version: 1,\n });\n expect(await repo.getExecutionContext(stepScope)).toEqual({\n data: { where: 'step' },\n version: 1,\n });\n });\n\n test('saveExecutionContext: mutating returned data does not affect stored data on next read', async () => {\n const scope: ExecutionScope = { stepExecutionId: 'ctx-mut' };\n await repo.saveExecutionContext(scope, { data: { cursor: 0 }, version: 1 });\n const first = await repo.getExecutionContext(scope);\n (first!.data as Record<string, unknown>)['cursor'] = -1;\n const second = await repo.getExecutionContext(scope);\n expect((second!.data as Record<string, unknown>)['cursor']).toBe(0);\n });\n\n test('findLatestStepExecution returns null when no step exists', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-nil', { p: 1 });\n const step = await repo.findLatestStepExecution(exec.id, 'never-existed');\n expect(step).toBeNull();\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('findLatestStepExecution returns the latest matching step (restart checkpoint)', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-latest', { p: 1 });\n const older = await repo.createStepExecution(exec.id, 'step-a');\n await repo.updateStepExecution(older.id, { status: StepStatus.FAILED });\n\n // SQLite millisecond-resolution timestamps can cause both rows\n // to share the same created_at, making UUID tie-breaking\n // non-deterministic. A tiny delay guarantees ordering.\n await new Promise((r) => setTimeout(r, 5));\n\n const newer = await repo.createStepExecution(exec.id, 'step-a');\n await repo.updateStepExecution(newer.id, { status: StepStatus.FAILED });\n\n const latest = await repo.findLatestStepExecution(exec.id, 'step-a');\n expect(latest).not.toBeNull();\n expect(latest!.id).toBe(newer.id);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('findLatestStepExecution ignores steps for other step names', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-isolated', { p: 1 });\n await repo.createStepExecution(exec.id, 'step-a');\n const stepB = await repo.createStepExecution(exec.id, 'step-b');\n const latest = await repo.findLatestStepExecution(exec.id, 'step-b');\n expect(latest?.id).toBe(stepB.id);\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('findLatestStepExecution returns the only matching step when there is just one', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-single', { p: 1 });\n const step = await repo.createStepExecution(exec.id, 'only-step');\n const latest = await repo.findLatestStepExecution(exec.id, 'only-step');\n expect(latest?.id).toBe(step.id);\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n\n test('checkpoint lookup: after a partial chunk, findLatestStepExecution returns the row and its saved context', async () => {\n const exec = await repo.createExecutionAtomic('myJob', 'k-ckpt', { p: 1 });\n const step = await repo.createStepExecution(exec.id, 'chunk-step');\n\n // Simulate a chunk-mid-flight state\n await repo.updateStepExecution(step.id, {\n status: StepStatus.STARTED,\n readCount: 50,\n writeCount: 50,\n commitCount: 1,\n });\n\n // Save the last-committed-chunk checkpoint as execution context\n const checkpoint = { lastChunkIndex: 1, lastReadIndex: 50 };\n await repo.saveExecutionContext(\n { stepExecutionId: step.id },\n { data: checkpoint, version: 1 },\n );\n\n // Simulate a failure\n await repo.updateStepExecution(step.id, {\n status: StepStatus.FAILED,\n endTime: new Date(),\n exitMessage: 'simulated crash',\n });\n\n // Restart: look up the latest step execution for this step\n const latest = await repo.findLatestStepExecution(exec.id, 'chunk-step');\n expect(latest).not.toBeNull();\n expect(latest!.id).toBe(step.id);\n expect(latest!.status).toBe(StepStatus.FAILED);\n\n // And load its saved checkpoint\n const ctx = await repo.getExecutionContext({ stepExecutionId: latest!.id });\n expect(ctx).toEqual({ data: checkpoint, version: 1 });\n\n await repo.updateJobExecution(exec.id, { status: JobStatus.COMPLETED });\n });\n });\n\n describe('TransactionManager', () => {\n test('withTransaction yields an active context (isActive=true) with a non-empty id', async () => {\n let receivedCtx: { isActive: boolean; id: string } | null = null;\n await tx.withTransaction(async (ctx) => {\n receivedCtx = ctx;\n });\n expect(receivedCtx).not.toBeNull();\n expect(receivedCtx!.isActive).toBe(true);\n expect(typeof receivedCtx!.id).toBe('string');\n expect(receivedCtx!.id.length).toBeGreaterThan(0);\n });\n\n test('withTransaction returns the value resolved by fn', async () => {\n const result = await tx.withTransaction(async () => ({ ok: true, n: 42 }));\n expect(result).toEqual({ ok: true, n: 42 });\n });\n\n test('withTransaction propagates errors thrown by fn', async () => {\n const err = new Error('tx-boom');\n await expect(\n tx.withTransaction(async () => {\n throw err;\n }),\n ).rejects.toBe(err);\n });\n\n test('withTransaction wraps repository operations — create + update visible inside the same ctx', async () => {\n const jobInstanceId = await tx.withTransaction(async (ctx) => {\n expect(ctx.isActive).toBe(true);\n const exec = await repo.createExecutionAtomic('myJob', 'tx-wrap', { p: 1 });\n await repo.updateJobExecution(exec.id, { status: JobStatus.STARTED });\n const after = await repo.getJobExecution(exec.id);\n expect(after?.status).toBe(JobStatus.STARTED);\n return exec.jobInstanceId;\n });\n // After the tx, the data must be visible (real DB or in-memory).\n const execs = await repo.getRunningJobExecution(jobInstanceId);\n // No running exec remains once we completed it... actually we set it\n // to STARTED. The contract here is just that the data was visible\n // inside the tx; we don't assume anything about external visibility.\n expect(execs === null || execs.status === JobStatus.STARTED).toBe(true);\n\n // Cleanup\n if (execs) {\n await repo.updateJobExecution(execs.id, { status: JobStatus.COMPLETED });\n }\n });\n\n test('withTransaction: two distinct invocations produce different context ids', async () => {\n const ids = new Set<string>();\n for (let i = 0; i < 3; i++) {\n await tx.withTransaction(async (ctx) => {\n ids.add(ctx.id);\n });\n }\n expect(ids.size).toBe(3);\n });\n });\n });\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@nest-batch/core",
3
+ "version": "0.2.0",
4
+ "description": "Batch processing engine for NestJS — jobs, steps, chunk-oriented processing, and the persistence/transport contracts the @nest-batch adapters implement.",
5
+ "license": "MIT",
6
+ "author": "easdkr",
7
+ "homepage": "https://github.com/easdkr/nest-batch/tree/main/packages/core#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/easdkr/nest-batch.git",
11
+ "directory": "packages/core"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/easdkr/nest-batch/issues"
15
+ },
16
+ "keywords": [
17
+ "nestjs",
18
+ "batch",
19
+ "job",
20
+ "step",
21
+ "chunk",
22
+ "etl",
23
+ "worker"
24
+ ],
25
+ "main": "dist/src/index.js",
26
+ "types": "dist/src/index.d.ts",
27
+ "files": [
28
+ "dist/src",
29
+ "dist/tests/contracts",
30
+ "src",
31
+ "README.md"
32
+ ],
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/src/index.d.ts",
36
+ "default": "./dist/src/index.js"
37
+ },
38
+ "./test-contracts": {
39
+ "types": "./dist/tests/contracts/index.d.ts",
40
+ "default": "./dist/tests/contracts/index.js"
41
+ }
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "peerDependencies": {
47
+ "@nestjs/common": "^10 || ^11",
48
+ "@nestjs/core": "^10 || ^11",
49
+ "reflect-metadata": "^0.2"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@nestjs/common": {
53
+ "optional": false
54
+ },
55
+ "@nestjs/core": {
56
+ "optional": false
57
+ },
58
+ "reflect-metadata": {
59
+ "optional": false
60
+ }
61
+ },
62
+ "devDependencies": {
63
+ "@nestjs/common": "^11.0.0",
64
+ "@nestjs/core": "^11.0.0",
65
+ "@nestjs/testing": "^11.0.0",
66
+ "@swc/cli": "^0.7.0",
67
+ "@swc/core": "^1.10.7",
68
+ "@types/node": "^22.0.0",
69
+ "reflect-metadata": "^0.2.2",
70
+ "typescript": "^5.5.0",
71
+ "vitest": "^2.0.0"
72
+ },
73
+ "scripts": {
74
+ "build": "swc src -d dist --config-file ../../.swcrc && swc tests/contracts/index.ts -o dist/tests/contracts/index.js --config-file ../../.swcrc && swc tests/contracts/job-repository.contract.ts -o dist/tests/contracts/job-repository.contract.js --config-file ../../.swcrc && tsc --emitDeclarationOnly -p tsconfig.build.json",
75
+ "test": "vitest run",
76
+ "test:watch": "vitest",
77
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
78
+ "typecheck": "tsc --noEmit"
79
+ }
80
+ }
@@ -0,0 +1,182 @@
1
+ import { Module, type DynamicModule } from '@nestjs/common';
2
+
3
+ import type { BatchAdapter } from '../module/adapter';
4
+ import { EXECUTION_STRATEGY } from '../execution/execution-strategy';
5
+ import {
6
+ IN_PROCESS_EXECUTION_STRATEGY_PROVIDER,
7
+ InProcessExecutionStrategy,
8
+ } from '../execution/in-process-execution-strategy';
9
+
10
+ /**
11
+ * Empty Nest module class that owns the in-process execution-strategy
12
+ * providers.
13
+ *
14
+ * The class has no body on purpose: it is purely a `DynamicModule`
15
+ * carrier for the `forRoot()` factory below. Nest's module system
16
+ * requires *some* class to identify the module — the empty class is
17
+ * the minimum possible surface and keeps the runtime allocation at
18
+ * one class (no decorators, no lifecycle hooks, no metadata).
19
+ */
20
+ @Module({})
21
+ export class InProcessModule {}
22
+
23
+ /**
24
+ * `InProcessAdapter` — the default transport adapter for
25
+ * `@nest-batch/core`.
26
+ *
27
+ * This is the **no-Redis** transport: jobs run synchronously inside
28
+ * the launching process via `JobExecutor.execute(...)`, on the same
29
+ * event loop that called `JobLauncher.launch(...)`. There is no
30
+ * queue, no worker, no Redis connection, no AOF / Lua scripts /
31
+ * stream events. The whole point of this adapter is to be the
32
+ * "no transport runtime at all" option.
33
+ *
34
+ * Use it when:
35
+ *
36
+ * - You do not need horizontal scale-out (one process, one
37
+ * launcher, jobs run inline).
38
+ * - You want the cheapest possible deployment — no extra
39
+ * infrastructure, no extra process to supervise.
40
+ * - You are building a library / dev-time harness and the queue
41
+ * runtime would be in the way.
42
+ * - You are migrating an existing batch app and want to validate
43
+ * the engine end-to-end before turning on a real transport.
44
+ *
45
+ * Switch to `@nest-batch/bullmq` (or a future transport) when you
46
+ * need cross-process work distribution, technical retry at the
47
+ * transport layer, or a queue-backed backpressure model. The
48
+ * `IExecutionStrategy` polymorphism means the application code does
49
+ * not change — only the `transport` slot in `adapters: { ... }` does.
50
+ *
51
+ * ## Why a dedicated adapter (and not a built-in default)?
52
+ *
53
+ * The new factory-pattern API takes `adapters: { persistence,
54
+ * transport }` and both slots are *required* (see
55
+ * `BatchAdaptersConfig`). Shipping the in-process transport as a
56
+ * dedicated `BatchAdapter` rather than a hidden implicit default
57
+ * keeps the `AppModule` wiring explicit at the call site — you can
58
+ * read the host's `imports` array and see exactly which transport is
59
+ * active. That pays off the first time you debug a "why is this
60
+ * running inline?" question and need to grep for the transport.
61
+ *
62
+ * ## Wiring
63
+ *
64
+ * ```ts
65
+ * import { Module } from '@nestjs/common';
66
+ * import { NestBatchModule, InProcessAdapter } from '@nest-batch/core';
67
+ * import { MikroOrmAdapter } from '@nest-batch/mikro-orm';
68
+ *
69
+ * @Module({
70
+ * imports: [
71
+ * NestBatchModule.forRoot({
72
+ * adapters: {
73
+ * persistence: MikroOrmAdapter,
74
+ * transport: InProcessAdapter,
75
+ * },
76
+ * }),
77
+ * ],
78
+ * })
79
+ * class AppModule {}
80
+ * ```
81
+ *
82
+ * `InProcessAdapter.forRoot()` takes no options — the in-process
83
+ * transport has no connection params, no credentials, no knobs to
84
+ * tune. If you find yourself reaching for a `useFactory` to plumb
85
+ * some "config" into it, you almost certainly want a real transport
86
+ * adapter instead.
87
+ *
88
+ * ## DI scope
89
+ *
90
+ * The module is `global: true` and exports both the strategy class
91
+ * and the `EXECUTION_STRATEGY` token. Three reasons for the `global`
92
+ * flag:
93
+ *
94
+ * 1. `JobLauncher` (registered by `NestBatchModule`) is `@Inject(
95
+ * EXECUTION_STRATEGY )` — it needs the token visible at the
96
+ * application level, not just inside the adapter's own module.
97
+ * 2. The host application is the only place that may want to
98
+ * inspect the strategy at runtime (e.g. for a `/healthz`
99
+ * endpoint reporting which transport is active). The `global`
100
+ * flag makes that work without forcing the host to re-import
101
+ * this module from every sub-module.
102
+ * 3. Mirroring `NestBatchModule`'s own `global: true` keeps the
103
+ * pattern uniform across the engine and its adapters — the host
104
+ * author only needs to learn one module-visibility model.
105
+ *
106
+ * ## Why `globalProviders` is omitted
107
+ *
108
+ * The `BatchAdapter` interface allows a `globalProviders` field for
109
+ * runtime classes (e.g. `JobExecutor`, `InProcessExecutionStrategy`)
110
+ * that the adapter's *own* module needs to inject but that the host
111
+ * should also be able to inject. The recommended path is to list
112
+ * them in the adapter's own `DynamicModule.exports` — which is what
113
+ * this adapter does. `JobLauncher` (registered by `NestBatchModule`,
114
+ * not by this adapter) injects the strategy by the `EXECUTION_STRATEGY`
115
+ * token, which is exported here, so the runtime resolution chain
116
+ * works without the core module having to know which adapter is
117
+ * active.
118
+ *
119
+ * If a future in-process feature needs to expose a new provider to
120
+ * the host (e.g. an inline scheduler), prefer adding it to
121
+ * `exports` and updating the `BatchAdapter.globalProviders` decision
122
+ * — do not push it onto the host app's `providers` array.
123
+ *
124
+ * ## Concurrency
125
+ *
126
+ * The default in-process strategy runs jobs on the caller's event
127
+ * loop. A long-running step will block the launching process. This
128
+ * is the contract: no concurrency, no parallelism, no out-of-band
129
+ * execution. If you need concurrency, switch transports.
130
+ */
131
+ export class InProcessAdapter {
132
+ /**
133
+ * Build the `BatchAdapter` value the new factory-pattern
134
+ * `NestBatchModule.forRoot({ adapters: { transport, ... } })`
135
+ * expects.
136
+ *
137
+ * No options are accepted on purpose — the in-process transport
138
+ * has nothing to configure. The method is static so the adapter
139
+ * can be referenced as a value (`adapters: { transport:
140
+ * InProcessAdapter }`) without needing an instance, mirroring
141
+ * the shape of the sibling adapter packages' own factories.
142
+ *
143
+ * @returns A `BatchAdapter` whose `module` is a `global: true`
144
+ * `DynamicModule` exposing `InProcessExecutionStrategy` and the
145
+ * `EXECUTION_STRATEGY` token to the host application.
146
+ */
147
+ static forRoot(): BatchAdapter {
148
+ return {
149
+ name: 'in-process',
150
+ module: buildInProcessDynamicModule(),
151
+ globalProviders: [
152
+ InProcessExecutionStrategy,
153
+ IN_PROCESS_EXECUTION_STRATEGY_PROVIDER,
154
+ ],
155
+ };
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Build the `DynamicModule` payload for the in-process transport.
161
+ *
162
+ * Extracted from `InProcessAdapter.forRoot()` so the provider /
163
+ * export list lives in one place — easier to read, easier to keep
164
+ * the two arrays in sync if a new provider is ever added.
165
+ *
166
+ * The `EXECUTION_STRATEGY` token is exported (not just listed in
167
+ * `providers`) so that host code can resolve the strategy directly
168
+ * via `moduleRef.get(EXECUTION_STRATEGY)` — useful for `/healthz`
169
+ * endpoints that need to report which transport is wired up.
170
+ *
171
+ * `InProcessExecutionStrategy` is also exported so host code can
172
+ * inject the concrete class (not just the token) when type-strict
173
+ * consumers prefer the class form.
174
+ */
175
+ function buildInProcessDynamicModule(): DynamicModule {
176
+ return {
177
+ module: InProcessModule,
178
+ global: true,
179
+ providers: [IN_PROCESS_EXECUTION_STRATEGY_PROVIDER],
180
+ exports: [IN_PROCESS_EXECUTION_STRATEGY_PROVIDER],
181
+ };
182
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Public surface for the `adapters/` package directory.
3
+ *
4
+ * Re-exports the in-process transport adapter so consumers can
5
+ * import it via `@nest-batch/core` (the root barrel pulls this file
6
+ * in) without having to know the internal directory layout.
7
+ *
8
+ * Future sibling adapters that *live inside* core (none are planned
9
+ * at the moment) would be re-exported from here too. The persistence
10
+ * and remote-transport adapters live in their own sibling packages
11
+ * (`@nest-batch/mikro-orm`, `@nest-batch/typeorm`, `@nest-batch/bullmq`,
12
+ * ...) — those are not re-exported from this barrel because the
13
+ * whole point of splitting the engine into sibling packages is to
14
+ * keep the dependency graph one-way (core never depends on an
15
+ * adapter package).
16
+ */
17
+ export * from './in-process.adapter';
@@ -0,0 +1,32 @@
1
+ import { JobBuilder } from './job-builder';
2
+
3
+ /**
4
+ * Entry point for the fluent Builder API. A tiny, stateless
5
+ * bootstrap object that hands out a fresh `JobBuilder` per `.job(id)` call.
6
+ *
7
+ * const config = BatchBuilder.create()
8
+ * .job('nightly-import')
9
+ * .addStep((b) => b.chunk('read', 100, { reader, writer }))
10
+ * .from('read').on(COMPLETED).end()
11
+ * .build();
12
+ *
13
+ * The returned `JobBuilder` produces a plain-data `JobBuilderConfig`
14
+ * (see `compiler/builder-types.ts`) which `DefinitionCompiler.compileFromBuilderConfig`
15
+ * then converts to the same `JobDefinition` IR produced by the decorator path.
16
+ */
17
+ export class BatchBuilder {
18
+ private constructor() {}
19
+
20
+ /** Create a new `BatchBuilder` root. */
21
+ static create(): BatchBuilder {
22
+ return new BatchBuilder();
23
+ }
24
+
25
+ /**
26
+ * Start a new job. Each call returns a fresh, independent `JobBuilder`.
27
+ * A single `BatchBuilder` can therefore be used to bootstrap many jobs.
28
+ */
29
+ job(id: string): JobBuilder {
30
+ return JobBuilder.create(id);
31
+ }
32
+ }
@@ -0,0 +1,141 @@
1
+ import type {
2
+ DeciderDefinition,
3
+ FlowTransitionPattern,
4
+ ReusableFlowDefinition,
5
+ TransitionDefinition,
6
+ } from '../core/ir';
7
+
8
+ /**
9
+ * Focused fluent builder for a single `TransitionDefinition`.
10
+ *
11
+ * Mirrors the flow methods exposed on `JobBuilder` (`from` / `on` / `to` /
12
+ * `end`) but is a standalone, single-use object: `.build()` produces a
13
+ * fully-validated `TransitionDefinition` value, and the instance is then
14
+ * discarded.
15
+ *
16
+ * Two intended usages:
17
+ *
18
+ * 1. **Standalone** — when callers want to build a transition literal
19
+ * outside of a `JobBuilder` (e.g. inside helper functions or test
20
+ * fixtures that don't need the full job context):
21
+ *
22
+ * const t = new FlowBuilder()
23
+ * .from('s1')
24
+ * .on(FlowExecutionStatus.FAILED)
25
+ * .to('recovery')
26
+ * .build();
27
+ *
28
+ * 2. **Reuse** — the same chain shape as `JobBuilder`'s flow methods.
29
+ * This class is the canonical type the chain returns at the
30
+ * `.from(stepId)` step; `JobBuilder.from` simply exposes the same
31
+ * shape via its own convenience methods.
32
+ *
33
+ * The class is intentionally minimal: no Nest DI, no execution, no
34
+ * validation beyond "is the transition fully specified?" — the
35
+ * `DefinitionValidator` does the graph-level checks
36
+ * (reachability, cycles, missing targets) downstream.
37
+ */
38
+ export class FlowBuilder {
39
+ private fromStepId?: string;
40
+ private onStatus?: FlowTransitionPattern;
41
+ private toStepId: string | null | undefined;
42
+ private committed = false;
43
+
44
+ /**
45
+ * Convenience constructor that immediately calls `.from(stepId)`.
46
+ *
47
+ * FlowBuilder.from('s1').on(FAILED).to('s2').build()
48
+ */
49
+ static from(stepId: string): FlowBuilder {
50
+ return new FlowBuilder().from(stepId);
51
+ }
52
+
53
+ /** Set the source step of the transition. */
54
+ from(stepId: string): this {
55
+ if (this.committed) {
56
+ throw new Error('FlowBuilder already committed; create a new instance');
57
+ }
58
+ this.fromStepId = stepId;
59
+ return this;
60
+ }
61
+
62
+ /** Set the status that triggers the transition. Must follow `.from()`. */
63
+ on(status: FlowTransitionPattern): this {
64
+ if (this.committed) {
65
+ throw new Error('FlowBuilder already committed; create a new instance');
66
+ }
67
+ if (this.fromStepId === undefined) {
68
+ throw new Error('FlowBuilder: call .from(stepId) before .on(status)');
69
+ }
70
+ this.onStatus = status;
71
+ return this;
72
+ }
73
+
74
+ /** Set the target step and commit. `null` is reserved for `.end()`. */
75
+ to(stepId: string): this {
76
+ if (this.committed) {
77
+ throw new Error('FlowBuilder already committed; create a new instance');
78
+ }
79
+ if (this.fromStepId === undefined || this.onStatus === undefined) {
80
+ throw new Error('FlowBuilder: call .from() and .on() before .to()');
81
+ }
82
+ this.toStepId = stepId;
83
+ this.committed = true;
84
+ return this;
85
+ }
86
+
87
+ /** End the transition (target = null) and commit. */
88
+ end(): this {
89
+ if (this.committed) {
90
+ throw new Error('FlowBuilder already committed; create a new instance');
91
+ }
92
+ if (this.fromStepId === undefined || this.onStatus === undefined) {
93
+ throw new Error('FlowBuilder: call .from() and .on() before .end()');
94
+ }
95
+ this.toStepId = null;
96
+ this.committed = true;
97
+ return this;
98
+ }
99
+
100
+ /**
101
+ * Produce the final `TransitionDefinition`. Throws if the chain is
102
+ * incomplete (missing from/on, or never committed via `.to()`/`.end()`).
103
+ */
104
+ build(): TransitionDefinition {
105
+ if (!this.committed) {
106
+ throw new Error('FlowBuilder: must be committed via .to() or .end()');
107
+ }
108
+ if (this.fromStepId === undefined) {
109
+ throw new Error('FlowBuilder: missing .from(stepId)');
110
+ }
111
+ if (this.onStatus === undefined) {
112
+ throw new Error('FlowBuilder: missing .on(status)');
113
+ }
114
+ if (this.toStepId === undefined) {
115
+ throw new Error('FlowBuilder: missing .to(stepId) or .end()');
116
+ }
117
+ return {
118
+ fromStepId: this.fromStepId,
119
+ onStatus: this.onStatus,
120
+ toStepId: this.toStepId,
121
+ };
122
+ }
123
+ }
124
+
125
+ export function defineReusableFlow(
126
+ definition: ReusableFlowDefinition,
127
+ ): ReusableFlowDefinition {
128
+ return Object.freeze({
129
+ transitions: Object.freeze([...definition.transitions]),
130
+ ...(definition.deciders !== undefined
131
+ ? { deciders: Object.freeze([...definition.deciders]) }
132
+ : {}),
133
+ });
134
+ }
135
+
136
+ export function defineDecider(
137
+ afterStepId: string,
138
+ decide: DeciderDefinition['decide'],
139
+ ): DeciderDefinition {
140
+ return Object.freeze({ afterStepId, decide });
141
+ }
@@ -0,0 +1,4 @@
1
+ export * from './batch-builder';
2
+ export * from './job-builder';
3
+ export * from './step-builder';
4
+ export * from './flow-builder';