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
|
@@ -1,739 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { ReqonLexer } from '../lexer/index.js';
|
|
3
|
-
import { ReqonParser } from './parser.js';
|
|
4
|
-
|
|
5
|
-
describe('ReqonParser', () => {
|
|
6
|
-
function parse(source: string) {
|
|
7
|
-
const lexer = new ReqonLexer(source);
|
|
8
|
-
const tokens = lexer.tokenize();
|
|
9
|
-
const parser = new ReqonParser(tokens);
|
|
10
|
-
return parser.parse();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
it('parses a simple mission', () => {
|
|
14
|
-
const source = `
|
|
15
|
-
mission TestMission {
|
|
16
|
-
source API {
|
|
17
|
-
auth: bearer,
|
|
18
|
-
base: "https://api.example.com"
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
store items: memory("items")
|
|
22
|
-
|
|
23
|
-
action FetchItems {
|
|
24
|
-
get "/items"
|
|
25
|
-
|
|
26
|
-
store response -> items {
|
|
27
|
-
key: .id
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
run FetchItems
|
|
32
|
-
}
|
|
33
|
-
`;
|
|
34
|
-
|
|
35
|
-
const program = parse(source);
|
|
36
|
-
|
|
37
|
-
expect(program.type).toBe('ReqonProgram');
|
|
38
|
-
expect(program.statements).toHaveLength(1);
|
|
39
|
-
|
|
40
|
-
const mission = program.statements[0];
|
|
41
|
-
expect(mission.type).toBe('MissionDefinition');
|
|
42
|
-
|
|
43
|
-
if (mission.type === 'MissionDefinition') {
|
|
44
|
-
expect(mission.name).toBe('TestMission');
|
|
45
|
-
expect(mission.sources).toHaveLength(1);
|
|
46
|
-
expect(mission.stores).toHaveLength(1);
|
|
47
|
-
expect(mission.actions).toHaveLength(1);
|
|
48
|
-
expect(mission.pipeline.stages).toHaveLength(1);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('parses fetch with pagination', () => {
|
|
53
|
-
const source = `
|
|
54
|
-
mission PaginatedFetch {
|
|
55
|
-
source API {
|
|
56
|
-
auth: oauth2,
|
|
57
|
-
base: "https://api.example.com"
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
store items: memory("items")
|
|
61
|
-
|
|
62
|
-
action FetchAll {
|
|
63
|
-
get "/items" {
|
|
64
|
-
paginate: offset(page, 50),
|
|
65
|
-
until: response.items.length == 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
store response.items -> items {
|
|
69
|
-
key: .id
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
run FetchAll
|
|
74
|
-
}
|
|
75
|
-
`;
|
|
76
|
-
|
|
77
|
-
const program = parse(source);
|
|
78
|
-
const mission = program.statements[0];
|
|
79
|
-
|
|
80
|
-
if (mission.type === 'MissionDefinition') {
|
|
81
|
-
const action = mission.actions[0];
|
|
82
|
-
const fetchStep = action.steps[0];
|
|
83
|
-
|
|
84
|
-
if (fetchStep.type === 'FetchStep') {
|
|
85
|
-
expect(fetchStep.paginate).toBeDefined();
|
|
86
|
-
expect(fetchStep.paginate?.type).toBe('offset');
|
|
87
|
-
expect(fetchStep.paginate?.pageSize).toBe(50);
|
|
88
|
-
expect(fetchStep.until).toBeDefined();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('parses for loops with conditions', () => {
|
|
94
|
-
const source = `
|
|
95
|
-
mission IterateItems {
|
|
96
|
-
source API {
|
|
97
|
-
auth: bearer,
|
|
98
|
-
base: "https://api.example.com"
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
store items: memory("items")
|
|
102
|
-
|
|
103
|
-
action ProcessItems {
|
|
104
|
-
for item in items where .status == "pending" {
|
|
105
|
-
get "/items/{item.id}"
|
|
106
|
-
|
|
107
|
-
store response -> items {
|
|
108
|
-
key: .id,
|
|
109
|
-
upsert: true
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
run ProcessItems
|
|
115
|
-
}
|
|
116
|
-
`;
|
|
117
|
-
|
|
118
|
-
const program = parse(source);
|
|
119
|
-
const mission = program.statements[0];
|
|
120
|
-
|
|
121
|
-
if (mission.type === 'MissionDefinition') {
|
|
122
|
-
const action = mission.actions[0];
|
|
123
|
-
const forStep = action.steps[0];
|
|
124
|
-
|
|
125
|
-
if (forStep.type === 'ForStep') {
|
|
126
|
-
expect(forStep.variable).toBe('item');
|
|
127
|
-
expect(forStep.condition).toBeDefined();
|
|
128
|
-
expect(forStep.steps).toHaveLength(2);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('parses map steps with match expressions', () => {
|
|
134
|
-
const source = `
|
|
135
|
-
mission MapItems {
|
|
136
|
-
source API {
|
|
137
|
-
auth: bearer,
|
|
138
|
-
base: "https://api.example.com"
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
store raw: memory("raw")
|
|
142
|
-
store normalized: memory("normalized")
|
|
143
|
-
|
|
144
|
-
action Normalize {
|
|
145
|
-
for item in raw {
|
|
146
|
-
map item -> StandardItem {
|
|
147
|
-
id: .external_id,
|
|
148
|
-
status: match .state {
|
|
149
|
-
"active" => "enabled",
|
|
150
|
-
"inactive" => "disabled",
|
|
151
|
-
_ => "unknown"
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
store response -> normalized {
|
|
156
|
-
key: .id
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
run Normalize
|
|
162
|
-
}
|
|
163
|
-
`;
|
|
164
|
-
|
|
165
|
-
const program = parse(source);
|
|
166
|
-
const mission = program.statements[0];
|
|
167
|
-
|
|
168
|
-
if (mission.type === 'MissionDefinition') {
|
|
169
|
-
const action = mission.actions[0];
|
|
170
|
-
const forStep = action.steps[0];
|
|
171
|
-
|
|
172
|
-
if (forStep.type === 'ForStep') {
|
|
173
|
-
const mapStep = forStep.steps[0];
|
|
174
|
-
if (mapStep.type === 'MapStep') {
|
|
175
|
-
expect(mapStep.targetSchema).toBe('StandardItem');
|
|
176
|
-
expect(mapStep.mappings).toHaveLength(2);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('parses validation steps', () => {
|
|
183
|
-
const source = `
|
|
184
|
-
mission ValidateData {
|
|
185
|
-
source API {
|
|
186
|
-
auth: bearer,
|
|
187
|
-
base: "https://api.example.com"
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
store data: memory("data")
|
|
191
|
-
|
|
192
|
-
action Fetch {
|
|
193
|
-
get "/data"
|
|
194
|
-
|
|
195
|
-
validate response {
|
|
196
|
-
assume length(.items) > 0,
|
|
197
|
-
assume .count > 0
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
store response.items -> data {
|
|
201
|
-
key: .id
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
run Fetch
|
|
206
|
-
}
|
|
207
|
-
`;
|
|
208
|
-
|
|
209
|
-
const program = parse(source);
|
|
210
|
-
const mission = program.statements[0];
|
|
211
|
-
|
|
212
|
-
if (mission.type === 'MissionDefinition') {
|
|
213
|
-
const action = mission.actions[0];
|
|
214
|
-
const validateStep = action.steps[1];
|
|
215
|
-
|
|
216
|
-
if (validateStep.type === 'ValidateStep') {
|
|
217
|
-
expect(validateStep.constraints).toHaveLength(2);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('parses pipeline with multiple stages', () => {
|
|
223
|
-
const source = `
|
|
224
|
-
mission MultiStage {
|
|
225
|
-
source API {
|
|
226
|
-
auth: bearer,
|
|
227
|
-
base: "https://api.example.com"
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
store data: memory("data")
|
|
231
|
-
|
|
232
|
-
action Step1 {
|
|
233
|
-
get "/step1"
|
|
234
|
-
store response -> data { key: .id }
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
action Step2 {
|
|
238
|
-
get "/step2"
|
|
239
|
-
store response -> data { key: .id }
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
action Step3 {
|
|
243
|
-
get "/step3"
|
|
244
|
-
store response -> data { key: .id }
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
run Step1 then Step2 then Step3
|
|
248
|
-
}
|
|
249
|
-
`;
|
|
250
|
-
|
|
251
|
-
const program = parse(source);
|
|
252
|
-
const mission = program.statements[0];
|
|
253
|
-
|
|
254
|
-
if (mission.type === 'MissionDefinition') {
|
|
255
|
-
expect(mission.pipeline.stages).toHaveLength(3);
|
|
256
|
-
expect(mission.pipeline.stages[0].action).toBe('Step1');
|
|
257
|
-
expect(mission.pipeline.stages[1].action).toBe('Step2');
|
|
258
|
-
expect(mission.pipeline.stages[2].action).toBe('Step3');
|
|
259
|
-
}
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it('parses parallel stages with bracket syntax', () => {
|
|
263
|
-
const source = `
|
|
264
|
-
mission ParallelSync {
|
|
265
|
-
source API {
|
|
266
|
-
auth: bearer,
|
|
267
|
-
base: "https://api.example.com"
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
store orders: memory("orders")
|
|
271
|
-
store payments: memory("payments")
|
|
272
|
-
store reconciled: memory("reconciled")
|
|
273
|
-
|
|
274
|
-
action FetchOrders {
|
|
275
|
-
get "/orders"
|
|
276
|
-
store response -> orders { key: .id }
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
action FetchPayments {
|
|
280
|
-
get "/payments"
|
|
281
|
-
store response -> payments { key: .id }
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
action Reconcile {
|
|
285
|
-
get "/reconcile"
|
|
286
|
-
store response -> reconciled { key: .id }
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
run [FetchOrders, FetchPayments] then Reconcile
|
|
290
|
-
}
|
|
291
|
-
`;
|
|
292
|
-
|
|
293
|
-
const program = parse(source);
|
|
294
|
-
const mission = program.statements[0];
|
|
295
|
-
|
|
296
|
-
if (mission.type === 'MissionDefinition') {
|
|
297
|
-
expect(mission.pipeline.stages).toHaveLength(2);
|
|
298
|
-
|
|
299
|
-
// First stage is parallel
|
|
300
|
-
const parallelStage = mission.pipeline.stages[0];
|
|
301
|
-
expect(parallelStage.actions).toBeDefined();
|
|
302
|
-
expect(parallelStage.actions).toEqual(['FetchOrders', 'FetchPayments']);
|
|
303
|
-
expect(parallelStage.action).toBeUndefined();
|
|
304
|
-
|
|
305
|
-
// Second stage is sequential
|
|
306
|
-
const sequentialStage = mission.pipeline.stages[1];
|
|
307
|
-
expect(sequentialStage.action).toBe('Reconcile');
|
|
308
|
-
expect(sequentialStage.actions).toBeUndefined();
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('parses multiple parallel stages', () => {
|
|
313
|
-
const source = `
|
|
314
|
-
mission ComplexPipeline {
|
|
315
|
-
source API {
|
|
316
|
-
auth: bearer,
|
|
317
|
-
base: "https://api.example.com"
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
store data: memory("data")
|
|
321
|
-
|
|
322
|
-
action A { get "/a" }
|
|
323
|
-
action B { get "/b" }
|
|
324
|
-
action C { get "/c" }
|
|
325
|
-
action D { get "/d" }
|
|
326
|
-
action E { get "/e" }
|
|
327
|
-
|
|
328
|
-
run A then [B, C, D] then E
|
|
329
|
-
}
|
|
330
|
-
`;
|
|
331
|
-
|
|
332
|
-
const program = parse(source);
|
|
333
|
-
const mission = program.statements[0];
|
|
334
|
-
|
|
335
|
-
if (mission.type === 'MissionDefinition') {
|
|
336
|
-
expect(mission.pipeline.stages).toHaveLength(3);
|
|
337
|
-
|
|
338
|
-
expect(mission.pipeline.stages[0].action).toBe('A');
|
|
339
|
-
expect(mission.pipeline.stages[1].actions).toEqual(['B', 'C', 'D']);
|
|
340
|
-
expect(mission.pipeline.stages[2].action).toBe('E');
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
it('parses parallel stage with three actions', () => {
|
|
345
|
-
const source = `
|
|
346
|
-
mission TripleParallel {
|
|
347
|
-
source API {
|
|
348
|
-
auth: bearer,
|
|
349
|
-
base: "https://api.example.com"
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
store data: memory("data")
|
|
353
|
-
|
|
354
|
-
action X { get "/x" }
|
|
355
|
-
action Y { get "/y" }
|
|
356
|
-
action Z { get "/z" }
|
|
357
|
-
|
|
358
|
-
run [X, Y, Z]
|
|
359
|
-
}
|
|
360
|
-
`;
|
|
361
|
-
|
|
362
|
-
const program = parse(source);
|
|
363
|
-
const mission = program.statements[0];
|
|
364
|
-
|
|
365
|
-
if (mission.type === 'MissionDefinition') {
|
|
366
|
-
expect(mission.pipeline.stages).toHaveLength(1);
|
|
367
|
-
expect(mission.pipeline.stages[0].actions).toEqual(['X', 'Y', 'Z']);
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it('parses let statements in actions', () => {
|
|
372
|
-
const source = `
|
|
373
|
-
mission TestLet {
|
|
374
|
-
source API {
|
|
375
|
-
auth: bearer,
|
|
376
|
-
base: "https://api.example.com"
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
store items: memory("items")
|
|
380
|
-
|
|
381
|
-
action ProcessItems {
|
|
382
|
-
let baseUrl = "https://api.example.com"
|
|
383
|
-
let pageSize = 50
|
|
384
|
-
let config = { enabled: true }
|
|
385
|
-
|
|
386
|
-
get "/items"
|
|
387
|
-
|
|
388
|
-
let itemCount = length(response.items)
|
|
389
|
-
|
|
390
|
-
store response -> items {
|
|
391
|
-
key: .id
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
run ProcessItems
|
|
396
|
-
}
|
|
397
|
-
`;
|
|
398
|
-
|
|
399
|
-
const program = parse(source);
|
|
400
|
-
const mission = program.statements[0];
|
|
401
|
-
|
|
402
|
-
if (mission.type === 'MissionDefinition') {
|
|
403
|
-
const action = mission.actions[0];
|
|
404
|
-
expect(action.steps).toHaveLength(5);
|
|
405
|
-
|
|
406
|
-
const letStep1 = action.steps[0];
|
|
407
|
-
expect(letStep1.type).toBe('LetStep');
|
|
408
|
-
if (letStep1.type === 'LetStep') {
|
|
409
|
-
expect(letStep1.name).toBe('baseUrl');
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const letStep2 = action.steps[1];
|
|
413
|
-
expect(letStep2.type).toBe('LetStep');
|
|
414
|
-
if (letStep2.type === 'LetStep') {
|
|
415
|
-
expect(letStep2.name).toBe('pageSize');
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const letStep3 = action.steps[2];
|
|
419
|
-
expect(letStep3.type).toBe('LetStep');
|
|
420
|
-
if (letStep3.type === 'LetStep') {
|
|
421
|
-
expect(letStep3.name).toBe('config');
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
const fetchStep = action.steps[3];
|
|
425
|
-
expect(fetchStep.type).toBe('FetchStep');
|
|
426
|
-
|
|
427
|
-
const letStep4 = action.steps[4];
|
|
428
|
-
expect(letStep4.type).toBe('LetStep');
|
|
429
|
-
if (letStep4.type === 'LetStep') {
|
|
430
|
-
expect(letStep4.name).toBe('itemCount');
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
it('parses let statements in for loops', () => {
|
|
436
|
-
const source = `
|
|
437
|
-
mission TestLetInLoop {
|
|
438
|
-
source API {
|
|
439
|
-
auth: bearer,
|
|
440
|
-
base: "https://api.example.com"
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
store items: memory("items")
|
|
444
|
-
|
|
445
|
-
action ProcessItems {
|
|
446
|
-
for item in items {
|
|
447
|
-
let itemId = item.id
|
|
448
|
-
get "/items/{itemId}"
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
run ProcessItems
|
|
453
|
-
}
|
|
454
|
-
`;
|
|
455
|
-
|
|
456
|
-
const program = parse(source);
|
|
457
|
-
const mission = program.statements[0];
|
|
458
|
-
|
|
459
|
-
if (mission.type === 'MissionDefinition') {
|
|
460
|
-
const action = mission.actions[0];
|
|
461
|
-
const forStep = action.steps[0];
|
|
462
|
-
|
|
463
|
-
if (forStep.type === 'ForStep') {
|
|
464
|
-
expect(forStep.steps).toHaveLength(2);
|
|
465
|
-
|
|
466
|
-
const letStep = forStep.steps[0];
|
|
467
|
-
expect(letStep.type).toBe('LetStep');
|
|
468
|
-
if (letStep.type === 'LetStep') {
|
|
469
|
-
expect(letStep.name).toBe('itemId');
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
// ============================================
|
|
476
|
-
// Parse-time validation tests
|
|
477
|
-
// ============================================
|
|
478
|
-
|
|
479
|
-
describe('parse-time validation', () => {
|
|
480
|
-
it('throws error for undefined store reference', () => {
|
|
481
|
-
const source = `
|
|
482
|
-
mission TestMission {
|
|
483
|
-
source API {
|
|
484
|
-
auth: bearer,
|
|
485
|
-
base: "https://api.example.com"
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
store items: memory("items")
|
|
489
|
-
|
|
490
|
-
action FetchItems {
|
|
491
|
-
get "/items"
|
|
492
|
-
store response -> nonexistent { key: .id }
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
run FetchItems
|
|
496
|
-
}
|
|
497
|
-
`;
|
|
498
|
-
|
|
499
|
-
expect(() => parse(source)).toThrow(/Store 'nonexistent' is not defined/);
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
it('throws error for undefined action in pipeline', () => {
|
|
503
|
-
const source = `
|
|
504
|
-
mission TestMission {
|
|
505
|
-
source API {
|
|
506
|
-
auth: bearer,
|
|
507
|
-
base: "https://api.example.com"
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
store items: memory("items")
|
|
511
|
-
|
|
512
|
-
action FetchItems {
|
|
513
|
-
get "/items"
|
|
514
|
-
store response -> items { key: .id }
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
run NonexistentAction
|
|
518
|
-
}
|
|
519
|
-
`;
|
|
520
|
-
|
|
521
|
-
expect(() => parse(source)).toThrow(/Action 'NonexistentAction' is not defined/);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
it('throws error for undefined action in parallel pipeline', () => {
|
|
525
|
-
const source = `
|
|
526
|
-
mission TestMission {
|
|
527
|
-
source API {
|
|
528
|
-
auth: bearer,
|
|
529
|
-
base: "https://api.example.com"
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
store items: memory("items")
|
|
533
|
-
|
|
534
|
-
action FetchItems {
|
|
535
|
-
get "/items"
|
|
536
|
-
store response -> items { key: .id }
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
run [FetchItems, MissingAction]
|
|
540
|
-
}
|
|
541
|
-
`;
|
|
542
|
-
|
|
543
|
-
expect(() => parse(source)).toThrow(/Action 'MissingAction' is not defined/);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
it('throws error for undefined source in fetch step', () => {
|
|
547
|
-
const source = `
|
|
548
|
-
mission TestMission {
|
|
549
|
-
source API {
|
|
550
|
-
auth: bearer,
|
|
551
|
-
base: "https://api.example.com"
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
store items: memory("items")
|
|
555
|
-
|
|
556
|
-
action FetchItems {
|
|
557
|
-
get "/items" {
|
|
558
|
-
source: NonexistentSource
|
|
559
|
-
}
|
|
560
|
-
store response -> items { key: .id }
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
run FetchItems
|
|
564
|
-
}
|
|
565
|
-
`;
|
|
566
|
-
|
|
567
|
-
expect(() => parse(source)).toThrow(/Source 'NonexistentSource' is not defined/);
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
it('throws error for undefined source in call step operationRef', () => {
|
|
571
|
-
const source = `
|
|
572
|
-
mission TestMission {
|
|
573
|
-
source API {
|
|
574
|
-
auth: bearer,
|
|
575
|
-
base: "https://api.example.com"
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
store items: memory("items")
|
|
579
|
-
|
|
580
|
-
action FetchItems {
|
|
581
|
-
call NonexistentSource.getItems
|
|
582
|
-
store response -> items { key: .id }
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
run FetchItems
|
|
586
|
-
}
|
|
587
|
-
`;
|
|
588
|
-
|
|
589
|
-
expect(() => parse(source)).toThrow(/Source 'NonexistentSource' is not defined/);
|
|
590
|
-
});
|
|
591
|
-
|
|
592
|
-
it('throws error for undefined store in nested for loop', () => {
|
|
593
|
-
const source = `
|
|
594
|
-
mission TestMission {
|
|
595
|
-
source API {
|
|
596
|
-
auth: bearer,
|
|
597
|
-
base: "https://api.example.com"
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
store items: memory("items")
|
|
601
|
-
|
|
602
|
-
action ProcessItems {
|
|
603
|
-
for item in items {
|
|
604
|
-
get "/item/{item.id}"
|
|
605
|
-
store response -> missing_store { key: .id }
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
run ProcessItems
|
|
610
|
-
}
|
|
611
|
-
`;
|
|
612
|
-
|
|
613
|
-
expect(() => parse(source)).toThrow(/Store 'missing_store' is not defined/);
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
it('includes available stores in error message', () => {
|
|
617
|
-
const source = `
|
|
618
|
-
mission TestMission {
|
|
619
|
-
source API {
|
|
620
|
-
auth: bearer,
|
|
621
|
-
base: "https://api.example.com"
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
store items: memory("items")
|
|
625
|
-
store users: memory("users")
|
|
626
|
-
|
|
627
|
-
action FetchItems {
|
|
628
|
-
get "/items"
|
|
629
|
-
store response -> nonexistent { key: .id }
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
run FetchItems
|
|
633
|
-
}
|
|
634
|
-
`;
|
|
635
|
-
|
|
636
|
-
expect(() => parse(source)).toThrow(/Available stores: items, users/);
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
it('includes available actions in error message', () => {
|
|
640
|
-
const source = `
|
|
641
|
-
mission TestMission {
|
|
642
|
-
source API {
|
|
643
|
-
auth: bearer,
|
|
644
|
-
base: "https://api.example.com"
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
store items: memory("items")
|
|
648
|
-
|
|
649
|
-
action FetchItems {
|
|
650
|
-
get "/items"
|
|
651
|
-
store response -> items { key: .id }
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
action ProcessItems {
|
|
655
|
-
get "/process"
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
run MissingAction
|
|
659
|
-
}
|
|
660
|
-
`;
|
|
661
|
-
|
|
662
|
-
expect(() => parse(source)).toThrow(/Available actions: FetchItems, ProcessItems/);
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
it('accepts valid store references', () => {
|
|
666
|
-
const source = `
|
|
667
|
-
mission TestMission {
|
|
668
|
-
source API {
|
|
669
|
-
auth: bearer,
|
|
670
|
-
base: "https://api.example.com"
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
store items: memory("items")
|
|
674
|
-
store processed: memory("processed")
|
|
675
|
-
|
|
676
|
-
action FetchAndStore {
|
|
677
|
-
get "/items"
|
|
678
|
-
store response -> items { key: .id }
|
|
679
|
-
store response -> processed { key: .id }
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
run FetchAndStore
|
|
683
|
-
}
|
|
684
|
-
`;
|
|
685
|
-
|
|
686
|
-
expect(() => parse(source)).not.toThrow();
|
|
687
|
-
});
|
|
688
|
-
|
|
689
|
-
it('accepts valid action references in complex pipeline', () => {
|
|
690
|
-
const source = `
|
|
691
|
-
mission TestMission {
|
|
692
|
-
source API {
|
|
693
|
-
auth: bearer,
|
|
694
|
-
base: "https://api.example.com"
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
store items: memory("items")
|
|
698
|
-
|
|
699
|
-
action Step1 { get "/1" }
|
|
700
|
-
action Step2 { get "/2" }
|
|
701
|
-
action Step3 { get "/3" }
|
|
702
|
-
|
|
703
|
-
run Step1 then [Step2, Step3]
|
|
704
|
-
}
|
|
705
|
-
`;
|
|
706
|
-
|
|
707
|
-
expect(() => parse(source)).not.toThrow();
|
|
708
|
-
});
|
|
709
|
-
|
|
710
|
-
it('accepts valid source reference in fetch step', () => {
|
|
711
|
-
const source = `
|
|
712
|
-
mission TestMission {
|
|
713
|
-
source API {
|
|
714
|
-
auth: bearer,
|
|
715
|
-
base: "https://api.example.com"
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
source OtherAPI {
|
|
719
|
-
auth: bearer,
|
|
720
|
-
base: "https://other.example.com"
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
store items: memory("items")
|
|
724
|
-
|
|
725
|
-
action FetchItems {
|
|
726
|
-
get "/items" {
|
|
727
|
-
source: OtherAPI
|
|
728
|
-
}
|
|
729
|
-
store response -> items { key: .id }
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
run FetchItems
|
|
733
|
-
}
|
|
734
|
-
`;
|
|
735
|
-
|
|
736
|
-
expect(() => parse(source)).not.toThrow();
|
|
737
|
-
});
|
|
738
|
-
});
|
|
739
|
-
});
|