reqon-dsl 0.2.0 → 0.3.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 +22 -0
- package/dist/ast/nodes.d.ts +83 -4
- package/dist/ast/nodes.js +14 -0
- package/dist/auth/circuit-breaker.js +7 -6
- package/dist/auth/rate-limiter.d.ts +4 -0
- package/dist/auth/rate-limiter.js +9 -16
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +84 -4
- package/dist/config/constants.d.ts +141 -0
- package/dist/config/constants.js +128 -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 +88 -0
- package/dist/control/server.js +238 -0
- package/dist/control/types.d.ts +55 -0
- package/dist/control/types.js +7 -0
- package/dist/debug/cli-debugger.d.ts +17 -0
- package/dist/debug/cli-debugger.js +180 -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/index.d.ts +21 -1
- package/dist/index.js +33 -2
- package/dist/interpreter/context.d.ts +14 -0
- package/dist/interpreter/context.js +15 -0
- package/dist/interpreter/evaluator.d.ts +63 -1
- package/dist/interpreter/evaluator.js +186 -39
- package/dist/interpreter/executor.d.ts +70 -14
- package/dist/interpreter/executor.js +503 -174
- package/dist/interpreter/fetch-handler.d.ts +9 -0
- package/dist/interpreter/fetch-handler.js +133 -24
- package/dist/interpreter/http.d.ts +5 -0
- package/dist/interpreter/http.js +26 -12
- package/dist/interpreter/index.d.ts +3 -1
- package/dist/interpreter/index.js +2 -0
- package/dist/interpreter/pagination.d.ts +11 -2
- package/dist/interpreter/pagination.js +95 -31
- 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 +13 -0
- package/dist/interpreter/step-handlers/for-handler.js +71 -4
- 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 +43 -16
- 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 +11 -1
- package/dist/interpreter/step-handlers/store-handler.js +45 -13
- 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 +4 -2
- package/dist/interpreter/step-handlers/webhook-handler.d.ts +3 -0
- package/dist/interpreter/step-handlers/webhook-handler.js +18 -2
- package/dist/interpreter/store-manager.d.ts +46 -0
- package/dist/interpreter/store-manager.js +66 -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/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.js +451 -0
- package/dist/oas/index.d.ts +2 -0
- package/dist/oas/index.js +1 -0
- package/dist/oas/mock-generator.d.ts +12 -0
- package/dist/oas/mock-generator.js +187 -0
- package/dist/observability/events.d.ts +244 -0
- package/dist/observability/events.js +90 -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 +259 -0
- package/dist/observability/otel.d.ts +135 -0
- package/dist/observability/otel.js +386 -0
- package/dist/parser/action-parser.d.ts +105 -0
- package/dist/parser/action-parser.js +645 -0
- package/dist/parser/expressions.d.ts +13 -0
- package/dist/parser/expressions.js +72 -2
- package/dist/parser/fetch-parser.d.ts +27 -0
- package/dist/parser/fetch-parser.js +269 -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 +14 -0
- package/dist/pause/index.js +11 -0
- package/dist/pause/manager.d.ts +118 -0
- package/dist/pause/manager.js +245 -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 +156 -0
- package/dist/plugin.d.ts +9 -12
- package/dist/plugin.js +10 -13
- package/dist/stores/factory.d.ts +1 -1
- package/dist/stores/factory.js +3 -2
- package/dist/stores/file.d.ts +26 -0
- package/dist/stores/file.js +64 -10
- 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 +11 -0
- package/dist/stores/types.d.ts +17 -0
- package/dist/stores/types.js +12 -0
- package/dist/trace/index.d.ts +16 -0
- package/dist/trace/index.js +12 -0
- package/dist/trace/recorder.d.ts +71 -0
- package/dist/trace/recorder.js +144 -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 +69 -0
- package/dist/trace/store.js +225 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/type-guards.d.ts +58 -0
- package/dist/utils/type-guards.js +92 -0
- package/dist/webhook/server.js +7 -6
- package/package.json +55 -6
- 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,451 @@
|
|
|
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 { parse, execute, fromPath } from '../index.js';
|
|
21
|
+
import { createStore, } from '../stores/index.js';
|
|
22
|
+
// Global store registry for cross-execution access
|
|
23
|
+
const storeRegistry = new Map();
|
|
24
|
+
let serverConfig = {
|
|
25
|
+
workingDirectory: process.cwd(),
|
|
26
|
+
verbose: false,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Format execution result for MCP response
|
|
30
|
+
*/
|
|
31
|
+
function formatExecutionResult(result) {
|
|
32
|
+
const output = {
|
|
33
|
+
success: result.success,
|
|
34
|
+
duration: result.duration,
|
|
35
|
+
actionsRun: result.actionsRun,
|
|
36
|
+
};
|
|
37
|
+
if (result.errors && result.errors.length > 0) {
|
|
38
|
+
output.errors = result.errors.map((e) => ({
|
|
39
|
+
action: e.action,
|
|
40
|
+
step: e.step,
|
|
41
|
+
message: e.message,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
// Include store summaries
|
|
45
|
+
if (result.stores && result.stores.size > 0) {
|
|
46
|
+
output.stores = Array.from(result.stores.keys());
|
|
47
|
+
}
|
|
48
|
+
if (result.executionId) {
|
|
49
|
+
output.executionId = result.executionId;
|
|
50
|
+
}
|
|
51
|
+
return JSON.stringify(output, null, 2);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create executor config
|
|
55
|
+
*/
|
|
56
|
+
function createExecutorConfig(options) {
|
|
57
|
+
return {
|
|
58
|
+
verbose: options?.verbose ?? serverConfig.verbose,
|
|
59
|
+
dryRun: options?.dryRun ?? false,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
// Define available tools
|
|
63
|
+
const tools = [
|
|
64
|
+
{
|
|
65
|
+
name: 'reqon.execute',
|
|
66
|
+
description: 'Execute a Reqon mission from DSL source code. Returns execution results including any stored data.',
|
|
67
|
+
inputSchema: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
source: {
|
|
71
|
+
type: 'string',
|
|
72
|
+
description: 'Reqon DSL source code defining the mission',
|
|
73
|
+
},
|
|
74
|
+
verbose: {
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
description: 'Enable verbose logging',
|
|
77
|
+
default: false,
|
|
78
|
+
},
|
|
79
|
+
dryRun: {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
description: 'Validate without executing HTTP requests',
|
|
82
|
+
default: false,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
required: ['source'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'reqon.execute_file',
|
|
90
|
+
description: 'Execute a Reqon mission from a file or folder path. Supports both single .reqon files and mission folders.',
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: 'object',
|
|
93
|
+
properties: {
|
|
94
|
+
path: {
|
|
95
|
+
type: 'string',
|
|
96
|
+
description: 'Path to .reqon file or mission folder (relative to working directory)',
|
|
97
|
+
},
|
|
98
|
+
verbose: {
|
|
99
|
+
type: 'boolean',
|
|
100
|
+
description: 'Enable verbose logging',
|
|
101
|
+
default: false,
|
|
102
|
+
},
|
|
103
|
+
dryRun: {
|
|
104
|
+
type: 'boolean',
|
|
105
|
+
description: 'Validate without executing HTTP requests',
|
|
106
|
+
default: false,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
required: ['path'],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'reqon.parse',
|
|
114
|
+
description: 'Parse Reqon DSL source and return the AST structure. Useful for validation without execution.',
|
|
115
|
+
inputSchema: {
|
|
116
|
+
type: 'object',
|
|
117
|
+
properties: {
|
|
118
|
+
source: {
|
|
119
|
+
type: 'string',
|
|
120
|
+
description: 'Reqon DSL source code to parse',
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
required: ['source'],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'reqon.query_store',
|
|
128
|
+
description: 'Query data from a registered Reqon store. Returns matching records.',
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: {
|
|
132
|
+
store: {
|
|
133
|
+
type: 'string',
|
|
134
|
+
description: 'Name of the store to query',
|
|
135
|
+
},
|
|
136
|
+
filter: {
|
|
137
|
+
type: 'object',
|
|
138
|
+
description: 'Filter criteria',
|
|
139
|
+
properties: {
|
|
140
|
+
where: {
|
|
141
|
+
type: 'object',
|
|
142
|
+
description: 'Field equality conditions',
|
|
143
|
+
},
|
|
144
|
+
limit: {
|
|
145
|
+
type: 'number',
|
|
146
|
+
description: 'Maximum records to return',
|
|
147
|
+
},
|
|
148
|
+
offset: {
|
|
149
|
+
type: 'number',
|
|
150
|
+
description: 'Number of records to skip',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
required: ['store'],
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'reqon.list_stores',
|
|
160
|
+
description: 'List all registered stores and their record counts.',
|
|
161
|
+
inputSchema: {
|
|
162
|
+
type: 'object',
|
|
163
|
+
properties: {},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'reqon.register_store',
|
|
168
|
+
description: 'Register a store for use across executions. Stores persist in memory during the server session.',
|
|
169
|
+
inputSchema: {
|
|
170
|
+
type: 'object',
|
|
171
|
+
properties: {
|
|
172
|
+
name: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
description: 'Store name for reference',
|
|
175
|
+
},
|
|
176
|
+
type: {
|
|
177
|
+
type: 'string',
|
|
178
|
+
enum: ['memory', 'file'],
|
|
179
|
+
description: 'Store type',
|
|
180
|
+
default: 'memory',
|
|
181
|
+
},
|
|
182
|
+
path: {
|
|
183
|
+
type: 'string',
|
|
184
|
+
description: 'File path for file-based stores',
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
required: ['name'],
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
];
|
|
191
|
+
// Create server instance
|
|
192
|
+
const server = new Server({
|
|
193
|
+
name: 'reqon-mcp-server',
|
|
194
|
+
version: '0.1.0',
|
|
195
|
+
}, {
|
|
196
|
+
capabilities: {
|
|
197
|
+
tools: {},
|
|
198
|
+
resources: {},
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
// Handle tool listing
|
|
202
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
203
|
+
return { tools };
|
|
204
|
+
});
|
|
205
|
+
// Handle tool execution
|
|
206
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
207
|
+
const { name, arguments: args } = request.params;
|
|
208
|
+
try {
|
|
209
|
+
switch (name) {
|
|
210
|
+
case 'reqon.execute': {
|
|
211
|
+
const { source, verbose, dryRun } = args;
|
|
212
|
+
const config = createExecutorConfig({ verbose, dryRun });
|
|
213
|
+
const result = await execute(source, config);
|
|
214
|
+
return {
|
|
215
|
+
content: [
|
|
216
|
+
{
|
|
217
|
+
type: 'text',
|
|
218
|
+
text: formatExecutionResult(result),
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
case 'reqon.execute_file': {
|
|
224
|
+
const { path, verbose, dryRun } = args;
|
|
225
|
+
const config = createExecutorConfig({ verbose, dryRun });
|
|
226
|
+
const result = await fromPath(path, config);
|
|
227
|
+
return {
|
|
228
|
+
content: [
|
|
229
|
+
{
|
|
230
|
+
type: 'text',
|
|
231
|
+
text: formatExecutionResult(result),
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
case 'reqon.parse': {
|
|
237
|
+
const { source } = args;
|
|
238
|
+
const program = parse(source);
|
|
239
|
+
// Summarize AST for readability
|
|
240
|
+
const summary = {
|
|
241
|
+
type: 'ReqonProgram',
|
|
242
|
+
statements: program.statements.length,
|
|
243
|
+
missions: program.statements
|
|
244
|
+
.filter((s) => s.type === 'MissionDefinition')
|
|
245
|
+
.map((m) => ({
|
|
246
|
+
name: m.name,
|
|
247
|
+
sources: m.sources?.length ?? 0,
|
|
248
|
+
stores: m.stores?.length ?? 0,
|
|
249
|
+
actions: m.actions?.length ?? 0,
|
|
250
|
+
hasSchedule: !!m.schedule,
|
|
251
|
+
})),
|
|
252
|
+
};
|
|
253
|
+
return {
|
|
254
|
+
content: [
|
|
255
|
+
{
|
|
256
|
+
type: 'text',
|
|
257
|
+
text: JSON.stringify(summary, null, 2),
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
case 'reqon.query_store': {
|
|
263
|
+
const { store: storeName, filter } = args;
|
|
264
|
+
const store = storeRegistry.get(storeName);
|
|
265
|
+
if (!store) {
|
|
266
|
+
return {
|
|
267
|
+
isError: true,
|
|
268
|
+
content: [
|
|
269
|
+
{
|
|
270
|
+
type: 'text',
|
|
271
|
+
text: `Store "${storeName}" not found. Available stores: ${Array.from(storeRegistry.keys()).join(', ') || '(none)'}`,
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const records = await store.list(filter);
|
|
277
|
+
const count = await store.count(filter);
|
|
278
|
+
return {
|
|
279
|
+
content: [
|
|
280
|
+
{
|
|
281
|
+
type: 'text',
|
|
282
|
+
text: JSON.stringify({
|
|
283
|
+
store: storeName,
|
|
284
|
+
totalMatching: count,
|
|
285
|
+
returned: records.length,
|
|
286
|
+
data: records,
|
|
287
|
+
}, null, 2),
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
case 'reqon.list_stores': {
|
|
293
|
+
const stores = [];
|
|
294
|
+
for (const [name, store] of storeRegistry) {
|
|
295
|
+
const count = await store.count();
|
|
296
|
+
stores.push({ name, count });
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
content: [
|
|
300
|
+
{
|
|
301
|
+
type: 'text',
|
|
302
|
+
text: JSON.stringify({
|
|
303
|
+
stores,
|
|
304
|
+
total: stores.length,
|
|
305
|
+
}, null, 2),
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
case 'reqon.register_store': {
|
|
311
|
+
const { name, type = 'memory', path } = args;
|
|
312
|
+
if (storeRegistry.has(name)) {
|
|
313
|
+
return {
|
|
314
|
+
content: [
|
|
315
|
+
{
|
|
316
|
+
type: 'text',
|
|
317
|
+
text: `Store "${name}" already registered`,
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
const store = createStore({
|
|
323
|
+
type,
|
|
324
|
+
name,
|
|
325
|
+
baseDir: path ?? '.reqon-data',
|
|
326
|
+
});
|
|
327
|
+
storeRegistry.set(name, store);
|
|
328
|
+
return {
|
|
329
|
+
content: [
|
|
330
|
+
{
|
|
331
|
+
type: 'text',
|
|
332
|
+
text: `Store "${name}" registered (type: ${type})`,
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
default:
|
|
338
|
+
return {
|
|
339
|
+
isError: true,
|
|
340
|
+
content: [
|
|
341
|
+
{
|
|
342
|
+
type: 'text',
|
|
343
|
+
text: `Unknown tool: ${name}`,
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
351
|
+
return {
|
|
352
|
+
isError: true,
|
|
353
|
+
content: [
|
|
354
|
+
{
|
|
355
|
+
type: 'text',
|
|
356
|
+
text: `Error: ${message}`,
|
|
357
|
+
},
|
|
358
|
+
],
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
// Handle resource listing
|
|
363
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
364
|
+
const resources = [
|
|
365
|
+
{
|
|
366
|
+
uri: 'reqon://stores',
|
|
367
|
+
name: 'Reqon Stores',
|
|
368
|
+
description: 'List of all registered data stores',
|
|
369
|
+
mimeType: 'application/json',
|
|
370
|
+
},
|
|
371
|
+
];
|
|
372
|
+
// Add individual store resources
|
|
373
|
+
for (const name of storeRegistry.keys()) {
|
|
374
|
+
resources.push({
|
|
375
|
+
uri: `reqon://stores/${name}`,
|
|
376
|
+
name: `Store: ${name}`,
|
|
377
|
+
description: `Data from the "${name}" store`,
|
|
378
|
+
mimeType: 'application/json',
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
return { resources };
|
|
382
|
+
});
|
|
383
|
+
// Handle resource reading
|
|
384
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
385
|
+
const { uri } = request.params;
|
|
386
|
+
if (uri === 'reqon://stores') {
|
|
387
|
+
const stores = [];
|
|
388
|
+
for (const [name, store] of storeRegistry) {
|
|
389
|
+
const count = await store.count();
|
|
390
|
+
stores.push({ name, count });
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
contents: [
|
|
394
|
+
{
|
|
395
|
+
uri,
|
|
396
|
+
mimeType: 'application/json',
|
|
397
|
+
text: JSON.stringify(stores, null, 2),
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
const storeMatch = uri.match(/^reqon:\/\/stores\/(.+)$/);
|
|
403
|
+
if (storeMatch) {
|
|
404
|
+
const storeName = storeMatch[1];
|
|
405
|
+
const store = storeRegistry.get(storeName);
|
|
406
|
+
if (!store) {
|
|
407
|
+
throw new Error(`Store "${storeName}" not found`);
|
|
408
|
+
}
|
|
409
|
+
const records = await store.list({ limit: 100 });
|
|
410
|
+
const count = await store.count();
|
|
411
|
+
return {
|
|
412
|
+
contents: [
|
|
413
|
+
{
|
|
414
|
+
uri,
|
|
415
|
+
mimeType: 'application/json',
|
|
416
|
+
text: JSON.stringify({
|
|
417
|
+
store: storeName,
|
|
418
|
+
totalRecords: count,
|
|
419
|
+
data: records,
|
|
420
|
+
}, null, 2),
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
426
|
+
});
|
|
427
|
+
// Start server
|
|
428
|
+
async function main() {
|
|
429
|
+
// Parse CLI arguments
|
|
430
|
+
const args = process.argv.slice(2);
|
|
431
|
+
for (let i = 0; i < args.length; i++) {
|
|
432
|
+
if (args[i] === '--verbose' || args[i] === '-v') {
|
|
433
|
+
serverConfig.verbose = true;
|
|
434
|
+
}
|
|
435
|
+
if (args[i] === '--cwd' && args[i + 1]) {
|
|
436
|
+
serverConfig.workingDirectory = args[++i];
|
|
437
|
+
process.chdir(serverConfig.workingDirectory);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const transport = new StdioServerTransport();
|
|
441
|
+
await server.connect(transport);
|
|
442
|
+
// Log to stderr so it doesn't interfere with MCP protocol on stdout
|
|
443
|
+
console.error('Reqon MCP Server running on stdio');
|
|
444
|
+
if (serverConfig.verbose) {
|
|
445
|
+
console.error(` Working directory: ${serverConfig.workingDirectory}`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
main().catch((error) => {
|
|
449
|
+
console.error('Server error:', error);
|
|
450
|
+
process.exit(1);
|
|
451
|
+
});
|
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
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate mock data from an OpenAPI schema.
|
|
3
|
+
* Used for dry-run mode to produce realistic mock responses.
|
|
4
|
+
*/
|
|
5
|
+
export function generateMockData(schema, options = {}) {
|
|
6
|
+
const ctx = {
|
|
7
|
+
depth: 0,
|
|
8
|
+
maxDepth: options.maxDepth ?? 3,
|
|
9
|
+
arrayLength: options.arrayLength ?? 2,
|
|
10
|
+
seenRefs: new Set(),
|
|
11
|
+
counter: { value: 0 },
|
|
12
|
+
};
|
|
13
|
+
return generateValue(schema, ctx);
|
|
14
|
+
}
|
|
15
|
+
function generateValue(schema, ctx) {
|
|
16
|
+
// Handle nullable - only return null if explicitly marked nullable
|
|
17
|
+
// and we're past the top level (depth > 0). Use strict equality check
|
|
18
|
+
// to avoid false positives from undefined/truthy coercion.
|
|
19
|
+
if (schema.nullable === true && ctx.depth > 1) {
|
|
20
|
+
// Return null ~20% of the time for nullable fields deep in the tree
|
|
21
|
+
if (Math.random() < 0.2) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Handle enum - pick first value
|
|
26
|
+
if (schema.enum && schema.enum.length > 0) {
|
|
27
|
+
return schema.enum[0];
|
|
28
|
+
}
|
|
29
|
+
// Handle example if provided
|
|
30
|
+
if (schema.example !== undefined) {
|
|
31
|
+
return schema.example;
|
|
32
|
+
}
|
|
33
|
+
// Handle default if provided
|
|
34
|
+
if (schema.default !== undefined) {
|
|
35
|
+
return schema.default;
|
|
36
|
+
}
|
|
37
|
+
// Check for allOf/oneOf/anyOf
|
|
38
|
+
if (schema.allOf && schema.allOf.length > 0) {
|
|
39
|
+
// Merge all schemas
|
|
40
|
+
const merged = {};
|
|
41
|
+
for (const subSchema of schema.allOf) {
|
|
42
|
+
const subValue = generateValue(subSchema, ctx);
|
|
43
|
+
if (typeof subValue === 'object' && subValue !== null) {
|
|
44
|
+
Object.assign(merged, subValue);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return merged;
|
|
48
|
+
}
|
|
49
|
+
if (schema.oneOf && schema.oneOf.length > 0) {
|
|
50
|
+
return generateValue(schema.oneOf[0], ctx);
|
|
51
|
+
}
|
|
52
|
+
if (schema.anyOf && schema.anyOf.length > 0) {
|
|
53
|
+
return generateValue(schema.anyOf[0], ctx);
|
|
54
|
+
}
|
|
55
|
+
// Generate based on type
|
|
56
|
+
switch (schema.type) {
|
|
57
|
+
case 'string':
|
|
58
|
+
return generateString(schema, ctx);
|
|
59
|
+
case 'number':
|
|
60
|
+
return generateNumber(schema);
|
|
61
|
+
case 'integer':
|
|
62
|
+
return generateInteger(schema);
|
|
63
|
+
case 'boolean':
|
|
64
|
+
return true;
|
|
65
|
+
case 'array':
|
|
66
|
+
return generateArray(schema, ctx);
|
|
67
|
+
case 'object':
|
|
68
|
+
return generateObject(schema, ctx);
|
|
69
|
+
default: {
|
|
70
|
+
// No type specified - try to infer from properties
|
|
71
|
+
// Cast to SchemaObject to access properties on untyped schemas
|
|
72
|
+
const untyped = schema;
|
|
73
|
+
if (untyped.properties) {
|
|
74
|
+
return generateObject(untyped, ctx);
|
|
75
|
+
}
|
|
76
|
+
// Return empty object as fallback
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function generateString(schema, ctx) {
|
|
82
|
+
// Handle format
|
|
83
|
+
switch (schema.format) {
|
|
84
|
+
case 'date':
|
|
85
|
+
return '2024-01-15';
|
|
86
|
+
case 'date-time':
|
|
87
|
+
return '2024-01-15T10:30:00Z';
|
|
88
|
+
case 'email':
|
|
89
|
+
return `user${ctx.counter.value++}@example.com`;
|
|
90
|
+
case 'uri':
|
|
91
|
+
case 'url':
|
|
92
|
+
return 'https://example.com';
|
|
93
|
+
case 'uuid': {
|
|
94
|
+
// Generate unique UUIDs using counter
|
|
95
|
+
const id = ctx.counter.value++;
|
|
96
|
+
const hex = id.toString(16).padStart(12, '0');
|
|
97
|
+
return `550e8400-e29b-41d4-a716-${hex}`;
|
|
98
|
+
}
|
|
99
|
+
case 'hostname':
|
|
100
|
+
return 'example.com';
|
|
101
|
+
case 'ipv4':
|
|
102
|
+
return '192.168.1.1';
|
|
103
|
+
case 'ipv6':
|
|
104
|
+
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
|
|
105
|
+
case 'byte':
|
|
106
|
+
return 'SGVsbG8gV29ybGQ='; // Base64 encoded "Hello World"
|
|
107
|
+
case 'binary':
|
|
108
|
+
return '<binary>';
|
|
109
|
+
case 'password':
|
|
110
|
+
return '********';
|
|
111
|
+
case 'phone':
|
|
112
|
+
return '+1-555-555-5555';
|
|
113
|
+
}
|
|
114
|
+
// Respect minLength/maxLength
|
|
115
|
+
const minLen = schema.minLength ?? 0;
|
|
116
|
+
const maxLen = schema.maxLength ?? 50;
|
|
117
|
+
const targetLen = Math.max(minLen, Math.min(8, maxLen));
|
|
118
|
+
// Generate a simple mock string
|
|
119
|
+
const base = 'mock_value';
|
|
120
|
+
if (base.length >= targetLen) {
|
|
121
|
+
return base.substring(0, targetLen);
|
|
122
|
+
}
|
|
123
|
+
return base.padEnd(targetLen, '_');
|
|
124
|
+
}
|
|
125
|
+
function generateNumber(schema) {
|
|
126
|
+
const min = schema.minimum ?? 0;
|
|
127
|
+
const max = schema.maximum ?? 100;
|
|
128
|
+
// Generate a value in range
|
|
129
|
+
const value = min + (max - min) / 2;
|
|
130
|
+
// Handle multipleOf
|
|
131
|
+
if (schema.multipleOf) {
|
|
132
|
+
return Math.round(value / schema.multipleOf) * schema.multipleOf;
|
|
133
|
+
}
|
|
134
|
+
return Math.round(value * 100) / 100;
|
|
135
|
+
}
|
|
136
|
+
function generateInteger(schema) {
|
|
137
|
+
const min = schema.minimum ?? 0;
|
|
138
|
+
const max = schema.maximum ?? 100;
|
|
139
|
+
// Generate integer in range
|
|
140
|
+
const value = Math.floor(min + (max - min) / 2);
|
|
141
|
+
// Handle multipleOf
|
|
142
|
+
if (schema.multipleOf) {
|
|
143
|
+
return Math.round(value / schema.multipleOf) * schema.multipleOf;
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
function generateArray(schema, ctx) {
|
|
148
|
+
// Check depth limit
|
|
149
|
+
if (ctx.depth >= ctx.maxDepth) {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
// Determine array length
|
|
153
|
+
const minItems = schema.minItems ?? 0;
|
|
154
|
+
const maxItems = schema.maxItems ?? ctx.arrayLength;
|
|
155
|
+
const length = Math.max(minItems, Math.min(ctx.arrayLength, maxItems));
|
|
156
|
+
if (!schema.items) {
|
|
157
|
+
return Array(length).fill({});
|
|
158
|
+
}
|
|
159
|
+
const itemSchema = schema.items;
|
|
160
|
+
const items = [];
|
|
161
|
+
for (let i = 0; i < length; i++) {
|
|
162
|
+
items.push(generateValue(itemSchema, {
|
|
163
|
+
...ctx,
|
|
164
|
+
depth: ctx.depth + 1,
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
return items;
|
|
168
|
+
}
|
|
169
|
+
function generateObject(schema, ctx) {
|
|
170
|
+
// Check depth limit
|
|
171
|
+
if (ctx.depth >= ctx.maxDepth) {
|
|
172
|
+
return {};
|
|
173
|
+
}
|
|
174
|
+
const result = {};
|
|
175
|
+
const properties = schema.properties;
|
|
176
|
+
if (!properties) {
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
// Include all properties at any depth to generate complete mock data
|
|
180
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
181
|
+
result[key] = generateValue(propSchema, {
|
|
182
|
+
...ctx,
|
|
183
|
+
depth: ctx.depth + 1,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|