reqon-dsl 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 (388) hide show
  1. package/.claude/settings.local.json +31 -0
  2. package/.claude/skills/api-integration.md +125 -0
  3. package/.claude/skills/database-schema.md +51 -0
  4. package/.claude/skills/dsl-design.md +80 -0
  5. package/.claude/skills/property-testing.md +143 -0
  6. package/.claude/skills/reqon/SKILL.md +44 -0
  7. package/.claude/skills/reqon/references/examples.md +206 -0
  8. package/.claude/skills/reqon/references/syntax.md +263 -0
  9. package/.claude/skills/vscode-extension.md +113 -0
  10. package/.github/dependabot.yml +32 -0
  11. package/.github/pull_request_template.md +21 -0
  12. package/.github/workflows/ci.yml +174 -0
  13. package/.github/workflows/release.yml +73 -0
  14. package/CLAUDE.md +72 -0
  15. package/CONTRIBUTING.md +161 -0
  16. package/README.md +235 -0
  17. package/TODO.md +51 -0
  18. package/dist/ast/index.d.ts +1 -0
  19. package/dist/ast/index.js +1 -0
  20. package/dist/ast/nodes.d.ts +237 -0
  21. package/dist/ast/nodes.js +12 -0
  22. package/dist/auth/auth.test.d.ts +1 -0
  23. package/dist/auth/auth.test.js +255 -0
  24. package/dist/auth/circuit-breaker.d.ts +115 -0
  25. package/dist/auth/circuit-breaker.js +267 -0
  26. package/dist/auth/credentials.d.ts +91 -0
  27. package/dist/auth/credentials.js +169 -0
  28. package/dist/auth/index.d.ts +5 -0
  29. package/dist/auth/index.js +8 -0
  30. package/dist/auth/oauth2-provider.d.ts +41 -0
  31. package/dist/auth/oauth2-provider.js +131 -0
  32. package/dist/auth/rate-limiter.d.ts +61 -0
  33. package/dist/auth/rate-limiter.js +380 -0
  34. package/dist/auth/token-store.d.ts +30 -0
  35. package/dist/auth/token-store.js +148 -0
  36. package/dist/auth/types.d.ts +142 -0
  37. package/dist/auth/types.js +1 -0
  38. package/dist/cli.d.ts +2 -0
  39. package/dist/cli.js +270 -0
  40. package/dist/errors/errors.test.d.ts +1 -0
  41. package/dist/errors/errors.test.js +165 -0
  42. package/dist/errors/index.d.ts +83 -0
  43. package/dist/errors/index.js +159 -0
  44. package/dist/execution/execution.test.d.ts +1 -0
  45. package/dist/execution/execution.test.js +246 -0
  46. package/dist/execution/index.d.ts +4 -0
  47. package/dist/execution/index.js +2 -0
  48. package/dist/execution/state.d.ts +136 -0
  49. package/dist/execution/state.js +82 -0
  50. package/dist/execution/store.d.ts +52 -0
  51. package/dist/execution/store.js +120 -0
  52. package/dist/index.d.ts +27 -0
  53. package/dist/index.js +57 -0
  54. package/dist/integration.test.d.ts +1 -0
  55. package/dist/integration.test.js +168 -0
  56. package/dist/interpreter/context.d.ts +15 -0
  57. package/dist/interpreter/context.js +29 -0
  58. package/dist/interpreter/evaluator.d.ts +5 -0
  59. package/dist/interpreter/evaluator.js +223 -0
  60. package/dist/interpreter/evaluator.test.d.ts +1 -0
  61. package/dist/interpreter/evaluator.test.js +512 -0
  62. package/dist/interpreter/executor.d.ts +131 -0
  63. package/dist/interpreter/executor.js +663 -0
  64. package/dist/interpreter/fetch-handler.d.ts +43 -0
  65. package/dist/interpreter/fetch-handler.js +203 -0
  66. package/dist/interpreter/http.d.ts +57 -0
  67. package/dist/interpreter/http.js +210 -0
  68. package/dist/interpreter/http.test.d.ts +1 -0
  69. package/dist/interpreter/http.test.js +299 -0
  70. package/dist/interpreter/index.d.ts +7 -0
  71. package/dist/interpreter/index.js +7 -0
  72. package/dist/interpreter/pagination.d.ts +63 -0
  73. package/dist/interpreter/pagination.js +155 -0
  74. package/dist/interpreter/progress.test.d.ts +1 -0
  75. package/dist/interpreter/progress.test.js +216 -0
  76. package/dist/interpreter/schema-matcher.d.ts +16 -0
  77. package/dist/interpreter/schema-matcher.js +136 -0
  78. package/dist/interpreter/schema-matcher.test.d.ts +1 -0
  79. package/dist/interpreter/schema-matcher.test.js +122 -0
  80. package/dist/interpreter/signals.d.ts +57 -0
  81. package/dist/interpreter/signals.js +73 -0
  82. package/dist/interpreter/step-handlers/for-handler.d.ts +17 -0
  83. package/dist/interpreter/step-handlers/for-handler.js +51 -0
  84. package/dist/interpreter/step-handlers/index.d.ts +8 -0
  85. package/dist/interpreter/step-handlers/index.js +8 -0
  86. package/dist/interpreter/step-handlers/map-handler.d.ts +10 -0
  87. package/dist/interpreter/step-handlers/map-handler.js +20 -0
  88. package/dist/interpreter/step-handlers/match-handler.d.ts +27 -0
  89. package/dist/interpreter/step-handlers/match-handler.js +61 -0
  90. package/dist/interpreter/step-handlers/store-handler.d.ts +13 -0
  91. package/dist/interpreter/step-handlers/store-handler.js +66 -0
  92. package/dist/interpreter/step-handlers/types.d.ts +15 -0
  93. package/dist/interpreter/step-handlers/types.js +1 -0
  94. package/dist/interpreter/step-handlers/validate-handler.d.ts +10 -0
  95. package/dist/interpreter/step-handlers/validate-handler.js +26 -0
  96. package/dist/interpreter/step-handlers/webhook-handler.d.ts +36 -0
  97. package/dist/interpreter/step-handlers/webhook-handler.js +104 -0
  98. package/dist/lexer/index.d.ts +10 -0
  99. package/dist/lexer/index.js +12 -0
  100. package/dist/lexer/lexer.d.ts +24 -0
  101. package/dist/lexer/lexer.js +264 -0
  102. package/dist/lexer/lexer.test.d.ts +1 -0
  103. package/dist/lexer/lexer.test.js +259 -0
  104. package/dist/lexer/tokens.d.ts +69 -0
  105. package/dist/lexer/tokens.js +146 -0
  106. package/dist/loader/index.d.ts +36 -0
  107. package/dist/loader/index.js +220 -0
  108. package/dist/loader/loader.test.d.ts +1 -0
  109. package/dist/loader/loader.test.js +287 -0
  110. package/dist/oas/index.d.ts +4 -0
  111. package/dist/oas/index.js +2 -0
  112. package/dist/oas/loader.d.ts +21 -0
  113. package/dist/oas/loader.js +82 -0
  114. package/dist/oas/oas.test.d.ts +1 -0
  115. package/dist/oas/oas.test.js +218 -0
  116. package/dist/oas/validator.d.ts +12 -0
  117. package/dist/oas/validator.js +227 -0
  118. package/dist/parser/base.d.ts +33 -0
  119. package/dist/parser/base.js +97 -0
  120. package/dist/parser/expressions.d.ts +27 -0
  121. package/dist/parser/expressions.js +248 -0
  122. package/dist/parser/expressions.test.d.ts +1 -0
  123. package/dist/parser/expressions.test.js +378 -0
  124. package/dist/parser/index.d.ts +3 -0
  125. package/dist/parser/index.js +3 -0
  126. package/dist/parser/match.test.d.ts +1 -0
  127. package/dist/parser/match.test.js +254 -0
  128. package/dist/parser/parser.d.ts +68 -0
  129. package/dist/parser/parser.js +1229 -0
  130. package/dist/parser/parser.test.d.ts +1 -0
  131. package/dist/parser/parser.test.js +333 -0
  132. package/dist/parser/schedule.test.d.ts +1 -0
  133. package/dist/parser/schedule.test.js +241 -0
  134. package/dist/plugin.d.ts +35 -0
  135. package/dist/plugin.js +68 -0
  136. package/dist/scheduler/cron-parser.d.ts +32 -0
  137. package/dist/scheduler/cron-parser.js +198 -0
  138. package/dist/scheduler/cron-parser.test.d.ts +1 -0
  139. package/dist/scheduler/cron-parser.test.js +188 -0
  140. package/dist/scheduler/index.d.ts +3 -0
  141. package/dist/scheduler/index.js +2 -0
  142. package/dist/scheduler/scheduler.d.ts +81 -0
  143. package/dist/scheduler/scheduler.js +376 -0
  144. package/dist/scheduler/types.d.ts +65 -0
  145. package/dist/scheduler/types.js +1 -0
  146. package/dist/stores/factory.d.ts +36 -0
  147. package/dist/stores/factory.js +73 -0
  148. package/dist/stores/file.d.ts +60 -0
  149. package/dist/stores/file.js +173 -0
  150. package/dist/stores/file.test.d.ts +1 -0
  151. package/dist/stores/file.test.js +165 -0
  152. package/dist/stores/index.d.ts +6 -0
  153. package/dist/stores/index.js +5 -0
  154. package/dist/stores/memory.d.ts +19 -0
  155. package/dist/stores/memory.js +51 -0
  156. package/dist/stores/memory.test.d.ts +1 -0
  157. package/dist/stores/memory.test.js +157 -0
  158. package/dist/stores/postgrest.d.ts +55 -0
  159. package/dist/stores/postgrest.js +217 -0
  160. package/dist/stores/stores.test.d.ts +1 -0
  161. package/dist/stores/stores.test.js +158 -0
  162. package/dist/stores/types.d.ts +31 -0
  163. package/dist/stores/types.js +26 -0
  164. package/dist/sync/index.d.ts +4 -0
  165. package/dist/sync/index.js +2 -0
  166. package/dist/sync/state.d.ts +69 -0
  167. package/dist/sync/state.js +66 -0
  168. package/dist/sync/store.d.ts +49 -0
  169. package/dist/sync/store.js +93 -0
  170. package/dist/sync/sync.test.d.ts +1 -0
  171. package/dist/sync/sync.test.js +221 -0
  172. package/dist/utils/async.d.ts +7 -0
  173. package/dist/utils/async.js +9 -0
  174. package/dist/utils/file.d.ts +38 -0
  175. package/dist/utils/file.js +92 -0
  176. package/dist/utils/index.d.ts +4 -0
  177. package/dist/utils/index.js +4 -0
  178. package/dist/utils/logger.d.ts +34 -0
  179. package/dist/utils/logger.js +39 -0
  180. package/dist/utils/path.d.ts +12 -0
  181. package/dist/utils/path.js +41 -0
  182. package/dist/webhook/index.d.ts +8 -0
  183. package/dist/webhook/index.js +7 -0
  184. package/dist/webhook/server.d.ts +84 -0
  185. package/dist/webhook/server.js +319 -0
  186. package/dist/webhook/store.d.ts +67 -0
  187. package/dist/webhook/store.js +193 -0
  188. package/dist/webhook/types.d.ts +88 -0
  189. package/dist/webhook/types.js +6 -0
  190. package/docusaurus/README.md +41 -0
  191. package/docusaurus/docs/advanced/execution-state.md +283 -0
  192. package/docusaurus/docs/advanced/extending-reqon.md +388 -0
  193. package/docusaurus/docs/advanced/multi-file-missions.md +250 -0
  194. package/docusaurus/docs/advanced/parallel-execution.md +353 -0
  195. package/docusaurus/docs/api-reference.md +443 -0
  196. package/docusaurus/docs/authentication/api-key.md +339 -0
  197. package/docusaurus/docs/authentication/basic.md +276 -0
  198. package/docusaurus/docs/authentication/bearer.md +282 -0
  199. package/docusaurus/docs/authentication/oauth2.md +317 -0
  200. package/docusaurus/docs/authentication/overview.md +251 -0
  201. package/docusaurus/docs/cli.md +229 -0
  202. package/docusaurus/docs/core-concepts/actions.md +286 -0
  203. package/docusaurus/docs/core-concepts/missions.md +264 -0
  204. package/docusaurus/docs/core-concepts/schemas.md +353 -0
  205. package/docusaurus/docs/core-concepts/sources.md +339 -0
  206. package/docusaurus/docs/core-concepts/stores.md +332 -0
  207. package/docusaurus/docs/dsl-syntax/expressions.md +361 -0
  208. package/docusaurus/docs/dsl-syntax/fetch.md +293 -0
  209. package/docusaurus/docs/dsl-syntax/for-loops.md +324 -0
  210. package/docusaurus/docs/dsl-syntax/map.md +345 -0
  211. package/docusaurus/docs/dsl-syntax/match.md +387 -0
  212. package/docusaurus/docs/dsl-syntax/pipelines.md +397 -0
  213. package/docusaurus/docs/dsl-syntax/validate.md +401 -0
  214. package/docusaurus/docs/error-handling/dead-letter-queues.md +399 -0
  215. package/docusaurus/docs/error-handling/flow-control.md +337 -0
  216. package/docusaurus/docs/error-handling/retry-strategies.md +368 -0
  217. package/docusaurus/docs/examples.md +488 -0
  218. package/docusaurus/docs/getting-started.md +256 -0
  219. package/docusaurus/docs/http/circuit-breaker.md +401 -0
  220. package/docusaurus/docs/http/incremental-sync.md +394 -0
  221. package/docusaurus/docs/http/pagination.md +361 -0
  222. package/docusaurus/docs/http/rate-limiting.md +383 -0
  223. package/docusaurus/docs/http/requests.md +328 -0
  224. package/docusaurus/docs/http/retry.md +402 -0
  225. package/docusaurus/docs/intro.md +90 -0
  226. package/docusaurus/docs/openapi/loading-specs.md +305 -0
  227. package/docusaurus/docs/openapi/operation-calls.md +314 -0
  228. package/docusaurus/docs/openapi/overview.md +212 -0
  229. package/docusaurus/docs/openapi/response-validation.md +344 -0
  230. package/docusaurus/docs/scheduling/cron.md +305 -0
  231. package/docusaurus/docs/scheduling/daemon-mode.md +317 -0
  232. package/docusaurus/docs/scheduling/intervals.md +289 -0
  233. package/docusaurus/docs/scheduling/overview.md +231 -0
  234. package/docusaurus/docs/stores/custom-adapters.md +376 -0
  235. package/docusaurus/docs/stores/file.md +236 -0
  236. package/docusaurus/docs/stores/memory.md +193 -0
  237. package/docusaurus/docs/stores/overview.md +274 -0
  238. package/docusaurus/docs/stores/postgrest.md +316 -0
  239. package/docusaurus/docusaurus.config.ts +148 -0
  240. package/docusaurus/package-lock.json +18029 -0
  241. package/docusaurus/package.json +47 -0
  242. package/docusaurus/sidebars.ts +155 -0
  243. package/docusaurus/src/components/HomepageFeatures/index.tsx +105 -0
  244. package/docusaurus/src/components/HomepageFeatures/styles.module.css +12 -0
  245. package/docusaurus/src/css/custom.css +169 -0
  246. package/docusaurus/src/pages/index.module.css +48 -0
  247. package/docusaurus/src/pages/index.tsx +110 -0
  248. package/docusaurus/src/pages/markdown-page.md +7 -0
  249. package/docusaurus/static/.nojekyll +0 -0
  250. package/docusaurus/static/img/docusaurus-social-card.jpg +0 -0
  251. package/docusaurus/static/img/docusaurus.png +0 -0
  252. package/docusaurus/static/img/favicon.ico +0 -0
  253. package/docusaurus/static/img/logo.svg +10 -0
  254. package/docusaurus/static/img/undraw_docusaurus_mountain.svg +171 -0
  255. package/docusaurus/static/img/undraw_docusaurus_react.svg +170 -0
  256. package/docusaurus/static/img/undraw_docusaurus_tree.svg +40 -0
  257. package/docusaurus/tsconfig.json +8 -0
  258. package/examples/README.md +112 -0
  259. package/examples/error-handling/README.md +150 -0
  260. package/examples/error-handling/payment-processor.vague +287 -0
  261. package/examples/github-sync/README.md +74 -0
  262. package/examples/github-sync/fetch-issues.vague +47 -0
  263. package/examples/github-sync/fetch-prs.vague +40 -0
  264. package/examples/github-sync/mission.vague +101 -0
  265. package/examples/github-sync/normalize.vague +70 -0
  266. package/examples/jsonplaceholder/README.md +28 -0
  267. package/examples/jsonplaceholder/posts.vague +48 -0
  268. package/examples/petstore/README.md +35 -0
  269. package/examples/petstore/openapi.yaml +97 -0
  270. package/examples/petstore/sync.vague +52 -0
  271. package/examples/temporal-comparison/README.md +297 -0
  272. package/examples/temporal-comparison/reconciliation.vague +355 -0
  273. package/examples/temporal-comparison/temporal/activities/index.ts +8 -0
  274. package/examples/temporal-comparison/temporal/activities/shipstation.ts +225 -0
  275. package/examples/temporal-comparison/temporal/activities/shopify.ts +257 -0
  276. package/examples/temporal-comparison/temporal/activities/storage.ts +198 -0
  277. package/examples/temporal-comparison/temporal/activities/stripe.ts +169 -0
  278. package/examples/temporal-comparison/temporal/activities/validation.ts +205 -0
  279. package/examples/temporal-comparison/temporal/client/schedule.ts +218 -0
  280. package/examples/temporal-comparison/temporal/config/retry.ts +63 -0
  281. package/examples/temporal-comparison/temporal/types/index.ts +129 -0
  282. package/examples/temporal-comparison/temporal/workers/main.ts +130 -0
  283. package/examples/temporal-comparison/temporal/workflows/orderReconciliation.ts +262 -0
  284. package/examples/xero/README.md +88 -0
  285. package/examples/xero/invoices.vague +189 -0
  286. package/package.json +40 -0
  287. package/src/api-integration.test.ts +954 -0
  288. package/src/ast/index.ts +1 -0
  289. package/src/ast/nodes.ts +310 -0
  290. package/src/auth/auth.test.ts +326 -0
  291. package/src/auth/circuit-breaker.test.ts +390 -0
  292. package/src/auth/circuit-breaker.ts +379 -0
  293. package/src/auth/credentials.test.ts +273 -0
  294. package/src/auth/credentials.ts +246 -0
  295. package/src/auth/index.ts +40 -0
  296. package/src/auth/oauth2-provider.ts +177 -0
  297. package/src/auth/rate-limiter.ts +459 -0
  298. package/src/auth/token-store.ts +177 -0
  299. package/src/auth/types.ts +159 -0
  300. package/src/benchmark/e2e.bench.ts +288 -0
  301. package/src/benchmark/evaluator.bench.ts +331 -0
  302. package/src/benchmark/fixtures.ts +295 -0
  303. package/src/benchmark/index.ts +108 -0
  304. package/src/benchmark/lexer.bench.ts +69 -0
  305. package/src/benchmark/parser.bench.ts +103 -0
  306. package/src/benchmark/resilience.bench.ts +193 -0
  307. package/src/benchmark/store.bench.ts +147 -0
  308. package/src/benchmark/utils.ts +230 -0
  309. package/src/cli.ts +313 -0
  310. package/src/errors/errors.test.ts +234 -0
  311. package/src/errors/index.ts +223 -0
  312. package/src/execution/execution.test.ts +307 -0
  313. package/src/execution/index.ts +21 -0
  314. package/src/execution/state.ts +207 -0
  315. package/src/execution/store.ts +188 -0
  316. package/src/index.ts +169 -0
  317. package/src/integration.test.ts +192 -0
  318. package/src/interpreter/context.ts +57 -0
  319. package/src/interpreter/evaluator.test.ts +796 -0
  320. package/src/interpreter/evaluator.ts +245 -0
  321. package/src/interpreter/executor.ts +946 -0
  322. package/src/interpreter/fetch-handler.ts +302 -0
  323. package/src/interpreter/http.test.ts +423 -0
  324. package/src/interpreter/http.ts +308 -0
  325. package/src/interpreter/index.ts +32 -0
  326. package/src/interpreter/pagination.ts +207 -0
  327. package/src/interpreter/progress.test.ts +276 -0
  328. package/src/interpreter/schema-matcher.test.ts +160 -0
  329. package/src/interpreter/schema-matcher.ts +168 -0
  330. package/src/interpreter/signals.ts +73 -0
  331. package/src/interpreter/step-handlers/for-handler.ts +65 -0
  332. package/src/interpreter/step-handlers/index.ts +17 -0
  333. package/src/interpreter/step-handlers/map-handler.ts +24 -0
  334. package/src/interpreter/step-handlers/match-handler.ts +101 -0
  335. package/src/interpreter/step-handlers/store-handler.ts +78 -0
  336. package/src/interpreter/step-handlers/types.ts +17 -0
  337. package/src/interpreter/step-handlers/validate-handler.ts +30 -0
  338. package/src/interpreter/step-handlers/webhook-handler.ts +142 -0
  339. package/src/lexer/index.ts +18 -0
  340. package/src/lexer/lexer.test.ts +316 -0
  341. package/src/lexer/tokens.ts +179 -0
  342. package/src/loader/index.ts +288 -0
  343. package/src/loader/loader.test.ts +360 -0
  344. package/src/oas/index.ts +4 -0
  345. package/src/oas/loader.ts +126 -0
  346. package/src/oas/oas.test.ts +254 -0
  347. package/src/oas/validator.ts +299 -0
  348. package/src/parser/base.ts +124 -0
  349. package/src/parser/expressions.test.ts +525 -0
  350. package/src/parser/expressions.ts +314 -0
  351. package/src/parser/index.ts +3 -0
  352. package/src/parser/match.test.ts +296 -0
  353. package/src/parser/parser.test.ts +739 -0
  354. package/src/parser/parser.ts +1469 -0
  355. package/src/parser/schedule.test.ts +287 -0
  356. package/src/parser/webhook.test.ts +248 -0
  357. package/src/plugin.ts +83 -0
  358. package/src/scheduler/cron-parser.test.ts +236 -0
  359. package/src/scheduler/cron-parser.ts +236 -0
  360. package/src/scheduler/index.ts +10 -0
  361. package/src/scheduler/scheduler.ts +443 -0
  362. package/src/scheduler/types.ts +71 -0
  363. package/src/stores/factory.ts +104 -0
  364. package/src/stores/file.test.ts +276 -0
  365. package/src/stores/file.ts +211 -0
  366. package/src/stores/index.ts +6 -0
  367. package/src/stores/memory.test.ts +238 -0
  368. package/src/stores/memory.ts +63 -0
  369. package/src/stores/postgrest.test.ts +488 -0
  370. package/src/stores/postgrest.ts +263 -0
  371. package/src/stores/stores.test.ts +197 -0
  372. package/src/stores/types.ts +58 -0
  373. package/src/sync/index.ts +16 -0
  374. package/src/sync/state.ts +126 -0
  375. package/src/sync/store.ts +139 -0
  376. package/src/sync/sync.test.ts +271 -0
  377. package/src/utils/async.ts +10 -0
  378. package/src/utils/file.ts +106 -0
  379. package/src/utils/index.ts +14 -0
  380. package/src/utils/logger.ts +53 -0
  381. package/src/utils/path.ts +47 -0
  382. package/src/webhook/index.ts +15 -0
  383. package/src/webhook/server.test.ts +253 -0
  384. package/src/webhook/server.ts +389 -0
  385. package/src/webhook/store.ts +239 -0
  386. package/src/webhook/types.ts +93 -0
  387. package/tsconfig.json +17 -0
  388. package/vitest.config.ts +39 -0
@@ -0,0 +1,65 @@
1
+ import type { ForStep, ActionStep } from '../../ast/nodes.js';
2
+ import type { StepHandler, StepHandlerDeps } from './types.js';
3
+ import { evaluate } from '../evaluator.js';
4
+ import { childContext, setVariable, getVariable } from '../context.js';
5
+ import type { ExecutionContext } from '../context.js';
6
+
7
+ export interface ForHandlerDeps extends StepHandlerDeps {
8
+ executeStep: (step: ActionStep, actionName: string, ctx: ExecutionContext) => Promise<void>;
9
+ actionName: string;
10
+ }
11
+
12
+ /**
13
+ * Handles for...in...where iteration steps
14
+ */
15
+ export class ForHandler implements StepHandler<ForStep> {
16
+ constructor(private deps: ForHandlerDeps) {}
17
+
18
+ async execute(step: ForStep): Promise<void> {
19
+ const collection = await this.getCollection(step);
20
+
21
+ // Apply filter if present
22
+ const filtered = step.condition
23
+ ? collection.filter((item) => evaluate(step.condition!, this.deps.ctx, item))
24
+ : collection;
25
+
26
+ this.deps.log(`Iterating over ${filtered.length} items`);
27
+
28
+ // Execute steps for each item
29
+ for (const item of filtered) {
30
+ await this.executeForItem(step, item);
31
+ }
32
+ }
33
+
34
+ private async getCollection(step: ForStep): Promise<unknown[]> {
35
+ let collection: unknown[];
36
+
37
+ if (step.collection.type === 'Identifier') {
38
+ // It's a store reference
39
+ const store = this.deps.ctx.stores.get(step.collection.name);
40
+ if (store) {
41
+ collection = await store.list();
42
+ } else {
43
+ collection = (getVariable(this.deps.ctx, step.collection.name) as unknown[]) ?? [];
44
+ }
45
+ } else {
46
+ collection = evaluate(step.collection, this.deps.ctx) as unknown[];
47
+ }
48
+
49
+ if (!Array.isArray(collection)) {
50
+ throw new Error('For loop collection must be an array');
51
+ }
52
+
53
+ return collection;
54
+ }
55
+
56
+ private async executeForItem(step: ForStep, item: unknown): Promise<void> {
57
+ const childCtx = childContext(this.deps.ctx);
58
+ setVariable(childCtx, step.variable, item);
59
+
60
+ // Execute each inner step with child context
61
+ for (const innerStep of step.steps) {
62
+ await this.deps.executeStep(innerStep, this.deps.actionName, childCtx);
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,17 @@
1
+ export { type StepHandler, type StepHandlerDeps } from './types.js';
2
+ export { ForHandler, type ForHandlerDeps } from './for-handler.js';
3
+ export { MapHandler } from './map-handler.js';
4
+ export { ValidateHandler } from './validate-handler.js';
5
+ export { StoreHandler } from './store-handler.js';
6
+ export { MatchHandler, type MatchHandlerDeps, type MatchResult } from './match-handler.js';
7
+ export { WebhookHandler, type WebhookHandlerDeps, type WebhookHandlerResult } from './webhook-handler.js';
8
+
9
+ // Export signals from the canonical location
10
+ export {
11
+ NoMatchError,
12
+ AbortError,
13
+ SkipSignal,
14
+ RetrySignal,
15
+ JumpSignal,
16
+ QueueSignal,
17
+ } from '../signals.js';
@@ -0,0 +1,24 @@
1
+ import type { MapStep } from '../../ast/nodes.js';
2
+ import type { StepHandler, StepHandlerDeps } from './types.js';
3
+ import { evaluate } from '../evaluator.js';
4
+
5
+ /**
6
+ * Handles map...-> transformation steps
7
+ */
8
+ export class MapHandler implements StepHandler<MapStep> {
9
+ constructor(private deps: StepHandlerDeps) {}
10
+
11
+ async execute(step: MapStep): Promise<void> {
12
+ const source = evaluate(step.source, this.deps.ctx) as Record<string, unknown>;
13
+
14
+ const mapped: Record<string, unknown> = {};
15
+
16
+ for (const mapping of step.mappings) {
17
+ mapped[mapping.field] = evaluate(mapping.expression, this.deps.ctx, source);
18
+ }
19
+
20
+ // Store mapped result in response for next step
21
+ this.deps.ctx.response = mapped;
22
+ this.deps.log(`Mapped to ${step.targetSchema}`);
23
+ }
24
+ }
@@ -0,0 +1,101 @@
1
+ import type { MatchStep, ActionStep, FlowDirective } from '../../ast/nodes.js';
2
+ import type { StepHandler, StepHandlerDeps } from './types.js';
3
+ import { evaluate } from '../evaluator.js';
4
+ import type { ExecutionContext } from '../context.js';
5
+ import { findMatchingSchema } from '../schema-matcher.js';
6
+ import {
7
+ NoMatchError,
8
+ AbortError,
9
+ SkipSignal,
10
+ RetrySignal,
11
+ JumpSignal,
12
+ QueueSignal,
13
+ } from '../signals.js';
14
+
15
+ /**
16
+ * Result of executing a match step
17
+ */
18
+ export interface MatchResult {
19
+ /** The schema that matched (or '_' for wildcard) */
20
+ matchedSchema: string;
21
+ /** Flow directive if the arm specifies one */
22
+ flow?: FlowDirective;
23
+ /** Whether steps were executed (vs flow directive) */
24
+ stepsExecuted: boolean;
25
+ }
26
+
27
+ export interface MatchHandlerDeps extends StepHandlerDeps {
28
+ executeStep: (step: ActionStep, actionName: string, ctx: ExecutionContext) => Promise<void>;
29
+ actionName: string;
30
+ }
31
+
32
+ /**
33
+ * Handles match steps (schema overloading with flow control)
34
+ */
35
+ export class MatchHandler {
36
+ constructor(private deps: MatchHandlerDeps) {}
37
+
38
+ async execute(step: MatchStep): Promise<void> {
39
+ const value = evaluate(step.target, this.deps.ctx);
40
+
41
+ // Get schema names from arms in order
42
+ const schemaNames = step.arms.map(arm => arm.schema);
43
+
44
+ // Find matching schema
45
+ const matchedSchema = findMatchingSchema(value, this.deps.ctx.schemas, schemaNames);
46
+
47
+ if (!matchedSchema) {
48
+ throw new NoMatchError(value);
49
+ }
50
+
51
+ this.deps.log(`Matched schema: ${matchedSchema}`);
52
+
53
+ // Find the matching arm
54
+ const arm = step.arms.find(a => a.schema === matchedSchema);
55
+
56
+ if (!arm) {
57
+ // Shouldn't happen if findMatchingSchema works correctly
58
+ throw new NoMatchError(value);
59
+ }
60
+
61
+ // Handle flow directive
62
+ if (arm.flow) {
63
+ // 'continue' means proceed normally - don't throw
64
+ if (arm.flow.type === 'continue') {
65
+ return;
66
+ }
67
+ this.handleFlowDirective(arm.flow, value);
68
+ }
69
+
70
+ // Execute steps
71
+ if (arm.steps) {
72
+ for (const innerStep of arm.steps) {
73
+ await this.deps.executeStep(innerStep, this.deps.actionName, this.deps.ctx);
74
+ }
75
+ }
76
+ }
77
+
78
+ private handleFlowDirective(flow: Exclude<FlowDirective, { type: 'continue' }>, value: unknown): never {
79
+ switch (flow.type) {
80
+ case 'skip':
81
+ throw new SkipSignal();
82
+
83
+ case 'abort':
84
+ throw new AbortError(flow.message);
85
+
86
+ case 'retry':
87
+ throw new RetrySignal(flow.backoff);
88
+
89
+ case 'jump':
90
+ throw new JumpSignal(flow.action, flow.then);
91
+
92
+ case 'queue':
93
+ throw new QueueSignal(value, flow.target);
94
+
95
+ default:
96
+ // This should never happen if TypeScript is working correctly
97
+ const _exhaustive: never = flow;
98
+ throw new Error(`Unknown flow directive: ${(_exhaustive as FlowDirective).type}`);
99
+ }
100
+ }
101
+ }
@@ -0,0 +1,78 @@
1
+ import type { StoreStep } from '../../ast/nodes.js';
2
+ import type { StepHandler, StepHandlerDeps } from './types.js';
3
+ import type { StoreAdapter } from '../../stores/types.js';
4
+ import { evaluate } from '../evaluator.js';
5
+
6
+ /**
7
+ * Handles store steps for persisting data
8
+ */
9
+ export class StoreHandler implements StepHandler<StoreStep> {
10
+ constructor(private deps: StepHandlerDeps) {}
11
+
12
+ async execute(step: StoreStep): Promise<void> {
13
+ const store = this.deps.ctx.stores.get(step.target);
14
+ if (!store) {
15
+ throw new Error(`Store not found: ${step.target}`);
16
+ }
17
+
18
+ const source = evaluate(step.source, this.deps.ctx);
19
+
20
+ if (Array.isArray(source)) {
21
+ await this.storeMany(step, store, source);
22
+ } else {
23
+ await this.storeOne(step, store, source as Record<string, unknown>);
24
+ }
25
+ }
26
+
27
+ private async storeMany(step: StoreStep, store: StoreAdapter, items: unknown[]): Promise<void> {
28
+ // Use bulk operation if available and not doing upserts (which need individual handling)
29
+ if (store.bulkSet && !step.options.upsert) {
30
+ const records: Array<{ key: string; value: Record<string, unknown> }> = [];
31
+ for (const item of items) {
32
+ const record = item as Record<string, unknown>;
33
+ const key = step.options.key
34
+ ? String(evaluate(step.options.key, this.deps.ctx, record))
35
+ : String(record.id ?? Math.random());
36
+
37
+ if (step.options.partial !== undefined) {
38
+ record._partial = step.options.partial;
39
+ }
40
+ records.push({ key, value: record });
41
+ }
42
+ await store.bulkSet(records);
43
+ } else {
44
+ // Fall back to individual operations for upserts or stores without bulkSet
45
+ for (const item of items) {
46
+ const record = item as Record<string, unknown>;
47
+ await this.storeRecord(step, store, record);
48
+ }
49
+ }
50
+
51
+ this.deps.log(`Stored ${items.length} items to ${step.target}`);
52
+ }
53
+
54
+ private async storeOne(step: StoreStep, store: StoreAdapter, record: Record<string, unknown>): Promise<void> {
55
+ await this.storeRecord(step, store, record);
56
+ this.deps.log(`Stored item to ${step.target}`);
57
+ }
58
+
59
+ private async storeRecord(
60
+ step: StoreStep,
61
+ store: StoreAdapter,
62
+ record: Record<string, unknown>
63
+ ): Promise<void> {
64
+ const key = step.options.key
65
+ ? String(evaluate(step.options.key, this.deps.ctx, record))
66
+ : String(record.id ?? Math.random());
67
+
68
+ if (step.options.partial !== undefined) {
69
+ record._partial = step.options.partial;
70
+ }
71
+
72
+ if (step.options.upsert) {
73
+ await store.update(key, record);
74
+ } else {
75
+ await store.set(key, record);
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,17 @@
1
+ import type { ActionStep } from '../../ast/nodes.js';
2
+ import type { ExecutionContext } from '../context.js';
3
+
4
+ /**
5
+ * Dependencies injected into step handlers
6
+ */
7
+ export interface StepHandlerDeps {
8
+ ctx: ExecutionContext;
9
+ log: (message: string) => void;
10
+ }
11
+
12
+ /**
13
+ * Base interface for step handlers
14
+ */
15
+ export interface StepHandler<TStep extends ActionStep> {
16
+ execute(step: TStep): Promise<void>;
17
+ }
@@ -0,0 +1,30 @@
1
+ import type { ValidateStep } from '../../ast/nodes.js';
2
+ import type { StepHandler, StepHandlerDeps } from './types.js';
3
+ import { evaluate } from '../evaluator.js';
4
+
5
+ /**
6
+ * Handles validate steps with assume constraints
7
+ */
8
+ export class ValidateHandler implements StepHandler<ValidateStep> {
9
+ constructor(private deps: StepHandlerDeps) {}
10
+
11
+ async execute(step: ValidateStep): Promise<void> {
12
+ const target = evaluate(step.target, this.deps.ctx);
13
+
14
+ for (const constraint of step.constraints) {
15
+ const result = evaluate(constraint.condition, this.deps.ctx, target);
16
+
17
+ if (!result) {
18
+ const message = constraint.message ?? `Validation failed: ${JSON.stringify(constraint.condition)}`;
19
+
20
+ if (constraint.severity === 'error') {
21
+ throw new Error(message);
22
+ } else {
23
+ this.deps.log(`Warning: ${message}`);
24
+ }
25
+ }
26
+ }
27
+
28
+ this.deps.log('Validation passed');
29
+ }
30
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Webhook Handler
3
+ *
4
+ * Handles the 'wait' step for waiting on webhook callbacks.
5
+ */
6
+
7
+ import type { WebhookStep } from '../../ast/nodes.js';
8
+ import type { ExecutionContext } from '../context.js';
9
+ import { evaluate } from '../evaluator.js';
10
+ import type { WebhookServer, WebhookRegistration, WebhookEvent } from '../../webhook/index.js';
11
+ import { RetrySignal } from '../signals.js';
12
+
13
+ /**
14
+ * Dependencies for the webhook handler
15
+ */
16
+ export interface WebhookHandlerDeps {
17
+ ctx: ExecutionContext;
18
+ webhookServer: WebhookServer;
19
+ executionId: string;
20
+ log: (message: string) => void;
21
+ }
22
+
23
+ /**
24
+ * Result of webhook handler execution
25
+ */
26
+ export interface WebhookHandlerResult {
27
+ registration: WebhookRegistration;
28
+ events: WebhookEvent[];
29
+ webhookUrl: string;
30
+ }
31
+
32
+ /**
33
+ * Handler for webhook (wait) steps
34
+ */
35
+ export class WebhookHandler {
36
+ private deps: WebhookHandlerDeps;
37
+
38
+ constructor(deps: WebhookHandlerDeps) {
39
+ this.deps = deps;
40
+ }
41
+
42
+ /**
43
+ * Execute the wait step
44
+ */
45
+ async execute(step: WebhookStep): Promise<WebhookHandlerResult> {
46
+ const { ctx, webhookServer, executionId, log } = this.deps;
47
+
48
+ // Register webhook endpoint
49
+ const timeout = step.timeout ?? 300000; // 5 minutes default
50
+ const expectedEvents = step.expectedEvents ?? 1;
51
+
52
+ const registration = await webhookServer.register(executionId, {
53
+ path: step.path,
54
+ timeout,
55
+ expectedEvents,
56
+ filter: step.eventFilter ? JSON.stringify(step.eventFilter) : undefined,
57
+ });
58
+
59
+ const webhookUrl = webhookServer.getWebhookUrl(registration);
60
+ log(`Waiting for webhook: ${webhookUrl} (timeout: ${timeout}ms, expected: ${expectedEvents})`);
61
+
62
+ // Set the webhook URL in context for use in subsequent steps
63
+ ctx.response = {
64
+ webhookId: registration.id,
65
+ webhookUrl,
66
+ webhookPath: registration.path,
67
+ };
68
+
69
+ // Wait for webhook events
70
+ const result = await webhookServer.waitForEvents(registration.id, timeout);
71
+
72
+ if (result.timedOut) {
73
+ log(`Webhook timeout: ${webhookUrl}`);
74
+
75
+ // Check if retry is configured
76
+ if (step.retryOnTimeout) {
77
+ throw new RetrySignal(step.retryOnTimeout);
78
+ }
79
+
80
+ // If not retrying, still return partial results
81
+ if (result.events.length === 0) {
82
+ throw new Error(`Webhook timeout: no events received within ${timeout}ms`);
83
+ }
84
+ }
85
+
86
+ // Filter events if filter expression provided
87
+ let events = result.events;
88
+ if (step.eventFilter && events.length > 0) {
89
+ events = events.filter((event) => {
90
+ try {
91
+ const filterCtx = { ...ctx, response: event.body };
92
+ return evaluate(step.eventFilter!, filterCtx);
93
+ } catch {
94
+ return true; // Include on filter error
95
+ }
96
+ });
97
+ }
98
+
99
+ log(`Received ${events.length} webhook event(s)`);
100
+
101
+ // Set response to webhook events
102
+ if (events.length === 1) {
103
+ ctx.response = events[0].body;
104
+ } else {
105
+ ctx.response = events.map((e) => e.body);
106
+ }
107
+
108
+ // Store events if storage configured
109
+ if (step.storage) {
110
+ const store = ctx.stores.get(step.storage.target);
111
+ if (store) {
112
+ for (const event of events) {
113
+ const data = event.body as Record<string, unknown>;
114
+ let key: string;
115
+
116
+ if (step.storage.key) {
117
+ const keyCtx = { ...ctx, response: event.body };
118
+ const keyValue = evaluate(step.storage.key, keyCtx);
119
+ key = String(keyValue);
120
+ } else {
121
+ // Generate a key from the event ID
122
+ key = event.id;
123
+ }
124
+
125
+ await store.set(key, data);
126
+ log(`Stored webhook event: ${key}`);
127
+ }
128
+ } else {
129
+ log(`Warning: Store '${step.storage.target}' not found for webhook storage`);
130
+ }
131
+ }
132
+
133
+ // Clean up registration
134
+ await webhookServer.unregister(registration.id);
135
+
136
+ return {
137
+ registration,
138
+ events,
139
+ webhookUrl,
140
+ };
141
+ }
142
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Lexer module for Reqon.
3
+ *
4
+ * Uses Vague's Lexer with Reqon keywords registered via the plugin system.
5
+ * Importing this module automatically registers the Reqon plugin.
6
+ */
7
+
8
+ // Import plugin to auto-register Reqon keywords with Vague
9
+ import '../plugin.js';
10
+
11
+ // Re-export Vague's Lexer and TokenType as the primary lexer
12
+ export { Lexer, Lexer as ReqonLexer, TokenType, type Token } from 'vague-lang';
13
+
14
+ // Export Reqon-specific token types and keywords
15
+ export { ReqonTokenType, REQON_KEYWORDS } from './tokens.js';
16
+
17
+ // Re-export Token type with Reqon compatibility alias
18
+ export type { Token as ReqonToken } from 'vague-lang';