reqon-dsl 0.2.0 → 0.4.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 (450) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +45 -3
  3. package/dist/ast/nodes.d.ts +91 -4
  4. package/dist/ast/nodes.js +14 -0
  5. package/dist/auth/circuit-breaker.d.ts +11 -0
  6. package/dist/auth/circuit-breaker.js +90 -18
  7. package/dist/auth/credentials.d.ts +6 -1
  8. package/dist/auth/credentials.js +12 -4
  9. package/dist/auth/oauth2-provider.js +13 -3
  10. package/dist/auth/rate-limiter.d.ts +12 -1
  11. package/dist/auth/rate-limiter.js +39 -26
  12. package/dist/auth/token-store.js +8 -1
  13. package/dist/cli.d.ts +24 -1
  14. package/dist/cli.js +149 -10
  15. package/dist/config/constants.d.ts +152 -0
  16. package/dist/config/constants.js +139 -0
  17. package/dist/config/index.d.ts +4 -0
  18. package/dist/config/index.js +4 -0
  19. package/dist/control/index.d.ts +2 -0
  20. package/dist/control/index.js +1 -0
  21. package/dist/control/server.d.ts +105 -0
  22. package/dist/control/server.js +315 -0
  23. package/dist/control/types.d.ts +61 -0
  24. package/dist/control/types.js +7 -0
  25. package/dist/debug/cli-debugger.d.ts +17 -0
  26. package/dist/debug/cli-debugger.js +185 -0
  27. package/dist/debug/controller.d.ts +94 -0
  28. package/dist/debug/controller.js +45 -0
  29. package/dist/debug/index.d.ts +6 -0
  30. package/dist/debug/index.js +5 -0
  31. package/dist/errors/index.d.ts +67 -0
  32. package/dist/errors/index.js +89 -1
  33. package/dist/execution/index.d.ts +1 -1
  34. package/dist/execution/state.d.ts +24 -0
  35. package/dist/execution/store.js +2 -2
  36. package/dist/execution-log/events.d.ts +125 -0
  37. package/dist/execution-log/events.js +17 -0
  38. package/dist/execution-log/fold.d.ts +38 -0
  39. package/dist/execution-log/fold.js +54 -0
  40. package/dist/execution-log/index.d.ts +18 -0
  41. package/dist/execution-log/index.js +6 -0
  42. package/dist/execution-log/postgres-store.d.ts +36 -0
  43. package/dist/execution-log/postgres-store.js +108 -0
  44. package/dist/execution-log/resume.d.ts +11 -0
  45. package/dist/execution-log/resume.js +5 -0
  46. package/dist/execution-log/sqlite-store.d.ts +16 -0
  47. package/dist/execution-log/sqlite-store.js +101 -0
  48. package/dist/execution-log/store.d.ts +72 -0
  49. package/dist/execution-log/store.js +182 -0
  50. package/dist/index.d.ts +23 -2
  51. package/dist/index.js +35 -3
  52. package/dist/interpreter/context.d.ts +29 -0
  53. package/dist/interpreter/context.js +18 -0
  54. package/dist/interpreter/evaluator.d.ts +63 -1
  55. package/dist/interpreter/evaluator.js +219 -42
  56. package/dist/interpreter/executor.d.ts +132 -14
  57. package/dist/interpreter/executor.js +883 -178
  58. package/dist/interpreter/fetch-handler.d.ts +48 -1
  59. package/dist/interpreter/fetch-handler.js +216 -38
  60. package/dist/interpreter/http.d.ts +34 -0
  61. package/dist/interpreter/http.js +203 -28
  62. package/dist/interpreter/index.d.ts +5 -3
  63. package/dist/interpreter/index.js +4 -2
  64. package/dist/interpreter/pagination.d.ts +12 -3
  65. package/dist/interpreter/pagination.js +102 -32
  66. package/dist/interpreter/signals.d.ts +8 -0
  67. package/dist/interpreter/signals.js +12 -0
  68. package/dist/interpreter/source-manager.d.ts +75 -0
  69. package/dist/interpreter/source-manager.js +157 -0
  70. package/dist/interpreter/step-handlers/apply-handler.d.ts +29 -0
  71. package/dist/interpreter/step-handlers/apply-handler.js +79 -0
  72. package/dist/interpreter/step-handlers/for-handler.d.ts +16 -0
  73. package/dist/interpreter/step-handlers/for-handler.js +89 -7
  74. package/dist/interpreter/step-handlers/index.d.ts +4 -2
  75. package/dist/interpreter/step-handlers/index.js +4 -2
  76. package/dist/interpreter/step-handlers/match-handler.d.ts +9 -0
  77. package/dist/interpreter/step-handlers/match-handler.js +47 -17
  78. package/dist/interpreter/step-handlers/pause-handler.d.ts +52 -0
  79. package/dist/interpreter/step-handlers/pause-handler.js +87 -0
  80. package/dist/interpreter/step-handlers/store-handler.d.ts +17 -1
  81. package/dist/interpreter/step-handlers/store-handler.js +61 -20
  82. package/dist/interpreter/step-handlers/types.d.ts +3 -0
  83. package/dist/interpreter/step-handlers/validate-handler.d.ts +2 -1
  84. package/dist/interpreter/step-handlers/validate-handler.js +7 -2
  85. package/dist/interpreter/step-handlers/webhook-handler.d.ts +4 -0
  86. package/dist/interpreter/step-handlers/webhook-handler.js +31 -5
  87. package/dist/interpreter/store-manager.d.ts +46 -0
  88. package/dist/interpreter/store-manager.js +70 -0
  89. package/dist/lexer/index.d.ts +11 -4
  90. package/dist/lexer/index.js +11 -4
  91. package/dist/lexer/tokens.d.ts +17 -1
  92. package/dist/lexer/tokens.js +36 -0
  93. package/dist/loader/index.js +5 -8
  94. package/dist/mcp/index.d.ts +11 -0
  95. package/dist/mcp/index.js +11 -0
  96. package/dist/mcp/sandbox.d.ts +41 -0
  97. package/dist/mcp/sandbox.js +76 -0
  98. package/dist/mcp/server.d.ts +17 -0
  99. package/dist/mcp/server.js +504 -0
  100. package/dist/oas/index.d.ts +2 -0
  101. package/dist/oas/index.js +1 -0
  102. package/dist/oas/loader.d.ts +13 -1
  103. package/dist/oas/loader.js +25 -3
  104. package/dist/oas/mock-generator.d.ts +12 -0
  105. package/dist/oas/mock-generator.js +196 -0
  106. package/dist/oas/validator.js +45 -5
  107. package/dist/observability/events.d.ts +248 -0
  108. package/dist/observability/events.js +85 -0
  109. package/dist/observability/index.d.ts +15 -0
  110. package/dist/observability/index.js +12 -0
  111. package/dist/observability/logger.d.ts +106 -0
  112. package/dist/observability/logger.js +266 -0
  113. package/dist/observability/otel.d.ts +143 -0
  114. package/dist/observability/otel.js +421 -0
  115. package/dist/parser/action-parser.d.ts +105 -0
  116. package/dist/parser/action-parser.js +645 -0
  117. package/dist/parser/base.d.ts +7 -0
  118. package/dist/parser/base.js +11 -0
  119. package/dist/parser/expressions.d.ts +14 -0
  120. package/dist/parser/expressions.js +89 -6
  121. package/dist/parser/fetch-parser.d.ts +27 -0
  122. package/dist/parser/fetch-parser.js +280 -0
  123. package/dist/parser/index.d.ts +17 -0
  124. package/dist/parser/index.js +17 -0
  125. package/dist/parser/parser.d.ts +44 -46
  126. package/dist/parser/parser.js +122 -1070
  127. package/dist/parser/pipeline-parser.d.ts +12 -0
  128. package/dist/parser/pipeline-parser.js +52 -0
  129. package/dist/parser/schedule-parser.d.ts +7 -0
  130. package/dist/parser/schedule-parser.js +137 -0
  131. package/dist/parser/source-parser.d.ts +9 -0
  132. package/dist/parser/source-parser.js +151 -0
  133. package/dist/pause/index.d.ts +15 -0
  134. package/dist/pause/index.js +12 -0
  135. package/dist/pause/log-store.d.ts +33 -0
  136. package/dist/pause/log-store.js +98 -0
  137. package/dist/pause/manager.d.ts +130 -0
  138. package/dist/pause/manager.js +294 -0
  139. package/dist/pause/state.d.ts +93 -0
  140. package/dist/pause/state.js +103 -0
  141. package/dist/pause/store.d.ts +61 -0
  142. package/dist/pause/store.js +158 -0
  143. package/dist/plugin.d.ts +9 -12
  144. package/dist/plugin.js +10 -13
  145. package/dist/scheduler/cron-parser.d.ts +10 -3
  146. package/dist/scheduler/cron-parser.js +227 -48
  147. package/dist/scheduler/scheduler.js +56 -22
  148. package/dist/stores/factory.d.ts +7 -1
  149. package/dist/stores/factory.js +14 -3
  150. package/dist/stores/file.d.ts +26 -0
  151. package/dist/stores/file.js +67 -21
  152. package/dist/stores/index.d.ts +16 -1
  153. package/dist/stores/index.js +16 -1
  154. package/dist/stores/memory.d.ts +4 -0
  155. package/dist/stores/memory.js +8 -6
  156. package/dist/stores/postgrest.d.ts +28 -0
  157. package/dist/stores/postgrest.js +84 -37
  158. package/dist/stores/types.d.ts +17 -0
  159. package/dist/stores/types.js +12 -0
  160. package/dist/sync/index.d.ts +3 -2
  161. package/dist/sync/index.js +2 -1
  162. package/dist/sync/log-store.d.ts +30 -0
  163. package/dist/sync/log-store.js +45 -0
  164. package/dist/sync/store.js +1 -1
  165. package/dist/trace/index.d.ts +18 -0
  166. package/dist/trace/index.js +13 -0
  167. package/dist/trace/log-view.d.ts +57 -0
  168. package/dist/trace/log-view.js +76 -0
  169. package/dist/trace/recorder.d.ts +75 -0
  170. package/dist/trace/recorder.js +157 -0
  171. package/dist/trace/replay.d.ts +132 -0
  172. package/dist/trace/replay.js +264 -0
  173. package/dist/trace/state.d.ts +102 -0
  174. package/dist/trace/state.js +86 -0
  175. package/dist/trace/store.d.ts +75 -0
  176. package/dist/trace/store.js +250 -0
  177. package/dist/utils/deep-merge.d.ts +10 -0
  178. package/dist/utils/deep-merge.js +23 -0
  179. package/dist/utils/file.d.ts +13 -4
  180. package/dist/utils/file.js +70 -12
  181. package/dist/utils/index.d.ts +2 -1
  182. package/dist/utils/index.js +2 -1
  183. package/dist/utils/long-timeout.d.ts +19 -0
  184. package/dist/utils/long-timeout.js +33 -0
  185. package/dist/utils/path.d.ts +22 -1
  186. package/dist/utils/path.js +46 -1
  187. package/dist/utils/redact.d.ts +22 -0
  188. package/dist/utils/redact.js +42 -0
  189. package/dist/utils/type-guards.d.ts +58 -0
  190. package/dist/utils/type-guards.js +92 -0
  191. package/dist/webhook/server.d.ts +9 -0
  192. package/dist/webhook/server.js +122 -36
  193. package/dist/webhook/types.d.ts +9 -1
  194. package/package.json +76 -9
  195. package/.claude/settings.local.json +0 -31
  196. package/.claude/skills/api-integration.md +0 -125
  197. package/.claude/skills/database-schema.md +0 -51
  198. package/.claude/skills/dsl-design.md +0 -80
  199. package/.claude/skills/property-testing.md +0 -143
  200. package/.claude/skills/reqon/SKILL.md +0 -44
  201. package/.claude/skills/reqon/references/examples.md +0 -206
  202. package/.claude/skills/reqon/references/syntax.md +0 -263
  203. package/.claude/skills/vscode-extension.md +0 -113
  204. package/.github/dependabot.yml +0 -32
  205. package/.github/pull_request_template.md +0 -21
  206. package/.github/workflows/ci.yml +0 -174
  207. package/.github/workflows/release.yml +0 -73
  208. package/CLAUDE.md +0 -72
  209. package/CONTRIBUTING.md +0 -161
  210. package/TODO.md +0 -51
  211. package/dist/auth/auth.test.d.ts +0 -1
  212. package/dist/auth/auth.test.js +0 -255
  213. package/dist/errors/errors.test.d.ts +0 -1
  214. package/dist/errors/errors.test.js +0 -165
  215. package/dist/execution/execution.test.d.ts +0 -1
  216. package/dist/execution/execution.test.js +0 -246
  217. package/dist/integration.test.d.ts +0 -1
  218. package/dist/integration.test.js +0 -168
  219. package/dist/interpreter/evaluator.test.d.ts +0 -1
  220. package/dist/interpreter/evaluator.test.js +0 -512
  221. package/dist/interpreter/http.test.d.ts +0 -1
  222. package/dist/interpreter/http.test.js +0 -299
  223. package/dist/interpreter/progress.test.d.ts +0 -1
  224. package/dist/interpreter/progress.test.js +0 -216
  225. package/dist/interpreter/schema-matcher.test.d.ts +0 -1
  226. package/dist/interpreter/schema-matcher.test.js +0 -122
  227. package/dist/lexer/lexer.d.ts +0 -24
  228. package/dist/lexer/lexer.js +0 -264
  229. package/dist/lexer/lexer.test.d.ts +0 -1
  230. package/dist/lexer/lexer.test.js +0 -259
  231. package/dist/loader/loader.test.d.ts +0 -1
  232. package/dist/loader/loader.test.js +0 -287
  233. package/dist/oas/oas.test.d.ts +0 -1
  234. package/dist/oas/oas.test.js +0 -218
  235. package/dist/parser/expressions.test.d.ts +0 -1
  236. package/dist/parser/expressions.test.js +0 -378
  237. package/dist/parser/match.test.d.ts +0 -1
  238. package/dist/parser/match.test.js +0 -254
  239. package/dist/parser/parser.test.d.ts +0 -1
  240. package/dist/parser/parser.test.js +0 -333
  241. package/dist/parser/schedule.test.d.ts +0 -1
  242. package/dist/parser/schedule.test.js +0 -241
  243. package/dist/scheduler/cron-parser.test.d.ts +0 -1
  244. package/dist/scheduler/cron-parser.test.js +0 -188
  245. package/dist/stores/file.test.d.ts +0 -1
  246. package/dist/stores/file.test.js +0 -165
  247. package/dist/stores/memory.test.d.ts +0 -1
  248. package/dist/stores/memory.test.js +0 -157
  249. package/dist/stores/stores.test.d.ts +0 -1
  250. package/dist/stores/stores.test.js +0 -158
  251. package/dist/sync/sync.test.d.ts +0 -1
  252. package/dist/sync/sync.test.js +0 -221
  253. package/docusaurus/README.md +0 -41
  254. package/docusaurus/docs/advanced/execution-state.md +0 -283
  255. package/docusaurus/docs/advanced/extending-reqon.md +0 -388
  256. package/docusaurus/docs/advanced/multi-file-missions.md +0 -250
  257. package/docusaurus/docs/advanced/parallel-execution.md +0 -353
  258. package/docusaurus/docs/api-reference.md +0 -443
  259. package/docusaurus/docs/authentication/api-key.md +0 -339
  260. package/docusaurus/docs/authentication/basic.md +0 -276
  261. package/docusaurus/docs/authentication/bearer.md +0 -282
  262. package/docusaurus/docs/authentication/oauth2.md +0 -317
  263. package/docusaurus/docs/authentication/overview.md +0 -251
  264. package/docusaurus/docs/cli.md +0 -229
  265. package/docusaurus/docs/core-concepts/actions.md +0 -286
  266. package/docusaurus/docs/core-concepts/missions.md +0 -264
  267. package/docusaurus/docs/core-concepts/schemas.md +0 -353
  268. package/docusaurus/docs/core-concepts/sources.md +0 -339
  269. package/docusaurus/docs/core-concepts/stores.md +0 -332
  270. package/docusaurus/docs/dsl-syntax/expressions.md +0 -361
  271. package/docusaurus/docs/dsl-syntax/fetch.md +0 -293
  272. package/docusaurus/docs/dsl-syntax/for-loops.md +0 -324
  273. package/docusaurus/docs/dsl-syntax/map.md +0 -345
  274. package/docusaurus/docs/dsl-syntax/match.md +0 -387
  275. package/docusaurus/docs/dsl-syntax/pipelines.md +0 -397
  276. package/docusaurus/docs/dsl-syntax/validate.md +0 -401
  277. package/docusaurus/docs/error-handling/dead-letter-queues.md +0 -399
  278. package/docusaurus/docs/error-handling/flow-control.md +0 -337
  279. package/docusaurus/docs/error-handling/retry-strategies.md +0 -368
  280. package/docusaurus/docs/examples.md +0 -488
  281. package/docusaurus/docs/getting-started.md +0 -256
  282. package/docusaurus/docs/http/circuit-breaker.md +0 -401
  283. package/docusaurus/docs/http/incremental-sync.md +0 -394
  284. package/docusaurus/docs/http/pagination.md +0 -361
  285. package/docusaurus/docs/http/rate-limiting.md +0 -383
  286. package/docusaurus/docs/http/requests.md +0 -328
  287. package/docusaurus/docs/http/retry.md +0 -402
  288. package/docusaurus/docs/intro.md +0 -90
  289. package/docusaurus/docs/openapi/loading-specs.md +0 -305
  290. package/docusaurus/docs/openapi/operation-calls.md +0 -314
  291. package/docusaurus/docs/openapi/overview.md +0 -212
  292. package/docusaurus/docs/openapi/response-validation.md +0 -344
  293. package/docusaurus/docs/scheduling/cron.md +0 -305
  294. package/docusaurus/docs/scheduling/daemon-mode.md +0 -317
  295. package/docusaurus/docs/scheduling/intervals.md +0 -289
  296. package/docusaurus/docs/scheduling/overview.md +0 -231
  297. package/docusaurus/docs/stores/custom-adapters.md +0 -376
  298. package/docusaurus/docs/stores/file.md +0 -236
  299. package/docusaurus/docs/stores/memory.md +0 -193
  300. package/docusaurus/docs/stores/overview.md +0 -274
  301. package/docusaurus/docs/stores/postgrest.md +0 -316
  302. package/docusaurus/docusaurus.config.ts +0 -148
  303. package/docusaurus/package-lock.json +0 -18029
  304. package/docusaurus/package.json +0 -47
  305. package/docusaurus/sidebars.ts +0 -155
  306. package/docusaurus/src/components/HomepageFeatures/index.tsx +0 -105
  307. package/docusaurus/src/components/HomepageFeatures/styles.module.css +0 -12
  308. package/docusaurus/src/css/custom.css +0 -169
  309. package/docusaurus/src/pages/index.module.css +0 -48
  310. package/docusaurus/src/pages/index.tsx +0 -110
  311. package/docusaurus/src/pages/markdown-page.md +0 -7
  312. package/docusaurus/static/.nojekyll +0 -0
  313. package/docusaurus/static/img/docusaurus-social-card.jpg +0 -0
  314. package/docusaurus/static/img/docusaurus.png +0 -0
  315. package/docusaurus/static/img/favicon.ico +0 -0
  316. package/docusaurus/static/img/logo.svg +0 -10
  317. package/docusaurus/static/img/undraw_docusaurus_mountain.svg +0 -171
  318. package/docusaurus/static/img/undraw_docusaurus_react.svg +0 -170
  319. package/docusaurus/static/img/undraw_docusaurus_tree.svg +0 -40
  320. package/docusaurus/tsconfig.json +0 -8
  321. package/examples/README.md +0 -112
  322. package/examples/error-handling/README.md +0 -150
  323. package/examples/error-handling/payment-processor.vague +0 -287
  324. package/examples/github-sync/README.md +0 -74
  325. package/examples/github-sync/fetch-issues.vague +0 -47
  326. package/examples/github-sync/fetch-prs.vague +0 -40
  327. package/examples/github-sync/mission.vague +0 -101
  328. package/examples/github-sync/normalize.vague +0 -70
  329. package/examples/jsonplaceholder/README.md +0 -28
  330. package/examples/jsonplaceholder/posts.vague +0 -48
  331. package/examples/petstore/README.md +0 -35
  332. package/examples/petstore/openapi.yaml +0 -97
  333. package/examples/petstore/sync.vague +0 -52
  334. package/examples/temporal-comparison/README.md +0 -297
  335. package/examples/temporal-comparison/reconciliation.vague +0 -355
  336. package/examples/temporal-comparison/temporal/activities/index.ts +0 -8
  337. package/examples/temporal-comparison/temporal/activities/shipstation.ts +0 -225
  338. package/examples/temporal-comparison/temporal/activities/shopify.ts +0 -257
  339. package/examples/temporal-comparison/temporal/activities/storage.ts +0 -198
  340. package/examples/temporal-comparison/temporal/activities/stripe.ts +0 -169
  341. package/examples/temporal-comparison/temporal/activities/validation.ts +0 -205
  342. package/examples/temporal-comparison/temporal/client/schedule.ts +0 -218
  343. package/examples/temporal-comparison/temporal/config/retry.ts +0 -63
  344. package/examples/temporal-comparison/temporal/types/index.ts +0 -129
  345. package/examples/temporal-comparison/temporal/workers/main.ts +0 -130
  346. package/examples/temporal-comparison/temporal/workflows/orderReconciliation.ts +0 -262
  347. package/examples/xero/README.md +0 -88
  348. package/examples/xero/invoices.vague +0 -189
  349. package/src/api-integration.test.ts +0 -954
  350. package/src/ast/index.ts +0 -1
  351. package/src/ast/nodes.ts +0 -310
  352. package/src/auth/auth.test.ts +0 -326
  353. package/src/auth/circuit-breaker.test.ts +0 -390
  354. package/src/auth/circuit-breaker.ts +0 -379
  355. package/src/auth/credentials.test.ts +0 -273
  356. package/src/auth/credentials.ts +0 -246
  357. package/src/auth/index.ts +0 -40
  358. package/src/auth/oauth2-provider.ts +0 -177
  359. package/src/auth/rate-limiter.ts +0 -459
  360. package/src/auth/token-store.ts +0 -177
  361. package/src/auth/types.ts +0 -159
  362. package/src/benchmark/e2e.bench.ts +0 -288
  363. package/src/benchmark/evaluator.bench.ts +0 -331
  364. package/src/benchmark/fixtures.ts +0 -295
  365. package/src/benchmark/index.ts +0 -108
  366. package/src/benchmark/lexer.bench.ts +0 -69
  367. package/src/benchmark/parser.bench.ts +0 -103
  368. package/src/benchmark/resilience.bench.ts +0 -193
  369. package/src/benchmark/store.bench.ts +0 -147
  370. package/src/benchmark/utils.ts +0 -230
  371. package/src/cli.ts +0 -313
  372. package/src/errors/errors.test.ts +0 -234
  373. package/src/errors/index.ts +0 -223
  374. package/src/execution/execution.test.ts +0 -307
  375. package/src/execution/index.ts +0 -21
  376. package/src/execution/state.ts +0 -207
  377. package/src/execution/store.ts +0 -188
  378. package/src/index.ts +0 -169
  379. package/src/integration.test.ts +0 -192
  380. package/src/interpreter/context.ts +0 -57
  381. package/src/interpreter/evaluator.test.ts +0 -796
  382. package/src/interpreter/evaluator.ts +0 -245
  383. package/src/interpreter/executor.ts +0 -946
  384. package/src/interpreter/fetch-handler.ts +0 -302
  385. package/src/interpreter/http.test.ts +0 -423
  386. package/src/interpreter/http.ts +0 -308
  387. package/src/interpreter/index.ts +0 -32
  388. package/src/interpreter/pagination.ts +0 -207
  389. package/src/interpreter/progress.test.ts +0 -276
  390. package/src/interpreter/schema-matcher.test.ts +0 -160
  391. package/src/interpreter/schema-matcher.ts +0 -168
  392. package/src/interpreter/signals.ts +0 -73
  393. package/src/interpreter/step-handlers/for-handler.ts +0 -65
  394. package/src/interpreter/step-handlers/index.ts +0 -17
  395. package/src/interpreter/step-handlers/map-handler.ts +0 -24
  396. package/src/interpreter/step-handlers/match-handler.ts +0 -101
  397. package/src/interpreter/step-handlers/store-handler.ts +0 -78
  398. package/src/interpreter/step-handlers/types.ts +0 -17
  399. package/src/interpreter/step-handlers/validate-handler.ts +0 -30
  400. package/src/interpreter/step-handlers/webhook-handler.ts +0 -142
  401. package/src/lexer/index.ts +0 -18
  402. package/src/lexer/lexer.test.ts +0 -316
  403. package/src/lexer/tokens.ts +0 -179
  404. package/src/loader/index.ts +0 -288
  405. package/src/loader/loader.test.ts +0 -360
  406. package/src/oas/index.ts +0 -4
  407. package/src/oas/loader.ts +0 -126
  408. package/src/oas/oas.test.ts +0 -254
  409. package/src/oas/validator.ts +0 -299
  410. package/src/parser/base.ts +0 -124
  411. package/src/parser/expressions.test.ts +0 -525
  412. package/src/parser/expressions.ts +0 -314
  413. package/src/parser/index.ts +0 -3
  414. package/src/parser/match.test.ts +0 -296
  415. package/src/parser/parser.test.ts +0 -739
  416. package/src/parser/parser.ts +0 -1469
  417. package/src/parser/schedule.test.ts +0 -287
  418. package/src/parser/webhook.test.ts +0 -248
  419. package/src/plugin.ts +0 -83
  420. package/src/scheduler/cron-parser.test.ts +0 -236
  421. package/src/scheduler/cron-parser.ts +0 -236
  422. package/src/scheduler/index.ts +0 -10
  423. package/src/scheduler/scheduler.ts +0 -443
  424. package/src/scheduler/types.ts +0 -71
  425. package/src/stores/factory.ts +0 -104
  426. package/src/stores/file.test.ts +0 -276
  427. package/src/stores/file.ts +0 -211
  428. package/src/stores/index.ts +0 -6
  429. package/src/stores/memory.test.ts +0 -238
  430. package/src/stores/memory.ts +0 -63
  431. package/src/stores/postgrest.test.ts +0 -488
  432. package/src/stores/postgrest.ts +0 -263
  433. package/src/stores/stores.test.ts +0 -197
  434. package/src/stores/types.ts +0 -58
  435. package/src/sync/index.ts +0 -16
  436. package/src/sync/state.ts +0 -126
  437. package/src/sync/store.ts +0 -139
  438. package/src/sync/sync.test.ts +0 -271
  439. package/src/utils/async.ts +0 -10
  440. package/src/utils/file.ts +0 -106
  441. package/src/utils/index.ts +0 -14
  442. package/src/utils/logger.ts +0 -53
  443. package/src/utils/path.ts +0 -47
  444. package/src/webhook/index.ts +0 -15
  445. package/src/webhook/server.test.ts +0 -253
  446. package/src/webhook/server.ts +0 -389
  447. package/src/webhook/store.ts +0 -239
  448. package/src/webhook/types.ts +0 -93
  449. package/tsconfig.json +0 -17
  450. package/vitest.config.ts +0 -39
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Execution event log — the durable, append-only record of a mission run.
3
+ *
4
+ * Every step's start, completion, and side effect is appended as it happens.
5
+ * Resume becomes "replay the log and fold to last state" (see {@link ./fold}),
6
+ * and trace/time-travel, audit, and idempotent resume all derive from this one
7
+ * structure. Recorded values (timestamps, effect ids, outputs) are read back on
8
+ * replay rather than re-derived, so replay is deterministic.
9
+ */
10
+ export type ExecutionEventType = 'mission.started' | 'step.started' | 'step.completed' | 'effect.applied' | 'page.completed' | 'checkpoint.advanced' | 'pause.created' | 'pause.resumed' | 'mission.completed' | 'mission.failed';
11
+ interface BaseEvent {
12
+ /** The run this event belongs to. */
13
+ executionId: string;
14
+ /** Event kind (discriminant). */
15
+ type: ExecutionEventType;
16
+ }
17
+ export interface MissionStartedEvent extends BaseEvent {
18
+ type: 'mission.started';
19
+ mission: string;
20
+ }
21
+ export interface StepStartedEvent extends BaseEvent {
22
+ type: 'step.started';
23
+ stepId: string;
24
+ action: string;
25
+ stepType: string;
26
+ attempt: number;
27
+ }
28
+ export interface StepCompletedEvent extends BaseEvent {
29
+ type: 'step.completed';
30
+ stepId: string;
31
+ attempt: number;
32
+ }
33
+ /**
34
+ * A side effect (a fetch or a store write) was applied. The {@link effectId}
35
+ * is the stable identity used to skip already-applied effects on replay.
36
+ */
37
+ export interface EffectAppliedEvent extends BaseEvent {
38
+ type: 'effect.applied';
39
+ stepId: string;
40
+ attempt: number;
41
+ effectType: 'fetch' | 'store';
42
+ effectId: string;
43
+ }
44
+ /**
45
+ * A page of a resumable (backfill) paginated fetch finished — its data is
46
+ * fetched and persisted. Carries the position to resume from: the next page
47
+ * index and/or cursor. `done` marks the natural end of pagination (the API had
48
+ * no more), distinct from stopping early on a per-run item cap, so a resume
49
+ * knows whether to continue or skip.
50
+ */
51
+ export interface PageCompletedEvent extends BaseEvent {
52
+ type: 'page.completed';
53
+ stepId: string;
54
+ /** Zero-based index of the next page to fetch on resume. */
55
+ page: number;
56
+ /** Cursor to resume from (cursor-based pagination). */
57
+ cursor?: string;
58
+ /**
59
+ * Records *fetched* on this page. NOTE: this is the fetched count, not the
60
+ * persisted count — the page's data is still only in memory when this event is
61
+ * recorded; the downstream store step persists it afterwards. A crash between
62
+ * this event and the store's `effect.applied` advances the resume cursor past a
63
+ * page whose data was never stored. See the known crash-window note in
64
+ * CODE_REVIEW.md (C2); a full fix defers this advance until after persistence.
65
+ */
66
+ recordCount?: number;
67
+ /** True once pagination has reached its natural end. */
68
+ done: boolean;
69
+ }
70
+ export interface CheckpointAdvancedEvent extends BaseEvent {
71
+ type: 'checkpoint.advanced';
72
+ key: string;
73
+ syncedAt: string;
74
+ /** Records fetched in the sync that advanced this checkpoint. */
75
+ recordCount?: number;
76
+ /** Opaque pagination cursor to resume from (cursor-based incremental sync). */
77
+ cursor?: string;
78
+ /** Mission that advanced the checkpoint (lets a shared log filter by mission). */
79
+ mission?: string;
80
+ }
81
+ export interface PauseCreatedEvent extends BaseEvent {
82
+ type: 'pause.created';
83
+ pauseId: string;
84
+ /**
85
+ * The full durable pause state (expiry, resume triggers, captured checkpoint).
86
+ * Carried in the log so a paused run — and the timer/webhook it waits on — can
87
+ * be reconstructed from the log alone, no separate pause file. Opaque to the
88
+ * log layer (typed `unknown` to avoid coupling it to the pause domain).
89
+ */
90
+ pause?: unknown;
91
+ }
92
+ export interface PauseResumedEvent extends BaseEvent {
93
+ type: 'pause.resumed';
94
+ pauseId: string;
95
+ resumedBy: string;
96
+ /** Terminal status of the pause: resumed (default), cancelled, or expired. */
97
+ status?: 'resumed' | 'cancelled' | 'expired';
98
+ /** Recorded resume time (ISO 8601). */
99
+ resumedAt?: string;
100
+ /** Payload delivered by a webhook resume. */
101
+ webhookPayload?: unknown;
102
+ }
103
+ export interface MissionCompletedEvent extends BaseEvent {
104
+ type: 'mission.completed';
105
+ }
106
+ export interface MissionFailedEvent extends BaseEvent {
107
+ type: 'mission.failed';
108
+ error: string;
109
+ }
110
+ /** An event as appended by a caller (the log assigns seq + timestamp). */
111
+ export type ExecutionEvent = MissionStartedEvent | StepStartedEvent | StepCompletedEvent | EffectAppliedEvent | PageCompletedEvent | CheckpointAdvancedEvent | PauseCreatedEvent | PauseResumedEvent | MissionCompletedEvent | MissionFailedEvent;
112
+ /** A persisted event: the appended event plus the log's assigned metadata. */
113
+ export type StoredEvent = ExecutionEvent & {
114
+ /** Monotonic sequence within the execution, starting at 0. */
115
+ seq: number;
116
+ /** Recorded wall-clock time (ISO 8601); read back on replay, never re-derived. */
117
+ at: string;
118
+ };
119
+ /**
120
+ * Stable identity for a side effect: `(executionId, stepId, attempt, effectType)`
121
+ * plus a caller-supplied discriminator (e.g. the request signature or record
122
+ * key). Replay uses this to skip effects already recorded as applied.
123
+ */
124
+ export declare function effectId(executionId: string, stepId: string, attempt: number, effectType: 'fetch' | 'store', discriminator: string): string;
125
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Execution event log — the durable, append-only record of a mission run.
3
+ *
4
+ * Every step's start, completion, and side effect is appended as it happens.
5
+ * Resume becomes "replay the log and fold to last state" (see {@link ./fold}),
6
+ * and trace/time-travel, audit, and idempotent resume all derive from this one
7
+ * structure. Recorded values (timestamps, effect ids, outputs) are read back on
8
+ * replay rather than re-derived, so replay is deterministic.
9
+ */
10
+ /**
11
+ * Stable identity for a side effect: `(executionId, stepId, attempt, effectType)`
12
+ * plus a caller-supplied discriminator (e.g. the request signature or record
13
+ * key). Replay uses this to skip effects already recorded as applied.
14
+ */
15
+ export function effectId(executionId, stepId, attempt, effectType, discriminator) {
16
+ return `${executionId}::${stepId}::${attempt}::${effectType}::${discriminator}`;
17
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Fold an execution event log down to current state.
3
+ *
4
+ * This is the heart of replay-based resume: replaying the log and folding it
5
+ * yields the exact state the run was in, including which effects already
6
+ * applied (so replay skips them) and which pause it is waiting on.
7
+ */
8
+ import type { StoredEvent } from './events.js';
9
+ export type FoldedStatus = 'pending' | 'running' | 'paused' | 'completed' | 'failed';
10
+ export interface FoldedState {
11
+ status: FoldedStatus;
12
+ /** Sequence of the last event folded (-1 for an empty log). */
13
+ lastSeq: number;
14
+ /** Step ids that have completed (replay skips re-running them). */
15
+ completedSteps: Set<string>;
16
+ /** Effect ids already applied (replay skips re-applying them). */
17
+ appliedEffects: Set<string>;
18
+ /** Latest synced-at per checkpoint key. */
19
+ checkpoints: Map<string, string>;
20
+ /** Resume position per backfill step id (last persisted page + cursor). */
21
+ pageProgress: Map<string, {
22
+ page: number;
23
+ cursor?: string;
24
+ done: boolean;
25
+ }>;
26
+ /** The pause this run is currently waiting on, if any. */
27
+ pendingPauseId?: string;
28
+ /**
29
+ * The last pause marked resumed in the log. A resume trigger (webhook/timeout)
30
+ * can record `pause.resumed` before the executor re-runs, so this lets the
31
+ * executor recognise it must continue past that pause rather than create a new
32
+ * one. Cleared once the run completes or fails.
33
+ */
34
+ resumedPauseId?: string;
35
+ /** Error message if the run failed. */
36
+ error?: string;
37
+ }
38
+ export declare function foldLog(events: StoredEvent[]): FoldedState;
@@ -0,0 +1,54 @@
1
+ export function foldLog(events) {
2
+ const state = {
3
+ status: 'pending',
4
+ lastSeq: -1,
5
+ completedSteps: new Set(),
6
+ appliedEffects: new Set(),
7
+ checkpoints: new Map(),
8
+ pageProgress: new Map(),
9
+ };
10
+ for (const event of events) {
11
+ state.lastSeq = event.seq;
12
+ switch (event.type) {
13
+ case 'mission.started':
14
+ state.status = 'running';
15
+ break;
16
+ case 'step.completed':
17
+ state.completedSteps.add(event.stepId);
18
+ break;
19
+ case 'effect.applied':
20
+ state.appliedEffects.add(event.effectId);
21
+ break;
22
+ case 'page.completed':
23
+ state.pageProgress.set(event.stepId, {
24
+ page: event.page,
25
+ cursor: event.cursor,
26
+ done: event.done,
27
+ });
28
+ break;
29
+ case 'checkpoint.advanced':
30
+ state.checkpoints.set(event.key, event.syncedAt);
31
+ break;
32
+ case 'pause.created':
33
+ state.status = 'paused';
34
+ state.pendingPauseId = event.pauseId;
35
+ break;
36
+ case 'pause.resumed':
37
+ state.status = 'running';
38
+ state.pendingPauseId = undefined;
39
+ state.resumedPauseId = event.pauseId;
40
+ break;
41
+ case 'mission.completed':
42
+ state.status = 'completed';
43
+ state.resumedPauseId = undefined;
44
+ break;
45
+ case 'mission.failed':
46
+ state.status = 'failed';
47
+ state.error = event.error;
48
+ state.resumedPauseId = undefined;
49
+ break;
50
+ // step.started carries no folded state on its own.
51
+ }
52
+ }
53
+ return state;
54
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Execution event log — the append-only foundation for durable execution.
3
+ *
4
+ * A running mission is modelled as an ordered log of events; resume is replay +
5
+ * fold (see {@link foldLog}), and idempotent effects fall out of recording an
6
+ * `effect.applied` event per side effect. This module is the seam the rest of
7
+ * the durable-execution work (transactional backend, exactly-once effects,
8
+ * trace/sync/pause as log views) builds on.
9
+ */
10
+ export type { ExecutionEvent, StoredEvent, ExecutionEventType, MissionStartedEvent, StepStartedEvent, StepCompletedEvent, EffectAppliedEvent, CheckpointAdvancedEvent, PauseCreatedEvent, PauseResumedEvent, MissionCompletedEvent, MissionFailedEvent, } from './events.js';
11
+ export { effectId } from './events.js';
12
+ export type { ExecutionLogStore, CheckpointRecord } from './store.js';
13
+ export { MemoryExecutionLog, FileExecutionLog, reduceCheckpoints } from './store.js';
14
+ export { SqliteExecutionLog } from './sqlite-store.js';
15
+ export { PostgresExecutionLog, type PostgresExecutionLogOptions } from './postgres-store.js';
16
+ export type { FoldedState, FoldedStatus } from './fold.js';
17
+ export { foldLog } from './fold.js';
18
+ export { loadState } from './resume.js';
@@ -0,0 +1,6 @@
1
+ export { effectId } from './events.js';
2
+ export { MemoryExecutionLog, FileExecutionLog, reduceCheckpoints } from './store.js';
3
+ export { SqliteExecutionLog } from './sqlite-store.js';
4
+ export { PostgresExecutionLog } from './postgres-store.js';
5
+ export { foldLog } from './fold.js';
6
+ export { loadState } from './resume.js';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Postgres-backed execution log — a transactional, multi-node durable backend.
3
+ *
4
+ * Like the SQLite backend, `pg` is an *optional* peer dependency imported lazily
5
+ * via a non-literal specifier, so the core package carries no database driver
6
+ * and a missing one yields a clear, actionable error.
7
+ *
8
+ * Multi-writer safety: `seq` is assigned inside the INSERT under a
9
+ * `(execution_id, seq)` primary key. If two appenders race and compute the same
10
+ * next seq, one wins and the other gets a unique-violation (SQLSTATE 23505) and
11
+ * retries against the now-higher max — so concurrent appenders always land on
12
+ * distinct, contiguous sequence numbers.
13
+ */
14
+ import type { ExecutionEvent, StoredEvent } from './events.js';
15
+ import type { CheckpointRecord, ExecutionLogStore } from './store.js';
16
+ export interface PostgresExecutionLogOptions {
17
+ /** Table to store events in. Default `reqon_execution_events`. */
18
+ table?: string;
19
+ }
20
+ export declare class PostgresExecutionLog implements ExecutionLogStore {
21
+ private connectionString;
22
+ private pool?;
23
+ private ready?;
24
+ private readonly table;
25
+ constructor(connectionString: string, options?: PostgresExecutionLogOptions);
26
+ private ensure;
27
+ private init;
28
+ append(event: ExecutionEvent): Promise<StoredEvent>;
29
+ read(executionId: string): Promise<StoredEvent[]>;
30
+ listCheckpoints(mission?: string): Promise<CheckpointRecord[]>;
31
+ listPauses(): Promise<StoredEvent[]>;
32
+ /** Drop all rows. Intended for test setup, not production use. */
33
+ reset(): Promise<void>;
34
+ /** Release the connection pool. */
35
+ close(): Promise<void>;
36
+ }
@@ -0,0 +1,108 @@
1
+ import { reduceCheckpoints } from './store.js';
2
+ const UNIQUE_VIOLATION = '23505';
3
+ const MAX_APPEND_ATTEMPTS = 8;
4
+ export class PostgresExecutionLog {
5
+ connectionString;
6
+ pool;
7
+ ready;
8
+ table;
9
+ constructor(connectionString, options = {}) {
10
+ this.connectionString = connectionString;
11
+ this.table = options.table ?? 'reqon_execution_events';
12
+ // The table name is interpolated into SQL (identifiers can't be bound), so
13
+ // constrain it to a safe identifier to keep that interpolation injection-free.
14
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(this.table)) {
15
+ throw new Error(`Invalid table name: ${this.table}`);
16
+ }
17
+ }
18
+ async ensure() {
19
+ if (this.pool)
20
+ return this.pool;
21
+ if (!this.ready)
22
+ this.ready = this.init();
23
+ return this.ready;
24
+ }
25
+ async init() {
26
+ let Pool;
27
+ try {
28
+ // Non-literal specifier: keeps the driver an optional dependency with no
29
+ // compile-time type coupling (no @types/pg required).
30
+ const specifier = 'pg';
31
+ const mod = (await import(specifier));
32
+ const ctor = mod.Pool ?? mod.default?.Pool;
33
+ if (!ctor)
34
+ throw new Error('pg.Pool not found');
35
+ Pool = ctor;
36
+ }
37
+ catch {
38
+ throw new Error("PostgresExecutionLog requires the optional peer dependency 'pg'. " +
39
+ 'Install it with: npm install pg');
40
+ }
41
+ const pool = new Pool({ connectionString: this.connectionString });
42
+ await pool.query(`CREATE TABLE IF NOT EXISTS ${this.table} (
43
+ execution_id text NOT NULL,
44
+ seq integer NOT NULL,
45
+ at text NOT NULL,
46
+ data jsonb NOT NULL,
47
+ PRIMARY KEY (execution_id, seq)
48
+ )`);
49
+ this.pool = pool;
50
+ return pool;
51
+ }
52
+ async append(event) {
53
+ const pool = await this.ensure();
54
+ const at = new Date().toISOString();
55
+ const data = JSON.stringify(event);
56
+ for (let attempt = 0; attempt < MAX_APPEND_ATTEMPTS; attempt++) {
57
+ try {
58
+ const res = await pool.query(`INSERT INTO ${this.table} (execution_id, seq, at, data)
59
+ VALUES (
60
+ $1,
61
+ (SELECT COALESCE(MAX(seq) + 1, 0) FROM ${this.table} WHERE execution_id = $1),
62
+ $2,
63
+ $3::jsonb
64
+ )
65
+ RETURNING seq`, [event.executionId, at, data]);
66
+ return { ...event, seq: res.rows[0].seq, at };
67
+ }
68
+ catch (err) {
69
+ // A concurrent appender claimed this seq first; retry against the new max.
70
+ if (err.code === UNIQUE_VIOLATION)
71
+ continue;
72
+ throw err;
73
+ }
74
+ }
75
+ throw new Error(`append failed after ${MAX_APPEND_ATTEMPTS} attempts for execution ${event.executionId}`);
76
+ }
77
+ async read(executionId) {
78
+ const pool = await this.ensure();
79
+ const res = await pool.query(`SELECT seq, at, data FROM ${this.table} WHERE execution_id = $1 ORDER BY seq ASC`, [executionId]);
80
+ // jsonb comes back already parsed; overlay the assigned seq + recorded time.
81
+ return res.rows.map((r) => ({ ...r.data, seq: r.seq, at: r.at }));
82
+ }
83
+ async listCheckpoints(mission) {
84
+ const pool = await this.ensure();
85
+ const res = await pool.query(`SELECT seq, at, data FROM ${this.table} WHERE data->>'type' = 'checkpoint.advanced'`);
86
+ const events = res.rows.map((r) => ({ ...r.data, seq: r.seq, at: r.at }));
87
+ return reduceCheckpoints(events, mission);
88
+ }
89
+ async listPauses() {
90
+ const pool = await this.ensure();
91
+ const res = await pool.query(`SELECT seq, at, data FROM ${this.table}
92
+ WHERE data->>'type' IN ('pause.created', 'pause.resumed')`);
93
+ return res.rows.map((r) => ({ ...r.data, seq: r.seq, at: r.at }));
94
+ }
95
+ /** Drop all rows. Intended for test setup, not production use. */
96
+ async reset() {
97
+ const pool = await this.ensure();
98
+ await pool.query(`TRUNCATE ${this.table}`);
99
+ }
100
+ /** Release the connection pool. */
101
+ async close() {
102
+ if (this.pool) {
103
+ await this.pool.end();
104
+ this.pool = undefined;
105
+ this.ready = undefined;
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Resume helpers: load the current folded state of a run from its log.
3
+ *
4
+ * Resume is "read the log, fold it, continue" — never a second execution. A
5
+ * replaying caller checks {@link FoldedState.appliedEffects} before re-running
6
+ * a side effect, so an effect recorded before a crash is skipped on resume.
7
+ */
8
+ import type { ExecutionLogStore } from './store.js';
9
+ import { type FoldedState } from './fold.js';
10
+ /** Read and fold an execution's log into its current state. */
11
+ export declare function loadState(store: ExecutionLogStore, executionId: string): Promise<FoldedState>;
@@ -0,0 +1,5 @@
1
+ import { foldLog } from './fold.js';
2
+ /** Read and fold an execution's log into its current state. */
3
+ export async function loadState(store, executionId) {
4
+ return foldLog(await store.read(executionId));
5
+ }
@@ -0,0 +1,16 @@
1
+ import type { ExecutionEvent, StoredEvent } from './events.js';
2
+ import type { CheckpointRecord, ExecutionLogStore } from './store.js';
3
+ export declare class SqliteExecutionLog implements ExecutionLogStore {
4
+ private path;
5
+ private db?;
6
+ private insertStmt?;
7
+ private readStmt?;
8
+ private checkpointStmt?;
9
+ private pauseStmt?;
10
+ constructor(path?: string);
11
+ private ensureDb;
12
+ append(event: ExecutionEvent): Promise<StoredEvent>;
13
+ read(executionId: string): Promise<StoredEvent[]>;
14
+ listCheckpoints(mission?: string): Promise<CheckpointRecord[]>;
15
+ listPauses(): Promise<StoredEvent[]>;
16
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * SQLite-backed execution log — durable, transactional state for single-process
3
+ * self-hosting (the "SQLite-of-durable-execution" lane).
4
+ *
5
+ * The `better-sqlite3` driver is an *optional* peer dependency: only installed
6
+ * by users who opt into the SQLite backend. It is imported lazily so the core
7
+ * package carries no native dependency, and a missing driver yields a clear,
8
+ * actionable error rather than an opaque module-resolution failure.
9
+ *
10
+ * Durability: WAL mode + `synchronous = NORMAL` gives fsync-backed commits that
11
+ * survive a process crash, and `seq` is assigned atomically inside the INSERT
12
+ * (guarded by a `(execution_id, seq)` primary key) so concurrent appenders
13
+ * cannot collide on a sequence number.
14
+ */
15
+ import { mkdir } from 'node:fs/promises';
16
+ import { dirname } from 'node:path';
17
+ import { reduceCheckpoints } from './store.js';
18
+ export class SqliteExecutionLog {
19
+ path;
20
+ db;
21
+ insertStmt;
22
+ readStmt;
23
+ checkpointStmt;
24
+ pauseStmt;
25
+ constructor(path = '.reqon-data/execution-log.sqlite') {
26
+ this.path = path;
27
+ }
28
+ async ensureDb() {
29
+ if (this.db)
30
+ return this.db;
31
+ if (this.path !== ':memory:') {
32
+ await mkdir(dirname(this.path), { recursive: true });
33
+ }
34
+ let Database;
35
+ try {
36
+ // Non-literal specifier: keeps the driver an optional dependency with no
37
+ // compile-time type coupling (no @types/better-sqlite3 required).
38
+ const specifier = 'better-sqlite3';
39
+ const mod = (await import(specifier));
40
+ Database = mod.default;
41
+ }
42
+ catch {
43
+ throw new Error("SqliteExecutionLog requires the optional peer dependency 'better-sqlite3'. " +
44
+ 'Install it with: npm install better-sqlite3');
45
+ }
46
+ const db = new Database(this.path);
47
+ db.pragma('journal_mode = WAL');
48
+ db.pragma('synchronous = NORMAL');
49
+ db.exec(`CREATE TABLE IF NOT EXISTS events (
50
+ execution_id TEXT NOT NULL,
51
+ seq INTEGER NOT NULL,
52
+ at TEXT NOT NULL,
53
+ data TEXT NOT NULL,
54
+ PRIMARY KEY (execution_id, seq)
55
+ )`);
56
+ // seq is computed inside the INSERT so it is assigned atomically, and
57
+ // RETURNING hands it back without a second round-trip.
58
+ this.insertStmt = db.prepare(`INSERT INTO events (execution_id, seq, at, data)
59
+ VALUES (
60
+ @id,
61
+ (SELECT COALESCE(MAX(seq) + 1, 0) FROM events WHERE execution_id = @id),
62
+ @at,
63
+ @data
64
+ )
65
+ RETURNING seq`);
66
+ this.readStmt = db.prepare(`SELECT seq, at, data FROM events WHERE execution_id = @id ORDER BY seq ASC`);
67
+ this.checkpointStmt = db.prepare(`SELECT execution_id, seq, at, data FROM events
68
+ WHERE json_extract(data, '$.type') = 'checkpoint.advanced'`);
69
+ this.pauseStmt = db.prepare(`SELECT execution_id, seq, at, data FROM events
70
+ WHERE json_extract(data, '$.type') IN ('pause.created', 'pause.resumed')`);
71
+ this.db = db;
72
+ return db;
73
+ }
74
+ async append(event) {
75
+ await this.ensureDb();
76
+ const at = new Date().toISOString();
77
+ const { executionId } = event;
78
+ const row = this.insertStmt.get({
79
+ id: executionId,
80
+ at,
81
+ data: JSON.stringify(event),
82
+ });
83
+ return { ...event, seq: row.seq, at };
84
+ }
85
+ async read(executionId) {
86
+ await this.ensureDb();
87
+ const rows = this.readStmt.all({ id: executionId });
88
+ return rows.map((r) => ({ ...JSON.parse(r.data), seq: r.seq, at: r.at }));
89
+ }
90
+ async listCheckpoints(mission) {
91
+ await this.ensureDb();
92
+ const rows = this.checkpointStmt.all({});
93
+ const events = rows.map((r) => ({ ...JSON.parse(r.data), seq: r.seq, at: r.at }));
94
+ return reduceCheckpoints(events, mission);
95
+ }
96
+ async listPauses() {
97
+ await this.ensureDb();
98
+ const rows = this.pauseStmt.all({});
99
+ return rows.map((r) => ({ ...JSON.parse(r.data), seq: r.seq, at: r.at }));
100
+ }
101
+ }
@@ -0,0 +1,72 @@
1
+ import type { ExecutionEvent, StoredEvent } from './events.js';
2
+ /**
3
+ * The latest sync checkpoint for a key, materialised across executions — the
4
+ * read model behind log-backed incremental sync. Derived from the most recent
5
+ * `checkpoint.advanced` event for each key.
6
+ */
7
+ export interface CheckpointRecord {
8
+ key: string;
9
+ syncedAt: string;
10
+ recordCount?: number;
11
+ cursor?: string;
12
+ mission?: string;
13
+ /** The execution that advanced this checkpoint. */
14
+ executionId: string;
15
+ }
16
+ export interface ExecutionLogStore {
17
+ /** Append one event; returns it with its assigned seq and recorded timestamp. */
18
+ append(event: ExecutionEvent): Promise<StoredEvent>;
19
+ /** Read all events for an execution, in append order. */
20
+ read(executionId: string): Promise<StoredEvent[]>;
21
+ /**
22
+ * Latest checkpoint per key across all executions in this store (optionally
23
+ * filtered by mission). The read model for log-backed incremental sync.
24
+ */
25
+ listCheckpoints(mission?: string): Promise<CheckpointRecord[]>;
26
+ /**
27
+ * All pause lifecycle events (pause.created / pause.resumed) across every
28
+ * execution in this store, in no guaranteed order. The raw input the
29
+ * log-backed pause store folds into pause state.
30
+ */
31
+ listPauses(): Promise<StoredEvent[]>;
32
+ }
33
+ /**
34
+ * Fold `checkpoint.advanced` events into the latest checkpoint per key. "Latest"
35
+ * is the furthest-advanced sync: ordered by `syncedAt` (so a checkpoint never
36
+ * moves backwards across runs — incremental sync stays monotonic), ties broken
37
+ * by the recording time `at` then `seq`. Shared by every store backend so the
38
+ * read-model semantics stay identical across them.
39
+ */
40
+ export declare function reduceCheckpoints(events: StoredEvent[], mission?: string): CheckpointRecord[];
41
+ /** In-memory execution log — for tests and ephemeral runs. */
42
+ export declare class MemoryExecutionLog implements ExecutionLogStore {
43
+ private events;
44
+ append(event: ExecutionEvent): Promise<StoredEvent>;
45
+ read(executionId: string): Promise<StoredEvent[]>;
46
+ listCheckpoints(mission?: string): Promise<CheckpointRecord[]>;
47
+ listPauses(): Promise<StoredEvent[]>;
48
+ }
49
+ /**
50
+ * Durable execution log: one append-only JSON-lines file per execution.
51
+ *
52
+ * Appends are O_APPEND single-line writes, so a crash mid-write can at worst
53
+ * leave a torn final line, which {@link read} skips. The log therefore survives
54
+ * a process restart — a resumed run reads its prior events back. Dev-grade: no
55
+ * atomic seq assignment or locking. For a transactional single-process backend
56
+ * use {@link SqliteExecutionLog}; Postgres (multi-node) is still to come.
57
+ */
58
+ export declare class FileExecutionLog implements ExecutionLogStore {
59
+ private dir;
60
+ /** Cached next-seq per execution, lazily initialised from disk. */
61
+ private counts;
62
+ constructor(dir?: string);
63
+ private pathFor;
64
+ append(event: ExecutionEvent): Promise<StoredEvent>;
65
+ read(executionId: string): Promise<StoredEvent[]>;
66
+ listCheckpoints(mission?: string): Promise<CheckpointRecord[]>;
67
+ listPauses(): Promise<StoredEvent[]>;
68
+ /** Read and parse every execution's events in this directory. */
69
+ private readAll;
70
+ private readRaw;
71
+ private parse;
72
+ }