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
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 3
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Dead Letter Queues
|
|
6
|
-
|
|
7
|
-
Dead letter queues (DLQ) store failed items for later processing. They prevent data loss when errors occur and allow for manual or automated retry.
|
|
8
|
-
|
|
9
|
-
## Basic Usage
|
|
10
|
-
|
|
11
|
-
```vague
|
|
12
|
-
mission DataSync {
|
|
13
|
-
store data: file("data")
|
|
14
|
-
store dlq: file("dead-letter-queue")
|
|
15
|
-
|
|
16
|
-
action FetchData {
|
|
17
|
-
get "/items"
|
|
18
|
-
|
|
19
|
-
for item in response.items {
|
|
20
|
-
get concat("/items/", item.id, "/details")
|
|
21
|
-
|
|
22
|
-
match response {
|
|
23
|
-
{ error: e } -> queue dlq {
|
|
24
|
-
item: {
|
|
25
|
-
itemId: item.id,
|
|
26
|
-
error: e,
|
|
27
|
-
timestamp: now()
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
_ -> store response -> data { key: item.id }
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
run FetchData
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Queue Directive Syntax
|
|
40
|
-
|
|
41
|
-
```vague
|
|
42
|
-
queue storeName {
|
|
43
|
-
item: objectToStore,
|
|
44
|
-
key: optionalKey
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### With Key
|
|
49
|
-
|
|
50
|
-
```vague
|
|
51
|
-
queue dlq {
|
|
52
|
-
item: { error: "failed" },
|
|
53
|
-
key: concat("error-", item.id)
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Without Key (Auto-Generated)
|
|
58
|
-
|
|
59
|
-
```vague
|
|
60
|
-
queue dlq {
|
|
61
|
-
item: { error: "failed" }
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## What to Include
|
|
66
|
-
|
|
67
|
-
### Minimum Information
|
|
68
|
-
|
|
69
|
-
```vague
|
|
70
|
-
queue dlq {
|
|
71
|
-
item: {
|
|
72
|
-
id: item.id,
|
|
73
|
-
error: response.error,
|
|
74
|
-
timestamp: now()
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Full Context
|
|
80
|
-
|
|
81
|
-
```vague
|
|
82
|
-
queue dlq {
|
|
83
|
-
item: {
|
|
84
|
-
// Identifiers
|
|
85
|
-
id: item.id,
|
|
86
|
-
batchId: batchId,
|
|
87
|
-
|
|
88
|
-
// Original data
|
|
89
|
-
originalItem: item,
|
|
90
|
-
|
|
91
|
-
// Error details
|
|
92
|
-
error: response.error,
|
|
93
|
-
errorCode: response.code,
|
|
94
|
-
errorDetails: response.details,
|
|
95
|
-
|
|
96
|
-
// Context
|
|
97
|
-
action: "FetchDetails",
|
|
98
|
-
source: "ExternalAPI",
|
|
99
|
-
|
|
100
|
-
// Timing
|
|
101
|
-
timestamp: now(),
|
|
102
|
-
attemptCount: 1,
|
|
103
|
-
|
|
104
|
-
// For retry
|
|
105
|
-
retryable: response.code >= 500
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## DLQ Patterns
|
|
111
|
-
|
|
112
|
-
### Simple Error Queue
|
|
113
|
-
|
|
114
|
-
```vague
|
|
115
|
-
mission Simple {
|
|
116
|
-
store dlq: file("errors")
|
|
117
|
-
|
|
118
|
-
action Process {
|
|
119
|
-
for item in items {
|
|
120
|
-
get concat("/api/", item.id)
|
|
121
|
-
|
|
122
|
-
match response {
|
|
123
|
-
{ error: _ } -> queue dlq { item: { id: item.id, response: response } },
|
|
124
|
-
_ -> continue
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Categorized Queues
|
|
132
|
-
|
|
133
|
-
```vague
|
|
134
|
-
mission Categorized {
|
|
135
|
-
store retryable: file("retryable-errors")
|
|
136
|
-
store permanent: file("permanent-errors")
|
|
137
|
-
store validation: file("validation-errors")
|
|
138
|
-
|
|
139
|
-
action Process {
|
|
140
|
-
for item in items {
|
|
141
|
-
get concat("/api/", item.id)
|
|
142
|
-
|
|
143
|
-
match response {
|
|
144
|
-
// Retryable errors
|
|
145
|
-
{ code: 429 } -> queue retryable { item: { id: item.id, reason: "rate_limit" } },
|
|
146
|
-
{ code: 500 } -> queue retryable { item: { id: item.id, reason: "server_error" } },
|
|
147
|
-
{ code: 503 } -> queue retryable { item: { id: item.id, reason: "unavailable" } },
|
|
148
|
-
|
|
149
|
-
// Permanent errors
|
|
150
|
-
{ code: 401 } -> queue permanent { item: { id: item.id, reason: "auth" } },
|
|
151
|
-
{ code: 403 } -> queue permanent { item: { id: item.id, reason: "forbidden" } },
|
|
152
|
-
{ code: 404 } -> queue permanent { item: { id: item.id, reason: "not_found" } },
|
|
153
|
-
|
|
154
|
-
// Validation errors
|
|
155
|
-
{ code: 400 } -> queue validation { item: { id: item.id, details: response } },
|
|
156
|
-
|
|
157
|
-
// Success
|
|
158
|
-
_ -> continue
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### DLQ with Retry Counter
|
|
166
|
-
|
|
167
|
-
```vague
|
|
168
|
-
for item in items {
|
|
169
|
-
get concat("/api/", item.id)
|
|
170
|
-
|
|
171
|
-
match response {
|
|
172
|
-
{ error: _ } where item.retryCount >= 3 -> {
|
|
173
|
-
// Max retries exceeded
|
|
174
|
-
queue permanentFailures {
|
|
175
|
-
item: { ...item, finalError: response.error }
|
|
176
|
-
}
|
|
177
|
-
skip
|
|
178
|
-
},
|
|
179
|
-
{ error: _ } -> {
|
|
180
|
-
// Queue for retry
|
|
181
|
-
queue retryQueue {
|
|
182
|
-
item: {
|
|
183
|
-
...item,
|
|
184
|
-
retryCount: (item.retryCount or 0) + 1,
|
|
185
|
-
lastError: response.error
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
skip
|
|
189
|
-
},
|
|
190
|
-
_ -> continue
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## Processing DLQ
|
|
196
|
-
|
|
197
|
-
### Manual Review
|
|
198
|
-
|
|
199
|
-
Export and review:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
reqon mission.vague --output ./exports/
|
|
203
|
-
# Review exports/dead-letter-queue.json
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Automated Retry
|
|
207
|
-
|
|
208
|
-
Create a retry mission:
|
|
209
|
-
|
|
210
|
-
```vague
|
|
211
|
-
mission RetryFailed {
|
|
212
|
-
store dlq: file("dead-letter-queue")
|
|
213
|
-
store data: file("data")
|
|
214
|
-
store permanentFailed: file("permanent-failures")
|
|
215
|
-
|
|
216
|
-
action RetryItems {
|
|
217
|
-
for item in dlq where .retryable == true {
|
|
218
|
-
get concat("/api/", item.originalItem.id)
|
|
219
|
-
|
|
220
|
-
match response {
|
|
221
|
-
{ error: _ } where item.attemptCount >= 5 -> {
|
|
222
|
-
// Give up after 5 attempts
|
|
223
|
-
store {
|
|
224
|
-
...item,
|
|
225
|
-
finalError: response.error
|
|
226
|
-
} -> permanentFailed { key: item.id }
|
|
227
|
-
delete dlq[item.id]
|
|
228
|
-
},
|
|
229
|
-
{ error: _ } -> {
|
|
230
|
-
// Update retry count
|
|
231
|
-
store {
|
|
232
|
-
...item,
|
|
233
|
-
attemptCount: item.attemptCount + 1,
|
|
234
|
-
lastAttempt: now(),
|
|
235
|
-
lastError: response.error
|
|
236
|
-
} -> dlq { key: item.id }
|
|
237
|
-
},
|
|
238
|
-
_ -> {
|
|
239
|
-
// Success! Remove from DLQ
|
|
240
|
-
store response -> data { key: item.originalItem.id }
|
|
241
|
-
delete dlq[item.id]
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
run RetryItems
|
|
248
|
-
}
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### Scheduled Retry
|
|
252
|
-
|
|
253
|
-
```vague
|
|
254
|
-
mission ScheduledRetry {
|
|
255
|
-
schedule: every 1 hour
|
|
256
|
-
|
|
257
|
-
store dlq: file("dead-letter-queue")
|
|
258
|
-
|
|
259
|
-
action RetryEligible {
|
|
260
|
-
for item in dlq where .lastAttempt < addHours(now(), -1) {
|
|
261
|
-
// Retry items not attempted in the last hour
|
|
262
|
-
// ... retry logic
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
run RetryEligible
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## DLQ with Notifications
|
|
271
|
-
|
|
272
|
-
```vague
|
|
273
|
-
action NotifyOnFailure {
|
|
274
|
-
for item in items {
|
|
275
|
-
get concat("/api/", item.id)
|
|
276
|
-
|
|
277
|
-
match response {
|
|
278
|
-
{ error: e } -> {
|
|
279
|
-
// Queue for retry
|
|
280
|
-
queue dlq { item: { id: item.id, error: e } }
|
|
281
|
-
|
|
282
|
-
// Check if threshold exceeded
|
|
283
|
-
match dlq {
|
|
284
|
-
_ where length(dlq) > 100 -> {
|
|
285
|
-
// Too many failures - alert
|
|
286
|
-
post NotificationAPI "/alerts" {
|
|
287
|
-
body: {
|
|
288
|
-
message: "DLQ threshold exceeded",
|
|
289
|
-
count: length(dlq),
|
|
290
|
-
timestamp: now()
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
},
|
|
294
|
-
_ -> continue
|
|
295
|
-
}
|
|
296
|
-
},
|
|
297
|
-
_ -> continue
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
## Best Practices
|
|
304
|
-
|
|
305
|
-
### Include Enough Context
|
|
306
|
-
|
|
307
|
-
```vague
|
|
308
|
-
queue dlq {
|
|
309
|
-
item: {
|
|
310
|
-
// What failed
|
|
311
|
-
id: item.id,
|
|
312
|
-
originalData: item,
|
|
313
|
-
|
|
314
|
-
// Why it failed
|
|
315
|
-
error: response.error,
|
|
316
|
-
errorCode: response.code,
|
|
317
|
-
|
|
318
|
-
// When it failed
|
|
319
|
-
timestamp: now(),
|
|
320
|
-
|
|
321
|
-
// Can we retry?
|
|
322
|
-
retryable: response.code >= 500,
|
|
323
|
-
|
|
324
|
-
// How many times have we tried?
|
|
325
|
-
attemptCount: 1
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
### Separate Retryable vs Permanent
|
|
331
|
-
|
|
332
|
-
```vague
|
|
333
|
-
// Retryable: server errors, rate limits
|
|
334
|
-
queue retryQueue { item: { ... } }
|
|
335
|
-
|
|
336
|
-
// Permanent: validation errors, not found
|
|
337
|
-
queue permanentQueue { item: { ... } }
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
### Set Retention Policies
|
|
341
|
-
|
|
342
|
-
Periodically clean old entries:
|
|
343
|
-
|
|
344
|
-
```vague
|
|
345
|
-
action CleanOldEntries {
|
|
346
|
-
for item in dlq where .timestamp < addDays(now(), -30) {
|
|
347
|
-
// Archive or delete items older than 30 days
|
|
348
|
-
delete dlq[item.id]
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### Monitor Queue Size
|
|
354
|
-
|
|
355
|
-
```vague
|
|
356
|
-
action MonitorDLQ {
|
|
357
|
-
match dlq {
|
|
358
|
-
_ where length(dlq) > 1000 -> {
|
|
359
|
-
// Alert on large queue
|
|
360
|
-
store {
|
|
361
|
-
alert: "DLQ size exceeded 1000",
|
|
362
|
-
size: length(dlq),
|
|
363
|
-
timestamp: now()
|
|
364
|
-
} -> alerts
|
|
365
|
-
},
|
|
366
|
-
_ -> continue
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
## Troubleshooting
|
|
372
|
-
|
|
373
|
-
### Queue Growing Too Fast
|
|
374
|
-
|
|
375
|
-
1. Check for systemic issues
|
|
376
|
-
2. Review error patterns
|
|
377
|
-
3. Fix root cause before retrying
|
|
378
|
-
|
|
379
|
-
### Items Never Succeed
|
|
380
|
-
|
|
381
|
-
Mark as permanent failure:
|
|
382
|
-
|
|
383
|
-
```vague
|
|
384
|
-
match item {
|
|
385
|
-
_ where item.attemptCount > 10 -> {
|
|
386
|
-
store item -> permanentFailures { key: item.id }
|
|
387
|
-
delete dlq[item.id]
|
|
388
|
-
},
|
|
389
|
-
_ -> continue
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
### Duplicate Processing
|
|
394
|
-
|
|
395
|
-
Use idempotent operations:
|
|
396
|
-
|
|
397
|
-
```vague
|
|
398
|
-
store response -> data { key: item.id, upsert: true }
|
|
399
|
-
```
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 1
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Flow Control Directives
|
|
6
|
-
|
|
7
|
-
Flow control directives determine what happens after pattern matching. They provide fine-grained control over error handling and execution flow.
|
|
8
|
-
|
|
9
|
-
## Available Directives
|
|
10
|
-
|
|
11
|
-
| Directive | Description |
|
|
12
|
-
|-----------|-------------|
|
|
13
|
-
| `continue` | Proceed to next step |
|
|
14
|
-
| `skip` | Skip remaining steps in current iteration |
|
|
15
|
-
| `abort` | Stop mission with error |
|
|
16
|
-
| `retry` | Retry previous request with backoff |
|
|
17
|
-
| `queue` | Send to dead letter queue |
|
|
18
|
-
| `jump...then` | Execute action, then continue |
|
|
19
|
-
|
|
20
|
-
## Continue
|
|
21
|
-
|
|
22
|
-
Proceed to the next step normally:
|
|
23
|
-
|
|
24
|
-
```vague
|
|
25
|
-
match response {
|
|
26
|
-
{ data: _ } -> continue,
|
|
27
|
-
_ -> abort "No data"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Execution continues here
|
|
31
|
-
store response.data -> data { key: .id }
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Use `continue` when:
|
|
35
|
-
- Pattern matches expected success case
|
|
36
|
-
- You want explicit confirmation of flow
|
|
37
|
-
|
|
38
|
-
## Skip
|
|
39
|
-
|
|
40
|
-
Skip remaining steps in the current loop iteration:
|
|
41
|
-
|
|
42
|
-
```vague
|
|
43
|
-
for item in items {
|
|
44
|
-
match item {
|
|
45
|
-
{ status: "inactive" } -> skip,
|
|
46
|
-
{ status: "deleted" } -> skip,
|
|
47
|
-
_ -> continue
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Only runs for active, non-deleted items
|
|
51
|
-
store item -> activeItems { key: .id }
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Use `skip` when:
|
|
56
|
-
- Item should be ignored but processing should continue
|
|
57
|
-
- Filtering within a loop
|
|
58
|
-
- Handling non-critical errors
|
|
59
|
-
|
|
60
|
-
## Abort
|
|
61
|
-
|
|
62
|
-
Stop mission execution immediately:
|
|
63
|
-
|
|
64
|
-
```vague
|
|
65
|
-
match response {
|
|
66
|
-
{ error: msg } -> abort msg,
|
|
67
|
-
{ error: _ } -> abort "Unknown error occurred",
|
|
68
|
-
_ -> continue
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
With custom message:
|
|
73
|
-
|
|
74
|
-
```vague
|
|
75
|
-
match response {
|
|
76
|
-
{ code: 401 } -> abort "Authentication failed - check credentials",
|
|
77
|
-
{ code: 403 } -> abort "Permission denied - check API permissions",
|
|
78
|
-
{ code: 404 } -> abort "Resource not found",
|
|
79
|
-
{ code: 500 } -> abort "Server error - try again later",
|
|
80
|
-
_ -> continue
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Use `abort` when:
|
|
85
|
-
- Unrecoverable error occurs
|
|
86
|
-
- Critical validation fails
|
|
87
|
-
- Continuing would cause data corruption
|
|
88
|
-
|
|
89
|
-
## Retry
|
|
90
|
-
|
|
91
|
-
Retry the previous HTTP request:
|
|
92
|
-
|
|
93
|
-
```vague
|
|
94
|
-
match response {
|
|
95
|
-
{ error: _, code: 429 } -> retry {
|
|
96
|
-
maxAttempts: 5,
|
|
97
|
-
backoff: exponential,
|
|
98
|
-
initialDelay: 1000,
|
|
99
|
-
maxDelay: 60000
|
|
100
|
-
},
|
|
101
|
-
_ -> continue
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### Retry Options
|
|
106
|
-
|
|
107
|
-
| Option | Description | Default |
|
|
108
|
-
|--------|-------------|---------|
|
|
109
|
-
| `maxAttempts` | Maximum retry attempts | 3 |
|
|
110
|
-
| `backoff` | Strategy: `exponential`, `linear`, `constant` | `exponential` |
|
|
111
|
-
| `initialDelay` | First retry delay (ms) | 1000 |
|
|
112
|
-
| `maxDelay` | Maximum delay (ms) | 30000 |
|
|
113
|
-
| `delay` | Fixed delay (overrides backoff) | - |
|
|
114
|
-
|
|
115
|
-
### Simple Retry
|
|
116
|
-
|
|
117
|
-
```vague
|
|
118
|
-
match response {
|
|
119
|
-
{ code: 503 } -> retry, // Uses defaults
|
|
120
|
-
_ -> continue
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Fixed Delay
|
|
125
|
-
|
|
126
|
-
```vague
|
|
127
|
-
match response {
|
|
128
|
-
{ code: 429, headers: h } -> retry {
|
|
129
|
-
delay: h["Retry-After"] * 1000
|
|
130
|
-
},
|
|
131
|
-
_ -> continue
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Queue
|
|
136
|
-
|
|
137
|
-
Send failed items to a dead letter queue:
|
|
138
|
-
|
|
139
|
-
```vague
|
|
140
|
-
match response {
|
|
141
|
-
{ error: e } -> queue dlq {
|
|
142
|
-
item: {
|
|
143
|
-
request: currentRequest,
|
|
144
|
-
error: e,
|
|
145
|
-
timestamp: now()
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
_ -> continue
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Queue Options
|
|
153
|
-
|
|
154
|
-
```vague
|
|
155
|
-
queue queueName {
|
|
156
|
-
item: itemToStore,
|
|
157
|
-
key: optionalKey
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
Store the queue as a regular store:
|
|
162
|
-
|
|
163
|
-
```vague
|
|
164
|
-
mission ErrorHandling {
|
|
165
|
-
store dlq: file("dead-letter-queue")
|
|
166
|
-
|
|
167
|
-
action Process {
|
|
168
|
-
get "/data"
|
|
169
|
-
|
|
170
|
-
match response {
|
|
171
|
-
{ error: e } -> queue dlq { item: { error: e } },
|
|
172
|
-
_ -> continue
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Jump Then
|
|
179
|
-
|
|
180
|
-
Execute another action, then continue or retry:
|
|
181
|
-
|
|
182
|
-
```vague
|
|
183
|
-
match response {
|
|
184
|
-
{ code: 401 } -> jump RefreshToken then retry,
|
|
185
|
-
_ -> continue
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
action RefreshToken {
|
|
189
|
-
post "/auth/refresh" {
|
|
190
|
-
body: { refreshToken: env("REFRESH_TOKEN") }
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
### Jump Then Retry
|
|
196
|
-
|
|
197
|
-
Common pattern for token refresh:
|
|
198
|
-
|
|
199
|
-
```vague
|
|
200
|
-
action FetchData {
|
|
201
|
-
get "/protected-resource"
|
|
202
|
-
|
|
203
|
-
match response {
|
|
204
|
-
{ code: 401 } -> jump RefreshToken then retry,
|
|
205
|
-
_ -> store response -> data { key: .id }
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
action RefreshToken {
|
|
210
|
-
post "/oauth/token" {
|
|
211
|
-
body: {
|
|
212
|
-
grant_type: "refresh_token",
|
|
213
|
-
refresh_token: env("REFRESH_TOKEN")
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// New token is automatically used
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Jump Then Continue
|
|
221
|
-
|
|
222
|
-
```vague
|
|
223
|
-
match response {
|
|
224
|
-
{ needsSetup: true } -> jump SetupResource then continue,
|
|
225
|
-
_ -> continue
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## Combining Directives
|
|
230
|
-
|
|
231
|
-
### Layered Error Handling
|
|
232
|
-
|
|
233
|
-
```vague
|
|
234
|
-
match response {
|
|
235
|
-
// Retry transient errors
|
|
236
|
-
{ code: 429 } -> retry { maxAttempts: 5 },
|
|
237
|
-
{ code: 503 } -> retry { maxAttempts: 3 },
|
|
238
|
-
{ code: 504 } -> retry { maxAttempts: 3 },
|
|
239
|
-
|
|
240
|
-
// Handle auth separately
|
|
241
|
-
{ code: 401 } -> jump RefreshToken then retry,
|
|
242
|
-
|
|
243
|
-
// Queue unrecoverable errors
|
|
244
|
-
{ code: 400, error: e } -> queue dlq { item: { error: e } },
|
|
245
|
-
|
|
246
|
-
// Abort on critical errors
|
|
247
|
-
{ code: 500, error: e } -> abort e,
|
|
248
|
-
|
|
249
|
-
// Skip missing resources
|
|
250
|
-
{ code: 404 } -> skip,
|
|
251
|
-
|
|
252
|
-
// Continue on success
|
|
253
|
-
_ -> continue
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### Per-Item Error Handling
|
|
258
|
-
|
|
259
|
-
```vague
|
|
260
|
-
for item in items {
|
|
261
|
-
get concat("/items/", item.id)
|
|
262
|
-
|
|
263
|
-
match response {
|
|
264
|
-
{ error: _, code: 404 } -> {
|
|
265
|
-
// Log and skip
|
|
266
|
-
store { id: item.id, status: "not_found" } -> missing
|
|
267
|
-
skip
|
|
268
|
-
},
|
|
269
|
-
{ error: e } -> {
|
|
270
|
-
// Queue for retry
|
|
271
|
-
queue failed { item: { id: item.id, error: e } }
|
|
272
|
-
skip
|
|
273
|
-
},
|
|
274
|
-
_ -> continue
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
store response -> processedItems { key: .id }
|
|
278
|
-
}
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
## Best Practices
|
|
282
|
-
|
|
283
|
-
### Be Specific
|
|
284
|
-
|
|
285
|
-
```vague
|
|
286
|
-
// Good: specific error handling
|
|
287
|
-
match response {
|
|
288
|
-
{ code: 401 } -> jump RefreshToken then retry,
|
|
289
|
-
{ code: 403 } -> abort "Permission denied",
|
|
290
|
-
{ code: 429 } -> retry { delay: 60000 },
|
|
291
|
-
{ code: 404 } -> skip,
|
|
292
|
-
{ error: e } -> abort e,
|
|
293
|
-
_ -> continue
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Avoid: too generic
|
|
297
|
-
match response {
|
|
298
|
-
{ error: _ } -> retry,
|
|
299
|
-
_ -> continue
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Always Have a Default
|
|
304
|
-
|
|
305
|
-
```vague
|
|
306
|
-
match response {
|
|
307
|
-
{ status: "ok" } -> continue,
|
|
308
|
-
{ status: "error" } -> abort "Error",
|
|
309
|
-
_ -> abort "Unexpected response" // Always have catch-all
|
|
310
|
-
}
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### Log Before Abort
|
|
314
|
-
|
|
315
|
-
```vague
|
|
316
|
-
match response {
|
|
317
|
-
{ error: e } -> {
|
|
318
|
-
store { error: e, timestamp: now() } -> errorLog
|
|
319
|
-
abort e
|
|
320
|
-
},
|
|
321
|
-
_ -> continue
|
|
322
|
-
}
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### Use Queue for Later Processing
|
|
326
|
-
|
|
327
|
-
```vague
|
|
328
|
-
match response {
|
|
329
|
-
{ error: "rate_limit" } -> queue retryQueue {
|
|
330
|
-
item: {
|
|
331
|
-
request: currentRequest,
|
|
332
|
-
retryAfter: response.retryAfter
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
_ -> continue
|
|
336
|
-
}
|
|
337
|
-
```
|