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,645 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action and step parsing
|
|
3
|
+
* Handles parsing of action definitions and all step types.
|
|
4
|
+
*/
|
|
5
|
+
import { TokenType, } from 'vague-lang';
|
|
6
|
+
import { ReqonTokenType } from '../lexer/tokens.js';
|
|
7
|
+
import { FetchParser } from './fetch-parser.js';
|
|
8
|
+
export class ActionParser extends FetchParser {
|
|
9
|
+
/**
|
|
10
|
+
* Parse a store definition
|
|
11
|
+
*/
|
|
12
|
+
parseStoreDefinition() {
|
|
13
|
+
this.consume(ReqonTokenType.STORE, "Expected 'store'");
|
|
14
|
+
const name = this.consumeIdentifier('Expected store name').value;
|
|
15
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
16
|
+
let storeType;
|
|
17
|
+
const typeToken = this.advance();
|
|
18
|
+
switch (typeToken.type) {
|
|
19
|
+
case ReqonTokenType.NOSQL:
|
|
20
|
+
storeType = 'nosql';
|
|
21
|
+
break;
|
|
22
|
+
case ReqonTokenType.SQL:
|
|
23
|
+
storeType = 'sql';
|
|
24
|
+
break;
|
|
25
|
+
case ReqonTokenType.MEMORY:
|
|
26
|
+
storeType = 'memory';
|
|
27
|
+
break;
|
|
28
|
+
case ReqonTokenType.FILE:
|
|
29
|
+
storeType = 'file';
|
|
30
|
+
break;
|
|
31
|
+
case ReqonTokenType.POSTGREST:
|
|
32
|
+
storeType = 'postgrest';
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
throw this.error(`Unknown store type: ${typeToken.value}`);
|
|
36
|
+
}
|
|
37
|
+
this.consume(TokenType.LPAREN, "Expected '('");
|
|
38
|
+
const target = this.consume(TokenType.STRING, 'Expected target name').value;
|
|
39
|
+
this.consume(TokenType.RPAREN, "Expected ')'");
|
|
40
|
+
return { type: 'StoreDefinition', name, storeType, target };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse an action definition
|
|
44
|
+
*/
|
|
45
|
+
parseAction() {
|
|
46
|
+
this.consume(ReqonTokenType.ACTION, "Expected 'action'");
|
|
47
|
+
const name = this.consume(TokenType.IDENTIFIER, 'Expected action name').value;
|
|
48
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
49
|
+
const steps = [];
|
|
50
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
51
|
+
steps.push(this.parseActionStep());
|
|
52
|
+
this.match(TokenType.COMMA);
|
|
53
|
+
}
|
|
54
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
55
|
+
return { type: 'ActionDefinition', name, steps };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Parse a single action step
|
|
59
|
+
*/
|
|
60
|
+
parseActionStep() {
|
|
61
|
+
if (this.check(ReqonTokenType.CALL))
|
|
62
|
+
return this.parseCallStep();
|
|
63
|
+
// Shorthand: get "/path", post "/path", etc.
|
|
64
|
+
if (this.checkHttpMethod())
|
|
65
|
+
return this.parseHttpMethodStep();
|
|
66
|
+
if (this.check(ReqonTokenType.FOR))
|
|
67
|
+
return this.parseForStep();
|
|
68
|
+
if (this.check(ReqonTokenType.MAP))
|
|
69
|
+
return this.parseMapStep();
|
|
70
|
+
if (this.check(ReqonTokenType.APPLY))
|
|
71
|
+
return this.parseApplyStep();
|
|
72
|
+
if (this.check(TokenType.VALIDATE))
|
|
73
|
+
return this.parseValidateStep();
|
|
74
|
+
if (this.check(ReqonTokenType.STORE))
|
|
75
|
+
return this.parseStoreStep();
|
|
76
|
+
if (this.check(TokenType.MATCH))
|
|
77
|
+
return this.parseMatchStep();
|
|
78
|
+
if (this.check(TokenType.LET))
|
|
79
|
+
return this.parseLetStep();
|
|
80
|
+
if (this.check(ReqonTokenType.WAIT))
|
|
81
|
+
return this.parseWaitStep();
|
|
82
|
+
if (this.check(ReqonTokenType.PAUSE))
|
|
83
|
+
return this.parsePauseStep();
|
|
84
|
+
throw this.error(`Expected action step, got: ${this.peek().value}`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parse a for loop step
|
|
88
|
+
*/
|
|
89
|
+
parseForStep() {
|
|
90
|
+
this.consume(ReqonTokenType.FOR, "Expected 'for'");
|
|
91
|
+
const variable = this.consumeIdentifier('Expected variable name').value;
|
|
92
|
+
this.consume(TokenType.IN, "Expected 'in'");
|
|
93
|
+
const collection = this.parseExpression();
|
|
94
|
+
let condition;
|
|
95
|
+
if (this.match(TokenType.WHERE)) {
|
|
96
|
+
condition = this.parseExpression();
|
|
97
|
+
}
|
|
98
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
99
|
+
const steps = [];
|
|
100
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
101
|
+
steps.push(this.parseActionStep());
|
|
102
|
+
this.match(TokenType.COMMA);
|
|
103
|
+
}
|
|
104
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
105
|
+
return { type: 'ForStep', variable, collection, condition, steps };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Parse a map step
|
|
109
|
+
*/
|
|
110
|
+
parseMapStep() {
|
|
111
|
+
this.consume(ReqonTokenType.MAP, "Expected 'map'");
|
|
112
|
+
const source = this.parseExpression();
|
|
113
|
+
this.consume(TokenType.RIGHT_ARROW, "Expected '->'");
|
|
114
|
+
const targetSchema = this.consume(TokenType.IDENTIFIER, 'Expected target schema').value;
|
|
115
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
116
|
+
const mappings = [];
|
|
117
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
118
|
+
const field = this.consumeName('Expected field name').value;
|
|
119
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
120
|
+
const expression = this.parseExpression();
|
|
121
|
+
mappings.push({ field, expression });
|
|
122
|
+
this.match(TokenType.COMMA);
|
|
123
|
+
}
|
|
124
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
125
|
+
return { type: 'MapStep', source, targetSchema, mappings };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Parse a transform definition
|
|
129
|
+
*/
|
|
130
|
+
parseTransform() {
|
|
131
|
+
this.consume(ReqonTokenType.TRANSFORM, "Expected 'transform'");
|
|
132
|
+
const name = this.consume(TokenType.IDENTIFIER, 'Expected transform name').value;
|
|
133
|
+
const variants = [];
|
|
134
|
+
// Check for simple syntax: transform Name: Source -> Target { ... }
|
|
135
|
+
// or: transform Name -> Target { ... }
|
|
136
|
+
if (this.match(TokenType.COLON)) {
|
|
137
|
+
// Simple syntax with explicit source schema
|
|
138
|
+
const sourceSchema = this.consume(TokenType.IDENTIFIER, 'Expected source schema').value;
|
|
139
|
+
this.consume(TokenType.RIGHT_ARROW, "Expected '->'");
|
|
140
|
+
const targetSchema = this.consume(TokenType.IDENTIFIER, 'Expected target schema').value;
|
|
141
|
+
const mappings = this.parseFieldMappings();
|
|
142
|
+
variants.push({ sourceSchema, targetSchema, mappings });
|
|
143
|
+
}
|
|
144
|
+
else if (this.match(TokenType.RIGHT_ARROW)) {
|
|
145
|
+
// Simple syntax without explicit source (inferred at runtime)
|
|
146
|
+
const targetSchema = this.consume(TokenType.IDENTIFIER, 'Expected target schema').value;
|
|
147
|
+
const mappings = this.parseFieldMappings();
|
|
148
|
+
variants.push({ sourceSchema: '_', targetSchema, mappings });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Overloaded syntax: multiple variants
|
|
152
|
+
this.consume(TokenType.LBRACE, "Expected '{' for transform variants");
|
|
153
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
154
|
+
const variant = this.parseTransformVariant();
|
|
155
|
+
variants.push(variant);
|
|
156
|
+
this.match(TokenType.COMMA);
|
|
157
|
+
}
|
|
158
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
159
|
+
}
|
|
160
|
+
if (variants.length === 0) {
|
|
161
|
+
throw this.error('Transform must have at least one variant');
|
|
162
|
+
}
|
|
163
|
+
// Validate: all variants must have the same target schema
|
|
164
|
+
const targetSchemas = new Set(variants.map((v) => v.targetSchema));
|
|
165
|
+
if (targetSchemas.size > 1) {
|
|
166
|
+
throw this.error(`All transform variants must have the same target schema. Found: ${[...targetSchemas].join(', ')}`);
|
|
167
|
+
}
|
|
168
|
+
return { type: 'TransformDefinition', name, variants };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Parse a single transform variant
|
|
172
|
+
*/
|
|
173
|
+
parseTransformVariant() {
|
|
174
|
+
this.consume(TokenType.LPAREN, "Expected '(' for variant source schema");
|
|
175
|
+
// Source schema: identifier or '_' for wildcard
|
|
176
|
+
let sourceSchema;
|
|
177
|
+
if (this.check(TokenType.IDENTIFIER)) {
|
|
178
|
+
sourceSchema = this.advance().value;
|
|
179
|
+
}
|
|
180
|
+
else if (this.peek().value === '_') {
|
|
181
|
+
this.advance();
|
|
182
|
+
sourceSchema = '_';
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
throw this.error('Expected schema name or _ for wildcard');
|
|
186
|
+
}
|
|
187
|
+
this.consume(TokenType.RPAREN, "Expected ')'");
|
|
188
|
+
// Optional guard condition: where condition
|
|
189
|
+
let guard;
|
|
190
|
+
if (this.match(TokenType.WHERE)) {
|
|
191
|
+
guard = this.parseExpression();
|
|
192
|
+
}
|
|
193
|
+
this.consume(TokenType.RIGHT_ARROW, "Expected '->'");
|
|
194
|
+
const targetSchema = this.consume(TokenType.IDENTIFIER, 'Expected target schema').value;
|
|
195
|
+
const mappings = this.parseFieldMappings();
|
|
196
|
+
return { sourceSchema, targetSchema, guard, mappings };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Parse field mappings: { field: expression, ... }
|
|
200
|
+
*/
|
|
201
|
+
parseFieldMappings() {
|
|
202
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
203
|
+
const mappings = [];
|
|
204
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
205
|
+
const field = this.consumeName('Expected field name').value;
|
|
206
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
207
|
+
const expression = this.parseExpression();
|
|
208
|
+
mappings.push({ field, expression });
|
|
209
|
+
this.match(TokenType.COMMA);
|
|
210
|
+
}
|
|
211
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
212
|
+
return mappings;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Parse apply step: apply TransformName to expression [as variableName]
|
|
216
|
+
*/
|
|
217
|
+
parseApplyStep() {
|
|
218
|
+
this.consume(ReqonTokenType.APPLY, "Expected 'apply'");
|
|
219
|
+
const transform = this.consume(TokenType.IDENTIFIER, 'Expected transform name').value;
|
|
220
|
+
this.consume(ReqonTokenType.TO, "Expected 'to'");
|
|
221
|
+
const source = this.parseExpression();
|
|
222
|
+
// Optional: as variableName
|
|
223
|
+
let as;
|
|
224
|
+
if (this.match(ReqonTokenType.AS)) {
|
|
225
|
+
as = this.consume(TokenType.IDENTIFIER, 'Expected variable name').value;
|
|
226
|
+
}
|
|
227
|
+
return { type: 'ApplyStep', transform, source, as };
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Parse validate step
|
|
231
|
+
*/
|
|
232
|
+
parseValidateStep() {
|
|
233
|
+
this.consume(TokenType.VALIDATE, "Expected 'validate'");
|
|
234
|
+
const target = this.parseExpression();
|
|
235
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
236
|
+
const constraints = [];
|
|
237
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
238
|
+
this.consume(TokenType.ASSUME, "Expected 'assume'");
|
|
239
|
+
const condition = this.parseExpression();
|
|
240
|
+
let message;
|
|
241
|
+
const severity = 'error';
|
|
242
|
+
constraints.push({ type: 'ValidationConstraint', condition, message, severity });
|
|
243
|
+
this.match(TokenType.COMMA);
|
|
244
|
+
}
|
|
245
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
246
|
+
return { type: 'ValidateStep', target, constraints };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Parse store step
|
|
250
|
+
*/
|
|
251
|
+
parseStoreStep() {
|
|
252
|
+
this.consume(ReqonTokenType.STORE, "Expected 'store'");
|
|
253
|
+
// Check for 'each' keyword (consume but not used yet - reserved for future)
|
|
254
|
+
this.match(ReqonTokenType.EACH);
|
|
255
|
+
const source = this.parseExpression();
|
|
256
|
+
this.consume(TokenType.RIGHT_ARROW, "Expected '->'");
|
|
257
|
+
const target = this.consumeIdentifier('Expected store name').value;
|
|
258
|
+
const options = {};
|
|
259
|
+
if (this.match(TokenType.LBRACE)) {
|
|
260
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
261
|
+
const key = this.parseStoreOptionKey();
|
|
262
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
263
|
+
switch (key) {
|
|
264
|
+
case 'key':
|
|
265
|
+
options.key = this.parseExpression();
|
|
266
|
+
break;
|
|
267
|
+
case 'partial':
|
|
268
|
+
options.partial = this.match(TokenType.TRUE);
|
|
269
|
+
if (!options.partial) {
|
|
270
|
+
this.consume(TokenType.FALSE, "Expected 'true' or 'false'");
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
273
|
+
case 'upsert':
|
|
274
|
+
options.upsert = this.match(TokenType.TRUE);
|
|
275
|
+
if (!options.upsert) {
|
|
276
|
+
this.consume(TokenType.FALSE, "Expected 'true' or 'false'");
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
this.match(TokenType.COMMA);
|
|
281
|
+
}
|
|
282
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
283
|
+
}
|
|
284
|
+
return { type: 'StoreStep', source, target, options };
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Parse a store option key, handling keyword tokens
|
|
288
|
+
*/
|
|
289
|
+
parseStoreOptionKey() {
|
|
290
|
+
if (this.check(ReqonTokenType.KEY)) {
|
|
291
|
+
this.advance();
|
|
292
|
+
return 'key';
|
|
293
|
+
}
|
|
294
|
+
else if (this.check(ReqonTokenType.PARTIAL)) {
|
|
295
|
+
this.advance();
|
|
296
|
+
return 'partial';
|
|
297
|
+
}
|
|
298
|
+
else if (this.check(ReqonTokenType.UPSERT)) {
|
|
299
|
+
this.advance();
|
|
300
|
+
return 'upsert';
|
|
301
|
+
}
|
|
302
|
+
return this.consume(TokenType.IDENTIFIER, 'Expected option key').value;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Parse match step (schema overloading)
|
|
306
|
+
*/
|
|
307
|
+
parseMatchStep() {
|
|
308
|
+
this.consume(TokenType.MATCH, "Expected 'match'");
|
|
309
|
+
const target = this.parseExpression();
|
|
310
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
311
|
+
const arms = [];
|
|
312
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
313
|
+
arms.push(this.parseMatchArm());
|
|
314
|
+
this.match(TokenType.COMMA);
|
|
315
|
+
}
|
|
316
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
317
|
+
return { type: 'MatchStep', target, arms };
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Parse a match arm
|
|
321
|
+
*/
|
|
322
|
+
parseMatchArm() {
|
|
323
|
+
// Schema name or '_' for wildcard
|
|
324
|
+
const schema = this.consume(TokenType.IDENTIFIER, 'Expected schema name or _').value;
|
|
325
|
+
// Optional guard condition: _ where <condition>
|
|
326
|
+
let guard;
|
|
327
|
+
if (this.match(TokenType.WHERE)) {
|
|
328
|
+
guard = this.parseExpression();
|
|
329
|
+
}
|
|
330
|
+
this.consume(TokenType.RIGHT_ARROW, "Expected '->'");
|
|
331
|
+
// Check for flow directives
|
|
332
|
+
const flow = this.tryParseFlowDirective();
|
|
333
|
+
if (flow) {
|
|
334
|
+
return { schema, guard, flow };
|
|
335
|
+
}
|
|
336
|
+
// Check for step block
|
|
337
|
+
if (this.check(TokenType.LBRACE)) {
|
|
338
|
+
this.advance();
|
|
339
|
+
const steps = [];
|
|
340
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
341
|
+
steps.push(this.parseActionStep());
|
|
342
|
+
this.match(TokenType.COMMA);
|
|
343
|
+
}
|
|
344
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
345
|
+
return { schema, guard, steps };
|
|
346
|
+
}
|
|
347
|
+
// Single step
|
|
348
|
+
const step = this.parseActionStep();
|
|
349
|
+
return { schema, guard, steps: [step] };
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Try to parse a flow directive
|
|
353
|
+
*/
|
|
354
|
+
tryParseFlowDirective() {
|
|
355
|
+
if (this.match(ReqonTokenType.CONTINUE)) {
|
|
356
|
+
return { type: 'continue' };
|
|
357
|
+
}
|
|
358
|
+
if (this.match(ReqonTokenType.SKIP)) {
|
|
359
|
+
return { type: 'skip' };
|
|
360
|
+
}
|
|
361
|
+
if (this.match(ReqonTokenType.ABORT)) {
|
|
362
|
+
let message;
|
|
363
|
+
if (this.check(TokenType.STRING)) {
|
|
364
|
+
message = this.advance().value;
|
|
365
|
+
}
|
|
366
|
+
return { type: 'abort', message };
|
|
367
|
+
}
|
|
368
|
+
if (this.match(ReqonTokenType.RETRY)) {
|
|
369
|
+
let backoff;
|
|
370
|
+
if (this.check(TokenType.LBRACE)) {
|
|
371
|
+
backoff = this.parseRetryConfig();
|
|
372
|
+
}
|
|
373
|
+
return { type: 'retry', backoff };
|
|
374
|
+
}
|
|
375
|
+
if (this.match(ReqonTokenType.QUEUE)) {
|
|
376
|
+
let target;
|
|
377
|
+
if (this.check(TokenType.IDENTIFIER)) {
|
|
378
|
+
target = this.advance().value;
|
|
379
|
+
}
|
|
380
|
+
return { type: 'queue', target };
|
|
381
|
+
}
|
|
382
|
+
if (this.match(ReqonTokenType.JUMP)) {
|
|
383
|
+
const action = this.consume(TokenType.IDENTIFIER, 'Expected action name').value;
|
|
384
|
+
let then;
|
|
385
|
+
if (this.match(TokenType.THEN)) {
|
|
386
|
+
if (this.match(ReqonTokenType.RETRY)) {
|
|
387
|
+
then = 'retry';
|
|
388
|
+
}
|
|
389
|
+
else if (this.match(ReqonTokenType.CONTINUE)) {
|
|
390
|
+
then = 'continue';
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
throw this.error("Expected 'retry' or 'continue' after 'then'");
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return { type: 'jump', action, then };
|
|
397
|
+
}
|
|
398
|
+
return undefined;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Parse let step (variable binding)
|
|
402
|
+
*/
|
|
403
|
+
parseLetStep() {
|
|
404
|
+
this.consume(TokenType.LET, "Expected 'let'");
|
|
405
|
+
const name = this.consumeIdentifier('Expected variable name').value;
|
|
406
|
+
this.consume(TokenType.EQUALS, "Expected '='");
|
|
407
|
+
const value = this.parseExpression();
|
|
408
|
+
return { type: 'LetStep', name, value };
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Parse wait step (webhook support)
|
|
412
|
+
*/
|
|
413
|
+
parseWaitStep() {
|
|
414
|
+
this.consume(ReqonTokenType.WAIT, "Expected 'wait'");
|
|
415
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
416
|
+
const step = { type: 'WebhookStep' };
|
|
417
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
418
|
+
const key = this.parseWaitOptionKey();
|
|
419
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
420
|
+
switch (key) {
|
|
421
|
+
case 'timeout':
|
|
422
|
+
step.timeout = parseInt(this.consume(TokenType.NUMBER, 'Expected timeout value').value, 10);
|
|
423
|
+
break;
|
|
424
|
+
case 'path':
|
|
425
|
+
step.path = this.consume(TokenType.STRING, 'Expected path string').value;
|
|
426
|
+
break;
|
|
427
|
+
case 'expectedEvents':
|
|
428
|
+
step.expectedEvents = parseInt(this.consume(TokenType.NUMBER, 'Expected number').value, 10);
|
|
429
|
+
break;
|
|
430
|
+
case 'eventFilter':
|
|
431
|
+
step.eventFilter = this.parseExpression();
|
|
432
|
+
break;
|
|
433
|
+
case 'retry':
|
|
434
|
+
step.retryOnTimeout = this.parseRetryConfig();
|
|
435
|
+
break;
|
|
436
|
+
case 'storage':
|
|
437
|
+
step.storage = this.parseWebhookStorageConfig();
|
|
438
|
+
break;
|
|
439
|
+
default:
|
|
440
|
+
throw this.error(`Unknown wait option: ${key}`);
|
|
441
|
+
}
|
|
442
|
+
this.match(TokenType.COMMA);
|
|
443
|
+
}
|
|
444
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
445
|
+
return step;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Parse a wait option key, handling keyword tokens
|
|
449
|
+
*/
|
|
450
|
+
parseWaitOptionKey() {
|
|
451
|
+
if (this.check(ReqonTokenType.TIMEOUT)) {
|
|
452
|
+
this.advance();
|
|
453
|
+
return 'timeout';
|
|
454
|
+
}
|
|
455
|
+
else if (this.check(ReqonTokenType.PATH)) {
|
|
456
|
+
this.advance();
|
|
457
|
+
return 'path';
|
|
458
|
+
}
|
|
459
|
+
else if (this.check(ReqonTokenType.EXPECTED_EVENTS)) {
|
|
460
|
+
this.advance();
|
|
461
|
+
return 'expectedEvents';
|
|
462
|
+
}
|
|
463
|
+
else if (this.check(ReqonTokenType.EVENT_FILTER)) {
|
|
464
|
+
this.advance();
|
|
465
|
+
return 'eventFilter';
|
|
466
|
+
}
|
|
467
|
+
else if (this.check(ReqonTokenType.RETRY)) {
|
|
468
|
+
this.advance();
|
|
469
|
+
return 'retry';
|
|
470
|
+
}
|
|
471
|
+
else if (this.check(ReqonTokenType.STORAGE)) {
|
|
472
|
+
this.advance();
|
|
473
|
+
return 'storage';
|
|
474
|
+
}
|
|
475
|
+
return this.consume(TokenType.IDENTIFIER, 'Expected option key').value;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Parse webhook storage config
|
|
479
|
+
*/
|
|
480
|
+
parseWebhookStorageConfig() {
|
|
481
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
482
|
+
let target;
|
|
483
|
+
let key;
|
|
484
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
485
|
+
let optionKey;
|
|
486
|
+
if (this.check(ReqonTokenType.KEY)) {
|
|
487
|
+
this.advance();
|
|
488
|
+
optionKey = 'key';
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
optionKey = this.consume(TokenType.IDENTIFIER, 'Expected option key').value;
|
|
492
|
+
}
|
|
493
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
494
|
+
switch (optionKey) {
|
|
495
|
+
case 'target':
|
|
496
|
+
target = this.consume(TokenType.IDENTIFIER, 'Expected store name').value;
|
|
497
|
+
break;
|
|
498
|
+
case 'key':
|
|
499
|
+
key = this.parseExpression();
|
|
500
|
+
break;
|
|
501
|
+
default:
|
|
502
|
+
throw this.error(`Unknown storage option: ${optionKey}`);
|
|
503
|
+
}
|
|
504
|
+
this.match(TokenType.COMMA);
|
|
505
|
+
}
|
|
506
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
507
|
+
if (!target) {
|
|
508
|
+
throw this.error('Webhook storage must have a target store');
|
|
509
|
+
}
|
|
510
|
+
return { target, key };
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Parse pause step: pause { duration: "7d", persist: FileStore, resume-on: timeout | webhook "/path" }
|
|
514
|
+
*/
|
|
515
|
+
parsePauseStep() {
|
|
516
|
+
this.consume(ReqonTokenType.PAUSE, "Expected 'pause'");
|
|
517
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
518
|
+
let duration;
|
|
519
|
+
let persist;
|
|
520
|
+
let resumeOn;
|
|
521
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
522
|
+
const key = this.parsePauseOptionKey();
|
|
523
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
524
|
+
switch (key) {
|
|
525
|
+
case 'duration':
|
|
526
|
+
if (this.check(TokenType.STRING)) {
|
|
527
|
+
duration = this.advance().value;
|
|
528
|
+
}
|
|
529
|
+
else if (this.check(TokenType.NUMBER)) {
|
|
530
|
+
duration = parseInt(this.advance().value, 10);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
throw this.error('Expected duration string or number');
|
|
534
|
+
}
|
|
535
|
+
break;
|
|
536
|
+
case 'persist':
|
|
537
|
+
persist = this.consume(TokenType.IDENTIFIER, 'Expected store name').value;
|
|
538
|
+
break;
|
|
539
|
+
case 'resumeOn':
|
|
540
|
+
resumeOn = this.parsePauseResumeTriggers();
|
|
541
|
+
break;
|
|
542
|
+
default:
|
|
543
|
+
throw this.error(`Unknown pause option: ${key}`);
|
|
544
|
+
}
|
|
545
|
+
this.match(TokenType.COMMA);
|
|
546
|
+
}
|
|
547
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
548
|
+
if (duration === undefined) {
|
|
549
|
+
throw this.error('Pause step requires a duration');
|
|
550
|
+
}
|
|
551
|
+
return { type: 'PauseStep', duration, persist, resumeOn };
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Parse pause option key, handling keyword tokens
|
|
555
|
+
*/
|
|
556
|
+
parsePauseOptionKey() {
|
|
557
|
+
if (this.check(ReqonTokenType.DURATION)) {
|
|
558
|
+
this.advance();
|
|
559
|
+
return 'duration';
|
|
560
|
+
}
|
|
561
|
+
else if (this.check(ReqonTokenType.PERSIST)) {
|
|
562
|
+
this.advance();
|
|
563
|
+
return 'persist';
|
|
564
|
+
}
|
|
565
|
+
else if (this.check(ReqonTokenType.RESUME_ON)) {
|
|
566
|
+
this.advance();
|
|
567
|
+
return 'resumeOn';
|
|
568
|
+
}
|
|
569
|
+
return this.consume(TokenType.IDENTIFIER, 'Expected option key').value;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Parse pause resume triggers: timeout | webhook "/path"
|
|
573
|
+
*/
|
|
574
|
+
parsePauseResumeTriggers() {
|
|
575
|
+
const triggers = [];
|
|
576
|
+
do {
|
|
577
|
+
if (this.check(ReqonTokenType.TIMEOUT)) {
|
|
578
|
+
this.advance();
|
|
579
|
+
triggers.push({ type: 'timeout' });
|
|
580
|
+
}
|
|
581
|
+
else if (this.check(ReqonTokenType.WAIT)) {
|
|
582
|
+
// 'wait' keyword for webhook trigger (reusing wait keyword)
|
|
583
|
+
this.advance();
|
|
584
|
+
const path = this.consume(TokenType.STRING, 'Expected webhook path').value;
|
|
585
|
+
let eventFilter;
|
|
586
|
+
if (this.match(TokenType.WHERE)) {
|
|
587
|
+
eventFilter = this.parseExpression();
|
|
588
|
+
}
|
|
589
|
+
triggers.push({ type: 'webhook', path, eventFilter });
|
|
590
|
+
}
|
|
591
|
+
else if (this.peek().value === 'webhook') {
|
|
592
|
+
// Allow 'webhook' as an identifier too
|
|
593
|
+
this.advance();
|
|
594
|
+
const path = this.consume(TokenType.STRING, 'Expected webhook path').value;
|
|
595
|
+
let eventFilter;
|
|
596
|
+
if (this.match(TokenType.WHERE)) {
|
|
597
|
+
eventFilter = this.parseExpression();
|
|
598
|
+
}
|
|
599
|
+
triggers.push({ type: 'webhook', path, eventFilter });
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
throw this.error('Expected timeout or webhook trigger');
|
|
603
|
+
}
|
|
604
|
+
} while (this.match(TokenType.PIPE)); // Allow: timeout | webhook "/path"
|
|
605
|
+
return triggers;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Parse a schema definition
|
|
609
|
+
*/
|
|
610
|
+
parseSchema() {
|
|
611
|
+
this.consume(TokenType.SCHEMA, "Expected 'schema'");
|
|
612
|
+
const name = this.consume(TokenType.IDENTIFIER, 'Expected schema name').value;
|
|
613
|
+
this.consume(TokenType.LBRACE, "Expected '{'");
|
|
614
|
+
const fields = [];
|
|
615
|
+
while (!this.check(TokenType.RBRACE) && !this.isAtEnd()) {
|
|
616
|
+
fields.push(this.parseFieldDefinition());
|
|
617
|
+
this.match(TokenType.COMMA);
|
|
618
|
+
}
|
|
619
|
+
this.consume(TokenType.RBRACE, "Expected '}'");
|
|
620
|
+
return {
|
|
621
|
+
type: 'SchemaDefinition',
|
|
622
|
+
name,
|
|
623
|
+
fields,
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Parse a field definition
|
|
628
|
+
*/
|
|
629
|
+
parseFieldDefinition() {
|
|
630
|
+
const name = this.consumeIdentifier('Expected field name').value;
|
|
631
|
+
this.consume(TokenType.COLON, "Expected ':'");
|
|
632
|
+
// Simplified field type parsing
|
|
633
|
+
const typeName = this.consume(TokenType.IDENTIFIER, 'Expected type').value;
|
|
634
|
+
// Handle optional/nullable type marker (?)
|
|
635
|
+
this.match(TokenType.QUESTION);
|
|
636
|
+
return {
|
|
637
|
+
type: 'FieldDefinition',
|
|
638
|
+
name,
|
|
639
|
+
fieldType: {
|
|
640
|
+
type: 'PrimitiveType',
|
|
641
|
+
name: typeName,
|
|
642
|
+
},
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
}
|
package/dist/parser/base.d.ts
CHANGED
|
@@ -21,6 +21,13 @@ export declare class ReqonParserBase {
|
|
|
21
21
|
* This is needed because 'get', 'post', etc. are valid variable/store names.
|
|
22
22
|
*/
|
|
23
23
|
protected consumeIdentifier(message: string): Token;
|
|
24
|
+
/**
|
|
25
|
+
* Consume a token in name/property position (after a dot, a map/transform field
|
|
26
|
+
* name, or the type name after `is`). Any reserved keyword's text is a valid name
|
|
27
|
+
* here because the position is unambiguous, so accept any non-EOF token and return
|
|
28
|
+
* it by value.
|
|
29
|
+
*/
|
|
30
|
+
protected consumeName(message: string): Token;
|
|
24
31
|
/**
|
|
25
32
|
* Check if current token is an identifier (including HTTP methods as identifiers)
|
|
26
33
|
*/
|
package/dist/parser/base.js
CHANGED
|
@@ -66,6 +66,17 @@ export class ReqonParserBase {
|
|
|
66
66
|
}
|
|
67
67
|
throw this.error(message);
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Consume a token in name/property position (after a dot, a map/transform field
|
|
71
|
+
* name, or the type name after `is`). Any reserved keyword's text is a valid name
|
|
72
|
+
* here because the position is unambiguous, so accept any non-EOF token and return
|
|
73
|
+
* it by value.
|
|
74
|
+
*/
|
|
75
|
+
consumeName(message) {
|
|
76
|
+
if (this.isAtEnd())
|
|
77
|
+
throw this.error(message);
|
|
78
|
+
return this.advance();
|
|
79
|
+
}
|
|
69
80
|
/**
|
|
70
81
|
* Check if current token is an identifier (including HTTP methods as identifiers)
|
|
71
82
|
*/
|