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,504 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Reqon MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes Reqon pipeline capabilities via the Model Context Protocol.
|
|
6
|
+
*
|
|
7
|
+
* Tools:
|
|
8
|
+
* - reqon.execute: Execute a mission from DSL source
|
|
9
|
+
* - reqon.execute_file: Execute a mission from a file/folder path
|
|
10
|
+
* - reqon.query_store: Query data from a named store
|
|
11
|
+
* - reqon.list_stores: List available stores
|
|
12
|
+
*
|
|
13
|
+
* Resources:
|
|
14
|
+
* - reqon://stores - List all stores
|
|
15
|
+
* - reqon://stores/{name} - Access store data
|
|
16
|
+
*/
|
|
17
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
19
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
import { z } from 'zod';
|
|
21
|
+
import { resolveWithinWorkingDir as confinePath, resolveDryRun, withTimeout, isStoreTypeAllowed, DEFAULT_EXECUTION_TIMEOUT_MS, } from './sandbox.js';
|
|
22
|
+
import { parse, execute, fromPath } from '../index.js';
|
|
23
|
+
import { createStore } from '../stores/index.js';
|
|
24
|
+
// Global store registry for cross-execution access
|
|
25
|
+
const storeRegistry = new Map();
|
|
26
|
+
const serverConfig = {
|
|
27
|
+
workingDirectory: process.cwd(),
|
|
28
|
+
verbose: false,
|
|
29
|
+
allowEffects: false,
|
|
30
|
+
executionTimeoutMs: DEFAULT_EXECUTION_TIMEOUT_MS,
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Resolve an untrusted path against the configured working directory and
|
|
34
|
+
* assert it stays inside it. Blocks `../` / absolute-path escapes.
|
|
35
|
+
*/
|
|
36
|
+
function resolveWithinWorkingDir(p) {
|
|
37
|
+
return confinePath(serverConfig.workingDirectory ?? process.cwd(), p);
|
|
38
|
+
}
|
|
39
|
+
// Argument schemas (validated against each tool's inputSchema via zod).
|
|
40
|
+
const executeArgsSchema = z.object({
|
|
41
|
+
source: z.string(),
|
|
42
|
+
verbose: z.boolean().optional(),
|
|
43
|
+
dryRun: z.boolean().optional(),
|
|
44
|
+
});
|
|
45
|
+
const executeFileArgsSchema = z.object({
|
|
46
|
+
path: z.string(),
|
|
47
|
+
verbose: z.boolean().optional(),
|
|
48
|
+
dryRun: z.boolean().optional(),
|
|
49
|
+
});
|
|
50
|
+
const registerStoreArgsSchema = z.object({
|
|
51
|
+
name: z.string(),
|
|
52
|
+
type: z.enum(['memory', 'file']).optional(),
|
|
53
|
+
path: z.string().optional(),
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Format execution result for MCP response
|
|
57
|
+
*/
|
|
58
|
+
function formatExecutionResult(result) {
|
|
59
|
+
const output = {
|
|
60
|
+
success: result.success,
|
|
61
|
+
duration: result.duration,
|
|
62
|
+
actionsRun: result.actionsRun,
|
|
63
|
+
};
|
|
64
|
+
if (result.errors && result.errors.length > 0) {
|
|
65
|
+
output.errors = result.errors.map((e) => ({
|
|
66
|
+
action: e.action,
|
|
67
|
+
step: e.step,
|
|
68
|
+
message: e.message,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
// Include store summaries
|
|
72
|
+
if (result.stores && result.stores.size > 0) {
|
|
73
|
+
output.stores = Array.from(result.stores.keys());
|
|
74
|
+
}
|
|
75
|
+
if (result.executionId) {
|
|
76
|
+
output.executionId = result.executionId;
|
|
77
|
+
}
|
|
78
|
+
return JSON.stringify(output, null, 2);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create executor config
|
|
82
|
+
*/
|
|
83
|
+
function createExecutorConfig(options) {
|
|
84
|
+
// Effects are opt-in at the server level. When disabled, force dryRun so an
|
|
85
|
+
// untrusted mission cannot reach the network or write to disk, regardless of
|
|
86
|
+
// what the caller requests.
|
|
87
|
+
return {
|
|
88
|
+
verbose: options?.verbose ?? serverConfig.verbose,
|
|
89
|
+
dryRun: resolveDryRun(serverConfig.allowEffects ?? false, options?.dryRun),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Define available tools
|
|
93
|
+
const tools = [
|
|
94
|
+
{
|
|
95
|
+
name: 'reqon.execute',
|
|
96
|
+
description: 'Execute a Reqon mission from DSL source code. Returns execution results including any stored data.',
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
source: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
description: 'Reqon DSL source code defining the mission',
|
|
103
|
+
},
|
|
104
|
+
verbose: {
|
|
105
|
+
type: 'boolean',
|
|
106
|
+
description: 'Enable verbose logging',
|
|
107
|
+
default: false,
|
|
108
|
+
},
|
|
109
|
+
dryRun: {
|
|
110
|
+
type: 'boolean',
|
|
111
|
+
description: 'Validate without executing HTTP requests',
|
|
112
|
+
default: false,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
required: ['source'],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'reqon.execute_file',
|
|
120
|
+
description: 'Execute a Reqon mission from a file or folder path. Supports both single .reqon files and mission folders.',
|
|
121
|
+
inputSchema: {
|
|
122
|
+
type: 'object',
|
|
123
|
+
properties: {
|
|
124
|
+
path: {
|
|
125
|
+
type: 'string',
|
|
126
|
+
description: 'Path to .reqon file or mission folder (relative to working directory)',
|
|
127
|
+
},
|
|
128
|
+
verbose: {
|
|
129
|
+
type: 'boolean',
|
|
130
|
+
description: 'Enable verbose logging',
|
|
131
|
+
default: false,
|
|
132
|
+
},
|
|
133
|
+
dryRun: {
|
|
134
|
+
type: 'boolean',
|
|
135
|
+
description: 'Validate without executing HTTP requests',
|
|
136
|
+
default: false,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
required: ['path'],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'reqon.parse',
|
|
144
|
+
description: 'Parse Reqon DSL source and return the AST structure. Useful for validation without execution.',
|
|
145
|
+
inputSchema: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
source: {
|
|
149
|
+
type: 'string',
|
|
150
|
+
description: 'Reqon DSL source code to parse',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
required: ['source'],
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'reqon.query_store',
|
|
158
|
+
description: 'Query data from a registered Reqon store. Returns matching records.',
|
|
159
|
+
inputSchema: {
|
|
160
|
+
type: 'object',
|
|
161
|
+
properties: {
|
|
162
|
+
store: {
|
|
163
|
+
type: 'string',
|
|
164
|
+
description: 'Name of the store to query',
|
|
165
|
+
},
|
|
166
|
+
filter: {
|
|
167
|
+
type: 'object',
|
|
168
|
+
description: 'Filter criteria',
|
|
169
|
+
properties: {
|
|
170
|
+
where: {
|
|
171
|
+
type: 'object',
|
|
172
|
+
description: 'Field equality conditions',
|
|
173
|
+
},
|
|
174
|
+
limit: {
|
|
175
|
+
type: 'number',
|
|
176
|
+
description: 'Maximum records to return',
|
|
177
|
+
},
|
|
178
|
+
offset: {
|
|
179
|
+
type: 'number',
|
|
180
|
+
description: 'Number of records to skip',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ['store'],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'reqon.list_stores',
|
|
190
|
+
description: 'List all registered stores and their record counts.',
|
|
191
|
+
inputSchema: {
|
|
192
|
+
type: 'object',
|
|
193
|
+
properties: {},
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: 'reqon.register_store',
|
|
198
|
+
description: 'Register a store for use across executions. Stores persist in memory during the server session.',
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: 'object',
|
|
201
|
+
properties: {
|
|
202
|
+
name: {
|
|
203
|
+
type: 'string',
|
|
204
|
+
description: 'Store name for reference',
|
|
205
|
+
},
|
|
206
|
+
type: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
enum: ['memory', 'file'],
|
|
209
|
+
description: 'Store type',
|
|
210
|
+
default: 'memory',
|
|
211
|
+
},
|
|
212
|
+
path: {
|
|
213
|
+
type: 'string',
|
|
214
|
+
description: 'File path for file-based stores',
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
required: ['name'],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
// Create server instance
|
|
222
|
+
const server = new Server({
|
|
223
|
+
name: 'reqon-mcp-server',
|
|
224
|
+
version: '0.1.0',
|
|
225
|
+
}, {
|
|
226
|
+
capabilities: {
|
|
227
|
+
tools: {},
|
|
228
|
+
resources: {},
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
// Handle tool listing
|
|
232
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
233
|
+
return { tools };
|
|
234
|
+
});
|
|
235
|
+
// Handle tool execution
|
|
236
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
237
|
+
const { name, arguments: args } = request.params;
|
|
238
|
+
try {
|
|
239
|
+
switch (name) {
|
|
240
|
+
case 'reqon.execute': {
|
|
241
|
+
const { source, verbose, dryRun } = executeArgsSchema.parse(args);
|
|
242
|
+
const config = createExecutorConfig({ verbose, dryRun });
|
|
243
|
+
const result = await withTimeout(execute(source, config), serverConfig.executionTimeoutMs ?? DEFAULT_EXECUTION_TIMEOUT_MS);
|
|
244
|
+
return {
|
|
245
|
+
content: [
|
|
246
|
+
{
|
|
247
|
+
type: 'text',
|
|
248
|
+
text: formatExecutionResult(result),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
case 'reqon.execute_file': {
|
|
254
|
+
const { path, verbose, dryRun } = executeFileArgsSchema.parse(args);
|
|
255
|
+
const safePath = resolveWithinWorkingDir(path);
|
|
256
|
+
const config = createExecutorConfig({ verbose, dryRun });
|
|
257
|
+
const result = await withTimeout(fromPath(safePath, config), serverConfig.executionTimeoutMs ?? DEFAULT_EXECUTION_TIMEOUT_MS);
|
|
258
|
+
return {
|
|
259
|
+
content: [
|
|
260
|
+
{
|
|
261
|
+
type: 'text',
|
|
262
|
+
text: formatExecutionResult(result),
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
case 'reqon.parse': {
|
|
268
|
+
const { source } = args;
|
|
269
|
+
const program = parse(source);
|
|
270
|
+
// Summarize AST for readability
|
|
271
|
+
const summary = {
|
|
272
|
+
type: 'ReqonProgram',
|
|
273
|
+
statements: program.statements.length,
|
|
274
|
+
missions: program.statements
|
|
275
|
+
.filter((s) => s.type === 'MissionDefinition')
|
|
276
|
+
.map((m) => ({
|
|
277
|
+
name: m.name,
|
|
278
|
+
sources: m.sources?.length ?? 0,
|
|
279
|
+
stores: m.stores?.length ?? 0,
|
|
280
|
+
actions: m.actions?.length ?? 0,
|
|
281
|
+
hasSchedule: !!m.schedule,
|
|
282
|
+
})),
|
|
283
|
+
};
|
|
284
|
+
return {
|
|
285
|
+
content: [
|
|
286
|
+
{
|
|
287
|
+
type: 'text',
|
|
288
|
+
text: JSON.stringify(summary, null, 2),
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
case 'reqon.query_store': {
|
|
294
|
+
const { store: storeName, filter } = args;
|
|
295
|
+
const store = storeRegistry.get(storeName);
|
|
296
|
+
if (!store) {
|
|
297
|
+
return {
|
|
298
|
+
isError: true,
|
|
299
|
+
content: [
|
|
300
|
+
{
|
|
301
|
+
type: 'text',
|
|
302
|
+
text: `Store "${storeName}" not found. Available stores: ${Array.from(storeRegistry.keys()).join(', ') || '(none)'}`,
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const records = await store.list(filter);
|
|
308
|
+
const count = await store.count(filter);
|
|
309
|
+
return {
|
|
310
|
+
content: [
|
|
311
|
+
{
|
|
312
|
+
type: 'text',
|
|
313
|
+
text: JSON.stringify({
|
|
314
|
+
store: storeName,
|
|
315
|
+
totalMatching: count,
|
|
316
|
+
returned: records.length,
|
|
317
|
+
data: records,
|
|
318
|
+
}, null, 2),
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
case 'reqon.list_stores': {
|
|
324
|
+
const stores = [];
|
|
325
|
+
for (const [name, store] of storeRegistry) {
|
|
326
|
+
const count = await store.count();
|
|
327
|
+
stores.push({ name, count });
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
content: [
|
|
331
|
+
{
|
|
332
|
+
type: 'text',
|
|
333
|
+
text: JSON.stringify({
|
|
334
|
+
stores,
|
|
335
|
+
total: stores.length,
|
|
336
|
+
}, null, 2),
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
case 'reqon.register_store': {
|
|
342
|
+
const { name, type = 'memory', path } = registerStoreArgsSchema.parse(args);
|
|
343
|
+
if (storeRegistry.has(name)) {
|
|
344
|
+
return {
|
|
345
|
+
content: [
|
|
346
|
+
{
|
|
347
|
+
type: 'text',
|
|
348
|
+
text: `Store "${name}" already registered`,
|
|
349
|
+
},
|
|
350
|
+
],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
// A file-backed store writes to disk, which is an effect. Refuse to
|
|
354
|
+
// register one unless effects are explicitly enabled, so a sandboxed
|
|
355
|
+
// (dryRun) server can't be coaxed into persisting data.
|
|
356
|
+
if (!isStoreTypeAllowed(type, serverConfig.allowEffects ?? false)) {
|
|
357
|
+
return {
|
|
358
|
+
isError: true,
|
|
359
|
+
content: [
|
|
360
|
+
{
|
|
361
|
+
type: 'text',
|
|
362
|
+
text: `File-backed stores are disabled in sandboxed mode. Start the server with --allow-effects to register a "file" store, or use type "memory".`,
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
// Confine a file store's base directory to the working directory.
|
|
368
|
+
const baseDir = resolveWithinWorkingDir(path ?? '.reqon-data');
|
|
369
|
+
const store = createStore({
|
|
370
|
+
type,
|
|
371
|
+
name,
|
|
372
|
+
baseDir,
|
|
373
|
+
});
|
|
374
|
+
storeRegistry.set(name, store);
|
|
375
|
+
return {
|
|
376
|
+
content: [
|
|
377
|
+
{
|
|
378
|
+
type: 'text',
|
|
379
|
+
text: `Store "${name}" registered (type: ${type})`,
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
default:
|
|
385
|
+
return {
|
|
386
|
+
isError: true,
|
|
387
|
+
content: [
|
|
388
|
+
{
|
|
389
|
+
type: 'text',
|
|
390
|
+
text: `Unknown tool: ${name}`,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch (error) {
|
|
397
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
398
|
+
return {
|
|
399
|
+
isError: true,
|
|
400
|
+
content: [
|
|
401
|
+
{
|
|
402
|
+
type: 'text',
|
|
403
|
+
text: `Error: ${message}`,
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
// Handle resource listing
|
|
410
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
411
|
+
const resources = [
|
|
412
|
+
{
|
|
413
|
+
uri: 'reqon://stores',
|
|
414
|
+
name: 'Reqon Stores',
|
|
415
|
+
description: 'List of all registered data stores',
|
|
416
|
+
mimeType: 'application/json',
|
|
417
|
+
},
|
|
418
|
+
];
|
|
419
|
+
// Add individual store resources
|
|
420
|
+
for (const name of storeRegistry.keys()) {
|
|
421
|
+
resources.push({
|
|
422
|
+
uri: `reqon://stores/${name}`,
|
|
423
|
+
name: `Store: ${name}`,
|
|
424
|
+
description: `Data from the "${name}" store`,
|
|
425
|
+
mimeType: 'application/json',
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return { resources };
|
|
429
|
+
});
|
|
430
|
+
// Handle resource reading
|
|
431
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
432
|
+
const { uri } = request.params;
|
|
433
|
+
if (uri === 'reqon://stores') {
|
|
434
|
+
const stores = [];
|
|
435
|
+
for (const [name, store] of storeRegistry) {
|
|
436
|
+
const count = await store.count();
|
|
437
|
+
stores.push({ name, count });
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
contents: [
|
|
441
|
+
{
|
|
442
|
+
uri,
|
|
443
|
+
mimeType: 'application/json',
|
|
444
|
+
text: JSON.stringify(stores, null, 2),
|
|
445
|
+
},
|
|
446
|
+
],
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
const storeMatch = uri.match(/^reqon:\/\/stores\/(.+)$/);
|
|
450
|
+
if (storeMatch) {
|
|
451
|
+
const storeName = storeMatch[1];
|
|
452
|
+
const store = storeRegistry.get(storeName);
|
|
453
|
+
if (!store) {
|
|
454
|
+
throw new Error(`Store "${storeName}" not found`);
|
|
455
|
+
}
|
|
456
|
+
const records = await store.list({ limit: 100 });
|
|
457
|
+
const count = await store.count();
|
|
458
|
+
return {
|
|
459
|
+
contents: [
|
|
460
|
+
{
|
|
461
|
+
uri,
|
|
462
|
+
mimeType: 'application/json',
|
|
463
|
+
text: JSON.stringify({
|
|
464
|
+
store: storeName,
|
|
465
|
+
totalRecords: count,
|
|
466
|
+
data: records,
|
|
467
|
+
}, null, 2),
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
473
|
+
});
|
|
474
|
+
// Start server
|
|
475
|
+
async function main() {
|
|
476
|
+
// Parse CLI arguments
|
|
477
|
+
const args = process.argv.slice(2);
|
|
478
|
+
for (let i = 0; i < args.length; i++) {
|
|
479
|
+
if (args[i] === '--verbose' || args[i] === '-v') {
|
|
480
|
+
serverConfig.verbose = true;
|
|
481
|
+
}
|
|
482
|
+
if (args[i] === '--cwd' && args[i + 1]) {
|
|
483
|
+
serverConfig.workingDirectory = args[++i];
|
|
484
|
+
process.chdir(serverConfig.workingDirectory);
|
|
485
|
+
}
|
|
486
|
+
if (args[i] === '--allow-effects') {
|
|
487
|
+
serverConfig.allowEffects = true;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
const transport = new StdioServerTransport();
|
|
491
|
+
await server.connect(transport);
|
|
492
|
+
// Log to stderr so it doesn't interfere with MCP protocol on stdout
|
|
493
|
+
console.error('Reqon MCP Server running on stdio');
|
|
494
|
+
console.error(serverConfig.allowEffects
|
|
495
|
+
? ' Effects ENABLED (--allow-effects): missions may make real network/filesystem calls.'
|
|
496
|
+
: ' Sandboxed: missions run in dryRun (no network/filesystem effects). Pass --allow-effects to enable.');
|
|
497
|
+
if (serverConfig.verbose) {
|
|
498
|
+
console.error(` Working directory: ${serverConfig.workingDirectory}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
main().catch((error) => {
|
|
502
|
+
console.error('Server error:', error);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
});
|
package/dist/oas/index.d.ts
CHANGED
|
@@ -2,3 +2,5 @@ export { loadOAS, resolveOperation, getResponseSchema, clearCache } from './load
|
|
|
2
2
|
export type { OASSource, OASOperation, OpenAPISpec } from './loader.js';
|
|
3
3
|
export { validateResponse } from './validator.js';
|
|
4
4
|
export type { ValidationResult, ValidationError } from './validator.js';
|
|
5
|
+
export { generateMockData } from './mock-generator.js';
|
|
6
|
+
export type { MockGeneratorOptions } from './mock-generator.js';
|
package/dist/oas/index.js
CHANGED
package/dist/oas/loader.d.ts
CHANGED
|
@@ -15,7 +15,19 @@ export interface OASSource {
|
|
|
15
15
|
operations: Map<string, OASOperation>;
|
|
16
16
|
schemas: Map<string, OpenAPIV3.SchemaObject>;
|
|
17
17
|
}
|
|
18
|
-
export
|
|
18
|
+
export interface LoadOASOptions {
|
|
19
|
+
/** Bypass the spec cache and re-parse. */
|
|
20
|
+
forceReload?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Allow `$ref` pointers to external documents, including remote http(s)
|
|
23
|
+
* URLs. Off by default: an OAS spec is often untrusted input, and resolving
|
|
24
|
+
* external $refs lets the parser fetch arbitrary hosts/files — an SSRF and
|
|
25
|
+
* resource-exhaustion sink. When false, only internal `#/...` references are
|
|
26
|
+
* resolved; external ones are not fetched.
|
|
27
|
+
*/
|
|
28
|
+
allowExternalRefs?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function loadOAS(specPath: string, optionsOrForceReload?: LoadOASOptions | boolean): Promise<OASSource>;
|
|
19
31
|
export declare function resolveOperation(source: OASSource, operationId: string): OASOperation;
|
|
20
32
|
export declare function getResponseSchema(source: OASSource, operationId: string, statusCode?: string): OpenAPIV3.SchemaObject | undefined;
|
|
21
33
|
export declare function clearCache(): void;
|
package/dist/oas/loader.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import SwaggerParser from '@apidevtools/swagger-parser';
|
|
2
2
|
// Cache loaded specs to avoid re-parsing
|
|
3
3
|
const specCache = new Map();
|
|
4
|
-
export async function loadOAS(specPath,
|
|
4
|
+
export async function loadOAS(specPath, optionsOrForceReload = {}) {
|
|
5
|
+
// Back-compat: a bare boolean used to mean `forceReload`.
|
|
6
|
+
const options = typeof optionsOrForceReload === 'boolean'
|
|
7
|
+
? { forceReload: optionsOrForceReload }
|
|
8
|
+
: optionsOrForceReload;
|
|
9
|
+
const { forceReload = false, allowExternalRefs = false } = options;
|
|
5
10
|
if (!forceReload && specCache.has(specPath)) {
|
|
6
11
|
return specCache.get(specPath);
|
|
7
12
|
}
|
|
8
|
-
|
|
13
|
+
// Default-deny external reference resolution to prevent SSRF / remote fetches.
|
|
14
|
+
const parserOptions = allowExternalRefs ? {} : { resolve: { external: false } };
|
|
15
|
+
const api = (await SwaggerParser.dereference(specPath, parserOptions));
|
|
9
16
|
const baseUrl = extractBaseUrl(api);
|
|
10
17
|
const operations = extractOperations(api);
|
|
11
18
|
const schemas = extractSchemas(api);
|
|
@@ -20,10 +27,25 @@ export async function loadOAS(specPath, forceReload = false) {
|
|
|
20
27
|
}
|
|
21
28
|
function extractBaseUrl(spec) {
|
|
22
29
|
if (spec.servers && spec.servers.length > 0) {
|
|
23
|
-
return spec.servers[0]
|
|
30
|
+
return resolveServerUrl(spec.servers[0]);
|
|
24
31
|
}
|
|
25
32
|
return '';
|
|
26
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve `{variable}` templating in a server URL using each variable's
|
|
36
|
+
* declared default. A template variable with no default is rejected rather
|
|
37
|
+
* than left raw (a raw `{var}` would otherwise be sent as part of request
|
|
38
|
+
* URLs).
|
|
39
|
+
*/
|
|
40
|
+
function resolveServerUrl(server) {
|
|
41
|
+
return server.url.replace(/\{([^{}]+)\}/g, (_match, name) => {
|
|
42
|
+
const variable = server.variables?.[name];
|
|
43
|
+
if (variable && variable.default !== undefined && variable.default !== '') {
|
|
44
|
+
return String(variable.default);
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`OAS server URL variable '{${name}}' has no default value (in "${server.url}")`);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
27
49
|
function extractOperations(spec) {
|
|
28
50
|
const operations = new Map();
|
|
29
51
|
if (!spec.paths)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from 'openapi-types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate mock data from an OpenAPI schema.
|
|
4
|
+
* Used for dry-run mode to produce realistic mock responses.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateMockData(schema: OpenAPIV3.SchemaObject, options?: MockGeneratorOptions): unknown;
|
|
7
|
+
export interface MockGeneratorOptions {
|
|
8
|
+
/** Maximum depth for nested objects (default: 3) */
|
|
9
|
+
maxDepth?: number;
|
|
10
|
+
/** Number of items to generate for arrays (default: 2) */
|
|
11
|
+
arrayLength?: number;
|
|
12
|
+
}
|