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
@@ -2,6 +2,7 @@ import type { FetchStep } from '../ast/nodes.js';
2
2
  import type { ExecutionContext } from './context.js';
3
3
  import type { OASSource } from '../oas/index.js';
4
4
  import { type SyncStore } from '../sync/index.js';
5
+ import type { EventType } from '../observability/index.js';
5
6
  export interface FetchHandlerDeps {
6
7
  ctx: ExecutionContext;
7
8
  oasSources: Map<string, OASSource>;
@@ -15,6 +16,37 @@ export interface FetchHandlerDeps {
15
16
  executionId?: string;
16
17
  dryRun?: boolean;
17
18
  log: (message: string) => void;
19
+ /** Optional event emitter for observability */
20
+ emit?: <T>(type: EventType, payload: T) => void;
21
+ /**
22
+ * When set (durable mode), mutating requests carry a stable Idempotency-Key
23
+ * derived from (executionId, stepId, request signature) so retries and
24
+ * replays don't double-apply server-side where the API honours the header.
25
+ */
26
+ idempotency?: {
27
+ executionId: string;
28
+ stepId: string;
29
+ };
30
+ /**
31
+ * Resumable (backfill) pagination, wired in durable mode. `resume` seeds the
32
+ * starting page/cursor from the folded log; `onPage` records each completed
33
+ * page back to the log; `maxItemsPerRun` bounds memory per run (a backfill
34
+ * that exceeds it stops cleanly and continues on the next resume).
35
+ */
36
+ pagination?: {
37
+ resume?: {
38
+ page: number;
39
+ cursor?: string;
40
+ done: boolean;
41
+ };
42
+ onPage?: (progress: {
43
+ page: number;
44
+ cursor?: string;
45
+ recordCount: number;
46
+ done: boolean;
47
+ }) => Promise<void>;
48
+ maxItemsPerRun?: number;
49
+ };
18
50
  }
19
51
  export interface FetchResult {
20
52
  data: unknown;
@@ -31,13 +63,28 @@ export declare class FetchHandler {
31
63
  * Execute a fetch step, handling OAS resolution, pagination, and sync checkpoints.
32
64
  */
33
65
  execute(step: FetchStep): Promise<FetchResult>;
66
+ private isRetryableError;
34
67
  /**
35
68
  * Record a sync checkpoint after successful fetch.
36
69
  */
37
- recordCheckpoint(key: string, step: FetchStep, data: unknown): Promise<void>;
70
+ recordCheckpoint(key: string, step: FetchStep, data: unknown, fallbackTime?: Date): Promise<Date | undefined>;
38
71
  private resolveFetchTarget;
39
72
  private resolveSinceParams;
73
+ /**
74
+ * Idempotency-Key header for a mutating request, when durable mode is on.
75
+ *
76
+ * GET is safe and gets no key. The key is a hash of
77
+ * (executionId, stepId, method, path, body) so it is stable across retries
78
+ * and replays of the same request, yet distinct per loop iteration (different
79
+ * path/body) — letting a cooperating API dedupe re-issued effects.
80
+ */
81
+ private idempotencyKeyFor;
40
82
  private executePaginated;
41
83
  private countRecords;
42
84
  private validateOASResponse;
85
+ /**
86
+ * Generate mock data for dry run mode.
87
+ * Uses OAS response schema if available, otherwise returns a simple placeholder.
88
+ */
89
+ private generateDryRunMockData;
43
90
  }
@@ -1,10 +1,17 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { evaluate, interpolatePath } from './evaluator.js';
2
- import { resolveOperation, getResponseSchema, validateResponse } from '../oas/index.js';
3
+ import { resolveOperation, getResponseSchema, validateResponse, generateMockData, } from '../oas/index.js';
3
4
  import { generateCheckpointKey, formatSinceDate } from '../sync/index.js';
4
5
  import { extractNestedValue } from '../utils/path.js';
5
6
  import { createPaginationStrategy } from './pagination.js';
6
7
  /** Maximum pages to fetch to prevent infinite loops */
7
8
  const MAX_PAGINATION_PAGES = 100;
9
+ /**
10
+ * Maximum items to accumulate in memory across all pages. Results are buffered
11
+ * in one array (no per-page streaming yet), so this caps memory regardless of
12
+ * page size. Hitting it stops pagination with a warning.
13
+ */
14
+ const MAX_PAGINATION_ITEMS = 100_000;
8
15
  /**
9
16
  * Handles HTTP fetch operations including pagination and incremental sync.
10
17
  * Extracted from MissionExecutor for better separation of concerns.
@@ -23,36 +30,92 @@ export class FetchHandler {
23
30
  if (!client) {
24
31
  throw new Error(`Source not found: ${resolved.sourceName}`);
25
32
  }
26
- // Resolve "since" query parameter for incremental sync
27
- const { query: sinceQuery, checkpointKey } = await this.resolveSinceParams(step, resolved.sourceName, resolved.operationId, resolved.path);
33
+ // Resolve "since" query parameter and/or header for incremental sync
34
+ const { query: sinceQuery, headers: sinceHeaders, checkpointKey, } = await this.resolveSinceParams(step, resolved.sourceName, resolved.operationId, resolved.path);
35
+ // Emit fetch.start event
36
+ this.deps.emit?.('fetch.start', {
37
+ source: resolved.sourceName,
38
+ method: resolved.method,
39
+ path: resolved.path,
40
+ isOAS: !!resolved.operationId,
41
+ operationId: resolved.operationId,
42
+ hasPagination: !!step.paginate,
43
+ hasSince: !!step.since,
44
+ });
45
+ const _fetchStartTime = Date.now(); // Reserved for fetch duration tracking
28
46
  if (this.deps.dryRun) {
47
+ const mockData = this.generateDryRunMockData(resolved.sourceName, resolved.operationId);
29
48
  this.deps.log('(dry run - skipping actual request)');
30
- return { data: { dryRun: true }, checkpointKey };
49
+ return { data: mockData, checkpointKey };
31
50
  }
32
51
  // Execute with or without pagination
33
52
  let data;
34
- if (step.paginate) {
35
- data = await this.executePaginated(step, client, resolved.path, resolved.method, resolved.sourceName, resolved.operationId, sinceQuery);
36
- }
37
- else {
38
- const response = await client.request({
53
+ let pagesFetched;
54
+ let statusCode = 200;
55
+ try {
56
+ if (step.paginate) {
57
+ const result = await this.executePaginated(step, client, resolved.path, resolved.method, resolved.sourceName, resolved.operationId, sinceQuery, sinceHeaders);
58
+ data = result;
59
+ pagesFetched = Array.isArray(result) ? undefined : 1; // Will be set by executePaginated
60
+ }
61
+ else {
62
+ const body = step.body ? evaluate(step.body, this.deps.ctx) : undefined;
63
+ const response = await client.request({
64
+ method: resolved.method,
65
+ path: resolved.path,
66
+ query: Object.keys(sinceQuery).length > 0 ? sinceQuery : undefined,
67
+ headers: Object.keys(sinceHeaders).length > 0 ? sinceHeaders : undefined,
68
+ body,
69
+ idempotencyKey: this.idempotencyKeyFor(resolved.method, resolved.path, body),
70
+ }, step.retry);
71
+ await this.validateOASResponse(resolved.sourceName, resolved.operationId, response.data);
72
+ data = response.data;
73
+ statusCode = response.status ?? 200;
74
+ }
75
+ // Emit fetch.complete event
76
+ this.deps.emit?.('fetch.complete', {
77
+ source: resolved.sourceName,
39
78
  method: resolved.method,
40
79
  path: resolved.path,
41
- query: Object.keys(sinceQuery).length > 0 ? sinceQuery : undefined,
42
- body: step.body ? evaluate(step.body, this.deps.ctx) : undefined,
43
- }, step.retry);
44
- await this.validateOASResponse(resolved.sourceName, resolved.operationId, response.data);
45
- data = response.data;
80
+ statusCode,
81
+ recordCount: this.countRecords(data) ?? 0,
82
+ pagesFetched,
83
+ });
84
+ }
85
+ catch (error) {
86
+ // Emit fetch.error event
87
+ this.deps.emit?.('fetch.error', {
88
+ source: resolved.sourceName,
89
+ path: resolved.path,
90
+ error: error.message,
91
+ retryable: this.isRetryableError(error),
92
+ });
93
+ throw error;
46
94
  }
47
95
  return { data, checkpointKey };
48
96
  }
97
+ isRetryableError(error) {
98
+ if (error instanceof Error) {
99
+ const message = error.message.toLowerCase();
100
+ return (message.includes('timeout') ||
101
+ message.includes('network') ||
102
+ message.includes('rate limit') ||
103
+ message.includes('429') ||
104
+ message.includes('503') ||
105
+ message.includes('502'));
106
+ }
107
+ return false;
108
+ }
49
109
  /**
50
110
  * Record a sync checkpoint after successful fetch.
51
111
  */
52
- async recordCheckpoint(key, step, data) {
112
+ async recordCheckpoint(key, step, data, fallbackTime) {
53
113
  if (!this.deps.syncStore)
54
- return;
55
- let syncedAt = new Date();
114
+ return undefined;
115
+ // Prefer the data's own clock; otherwise fall back to when the request was
116
+ // issued (not now), so records written server-side during the fetch are
117
+ // re-fetched next run rather than skipped on clock skew.
118
+ let syncedAt = fallbackTime ?? new Date();
56
119
  // If updateFrom is specified, extract the timestamp from response
57
120
  if (step.since?.updateFrom && data && typeof data === 'object') {
58
121
  const extracted = extractNestedValue(data, step.since.updateFrom);
@@ -76,6 +139,14 @@ export class FetchHandler {
76
139
  executionId: this.deps.executionId,
77
140
  });
78
141
  this.deps.log(`Recorded sync checkpoint: ${key} at ${syncedAt.toISOString()}`);
142
+ // Emit sync.checkpoint event
143
+ this.deps.emit?.('sync.checkpoint', {
144
+ checkpointKey: key,
145
+ lastSyncTime: syncedAt.toISOString(),
146
+ recordsFetched: recordCount ?? 0,
147
+ isIncremental: true,
148
+ });
149
+ return syncedAt;
79
150
  }
80
151
  resolveFetchTarget(step) {
81
152
  if (step.operationRef) {
@@ -92,7 +163,15 @@ export class FetchHandler {
92
163
  return { sourceName, method: operation.method, path, operationId };
93
164
  }
94
165
  // Traditional: explicit method + path
95
- const sourceName = step.source ?? this.deps.ctx.sources.keys().next().value;
166
+ let sourceName = step.source;
167
+ if (!sourceName) {
168
+ // Use the first available source as default
169
+ const firstSource = this.deps.ctx.sources.keys().next();
170
+ if (firstSource.done) {
171
+ throw new Error('No sources defined. Add a source to your mission before making fetch requests.');
172
+ }
173
+ sourceName = firstSource.value;
174
+ }
96
175
  const method = step.method;
97
176
  let path;
98
177
  if (step.path.type === 'Literal' && step.path.dataType === 'string') {
@@ -106,25 +185,55 @@ export class FetchHandler {
106
185
  }
107
186
  async resolveSinceParams(step, sourceName, operationId, path) {
108
187
  const query = {};
188
+ const headers = {};
109
189
  if (!step.since || !this.deps.syncStore) {
110
- return { query };
190
+ return { query, headers };
111
191
  }
112
192
  const checkpointKey = step.since.key ?? generateCheckpointKey(sourceName, operationId, path);
113
193
  if (step.since.type === 'lastSync') {
114
194
  const lastSync = await this.deps.syncStore.getLastSync(checkpointKey);
115
- const paramName = step.since.param ?? 'since';
116
195
  const format = step.since.format ?? 'iso';
117
- query[paramName] = formatSinceDate(lastSync, format);
118
- this.deps.log(`Incremental sync: ${paramName}=${query[paramName]} (key: ${checkpointKey})`);
196
+ const formattedDate = formatSinceDate(lastSync, format);
197
+ if (step.since.header) {
198
+ // Send as header (e.g., If-Modified-Since)
199
+ headers[step.since.header] = formattedDate;
200
+ this.deps.log(`Incremental sync: header ${step.since.header}=${formattedDate} (key: ${checkpointKey})`);
201
+ }
202
+ else {
203
+ // Send as query parameter (default behavior)
204
+ const paramName = step.since.param ?? 'since';
205
+ query[paramName] = formattedDate;
206
+ this.deps.log(`Incremental sync: ${paramName}=${formattedDate} (key: ${checkpointKey})`);
207
+ }
119
208
  }
120
209
  else if (step.since.type === 'expression' && step.since.expression) {
121
210
  const value = evaluate(step.since.expression, this.deps.ctx);
122
- const paramName = step.since.param ?? 'since';
123
- query[paramName] = String(value);
211
+ if (step.since.header) {
212
+ headers[step.since.header] = String(value);
213
+ }
214
+ else {
215
+ const paramName = step.since.param ?? 'since';
216
+ query[paramName] = String(value);
217
+ }
124
218
  }
125
- return { query, checkpointKey };
219
+ return { query, headers, checkpointKey };
220
+ }
221
+ /**
222
+ * Idempotency-Key header for a mutating request, when durable mode is on.
223
+ *
224
+ * GET is safe and gets no key. The key is a hash of
225
+ * (executionId, stepId, method, path, body) so it is stable across retries
226
+ * and replays of the same request, yet distinct per loop iteration (different
227
+ * path/body) — letting a cooperating API dedupe re-issued effects.
228
+ */
229
+ idempotencyKeyFor(method, path, body) {
230
+ if (!this.deps.idempotency || method === 'GET')
231
+ return undefined;
232
+ const { executionId, stepId } = this.deps.idempotency;
233
+ const signature = `${executionId}${stepId}${method}${path}${JSON.stringify(body ?? null)}`;
234
+ return createHash('sha256').update(signature).digest('hex').slice(0, 32);
126
235
  }
127
- async executePaginated(step, client, basePath, method, sourceName, operationId, sinceQuery = {}) {
236
+ async executePaginated(step, client, basePath, method, sourceName, operationId, sinceQuery = {}, sinceHeaders = {}) {
128
237
  const allResults = [];
129
238
  const paginate = step.paginate;
130
239
  const strategy = createPaginationStrategy(paginate);
@@ -132,32 +241,82 @@ export class FetchHandler {
132
241
  page: 0,
133
242
  pageSize: paginate.pageSize,
134
243
  };
244
+ // Resumable (backfill) pagination: seed the cursor/page from the last
245
+ // persisted position so a restart continues from where it stopped.
246
+ const backfill = this.deps.pagination;
247
+ if (step.backfill && backfill?.resume) {
248
+ if (backfill.resume.done) {
249
+ this.deps.log('Backfill already complete; nothing to fetch.');
250
+ return [];
251
+ }
252
+ ctx.page = backfill.resume.page;
253
+ ctx.cursor = backfill.resume.cursor;
254
+ this.deps.log(`Resuming backfill from page ${ctx.page + 1}`);
255
+ }
256
+ // Per-run item cap. For a backfill this bounds memory per run: when hit, the
257
+ // run stops *incomplete* and a later resume continues — so an arbitrarily
258
+ // large backfill completes across runs without buffering it all at once.
259
+ const itemCap = backfill?.maxItemsPerRun ?? MAX_PAGINATION_ITEMS;
135
260
  let hasMore = true;
261
+ let stoppedByCap = false;
136
262
  while (hasMore) {
137
263
  // Build query with pagination params
138
264
  const paginationQuery = strategy.buildQuery(ctx);
139
265
  const query = { ...sinceQuery, ...paginationQuery };
266
+ const headers = Object.keys(sinceHeaders).length > 0 ? sinceHeaders : undefined;
140
267
  this.deps.log(`Fetching page ${ctx.page + 1}...`);
141
- const response = await client.request({ method, path: basePath, query }, step.retry);
268
+ const response = await client.request({ method, path: basePath, query, headers }, step.retry);
142
269
  await this.validateOASResponse(sourceName, operationId, response.data);
143
270
  // Temporarily set response for until condition evaluation
144
271
  this.deps.ctx.response = response.data;
145
- // Check until condition
146
- if (step.until) {
147
- const shouldStop = evaluate(step.until, this.deps.ctx);
148
- if (shouldStop) {
149
- break;
150
- }
151
- }
152
- // Extract results using strategy
272
+ // Extract and append the current page BEFORE deciding whether to stop, so
273
+ // the page that satisfies `until` is not silently dropped.
153
274
  const pageResult = strategy.extractResults(response.data, ctx);
154
275
  allResults.push(...pageResult.items);
155
276
  hasMore = pageResult.hasMore;
156
- // Update cursor for next iteration
157
- if (pageResult.nextCursor) {
158
- ctx.cursor = pageResult.nextCursor;
277
+ // Advance the cursor. If the API echoes the cursor we just used, stop
278
+ // instead of looping to the page cap and duplicating items each round.
279
+ if (pageResult.nextCursor !== undefined) {
280
+ if (pageResult.nextCursor === ctx.cursor) {
281
+ this.deps.log(`Pagination cursor did not advance ('${pageResult.nextCursor}'); stopping.`);
282
+ hasMore = false;
283
+ }
284
+ else {
285
+ ctx.cursor = pageResult.nextCursor;
286
+ }
159
287
  }
160
288
  ctx.page++;
289
+ // `until` is checked after the current page has been appended.
290
+ if (hasMore && step.until && evaluate(step.until, this.deps.ctx)) {
291
+ hasMore = false;
292
+ }
293
+ // Memory safety: cap total accumulated items, not just page count. For a
294
+ // backfill this is a clean stop-and-resume boundary, not an end of data.
295
+ if (allResults.length >= itemCap) {
296
+ this.deps.log(`Pagination item limit (${itemCap}) reached`);
297
+ if (hasMore)
298
+ stoppedByCap = true;
299
+ hasMore = false;
300
+ }
301
+ // Record this page's position for a resumable backfill. `done` is the
302
+ // natural end of pagination — never set when we stopped on the item cap,
303
+ // so a resume knows to continue rather than treat the backfill as finished.
304
+ if (step.backfill && backfill?.onPage) {
305
+ await backfill.onPage({
306
+ page: ctx.page,
307
+ cursor: ctx.cursor,
308
+ recordCount: pageResult.items.length,
309
+ done: !hasMore && !stoppedByCap,
310
+ });
311
+ }
312
+ // Emit heartbeat after each page
313
+ this.deps.emit?.('fetch.heartbeat', {
314
+ source: sourceName,
315
+ path: basePath,
316
+ pagesProcessed: ctx.page,
317
+ itemsFetched: allResults.length,
318
+ hasMore,
319
+ });
161
320
  // Safety limit
162
321
  if (ctx.page >= MAX_PAGINATION_PAGES) {
163
322
  this.deps.log(`Warning: pagination limit (${MAX_PAGINATION_PAGES}) reached`);
@@ -200,4 +359,23 @@ export class FetchHandler {
200
359
  this.deps.log(`Response validation warnings for ${operationId}:\n${errorMessages}`);
201
360
  }
202
361
  }
362
+ /**
363
+ * Generate mock data for dry run mode.
364
+ * Uses OAS response schema if available, otherwise returns a simple placeholder.
365
+ */
366
+ generateDryRunMockData(sourceName, operationId) {
367
+ // Try to get schema from OAS source
368
+ if (operationId) {
369
+ const oasSource = this.deps.oasSources.get(sourceName);
370
+ if (oasSource) {
371
+ const schema = getResponseSchema(oasSource, operationId);
372
+ if (schema) {
373
+ this.deps.log(`Generating mock data from OAS schema for ${operationId}`);
374
+ return generateMockData(schema);
375
+ }
376
+ }
377
+ }
378
+ // Fallback to simple placeholder
379
+ return { _dryRun: true, _message: 'No OAS schema available for mock generation' };
380
+ }
203
381
  }
@@ -1,6 +1,14 @@
1
1
  import type { RetryConfig } from '../ast/nodes.js';
2
2
  import type { RateLimiter } from '../auth/types.js';
3
3
  import { CircuitBreaker } from '../auth/circuit-breaker.js';
4
+ /**
5
+ * Parse a `Retry-After` header into a delay in ms, clamped to `maxDelayMs`.
6
+ * The header may be delta-seconds (`120`) or an HTTP-date; a date in the past or
7
+ * an unparseable value yields 0 and `undefined` respectively. Clamping stops a
8
+ * hostile/broken server from pinning the client for hours, and the date branch
9
+ * stops `parseInt` from turning a date into `NaN` → `sleep(NaN)` → a tight loop.
10
+ */
11
+ export declare function parseRetryAfterMs(value: string | null | undefined, maxDelayMs: number): number | undefined;
4
12
  export interface HttpClientConfig {
5
13
  baseUrl: string;
6
14
  headers?: Record<string, string>;
@@ -9,6 +17,8 @@ export interface HttpClientConfig {
9
17
  circuitBreaker?: CircuitBreaker;
10
18
  /** Source name for rate limit and circuit breaker tracking */
11
19
  sourceName?: string;
20
+ /** Default per-request timeout in ms (overridden by RetryConfig.timeout) */
21
+ timeout?: number;
12
22
  }
13
23
  export interface AuthProvider {
14
24
  getToken(): Promise<string>;
@@ -20,6 +30,12 @@ export interface HttpRequest {
20
30
  body?: unknown;
21
31
  headers?: Record<string, string>;
22
32
  query?: Record<string, string>;
33
+ /**
34
+ * Opt a non-idempotent request (POST/PATCH) into automatic retries by
35
+ * supplying an idempotency key. Sent as the `Idempotency-Key` header so the
36
+ * server can dedup a re-sent write.
37
+ */
38
+ idempotencyKey?: string;
23
39
  }
24
40
  export interface HttpResponse<T = unknown> {
25
41
  status: number;
@@ -30,6 +46,21 @@ export declare class HttpClient {
30
46
  private config;
31
47
  constructor(config: HttpClientConfig);
32
48
  request<T = unknown>(req: HttpRequest, retry?: RetryConfig): Promise<HttpResponse<T>>;
49
+ /**
50
+ * Run a fetch with a per-attempt timeout. Aborts the request (freeing the
51
+ * connection and rate-limiter slot) if it exceeds `timeoutMs`, surfacing a
52
+ * retryable FetchError rather than hanging forever.
53
+ */
54
+ private fetchWithTimeout;
55
+ /**
56
+ * Parse a successful (2xx) response body. Handles empty/204 responses,
57
+ * returns non-JSON content as raw text, and caps the buffered size.
58
+ */
59
+ private parseResponseBody;
60
+ /** Read a response body to text, rejecting once it exceeds MAX_RESPONSE_BYTES. */
61
+ private readCappedText;
62
+ /** Read a short snippet of a body for an error message (best-effort). */
63
+ private safeReadSnippet;
33
64
  private buildUrl;
34
65
  private buildHeaders;
35
66
  private calculateDelay;
@@ -45,6 +76,8 @@ export declare class OAuth2AuthProvider implements AuthProvider {
45
76
  private tokenEndpoint?;
46
77
  private clientId?;
47
78
  private clientSecret?;
79
+ /** Single-flight guard: coalesces concurrent refreshes into one in-flight request */
80
+ private refreshPromise;
48
81
  constructor(config: {
49
82
  accessToken: string;
50
83
  refreshToken?: string;
@@ -54,4 +87,5 @@ export declare class OAuth2AuthProvider implements AuthProvider {
54
87
  });
55
88
  getToken(): Promise<string>;
56
89
  refreshToken(): Promise<string>;
90
+ private doRefresh;
57
91
  }