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.
- package/CHANGELOG.md +7 -0
- package/README.md +45 -3
- package/dist/ast/nodes.d.ts +91 -4
- package/dist/ast/nodes.js +14 -0
- package/dist/auth/circuit-breaker.d.ts +11 -0
- package/dist/auth/circuit-breaker.js +90 -18
- package/dist/auth/credentials.d.ts +6 -1
- package/dist/auth/credentials.js +12 -4
- package/dist/auth/oauth2-provider.js +13 -3
- package/dist/auth/rate-limiter.d.ts +12 -1
- package/dist/auth/rate-limiter.js +39 -26
- package/dist/auth/token-store.js +8 -1
- package/dist/cli.d.ts +24 -1
- package/dist/cli.js +149 -10
- package/dist/config/constants.d.ts +152 -0
- package/dist/config/constants.js +139 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.js +4 -0
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -0
- package/dist/control/server.d.ts +105 -0
- package/dist/control/server.js +315 -0
- package/dist/control/types.d.ts +61 -0
- package/dist/control/types.js +7 -0
- package/dist/debug/cli-debugger.d.ts +17 -0
- package/dist/debug/cli-debugger.js +185 -0
- package/dist/debug/controller.d.ts +94 -0
- package/dist/debug/controller.js +45 -0
- package/dist/debug/index.d.ts +6 -0
- package/dist/debug/index.js +5 -0
- package/dist/errors/index.d.ts +67 -0
- package/dist/errors/index.js +89 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/state.d.ts +24 -0
- package/dist/execution/store.js +2 -2
- package/dist/execution-log/events.d.ts +125 -0
- package/dist/execution-log/events.js +17 -0
- package/dist/execution-log/fold.d.ts +38 -0
- package/dist/execution-log/fold.js +54 -0
- package/dist/execution-log/index.d.ts +18 -0
- package/dist/execution-log/index.js +6 -0
- package/dist/execution-log/postgres-store.d.ts +36 -0
- package/dist/execution-log/postgres-store.js +108 -0
- package/dist/execution-log/resume.d.ts +11 -0
- package/dist/execution-log/resume.js +5 -0
- package/dist/execution-log/sqlite-store.d.ts +16 -0
- package/dist/execution-log/sqlite-store.js +101 -0
- package/dist/execution-log/store.d.ts +72 -0
- package/dist/execution-log/store.js +182 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.js +35 -3
- package/dist/interpreter/context.d.ts +29 -0
- package/dist/interpreter/context.js +18 -0
- package/dist/interpreter/evaluator.d.ts +63 -1
- package/dist/interpreter/evaluator.js +219 -42
- package/dist/interpreter/executor.d.ts +132 -14
- package/dist/interpreter/executor.js +883 -178
- package/dist/interpreter/fetch-handler.d.ts +48 -1
- package/dist/interpreter/fetch-handler.js +216 -38
- package/dist/interpreter/http.d.ts +34 -0
- package/dist/interpreter/http.js +203 -28
- package/dist/interpreter/index.d.ts +5 -3
- package/dist/interpreter/index.js +4 -2
- package/dist/interpreter/pagination.d.ts +12 -3
- package/dist/interpreter/pagination.js +102 -32
- package/dist/interpreter/signals.d.ts +8 -0
- package/dist/interpreter/signals.js +12 -0
- package/dist/interpreter/source-manager.d.ts +75 -0
- package/dist/interpreter/source-manager.js +157 -0
- package/dist/interpreter/step-handlers/apply-handler.d.ts +29 -0
- package/dist/interpreter/step-handlers/apply-handler.js +79 -0
- package/dist/interpreter/step-handlers/for-handler.d.ts +16 -0
- package/dist/interpreter/step-handlers/for-handler.js +89 -7
- package/dist/interpreter/step-handlers/index.d.ts +4 -2
- package/dist/interpreter/step-handlers/index.js +4 -2
- package/dist/interpreter/step-handlers/match-handler.d.ts +9 -0
- package/dist/interpreter/step-handlers/match-handler.js +47 -17
- package/dist/interpreter/step-handlers/pause-handler.d.ts +52 -0
- package/dist/interpreter/step-handlers/pause-handler.js +87 -0
- package/dist/interpreter/step-handlers/store-handler.d.ts +17 -1
- package/dist/interpreter/step-handlers/store-handler.js +61 -20
- package/dist/interpreter/step-handlers/types.d.ts +3 -0
- package/dist/interpreter/step-handlers/validate-handler.d.ts +2 -1
- package/dist/interpreter/step-handlers/validate-handler.js +7 -2
- package/dist/interpreter/step-handlers/webhook-handler.d.ts +4 -0
- package/dist/interpreter/step-handlers/webhook-handler.js +31 -5
- package/dist/interpreter/store-manager.d.ts +46 -0
- package/dist/interpreter/store-manager.js +70 -0
- package/dist/lexer/index.d.ts +11 -4
- package/dist/lexer/index.js +11 -4
- package/dist/lexer/tokens.d.ts +17 -1
- package/dist/lexer/tokens.js +36 -0
- package/dist/loader/index.js +5 -8
- package/dist/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/sandbox.d.ts +41 -0
- package/dist/mcp/sandbox.js +76 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.js +504 -0
- package/dist/oas/index.d.ts +2 -0
- package/dist/oas/index.js +1 -0
- package/dist/oas/loader.d.ts +13 -1
- package/dist/oas/loader.js +25 -3
- package/dist/oas/mock-generator.d.ts +12 -0
- package/dist/oas/mock-generator.js +196 -0
- package/dist/oas/validator.js +45 -5
- package/dist/observability/events.d.ts +248 -0
- package/dist/observability/events.js +85 -0
- package/dist/observability/index.d.ts +15 -0
- package/dist/observability/index.js +12 -0
- package/dist/observability/logger.d.ts +106 -0
- package/dist/observability/logger.js +266 -0
- package/dist/observability/otel.d.ts +143 -0
- package/dist/observability/otel.js +421 -0
- package/dist/parser/action-parser.d.ts +105 -0
- package/dist/parser/action-parser.js +645 -0
- package/dist/parser/base.d.ts +7 -0
- package/dist/parser/base.js +11 -0
- package/dist/parser/expressions.d.ts +14 -0
- package/dist/parser/expressions.js +89 -6
- package/dist/parser/fetch-parser.d.ts +27 -0
- package/dist/parser/fetch-parser.js +280 -0
- package/dist/parser/index.d.ts +17 -0
- package/dist/parser/index.js +17 -0
- package/dist/parser/parser.d.ts +44 -46
- package/dist/parser/parser.js +122 -1070
- package/dist/parser/pipeline-parser.d.ts +12 -0
- package/dist/parser/pipeline-parser.js +52 -0
- package/dist/parser/schedule-parser.d.ts +7 -0
- package/dist/parser/schedule-parser.js +137 -0
- package/dist/parser/source-parser.d.ts +9 -0
- package/dist/parser/source-parser.js +151 -0
- package/dist/pause/index.d.ts +15 -0
- package/dist/pause/index.js +12 -0
- package/dist/pause/log-store.d.ts +33 -0
- package/dist/pause/log-store.js +98 -0
- package/dist/pause/manager.d.ts +130 -0
- package/dist/pause/manager.js +294 -0
- package/dist/pause/state.d.ts +93 -0
- package/dist/pause/state.js +103 -0
- package/dist/pause/store.d.ts +61 -0
- package/dist/pause/store.js +158 -0
- package/dist/plugin.d.ts +9 -12
- package/dist/plugin.js +10 -13
- package/dist/scheduler/cron-parser.d.ts +10 -3
- package/dist/scheduler/cron-parser.js +227 -48
- package/dist/scheduler/scheduler.js +56 -22
- package/dist/stores/factory.d.ts +7 -1
- package/dist/stores/factory.js +14 -3
- package/dist/stores/file.d.ts +26 -0
- package/dist/stores/file.js +67 -21
- package/dist/stores/index.d.ts +16 -1
- package/dist/stores/index.js +16 -1
- package/dist/stores/memory.d.ts +4 -0
- package/dist/stores/memory.js +8 -6
- package/dist/stores/postgrest.d.ts +28 -0
- package/dist/stores/postgrest.js +84 -37
- package/dist/stores/types.d.ts +17 -0
- package/dist/stores/types.js +12 -0
- package/dist/sync/index.d.ts +3 -2
- package/dist/sync/index.js +2 -1
- package/dist/sync/log-store.d.ts +30 -0
- package/dist/sync/log-store.js +45 -0
- package/dist/sync/store.js +1 -1
- package/dist/trace/index.d.ts +18 -0
- package/dist/trace/index.js +13 -0
- package/dist/trace/log-view.d.ts +57 -0
- package/dist/trace/log-view.js +76 -0
- package/dist/trace/recorder.d.ts +75 -0
- package/dist/trace/recorder.js +157 -0
- package/dist/trace/replay.d.ts +132 -0
- package/dist/trace/replay.js +264 -0
- package/dist/trace/state.d.ts +102 -0
- package/dist/trace/state.js +86 -0
- package/dist/trace/store.d.ts +75 -0
- package/dist/trace/store.js +250 -0
- package/dist/utils/deep-merge.d.ts +10 -0
- package/dist/utils/deep-merge.js +23 -0
- package/dist/utils/file.d.ts +13 -4
- package/dist/utils/file.js +70 -12
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/long-timeout.d.ts +19 -0
- package/dist/utils/long-timeout.js +33 -0
- package/dist/utils/path.d.ts +22 -1
- package/dist/utils/path.js +46 -1
- package/dist/utils/redact.d.ts +22 -0
- package/dist/utils/redact.js +42 -0
- package/dist/utils/type-guards.d.ts +58 -0
- package/dist/utils/type-guards.js +92 -0
- package/dist/webhook/server.d.ts +9 -0
- package/dist/webhook/server.js +122 -36
- package/dist/webhook/types.d.ts +9 -1
- package/package.json +76 -9
- package/.claude/settings.local.json +0 -31
- package/.claude/skills/api-integration.md +0 -125
- package/.claude/skills/database-schema.md +0 -51
- package/.claude/skills/dsl-design.md +0 -80
- package/.claude/skills/property-testing.md +0 -143
- package/.claude/skills/reqon/SKILL.md +0 -44
- package/.claude/skills/reqon/references/examples.md +0 -206
- package/.claude/skills/reqon/references/syntax.md +0 -263
- package/.claude/skills/vscode-extension.md +0 -113
- package/.github/dependabot.yml +0 -32
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/ci.yml +0 -174
- package/.github/workflows/release.yml +0 -73
- package/CLAUDE.md +0 -72
- package/CONTRIBUTING.md +0 -161
- package/TODO.md +0 -51
- package/dist/auth/auth.test.d.ts +0 -1
- package/dist/auth/auth.test.js +0 -255
- package/dist/errors/errors.test.d.ts +0 -1
- package/dist/errors/errors.test.js +0 -165
- package/dist/execution/execution.test.d.ts +0 -1
- package/dist/execution/execution.test.js +0 -246
- package/dist/integration.test.d.ts +0 -1
- package/dist/integration.test.js +0 -168
- package/dist/interpreter/evaluator.test.d.ts +0 -1
- package/dist/interpreter/evaluator.test.js +0 -512
- package/dist/interpreter/http.test.d.ts +0 -1
- package/dist/interpreter/http.test.js +0 -299
- package/dist/interpreter/progress.test.d.ts +0 -1
- package/dist/interpreter/progress.test.js +0 -216
- package/dist/interpreter/schema-matcher.test.d.ts +0 -1
- package/dist/interpreter/schema-matcher.test.js +0 -122
- package/dist/lexer/lexer.d.ts +0 -24
- package/dist/lexer/lexer.js +0 -264
- package/dist/lexer/lexer.test.d.ts +0 -1
- package/dist/lexer/lexer.test.js +0 -259
- package/dist/loader/loader.test.d.ts +0 -1
- package/dist/loader/loader.test.js +0 -287
- package/dist/oas/oas.test.d.ts +0 -1
- package/dist/oas/oas.test.js +0 -218
- package/dist/parser/expressions.test.d.ts +0 -1
- package/dist/parser/expressions.test.js +0 -378
- package/dist/parser/match.test.d.ts +0 -1
- package/dist/parser/match.test.js +0 -254
- package/dist/parser/parser.test.d.ts +0 -1
- package/dist/parser/parser.test.js +0 -333
- package/dist/parser/schedule.test.d.ts +0 -1
- package/dist/parser/schedule.test.js +0 -241
- package/dist/scheduler/cron-parser.test.d.ts +0 -1
- package/dist/scheduler/cron-parser.test.js +0 -188
- package/dist/stores/file.test.d.ts +0 -1
- package/dist/stores/file.test.js +0 -165
- package/dist/stores/memory.test.d.ts +0 -1
- package/dist/stores/memory.test.js +0 -157
- package/dist/stores/stores.test.d.ts +0 -1
- package/dist/stores/stores.test.js +0 -158
- package/dist/sync/sync.test.d.ts +0 -1
- package/dist/sync/sync.test.js +0 -221
- package/docusaurus/README.md +0 -41
- package/docusaurus/docs/advanced/execution-state.md +0 -283
- package/docusaurus/docs/advanced/extending-reqon.md +0 -388
- package/docusaurus/docs/advanced/multi-file-missions.md +0 -250
- package/docusaurus/docs/advanced/parallel-execution.md +0 -353
- package/docusaurus/docs/api-reference.md +0 -443
- package/docusaurus/docs/authentication/api-key.md +0 -339
- package/docusaurus/docs/authentication/basic.md +0 -276
- package/docusaurus/docs/authentication/bearer.md +0 -282
- package/docusaurus/docs/authentication/oauth2.md +0 -317
- package/docusaurus/docs/authentication/overview.md +0 -251
- package/docusaurus/docs/cli.md +0 -229
- package/docusaurus/docs/core-concepts/actions.md +0 -286
- package/docusaurus/docs/core-concepts/missions.md +0 -264
- package/docusaurus/docs/core-concepts/schemas.md +0 -353
- package/docusaurus/docs/core-concepts/sources.md +0 -339
- package/docusaurus/docs/core-concepts/stores.md +0 -332
- package/docusaurus/docs/dsl-syntax/expressions.md +0 -361
- package/docusaurus/docs/dsl-syntax/fetch.md +0 -293
- package/docusaurus/docs/dsl-syntax/for-loops.md +0 -324
- package/docusaurus/docs/dsl-syntax/map.md +0 -345
- package/docusaurus/docs/dsl-syntax/match.md +0 -387
- package/docusaurus/docs/dsl-syntax/pipelines.md +0 -397
- package/docusaurus/docs/dsl-syntax/validate.md +0 -401
- package/docusaurus/docs/error-handling/dead-letter-queues.md +0 -399
- package/docusaurus/docs/error-handling/flow-control.md +0 -337
- package/docusaurus/docs/error-handling/retry-strategies.md +0 -368
- package/docusaurus/docs/examples.md +0 -488
- package/docusaurus/docs/getting-started.md +0 -256
- package/docusaurus/docs/http/circuit-breaker.md +0 -401
- package/docusaurus/docs/http/incremental-sync.md +0 -394
- package/docusaurus/docs/http/pagination.md +0 -361
- package/docusaurus/docs/http/rate-limiting.md +0 -383
- package/docusaurus/docs/http/requests.md +0 -328
- package/docusaurus/docs/http/retry.md +0 -402
- package/docusaurus/docs/intro.md +0 -90
- package/docusaurus/docs/openapi/loading-specs.md +0 -305
- package/docusaurus/docs/openapi/operation-calls.md +0 -314
- package/docusaurus/docs/openapi/overview.md +0 -212
- package/docusaurus/docs/openapi/response-validation.md +0 -344
- package/docusaurus/docs/scheduling/cron.md +0 -305
- package/docusaurus/docs/scheduling/daemon-mode.md +0 -317
- package/docusaurus/docs/scheduling/intervals.md +0 -289
- package/docusaurus/docs/scheduling/overview.md +0 -231
- package/docusaurus/docs/stores/custom-adapters.md +0 -376
- package/docusaurus/docs/stores/file.md +0 -236
- package/docusaurus/docs/stores/memory.md +0 -193
- package/docusaurus/docs/stores/overview.md +0 -274
- package/docusaurus/docs/stores/postgrest.md +0 -316
- package/docusaurus/docusaurus.config.ts +0 -148
- package/docusaurus/package-lock.json +0 -18029
- package/docusaurus/package.json +0 -47
- package/docusaurus/sidebars.ts +0 -155
- package/docusaurus/src/components/HomepageFeatures/index.tsx +0 -105
- package/docusaurus/src/components/HomepageFeatures/styles.module.css +0 -12
- package/docusaurus/src/css/custom.css +0 -169
- package/docusaurus/src/pages/index.module.css +0 -48
- package/docusaurus/src/pages/index.tsx +0 -110
- package/docusaurus/src/pages/markdown-page.md +0 -7
- package/docusaurus/static/.nojekyll +0 -0
- package/docusaurus/static/img/docusaurus-social-card.jpg +0 -0
- package/docusaurus/static/img/docusaurus.png +0 -0
- package/docusaurus/static/img/favicon.ico +0 -0
- package/docusaurus/static/img/logo.svg +0 -10
- package/docusaurus/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docusaurus/static/img/undraw_docusaurus_react.svg +0 -170
- package/docusaurus/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docusaurus/tsconfig.json +0 -8
- package/examples/README.md +0 -112
- package/examples/error-handling/README.md +0 -150
- package/examples/error-handling/payment-processor.vague +0 -287
- package/examples/github-sync/README.md +0 -74
- package/examples/github-sync/fetch-issues.vague +0 -47
- package/examples/github-sync/fetch-prs.vague +0 -40
- package/examples/github-sync/mission.vague +0 -101
- package/examples/github-sync/normalize.vague +0 -70
- package/examples/jsonplaceholder/README.md +0 -28
- package/examples/jsonplaceholder/posts.vague +0 -48
- package/examples/petstore/README.md +0 -35
- package/examples/petstore/openapi.yaml +0 -97
- package/examples/petstore/sync.vague +0 -52
- package/examples/temporal-comparison/README.md +0 -297
- package/examples/temporal-comparison/reconciliation.vague +0 -355
- package/examples/temporal-comparison/temporal/activities/index.ts +0 -8
- package/examples/temporal-comparison/temporal/activities/shipstation.ts +0 -225
- package/examples/temporal-comparison/temporal/activities/shopify.ts +0 -257
- package/examples/temporal-comparison/temporal/activities/storage.ts +0 -198
- package/examples/temporal-comparison/temporal/activities/stripe.ts +0 -169
- package/examples/temporal-comparison/temporal/activities/validation.ts +0 -205
- package/examples/temporal-comparison/temporal/client/schedule.ts +0 -218
- package/examples/temporal-comparison/temporal/config/retry.ts +0 -63
- package/examples/temporal-comparison/temporal/types/index.ts +0 -129
- package/examples/temporal-comparison/temporal/workers/main.ts +0 -130
- package/examples/temporal-comparison/temporal/workflows/orderReconciliation.ts +0 -262
- package/examples/xero/README.md +0 -88
- package/examples/xero/invoices.vague +0 -189
- package/src/api-integration.test.ts +0 -954
- package/src/ast/index.ts +0 -1
- package/src/ast/nodes.ts +0 -310
- package/src/auth/auth.test.ts +0 -326
- package/src/auth/circuit-breaker.test.ts +0 -390
- package/src/auth/circuit-breaker.ts +0 -379
- package/src/auth/credentials.test.ts +0 -273
- package/src/auth/credentials.ts +0 -246
- package/src/auth/index.ts +0 -40
- package/src/auth/oauth2-provider.ts +0 -177
- package/src/auth/rate-limiter.ts +0 -459
- package/src/auth/token-store.ts +0 -177
- package/src/auth/types.ts +0 -159
- package/src/benchmark/e2e.bench.ts +0 -288
- package/src/benchmark/evaluator.bench.ts +0 -331
- package/src/benchmark/fixtures.ts +0 -295
- package/src/benchmark/index.ts +0 -108
- package/src/benchmark/lexer.bench.ts +0 -69
- package/src/benchmark/parser.bench.ts +0 -103
- package/src/benchmark/resilience.bench.ts +0 -193
- package/src/benchmark/store.bench.ts +0 -147
- package/src/benchmark/utils.ts +0 -230
- package/src/cli.ts +0 -313
- package/src/errors/errors.test.ts +0 -234
- package/src/errors/index.ts +0 -223
- package/src/execution/execution.test.ts +0 -307
- package/src/execution/index.ts +0 -21
- package/src/execution/state.ts +0 -207
- package/src/execution/store.ts +0 -188
- package/src/index.ts +0 -169
- package/src/integration.test.ts +0 -192
- package/src/interpreter/context.ts +0 -57
- package/src/interpreter/evaluator.test.ts +0 -796
- package/src/interpreter/evaluator.ts +0 -245
- package/src/interpreter/executor.ts +0 -946
- package/src/interpreter/fetch-handler.ts +0 -302
- package/src/interpreter/http.test.ts +0 -423
- package/src/interpreter/http.ts +0 -308
- package/src/interpreter/index.ts +0 -32
- package/src/interpreter/pagination.ts +0 -207
- package/src/interpreter/progress.test.ts +0 -276
- package/src/interpreter/schema-matcher.test.ts +0 -160
- package/src/interpreter/schema-matcher.ts +0 -168
- package/src/interpreter/signals.ts +0 -73
- package/src/interpreter/step-handlers/for-handler.ts +0 -65
- package/src/interpreter/step-handlers/index.ts +0 -17
- package/src/interpreter/step-handlers/map-handler.ts +0 -24
- package/src/interpreter/step-handlers/match-handler.ts +0 -101
- package/src/interpreter/step-handlers/store-handler.ts +0 -78
- package/src/interpreter/step-handlers/types.ts +0 -17
- package/src/interpreter/step-handlers/validate-handler.ts +0 -30
- package/src/interpreter/step-handlers/webhook-handler.ts +0 -142
- package/src/lexer/index.ts +0 -18
- package/src/lexer/lexer.test.ts +0 -316
- package/src/lexer/tokens.ts +0 -179
- package/src/loader/index.ts +0 -288
- package/src/loader/loader.test.ts +0 -360
- package/src/oas/index.ts +0 -4
- package/src/oas/loader.ts +0 -126
- package/src/oas/oas.test.ts +0 -254
- package/src/oas/validator.ts +0 -299
- package/src/parser/base.ts +0 -124
- package/src/parser/expressions.test.ts +0 -525
- package/src/parser/expressions.ts +0 -314
- package/src/parser/index.ts +0 -3
- package/src/parser/match.test.ts +0 -296
- package/src/parser/parser.test.ts +0 -739
- package/src/parser/parser.ts +0 -1469
- package/src/parser/schedule.test.ts +0 -287
- package/src/parser/webhook.test.ts +0 -248
- package/src/plugin.ts +0 -83
- package/src/scheduler/cron-parser.test.ts +0 -236
- package/src/scheduler/cron-parser.ts +0 -236
- package/src/scheduler/index.ts +0 -10
- package/src/scheduler/scheduler.ts +0 -443
- package/src/scheduler/types.ts +0 -71
- package/src/stores/factory.ts +0 -104
- package/src/stores/file.test.ts +0 -276
- package/src/stores/file.ts +0 -211
- package/src/stores/index.ts +0 -6
- package/src/stores/memory.test.ts +0 -238
- package/src/stores/memory.ts +0 -63
- package/src/stores/postgrest.test.ts +0 -488
- package/src/stores/postgrest.ts +0 -263
- package/src/stores/stores.test.ts +0 -197
- package/src/stores/types.ts +0 -58
- package/src/sync/index.ts +0 -16
- package/src/sync/state.ts +0 -126
- package/src/sync/store.ts +0 -139
- package/src/sync/sync.test.ts +0 -271
- package/src/utils/async.ts +0 -10
- package/src/utils/file.ts +0 -106
- package/src/utils/index.ts +0 -14
- package/src/utils/logger.ts +0 -53
- package/src/utils/path.ts +0 -47
- package/src/webhook/index.ts +0 -15
- package/src/webhook/server.test.ts +0 -253
- package/src/webhook/server.ts +0 -389
- package/src/webhook/store.ts +0 -239
- package/src/webhook/types.ts +0 -93
- package/tsconfig.json +0 -17
- package/vitest.config.ts +0 -39
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceManager handles HTTP source initialization and configuration.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from MissionExecutor to improve separation of concerns.
|
|
5
|
+
* Responsible for:
|
|
6
|
+
* - Creating HTTP clients for sources
|
|
7
|
+
* - Configuring authentication providers
|
|
8
|
+
* - Loading and caching OAS specs
|
|
9
|
+
* - Configuring rate limiters and circuit breakers per source
|
|
10
|
+
*/
|
|
11
|
+
import type { SourceDefinition } from '../ast/nodes.js';
|
|
12
|
+
import type { ExecutionContext } from './context.js';
|
|
13
|
+
import { type OASSource } from '../oas/index.js';
|
|
14
|
+
import type { RateLimiter } from '../auth/types.js';
|
|
15
|
+
import type { CircuitBreaker } from '../auth/circuit-breaker.js';
|
|
16
|
+
export interface AuthConfig {
|
|
17
|
+
type: 'bearer' | 'oauth2' | 'none';
|
|
18
|
+
token?: string;
|
|
19
|
+
accessToken?: string;
|
|
20
|
+
refreshToken?: string;
|
|
21
|
+
tokenEndpoint?: string;
|
|
22
|
+
clientId?: string;
|
|
23
|
+
clientSecret?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SourceManagerConfig {
|
|
26
|
+
/** Auth configurations by source name */
|
|
27
|
+
auth?: Record<string, AuthConfig>;
|
|
28
|
+
/** Logging function */
|
|
29
|
+
log?: (message: string) => void;
|
|
30
|
+
/** Mission file directory for resolving relative paths */
|
|
31
|
+
missionDir?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface SourceManagerDeps {
|
|
34
|
+
rateLimiter: RateLimiter;
|
|
35
|
+
circuitBreaker: CircuitBreaker;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Manages HTTP source initialization and provides access to source configurations.
|
|
39
|
+
*/
|
|
40
|
+
export declare class SourceManager {
|
|
41
|
+
private oasSources;
|
|
42
|
+
private sourceConfigs;
|
|
43
|
+
private config;
|
|
44
|
+
private deps;
|
|
45
|
+
constructor(config: SourceManagerConfig, deps: SourceManagerDeps);
|
|
46
|
+
/**
|
|
47
|
+
* Initialize a source definition, creating the HTTP client and configuring resilience.
|
|
48
|
+
*/
|
|
49
|
+
initializeSource(source: SourceDefinition, ctx: ExecutionContext): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Initialize multiple sources.
|
|
52
|
+
*/
|
|
53
|
+
initializeSources(sources: SourceDefinition[], ctx: ExecutionContext): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Get the OAS source for a given source name.
|
|
56
|
+
*/
|
|
57
|
+
getOASSource(sourceName: string): OASSource | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Get the source configuration for a given source name.
|
|
60
|
+
*/
|
|
61
|
+
getSourceConfig(sourceName: string): SourceDefinition | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Get all OAS sources.
|
|
64
|
+
*/
|
|
65
|
+
getAllOASSources(): Map<string, OASSource>;
|
|
66
|
+
/**
|
|
67
|
+
* Get all source configurations.
|
|
68
|
+
*/
|
|
69
|
+
getAllSourceConfigs(): Map<string, SourceDefinition>;
|
|
70
|
+
private createAuthProvider;
|
|
71
|
+
private resolveBaseUrl;
|
|
72
|
+
private configureRateLimiter;
|
|
73
|
+
private configureCircuitBreaker;
|
|
74
|
+
private log;
|
|
75
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceManager handles HTTP source initialization and configuration.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from MissionExecutor to improve separation of concerns.
|
|
5
|
+
* Responsible for:
|
|
6
|
+
* - Creating HTTP clients for sources
|
|
7
|
+
* - Configuring authentication providers
|
|
8
|
+
* - Loading and caching OAS specs
|
|
9
|
+
* - Configuring rate limiters and circuit breakers per source
|
|
10
|
+
*/
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import { HttpClient, BearerAuthProvider, OAuth2AuthProvider } from './http.js';
|
|
13
|
+
import { loadOAS } from '../oas/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Manages HTTP source initialization and provides access to source configurations.
|
|
16
|
+
*/
|
|
17
|
+
export class SourceManager {
|
|
18
|
+
oasSources = new Map();
|
|
19
|
+
sourceConfigs = new Map();
|
|
20
|
+
config;
|
|
21
|
+
deps;
|
|
22
|
+
constructor(config, deps) {
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.deps = deps;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Initialize a source definition, creating the HTTP client and configuring resilience.
|
|
28
|
+
*/
|
|
29
|
+
async initializeSource(source, ctx) {
|
|
30
|
+
// Store source config for later reference
|
|
31
|
+
this.sourceConfigs.set(source.name, source);
|
|
32
|
+
const authProvider = this.createAuthProvider(source.name);
|
|
33
|
+
const baseUrl = await this.resolveBaseUrl(source);
|
|
34
|
+
this.configureRateLimiter(source);
|
|
35
|
+
this.configureCircuitBreaker(source);
|
|
36
|
+
const client = new HttpClient({
|
|
37
|
+
baseUrl,
|
|
38
|
+
auth: authProvider,
|
|
39
|
+
rateLimiter: this.deps.rateLimiter,
|
|
40
|
+
circuitBreaker: this.deps.circuitBreaker,
|
|
41
|
+
sourceName: source.name,
|
|
42
|
+
});
|
|
43
|
+
ctx.sources.set(source.name, client);
|
|
44
|
+
this.log(`Initialized source: ${source.name}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Initialize multiple sources.
|
|
48
|
+
*/
|
|
49
|
+
async initializeSources(sources, ctx) {
|
|
50
|
+
for (const source of sources) {
|
|
51
|
+
await this.initializeSource(source, ctx);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the OAS source for a given source name.
|
|
56
|
+
*/
|
|
57
|
+
getOASSource(sourceName) {
|
|
58
|
+
return this.oasSources.get(sourceName);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the source configuration for a given source name.
|
|
62
|
+
*/
|
|
63
|
+
getSourceConfig(sourceName) {
|
|
64
|
+
return this.sourceConfigs.get(sourceName);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get all OAS sources.
|
|
68
|
+
*/
|
|
69
|
+
getAllOASSources() {
|
|
70
|
+
return this.oasSources;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get all source configurations.
|
|
74
|
+
*/
|
|
75
|
+
getAllSourceConfigs() {
|
|
76
|
+
return this.sourceConfigs;
|
|
77
|
+
}
|
|
78
|
+
createAuthProvider(sourceName) {
|
|
79
|
+
const authConfig = this.config.auth?.[sourceName];
|
|
80
|
+
if (!authConfig) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
if (authConfig.type === 'bearer' && authConfig.token) {
|
|
84
|
+
return new BearerAuthProvider(authConfig.token);
|
|
85
|
+
}
|
|
86
|
+
if (authConfig.type === 'oauth2' && authConfig.accessToken) {
|
|
87
|
+
return new OAuth2AuthProvider({
|
|
88
|
+
accessToken: authConfig.accessToken,
|
|
89
|
+
refreshToken: authConfig.refreshToken,
|
|
90
|
+
tokenEndpoint: authConfig.tokenEndpoint,
|
|
91
|
+
clientId: authConfig.clientId,
|
|
92
|
+
clientSecret: authConfig.clientSecret,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
async resolveBaseUrl(source) {
|
|
98
|
+
let baseUrl = source.config.base;
|
|
99
|
+
// If source has OAS spec, load it
|
|
100
|
+
if (source.specPath) {
|
|
101
|
+
try {
|
|
102
|
+
// Resolve relative spec paths against mission directory
|
|
103
|
+
const specPath = this.config.missionDir
|
|
104
|
+
? resolve(this.config.missionDir, source.specPath)
|
|
105
|
+
: source.specPath;
|
|
106
|
+
const oasSource = await loadOAS(specPath);
|
|
107
|
+
this.oasSources.set(source.name, oasSource);
|
|
108
|
+
// Use base URL from OAS if not explicitly provided
|
|
109
|
+
if (!baseUrl) {
|
|
110
|
+
baseUrl = oasSource.baseUrl;
|
|
111
|
+
}
|
|
112
|
+
this.log(`Loaded OAS spec for ${source.name}: ${oasSource.operations.size} operations`);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
throw new Error(`Failed to load OAS spec for ${source.name}: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!baseUrl) {
|
|
119
|
+
throw new Error(`Source ${source.name} has no base URL (provide 'base' or OAS spec with servers)`);
|
|
120
|
+
}
|
|
121
|
+
return baseUrl;
|
|
122
|
+
}
|
|
123
|
+
configureRateLimiter(source) {
|
|
124
|
+
if (!source.config.rateLimit) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
this.deps.rateLimiter.configure(source.name, {
|
|
128
|
+
strategy: source.config.rateLimit.strategy,
|
|
129
|
+
maxWait: source.config.rateLimit.maxWait,
|
|
130
|
+
fallbackRpm: source.config.rateLimit.fallbackRpm,
|
|
131
|
+
});
|
|
132
|
+
this.log(`Rate limit config for ${source.name}: strategy=${source.config.rateLimit.strategy ?? 'pause'}, ` +
|
|
133
|
+
`maxWait=${source.config.rateLimit.maxWait ?? 300}s`);
|
|
134
|
+
}
|
|
135
|
+
configureCircuitBreaker(source) {
|
|
136
|
+
if (!source.config.circuitBreaker) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.deps.circuitBreaker.configure(source.name, {
|
|
140
|
+
failureThreshold: source.config.circuitBreaker.failureThreshold,
|
|
141
|
+
// Convert seconds to milliseconds for the circuit breaker
|
|
142
|
+
resetTimeout: source.config.circuitBreaker.resetTimeout
|
|
143
|
+
? source.config.circuitBreaker.resetTimeout * 1000
|
|
144
|
+
: undefined,
|
|
145
|
+
successThreshold: source.config.circuitBreaker.successThreshold,
|
|
146
|
+
failureWindow: source.config.circuitBreaker.failureWindow
|
|
147
|
+
? source.config.circuitBreaker.failureWindow * 1000
|
|
148
|
+
: undefined,
|
|
149
|
+
});
|
|
150
|
+
this.log(`Circuit breaker config for ${source.name}: ` +
|
|
151
|
+
`failureThreshold=${source.config.circuitBreaker.failureThreshold ?? 5}, ` +
|
|
152
|
+
`resetTimeout=${source.config.circuitBreaker.resetTimeout ?? 30}s`);
|
|
153
|
+
}
|
|
154
|
+
log(message) {
|
|
155
|
+
this.config.log?.(message);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ApplyStep, TransformDefinition } from '../../ast/nodes.js';
|
|
2
|
+
import type { StepHandler, StepHandlerDeps } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extended dependencies for ApplyHandler - includes transform definition
|
|
5
|
+
*/
|
|
6
|
+
export interface ApplyHandlerDeps extends StepHandlerDeps {
|
|
7
|
+
transform: TransformDefinition;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Handles apply transform steps with overloading support.
|
|
11
|
+
*
|
|
12
|
+
* The apply step applies a named transform to a source value.
|
|
13
|
+
* If the transform has multiple variants (overloaded), it finds
|
|
14
|
+
* the first matching variant based on schema matching and guards.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ApplyHandler implements StepHandler<ApplyStep> {
|
|
17
|
+
private deps;
|
|
18
|
+
constructor(deps: ApplyHandlerDeps);
|
|
19
|
+
execute(step: ApplyStep): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Find the first matching transform variant for the given source value.
|
|
22
|
+
*
|
|
23
|
+
* Matching rules:
|
|
24
|
+
* 1. Wildcard ('_') always matches
|
|
25
|
+
* 2. Named schema must match using schema matcher
|
|
26
|
+
* 3. Optional guard condition must evaluate to truthy
|
|
27
|
+
*/
|
|
28
|
+
private findMatchingVariant;
|
|
29
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { evaluate } from '../evaluator.js';
|
|
2
|
+
import { matchesSchema } from '../schema-matcher.js';
|
|
3
|
+
import { setVariable } from '../context.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handles apply transform steps with overloading support.
|
|
6
|
+
*
|
|
7
|
+
* The apply step applies a named transform to a source value.
|
|
8
|
+
* If the transform has multiple variants (overloaded), it finds
|
|
9
|
+
* the first matching variant based on schema matching and guards.
|
|
10
|
+
*/
|
|
11
|
+
export class ApplyHandler {
|
|
12
|
+
deps;
|
|
13
|
+
constructor(deps) {
|
|
14
|
+
this.deps = deps;
|
|
15
|
+
}
|
|
16
|
+
async execute(step) {
|
|
17
|
+
const source = evaluate(step.source, this.deps.ctx);
|
|
18
|
+
const transform = this.deps.transform;
|
|
19
|
+
// Find matching variant
|
|
20
|
+
const variant = this.findMatchingVariant(source, transform.variants);
|
|
21
|
+
if (!variant) {
|
|
22
|
+
throw new Error(`No matching transform variant found for '${transform.name}'. ` +
|
|
23
|
+
`Source does not match any of the ${transform.variants.length} variant(s).`);
|
|
24
|
+
}
|
|
25
|
+
// Apply the variant's mappings
|
|
26
|
+
const mapped = {};
|
|
27
|
+
for (const mapping of variant.mappings) {
|
|
28
|
+
mapped[mapping.field] = evaluate(mapping.expression, this.deps.ctx, source);
|
|
29
|
+
}
|
|
30
|
+
// Store result - either in a variable (if 'as' specified) or in response
|
|
31
|
+
if (step.as) {
|
|
32
|
+
setVariable(this.deps.ctx, step.as, mapped);
|
|
33
|
+
this.deps.log(`Applied ${transform.name} to ${step.as}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
this.deps.ctx.response = mapped;
|
|
37
|
+
this.deps.log(`Applied ${transform.name} -> ${variant.targetSchema}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Find the first matching transform variant for the given source value.
|
|
42
|
+
*
|
|
43
|
+
* Matching rules:
|
|
44
|
+
* 1. Wildcard ('_') always matches
|
|
45
|
+
* 2. Named schema must match using schema matcher
|
|
46
|
+
* 3. Optional guard condition must evaluate to truthy
|
|
47
|
+
*/
|
|
48
|
+
findMatchingVariant(source, variants) {
|
|
49
|
+
for (const variant of variants) {
|
|
50
|
+
// Wildcard always matches
|
|
51
|
+
if (variant.sourceSchema === '_') {
|
|
52
|
+
// Check guard if present
|
|
53
|
+
if (variant.guard) {
|
|
54
|
+
const guardResult = evaluate(variant.guard, this.deps.ctx, source);
|
|
55
|
+
if (!guardResult)
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
return variant;
|
|
59
|
+
}
|
|
60
|
+
// Check if source matches the schema
|
|
61
|
+
const schema = this.deps.ctx.schemas.get(variant.sourceSchema);
|
|
62
|
+
if (!schema) {
|
|
63
|
+
// Schema not defined - skip this variant
|
|
64
|
+
this.deps.log(`Warning: Schema '${variant.sourceSchema}' not found, skipping variant`);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (matchesSchema(source, schema)) {
|
|
68
|
+
// Check guard if present
|
|
69
|
+
if (variant.guard) {
|
|
70
|
+
const guardResult = evaluate(variant.guard, this.deps.ctx, source);
|
|
71
|
+
if (!guardResult)
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
return variant;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
import type { ForStep, ActionStep } from '../../ast/nodes.js';
|
|
2
2
|
import type { StepHandler, StepHandlerDeps } from './types.js';
|
|
3
3
|
import type { ExecutionContext } from '../context.js';
|
|
4
|
+
import { QueueSignal } from '../signals.js';
|
|
5
|
+
import type { DebugController, DebugSnapshot } from '../../debug/index.js';
|
|
4
6
|
export interface ForHandlerDeps extends StepHandlerDeps {
|
|
5
7
|
executeStep: (step: ActionStep, actionName: string, ctx: ExecutionContext) => Promise<void>;
|
|
6
8
|
actionName: string;
|
|
9
|
+
debugController?: DebugController;
|
|
10
|
+
captureDebugSnapshot?: (action: string, stepIndex: number, stepType: string, pauseReason: {
|
|
11
|
+
type: 'loop-iteration';
|
|
12
|
+
variable: string;
|
|
13
|
+
index: number;
|
|
14
|
+
total: number;
|
|
15
|
+
}, ctx: ExecutionContext) => DebugSnapshot;
|
|
16
|
+
handleDebugCommand?: (cmd: {
|
|
17
|
+
type: string;
|
|
18
|
+
}) => void;
|
|
19
|
+
/** Optional callback to check for pause requests (called every N iterations) */
|
|
20
|
+
checkPause?: () => Promise<void>;
|
|
21
|
+
/** Handle a `queue` directive raised within a loop item. */
|
|
22
|
+
handleQueue?: (signal: QueueSignal) => Promise<void>;
|
|
7
23
|
}
|
|
8
24
|
/**
|
|
9
25
|
* Handles for...in...where iteration steps
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { evaluate } from '../evaluator.js';
|
|
2
2
|
import { childContext, setVariable, getVariable } from '../context.js';
|
|
3
|
+
import { StepError } from '../../errors/index.js';
|
|
4
|
+
import { SkipSignal, QueueSignal } from '../signals.js';
|
|
5
|
+
/** Heartbeat interval for loop iterations */
|
|
6
|
+
const LOOP_HEARTBEAT_INTERVAL = 10;
|
|
3
7
|
/**
|
|
4
8
|
* Handles for...in...where iteration steps
|
|
5
9
|
*/
|
|
@@ -10,15 +14,77 @@ export class ForHandler {
|
|
|
10
14
|
}
|
|
11
15
|
async execute(step) {
|
|
12
16
|
const collection = await this.getCollection(step);
|
|
17
|
+
const originalCount = collection.length;
|
|
13
18
|
// Apply filter if present
|
|
14
19
|
const filtered = step.condition
|
|
15
20
|
? collection.filter((item) => evaluate(step.condition, this.deps.ctx, item))
|
|
16
21
|
: collection;
|
|
17
|
-
|
|
22
|
+
// Emit loop.start event
|
|
23
|
+
this.deps.emit?.('loop.start', {
|
|
24
|
+
variable: step.variable,
|
|
25
|
+
collectionSize: filtered.length,
|
|
26
|
+
hasFilter: !!step.condition,
|
|
27
|
+
});
|
|
28
|
+
this.deps.log(`Iterating over ${filtered.length} ${filtered.length === 1 ? 'item' : 'items'}`);
|
|
29
|
+
let processedCount = 0;
|
|
30
|
+
let failedCount = 0;
|
|
18
31
|
// Execute steps for each item
|
|
19
|
-
for (
|
|
20
|
-
|
|
32
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
33
|
+
const item = filtered[i];
|
|
34
|
+
// Check for pause request every N iterations
|
|
35
|
+
if (i > 0 && i % LOOP_HEARTBEAT_INTERVAL === 0) {
|
|
36
|
+
await this.deps.checkPause?.();
|
|
37
|
+
// Emit heartbeat every N iterations
|
|
38
|
+
this.deps.emit?.('loop.heartbeat', {
|
|
39
|
+
variable: step.variable,
|
|
40
|
+
current: i,
|
|
41
|
+
total: filtered.length,
|
|
42
|
+
processedCount,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
// Emit loop.iteration event
|
|
46
|
+
this.deps.emit?.('loop.iteration', {
|
|
47
|
+
variable: step.variable,
|
|
48
|
+
itemIndex: i,
|
|
49
|
+
totalItems: filtered.length,
|
|
50
|
+
});
|
|
51
|
+
// Debug pause point - before each loop iteration (step-into mode)
|
|
52
|
+
if (this.deps.debugController &&
|
|
53
|
+
this.deps.captureDebugSnapshot &&
|
|
54
|
+
this.deps.handleDebugCommand) {
|
|
55
|
+
const location = {
|
|
56
|
+
action: this.deps.actionName,
|
|
57
|
+
stepIndex: -1, // Use -1 for loop iterations
|
|
58
|
+
stepType: 'for-iteration',
|
|
59
|
+
isLoopIteration: true,
|
|
60
|
+
loopInfo: { variable: step.variable, index: i, total: filtered.length },
|
|
61
|
+
};
|
|
62
|
+
if (this.deps.debugController.shouldPause(location)) {
|
|
63
|
+
// Create child context to capture loop variable
|
|
64
|
+
const previewCtx = childContext(this.deps.ctx);
|
|
65
|
+
setVariable(previewCtx, step.variable, item);
|
|
66
|
+
const snapshot = this.deps.captureDebugSnapshot(this.deps.actionName, -1, 'for-iteration', { type: 'loop-iteration', variable: step.variable, index: i, total: filtered.length }, previewCtx);
|
|
67
|
+
const command = await this.deps.debugController.pause(snapshot);
|
|
68
|
+
this.deps.handleDebugCommand(command);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await this.executeForItem(step, item);
|
|
73
|
+
processedCount++;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
failedCount++;
|
|
77
|
+
throw error; // Re-throw to propagate
|
|
78
|
+
}
|
|
21
79
|
}
|
|
80
|
+
// Emit loop.complete event
|
|
81
|
+
this.deps.emit?.('loop.complete', {
|
|
82
|
+
variable: step.variable,
|
|
83
|
+
totalItems: filtered.length,
|
|
84
|
+
itemsProcessed: processedCount,
|
|
85
|
+
itemsSkipped: originalCount - filtered.length,
|
|
86
|
+
itemsFailed: failedCount,
|
|
87
|
+
});
|
|
22
88
|
}
|
|
23
89
|
async getCollection(step) {
|
|
24
90
|
let collection;
|
|
@@ -36,16 +102,32 @@ export class ForHandler {
|
|
|
36
102
|
collection = evaluate(step.collection, this.deps.ctx);
|
|
37
103
|
}
|
|
38
104
|
if (!Array.isArray(collection)) {
|
|
39
|
-
throw new
|
|
105
|
+
throw new StepError('For loop collection must be an array', 'for', {
|
|
106
|
+
action: this.deps.actionName,
|
|
107
|
+
});
|
|
40
108
|
}
|
|
41
109
|
return collection;
|
|
42
110
|
}
|
|
43
111
|
async executeForItem(step, item) {
|
|
44
112
|
const childCtx = childContext(this.deps.ctx);
|
|
45
113
|
setVariable(childCtx, step.variable, item);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
114
|
+
try {
|
|
115
|
+
// Execute each inner step with child context
|
|
116
|
+
for (const innerStep of step.steps) {
|
|
117
|
+
await this.deps.executeStep(innerStep, this.deps.actionName, childCtx);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
// `skip` skips the rest of this item's steps; the loop continues.
|
|
122
|
+
if (error instanceof SkipSignal) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// `queue` stashes the item and moves on to the next iteration.
|
|
126
|
+
if (error instanceof QueueSignal) {
|
|
127
|
+
await this.deps.handleQueue?.(error);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
49
131
|
}
|
|
50
132
|
}
|
|
51
133
|
}
|
|
@@ -4,5 +4,7 @@ export { MapHandler } from './map-handler.js';
|
|
|
4
4
|
export { ValidateHandler } from './validate-handler.js';
|
|
5
5
|
export { StoreHandler } from './store-handler.js';
|
|
6
6
|
export { MatchHandler, type MatchHandlerDeps, type MatchResult } from './match-handler.js';
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
7
|
+
export { ApplyHandler, type ApplyHandlerDeps } from './apply-handler.js';
|
|
8
|
+
export { WebhookHandler, type WebhookHandlerDeps, type WebhookHandlerResult, } from './webhook-handler.js';
|
|
9
|
+
export { PauseHandler, type PauseHandlerDeps, type PauseHandlerResult } from './pause-handler.js';
|
|
10
|
+
export { NoMatchError, AbortError, SkipSignal, RetrySignal, JumpSignal, QueueSignal, PauseSignal, } from '../signals.js';
|
|
@@ -3,6 +3,8 @@ export { MapHandler } from './map-handler.js';
|
|
|
3
3
|
export { ValidateHandler } from './validate-handler.js';
|
|
4
4
|
export { StoreHandler } from './store-handler.js';
|
|
5
5
|
export { MatchHandler } from './match-handler.js';
|
|
6
|
-
export {
|
|
6
|
+
export { ApplyHandler } from './apply-handler.js';
|
|
7
|
+
export { WebhookHandler, } from './webhook-handler.js';
|
|
8
|
+
export { PauseHandler } from './pause-handler.js';
|
|
7
9
|
// Export signals from the canonical location
|
|
8
|
-
export { NoMatchError, AbortError, SkipSignal, RetrySignal, JumpSignal, QueueSignal, } from '../signals.js';
|
|
10
|
+
export { NoMatchError, AbortError, SkipSignal, RetrySignal, JumpSignal, QueueSignal, PauseSignal, } from '../signals.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MatchStep, ActionStep, FlowDirective } from '../../ast/nodes.js';
|
|
2
2
|
import type { StepHandlerDeps } from './types.js';
|
|
3
3
|
import type { ExecutionContext } from '../context.js';
|
|
4
|
+
import type { DebugController, DebugSnapshot } from '../../debug/index.js';
|
|
4
5
|
/**
|
|
5
6
|
* Result of executing a match step
|
|
6
7
|
*/
|
|
@@ -15,6 +16,14 @@ export interface MatchResult {
|
|
|
15
16
|
export interface MatchHandlerDeps extends StepHandlerDeps {
|
|
16
17
|
executeStep: (step: ActionStep, actionName: string, ctx: ExecutionContext) => Promise<void>;
|
|
17
18
|
actionName: string;
|
|
19
|
+
debugController?: DebugController;
|
|
20
|
+
captureDebugSnapshot?: (action: string, stepIndex: number, stepType: string, pauseReason: {
|
|
21
|
+
type: 'match-arm';
|
|
22
|
+
schema: string;
|
|
23
|
+
}, ctx: ExecutionContext) => DebugSnapshot;
|
|
24
|
+
handleDebugCommand?: (cmd: {
|
|
25
|
+
type: string;
|
|
26
|
+
}) => void;
|
|
18
27
|
}
|
|
19
28
|
/**
|
|
20
29
|
* Handles match steps (schema overloading with flow control)
|
|
@@ -11,31 +11,60 @@ export class MatchHandler {
|
|
|
11
11
|
}
|
|
12
12
|
async execute(step) {
|
|
13
13
|
const value = evaluate(step.target, this.deps.ctx);
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
// Find matching arm, checking guards
|
|
15
|
+
let matchedArm = null;
|
|
16
|
+
for (const arm of step.arms) {
|
|
17
|
+
// Check if schema matches
|
|
18
|
+
if (arm.schema !== '_') {
|
|
19
|
+
// Check if this schema matches the value
|
|
20
|
+
const schemaMatches = findMatchingSchema(value, this.deps.ctx.schemas, [arm.schema]);
|
|
21
|
+
if (!schemaMatches) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// If there's a guard, check it
|
|
26
|
+
if (arm.guard) {
|
|
27
|
+
const guardResult = evaluate(arm.guard, this.deps.ctx, value);
|
|
28
|
+
if (!guardResult) {
|
|
29
|
+
continue; // Guard failed, try next arm
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Found a match
|
|
33
|
+
matchedArm = arm;
|
|
34
|
+
break;
|
|
20
35
|
}
|
|
21
|
-
|
|
22
|
-
// Find the matching arm
|
|
23
|
-
const arm = step.arms.find(a => a.schema === matchedSchema);
|
|
24
|
-
if (!arm) {
|
|
25
|
-
// Shouldn't happen if findMatchingSchema works correctly
|
|
36
|
+
if (!matchedArm) {
|
|
26
37
|
throw new NoMatchError(value);
|
|
27
38
|
}
|
|
39
|
+
this.deps.log(`Matched schema: ${matchedArm.schema}${matchedArm.guard ? ' (with guard)' : ''}`);
|
|
28
40
|
// Handle flow directive
|
|
29
|
-
if (
|
|
41
|
+
if (matchedArm.flow) {
|
|
30
42
|
// 'continue' means proceed normally - don't throw
|
|
31
|
-
if (
|
|
43
|
+
if (matchedArm.flow.type === 'continue') {
|
|
32
44
|
return;
|
|
33
45
|
}
|
|
34
|
-
this.handleFlowDirective(
|
|
46
|
+
this.handleFlowDirective(matchedArm.flow, value);
|
|
35
47
|
}
|
|
36
48
|
// Execute steps
|
|
37
|
-
if (
|
|
38
|
-
|
|
49
|
+
if (matchedArm.steps) {
|
|
50
|
+
// Debug pause point - before match arm body (step-into mode)
|
|
51
|
+
if (this.deps.debugController &&
|
|
52
|
+
this.deps.captureDebugSnapshot &&
|
|
53
|
+
this.deps.handleDebugCommand) {
|
|
54
|
+
const location = {
|
|
55
|
+
action: this.deps.actionName,
|
|
56
|
+
stepIndex: -1, // Use -1 for match arms
|
|
57
|
+
stepType: 'match-arm',
|
|
58
|
+
isMatchArm: true,
|
|
59
|
+
matchInfo: { schema: matchedArm.schema },
|
|
60
|
+
};
|
|
61
|
+
if (this.deps.debugController.shouldPause(location)) {
|
|
62
|
+
const snapshot = this.deps.captureDebugSnapshot(this.deps.actionName, -1, 'match-arm', { type: 'match-arm', schema: matchedArm.schema }, this.deps.ctx);
|
|
63
|
+
const command = await this.deps.debugController.pause(snapshot);
|
|
64
|
+
this.deps.handleDebugCommand(command);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
for (const innerStep of matchedArm.steps) {
|
|
39
68
|
await this.deps.executeStep(innerStep, this.deps.actionName, this.deps.ctx);
|
|
40
69
|
}
|
|
41
70
|
}
|
|
@@ -52,10 +81,11 @@ export class MatchHandler {
|
|
|
52
81
|
throw new JumpSignal(flow.action, flow.then);
|
|
53
82
|
case 'queue':
|
|
54
83
|
throw new QueueSignal(value, flow.target);
|
|
55
|
-
default:
|
|
84
|
+
default: {
|
|
56
85
|
// This should never happen if TypeScript is working correctly
|
|
57
86
|
const _exhaustive = flow;
|
|
58
87
|
throw new Error(`Unknown flow directive: ${_exhaustive.type}`);
|
|
88
|
+
}
|
|
59
89
|
}
|
|
60
90
|
}
|
|
61
91
|
}
|