reqon-dsl 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +45 -3
- package/dist/ast/nodes.d.ts +91 -4
- package/dist/ast/nodes.js +14 -0
- package/dist/auth/circuit-breaker.d.ts +11 -0
- package/dist/auth/circuit-breaker.js +90 -18
- package/dist/auth/credentials.d.ts +6 -1
- package/dist/auth/credentials.js +12 -4
- package/dist/auth/oauth2-provider.js +13 -3
- package/dist/auth/rate-limiter.d.ts +12 -1
- package/dist/auth/rate-limiter.js +39 -26
- package/dist/auth/token-store.js +8 -1
- package/dist/cli.d.ts +24 -1
- package/dist/cli.js +149 -10
- package/dist/config/constants.d.ts +152 -0
- package/dist/config/constants.js +139 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.js +4 -0
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -0
- package/dist/control/server.d.ts +105 -0
- package/dist/control/server.js +315 -0
- package/dist/control/types.d.ts +61 -0
- package/dist/control/types.js +7 -0
- package/dist/debug/cli-debugger.d.ts +17 -0
- package/dist/debug/cli-debugger.js +185 -0
- package/dist/debug/controller.d.ts +94 -0
- package/dist/debug/controller.js +45 -0
- package/dist/debug/index.d.ts +6 -0
- package/dist/debug/index.js +5 -0
- package/dist/errors/index.d.ts +67 -0
- package/dist/errors/index.js +89 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/state.d.ts +24 -0
- package/dist/execution/store.js +2 -2
- package/dist/execution-log/events.d.ts +125 -0
- package/dist/execution-log/events.js +17 -0
- package/dist/execution-log/fold.d.ts +38 -0
- package/dist/execution-log/fold.js +54 -0
- package/dist/execution-log/index.d.ts +18 -0
- package/dist/execution-log/index.js +6 -0
- package/dist/execution-log/postgres-store.d.ts +36 -0
- package/dist/execution-log/postgres-store.js +108 -0
- package/dist/execution-log/resume.d.ts +11 -0
- package/dist/execution-log/resume.js +5 -0
- package/dist/execution-log/sqlite-store.d.ts +16 -0
- package/dist/execution-log/sqlite-store.js +101 -0
- package/dist/execution-log/store.d.ts +72 -0
- package/dist/execution-log/store.js +182 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.js +35 -3
- package/dist/interpreter/context.d.ts +29 -0
- package/dist/interpreter/context.js +18 -0
- package/dist/interpreter/evaluator.d.ts +63 -1
- package/dist/interpreter/evaluator.js +219 -42
- package/dist/interpreter/executor.d.ts +132 -14
- package/dist/interpreter/executor.js +883 -178
- package/dist/interpreter/fetch-handler.d.ts +48 -1
- package/dist/interpreter/fetch-handler.js +216 -38
- package/dist/interpreter/http.d.ts +34 -0
- package/dist/interpreter/http.js +203 -28
- package/dist/interpreter/index.d.ts +5 -3
- package/dist/interpreter/index.js +4 -2
- package/dist/interpreter/pagination.d.ts +12 -3
- package/dist/interpreter/pagination.js +102 -32
- package/dist/interpreter/signals.d.ts +8 -0
- package/dist/interpreter/signals.js +12 -0
- package/dist/interpreter/source-manager.d.ts +75 -0
- package/dist/interpreter/source-manager.js +157 -0
- package/dist/interpreter/step-handlers/apply-handler.d.ts +29 -0
- package/dist/interpreter/step-handlers/apply-handler.js +79 -0
- package/dist/interpreter/step-handlers/for-handler.d.ts +16 -0
- package/dist/interpreter/step-handlers/for-handler.js +89 -7
- package/dist/interpreter/step-handlers/index.d.ts +4 -2
- package/dist/interpreter/step-handlers/index.js +4 -2
- package/dist/interpreter/step-handlers/match-handler.d.ts +9 -0
- package/dist/interpreter/step-handlers/match-handler.js +47 -17
- package/dist/interpreter/step-handlers/pause-handler.d.ts +52 -0
- package/dist/interpreter/step-handlers/pause-handler.js +87 -0
- package/dist/interpreter/step-handlers/store-handler.d.ts +17 -1
- package/dist/interpreter/step-handlers/store-handler.js +61 -20
- package/dist/interpreter/step-handlers/types.d.ts +3 -0
- package/dist/interpreter/step-handlers/validate-handler.d.ts +2 -1
- package/dist/interpreter/step-handlers/validate-handler.js +7 -2
- package/dist/interpreter/step-handlers/webhook-handler.d.ts +4 -0
- package/dist/interpreter/step-handlers/webhook-handler.js +31 -5
- package/dist/interpreter/store-manager.d.ts +46 -0
- package/dist/interpreter/store-manager.js +70 -0
- package/dist/lexer/index.d.ts +11 -4
- package/dist/lexer/index.js +11 -4
- package/dist/lexer/tokens.d.ts +17 -1
- package/dist/lexer/tokens.js +36 -0
- package/dist/loader/index.js +5 -8
- package/dist/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/sandbox.d.ts +41 -0
- package/dist/mcp/sandbox.js +76 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.js +504 -0
- package/dist/oas/index.d.ts +2 -0
- package/dist/oas/index.js +1 -0
- package/dist/oas/loader.d.ts +13 -1
- package/dist/oas/loader.js +25 -3
- package/dist/oas/mock-generator.d.ts +12 -0
- package/dist/oas/mock-generator.js +196 -0
- package/dist/oas/validator.js +45 -5
- package/dist/observability/events.d.ts +248 -0
- package/dist/observability/events.js +85 -0
- package/dist/observability/index.d.ts +15 -0
- package/dist/observability/index.js +12 -0
- package/dist/observability/logger.d.ts +106 -0
- package/dist/observability/logger.js +266 -0
- package/dist/observability/otel.d.ts +143 -0
- package/dist/observability/otel.js +421 -0
- package/dist/parser/action-parser.d.ts +105 -0
- package/dist/parser/action-parser.js +645 -0
- package/dist/parser/base.d.ts +7 -0
- package/dist/parser/base.js +11 -0
- package/dist/parser/expressions.d.ts +14 -0
- package/dist/parser/expressions.js +89 -6
- package/dist/parser/fetch-parser.d.ts +27 -0
- package/dist/parser/fetch-parser.js +280 -0
- package/dist/parser/index.d.ts +17 -0
- package/dist/parser/index.js +17 -0
- package/dist/parser/parser.d.ts +44 -46
- package/dist/parser/parser.js +122 -1070
- package/dist/parser/pipeline-parser.d.ts +12 -0
- package/dist/parser/pipeline-parser.js +52 -0
- package/dist/parser/schedule-parser.d.ts +7 -0
- package/dist/parser/schedule-parser.js +137 -0
- package/dist/parser/source-parser.d.ts +9 -0
- package/dist/parser/source-parser.js +151 -0
- package/dist/pause/index.d.ts +15 -0
- package/dist/pause/index.js +12 -0
- package/dist/pause/log-store.d.ts +33 -0
- package/dist/pause/log-store.js +98 -0
- package/dist/pause/manager.d.ts +130 -0
- package/dist/pause/manager.js +294 -0
- package/dist/pause/state.d.ts +93 -0
- package/dist/pause/state.js +103 -0
- package/dist/pause/store.d.ts +61 -0
- package/dist/pause/store.js +158 -0
- package/dist/plugin.d.ts +9 -12
- package/dist/plugin.js +10 -13
- package/dist/scheduler/cron-parser.d.ts +10 -3
- package/dist/scheduler/cron-parser.js +227 -48
- package/dist/scheduler/scheduler.js +56 -22
- package/dist/stores/factory.d.ts +7 -1
- package/dist/stores/factory.js +14 -3
- package/dist/stores/file.d.ts +26 -0
- package/dist/stores/file.js +67 -21
- package/dist/stores/index.d.ts +16 -1
- package/dist/stores/index.js +16 -1
- package/dist/stores/memory.d.ts +4 -0
- package/dist/stores/memory.js +8 -6
- package/dist/stores/postgrest.d.ts +28 -0
- package/dist/stores/postgrest.js +84 -37
- package/dist/stores/types.d.ts +17 -0
- package/dist/stores/types.js +12 -0
- package/dist/sync/index.d.ts +3 -2
- package/dist/sync/index.js +2 -1
- package/dist/sync/log-store.d.ts +30 -0
- package/dist/sync/log-store.js +45 -0
- package/dist/sync/store.js +1 -1
- package/dist/trace/index.d.ts +18 -0
- package/dist/trace/index.js +13 -0
- package/dist/trace/log-view.d.ts +57 -0
- package/dist/trace/log-view.js +76 -0
- package/dist/trace/recorder.d.ts +75 -0
- package/dist/trace/recorder.js +157 -0
- package/dist/trace/replay.d.ts +132 -0
- package/dist/trace/replay.js +264 -0
- package/dist/trace/state.d.ts +102 -0
- package/dist/trace/state.js +86 -0
- package/dist/trace/store.d.ts +75 -0
- package/dist/trace/store.js +250 -0
- package/dist/utils/deep-merge.d.ts +10 -0
- package/dist/utils/deep-merge.js +23 -0
- package/dist/utils/file.d.ts +13 -4
- package/dist/utils/file.js +70 -12
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/long-timeout.d.ts +19 -0
- package/dist/utils/long-timeout.js +33 -0
- package/dist/utils/path.d.ts +22 -1
- package/dist/utils/path.js +46 -1
- package/dist/utils/redact.d.ts +22 -0
- package/dist/utils/redact.js +42 -0
- package/dist/utils/type-guards.d.ts +58 -0
- package/dist/utils/type-guards.js +92 -0
- package/dist/webhook/server.d.ts +9 -0
- package/dist/webhook/server.js +122 -36
- package/dist/webhook/types.d.ts +9 -1
- package/package.json +76 -9
- package/.claude/settings.local.json +0 -31
- package/.claude/skills/api-integration.md +0 -125
- package/.claude/skills/database-schema.md +0 -51
- package/.claude/skills/dsl-design.md +0 -80
- package/.claude/skills/property-testing.md +0 -143
- package/.claude/skills/reqon/SKILL.md +0 -44
- package/.claude/skills/reqon/references/examples.md +0 -206
- package/.claude/skills/reqon/references/syntax.md +0 -263
- package/.claude/skills/vscode-extension.md +0 -113
- package/.github/dependabot.yml +0 -32
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/ci.yml +0 -174
- package/.github/workflows/release.yml +0 -73
- package/CLAUDE.md +0 -72
- package/CONTRIBUTING.md +0 -161
- package/TODO.md +0 -51
- package/dist/auth/auth.test.d.ts +0 -1
- package/dist/auth/auth.test.js +0 -255
- package/dist/errors/errors.test.d.ts +0 -1
- package/dist/errors/errors.test.js +0 -165
- package/dist/execution/execution.test.d.ts +0 -1
- package/dist/execution/execution.test.js +0 -246
- package/dist/integration.test.d.ts +0 -1
- package/dist/integration.test.js +0 -168
- package/dist/interpreter/evaluator.test.d.ts +0 -1
- package/dist/interpreter/evaluator.test.js +0 -512
- package/dist/interpreter/http.test.d.ts +0 -1
- package/dist/interpreter/http.test.js +0 -299
- package/dist/interpreter/progress.test.d.ts +0 -1
- package/dist/interpreter/progress.test.js +0 -216
- package/dist/interpreter/schema-matcher.test.d.ts +0 -1
- package/dist/interpreter/schema-matcher.test.js +0 -122
- package/dist/lexer/lexer.d.ts +0 -24
- package/dist/lexer/lexer.js +0 -264
- package/dist/lexer/lexer.test.d.ts +0 -1
- package/dist/lexer/lexer.test.js +0 -259
- package/dist/loader/loader.test.d.ts +0 -1
- package/dist/loader/loader.test.js +0 -287
- package/dist/oas/oas.test.d.ts +0 -1
- package/dist/oas/oas.test.js +0 -218
- package/dist/parser/expressions.test.d.ts +0 -1
- package/dist/parser/expressions.test.js +0 -378
- package/dist/parser/match.test.d.ts +0 -1
- package/dist/parser/match.test.js +0 -254
- package/dist/parser/parser.test.d.ts +0 -1
- package/dist/parser/parser.test.js +0 -333
- package/dist/parser/schedule.test.d.ts +0 -1
- package/dist/parser/schedule.test.js +0 -241
- package/dist/scheduler/cron-parser.test.d.ts +0 -1
- package/dist/scheduler/cron-parser.test.js +0 -188
- package/dist/stores/file.test.d.ts +0 -1
- package/dist/stores/file.test.js +0 -165
- package/dist/stores/memory.test.d.ts +0 -1
- package/dist/stores/memory.test.js +0 -157
- package/dist/stores/stores.test.d.ts +0 -1
- package/dist/stores/stores.test.js +0 -158
- package/dist/sync/sync.test.d.ts +0 -1
- package/dist/sync/sync.test.js +0 -221
- package/docusaurus/README.md +0 -41
- package/docusaurus/docs/advanced/execution-state.md +0 -283
- package/docusaurus/docs/advanced/extending-reqon.md +0 -388
- package/docusaurus/docs/advanced/multi-file-missions.md +0 -250
- package/docusaurus/docs/advanced/parallel-execution.md +0 -353
- package/docusaurus/docs/api-reference.md +0 -443
- package/docusaurus/docs/authentication/api-key.md +0 -339
- package/docusaurus/docs/authentication/basic.md +0 -276
- package/docusaurus/docs/authentication/bearer.md +0 -282
- package/docusaurus/docs/authentication/oauth2.md +0 -317
- package/docusaurus/docs/authentication/overview.md +0 -251
- package/docusaurus/docs/cli.md +0 -229
- package/docusaurus/docs/core-concepts/actions.md +0 -286
- package/docusaurus/docs/core-concepts/missions.md +0 -264
- package/docusaurus/docs/core-concepts/schemas.md +0 -353
- package/docusaurus/docs/core-concepts/sources.md +0 -339
- package/docusaurus/docs/core-concepts/stores.md +0 -332
- package/docusaurus/docs/dsl-syntax/expressions.md +0 -361
- package/docusaurus/docs/dsl-syntax/fetch.md +0 -293
- package/docusaurus/docs/dsl-syntax/for-loops.md +0 -324
- package/docusaurus/docs/dsl-syntax/map.md +0 -345
- package/docusaurus/docs/dsl-syntax/match.md +0 -387
- package/docusaurus/docs/dsl-syntax/pipelines.md +0 -397
- package/docusaurus/docs/dsl-syntax/validate.md +0 -401
- package/docusaurus/docs/error-handling/dead-letter-queues.md +0 -399
- package/docusaurus/docs/error-handling/flow-control.md +0 -337
- package/docusaurus/docs/error-handling/retry-strategies.md +0 -368
- package/docusaurus/docs/examples.md +0 -488
- package/docusaurus/docs/getting-started.md +0 -256
- package/docusaurus/docs/http/circuit-breaker.md +0 -401
- package/docusaurus/docs/http/incremental-sync.md +0 -394
- package/docusaurus/docs/http/pagination.md +0 -361
- package/docusaurus/docs/http/rate-limiting.md +0 -383
- package/docusaurus/docs/http/requests.md +0 -328
- package/docusaurus/docs/http/retry.md +0 -402
- package/docusaurus/docs/intro.md +0 -90
- package/docusaurus/docs/openapi/loading-specs.md +0 -305
- package/docusaurus/docs/openapi/operation-calls.md +0 -314
- package/docusaurus/docs/openapi/overview.md +0 -212
- package/docusaurus/docs/openapi/response-validation.md +0 -344
- package/docusaurus/docs/scheduling/cron.md +0 -305
- package/docusaurus/docs/scheduling/daemon-mode.md +0 -317
- package/docusaurus/docs/scheduling/intervals.md +0 -289
- package/docusaurus/docs/scheduling/overview.md +0 -231
- package/docusaurus/docs/stores/custom-adapters.md +0 -376
- package/docusaurus/docs/stores/file.md +0 -236
- package/docusaurus/docs/stores/memory.md +0 -193
- package/docusaurus/docs/stores/overview.md +0 -274
- package/docusaurus/docs/stores/postgrest.md +0 -316
- package/docusaurus/docusaurus.config.ts +0 -148
- package/docusaurus/package-lock.json +0 -18029
- package/docusaurus/package.json +0 -47
- package/docusaurus/sidebars.ts +0 -155
- package/docusaurus/src/components/HomepageFeatures/index.tsx +0 -105
- package/docusaurus/src/components/HomepageFeatures/styles.module.css +0 -12
- package/docusaurus/src/css/custom.css +0 -169
- package/docusaurus/src/pages/index.module.css +0 -48
- package/docusaurus/src/pages/index.tsx +0 -110
- package/docusaurus/src/pages/markdown-page.md +0 -7
- package/docusaurus/static/.nojekyll +0 -0
- package/docusaurus/static/img/docusaurus-social-card.jpg +0 -0
- package/docusaurus/static/img/docusaurus.png +0 -0
- package/docusaurus/static/img/favicon.ico +0 -0
- package/docusaurus/static/img/logo.svg +0 -10
- package/docusaurus/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docusaurus/static/img/undraw_docusaurus_react.svg +0 -170
- package/docusaurus/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docusaurus/tsconfig.json +0 -8
- package/examples/README.md +0 -112
- package/examples/error-handling/README.md +0 -150
- package/examples/error-handling/payment-processor.vague +0 -287
- package/examples/github-sync/README.md +0 -74
- package/examples/github-sync/fetch-issues.vague +0 -47
- package/examples/github-sync/fetch-prs.vague +0 -40
- package/examples/github-sync/mission.vague +0 -101
- package/examples/github-sync/normalize.vague +0 -70
- package/examples/jsonplaceholder/README.md +0 -28
- package/examples/jsonplaceholder/posts.vague +0 -48
- package/examples/petstore/README.md +0 -35
- package/examples/petstore/openapi.yaml +0 -97
- package/examples/petstore/sync.vague +0 -52
- package/examples/temporal-comparison/README.md +0 -297
- package/examples/temporal-comparison/reconciliation.vague +0 -355
- package/examples/temporal-comparison/temporal/activities/index.ts +0 -8
- package/examples/temporal-comparison/temporal/activities/shipstation.ts +0 -225
- package/examples/temporal-comparison/temporal/activities/shopify.ts +0 -257
- package/examples/temporal-comparison/temporal/activities/storage.ts +0 -198
- package/examples/temporal-comparison/temporal/activities/stripe.ts +0 -169
- package/examples/temporal-comparison/temporal/activities/validation.ts +0 -205
- package/examples/temporal-comparison/temporal/client/schedule.ts +0 -218
- package/examples/temporal-comparison/temporal/config/retry.ts +0 -63
- package/examples/temporal-comparison/temporal/types/index.ts +0 -129
- package/examples/temporal-comparison/temporal/workers/main.ts +0 -130
- package/examples/temporal-comparison/temporal/workflows/orderReconciliation.ts +0 -262
- package/examples/xero/README.md +0 -88
- package/examples/xero/invoices.vague +0 -189
- package/src/api-integration.test.ts +0 -954
- package/src/ast/index.ts +0 -1
- package/src/ast/nodes.ts +0 -310
- package/src/auth/auth.test.ts +0 -326
- package/src/auth/circuit-breaker.test.ts +0 -390
- package/src/auth/circuit-breaker.ts +0 -379
- package/src/auth/credentials.test.ts +0 -273
- package/src/auth/credentials.ts +0 -246
- package/src/auth/index.ts +0 -40
- package/src/auth/oauth2-provider.ts +0 -177
- package/src/auth/rate-limiter.ts +0 -459
- package/src/auth/token-store.ts +0 -177
- package/src/auth/types.ts +0 -159
- package/src/benchmark/e2e.bench.ts +0 -288
- package/src/benchmark/evaluator.bench.ts +0 -331
- package/src/benchmark/fixtures.ts +0 -295
- package/src/benchmark/index.ts +0 -108
- package/src/benchmark/lexer.bench.ts +0 -69
- package/src/benchmark/parser.bench.ts +0 -103
- package/src/benchmark/resilience.bench.ts +0 -193
- package/src/benchmark/store.bench.ts +0 -147
- package/src/benchmark/utils.ts +0 -230
- package/src/cli.ts +0 -313
- package/src/errors/errors.test.ts +0 -234
- package/src/errors/index.ts +0 -223
- package/src/execution/execution.test.ts +0 -307
- package/src/execution/index.ts +0 -21
- package/src/execution/state.ts +0 -207
- package/src/execution/store.ts +0 -188
- package/src/index.ts +0 -169
- package/src/integration.test.ts +0 -192
- package/src/interpreter/context.ts +0 -57
- package/src/interpreter/evaluator.test.ts +0 -796
- package/src/interpreter/evaluator.ts +0 -245
- package/src/interpreter/executor.ts +0 -946
- package/src/interpreter/fetch-handler.ts +0 -302
- package/src/interpreter/http.test.ts +0 -423
- package/src/interpreter/http.ts +0 -308
- package/src/interpreter/index.ts +0 -32
- package/src/interpreter/pagination.ts +0 -207
- package/src/interpreter/progress.test.ts +0 -276
- package/src/interpreter/schema-matcher.test.ts +0 -160
- package/src/interpreter/schema-matcher.ts +0 -168
- package/src/interpreter/signals.ts +0 -73
- package/src/interpreter/step-handlers/for-handler.ts +0 -65
- package/src/interpreter/step-handlers/index.ts +0 -17
- package/src/interpreter/step-handlers/map-handler.ts +0 -24
- package/src/interpreter/step-handlers/match-handler.ts +0 -101
- package/src/interpreter/step-handlers/store-handler.ts +0 -78
- package/src/interpreter/step-handlers/types.ts +0 -17
- package/src/interpreter/step-handlers/validate-handler.ts +0 -30
- package/src/interpreter/step-handlers/webhook-handler.ts +0 -142
- package/src/lexer/index.ts +0 -18
- package/src/lexer/lexer.test.ts +0 -316
- package/src/lexer/tokens.ts +0 -179
- package/src/loader/index.ts +0 -288
- package/src/loader/loader.test.ts +0 -360
- package/src/oas/index.ts +0 -4
- package/src/oas/loader.ts +0 -126
- package/src/oas/oas.test.ts +0 -254
- package/src/oas/validator.ts +0 -299
- package/src/parser/base.ts +0 -124
- package/src/parser/expressions.test.ts +0 -525
- package/src/parser/expressions.ts +0 -314
- package/src/parser/index.ts +0 -3
- package/src/parser/match.test.ts +0 -296
- package/src/parser/parser.test.ts +0 -739
- package/src/parser/parser.ts +0 -1469
- package/src/parser/schedule.test.ts +0 -287
- package/src/parser/webhook.test.ts +0 -248
- package/src/plugin.ts +0 -83
- package/src/scheduler/cron-parser.test.ts +0 -236
- package/src/scheduler/cron-parser.ts +0 -236
- package/src/scheduler/index.ts +0 -10
- package/src/scheduler/scheduler.ts +0 -443
- package/src/scheduler/types.ts +0 -71
- package/src/stores/factory.ts +0 -104
- package/src/stores/file.test.ts +0 -276
- package/src/stores/file.ts +0 -211
- package/src/stores/index.ts +0 -6
- package/src/stores/memory.test.ts +0 -238
- package/src/stores/memory.ts +0 -63
- package/src/stores/postgrest.test.ts +0 -488
- package/src/stores/postgrest.ts +0 -263
- package/src/stores/stores.test.ts +0 -197
- package/src/stores/types.ts +0 -58
- package/src/sync/index.ts +0 -16
- package/src/sync/state.ts +0 -126
- package/src/sync/store.ts +0 -139
- package/src/sync/sync.test.ts +0 -271
- package/src/utils/async.ts +0 -10
- package/src/utils/file.ts +0 -106
- package/src/utils/index.ts +0 -14
- package/src/utils/logger.ts +0 -53
- package/src/utils/path.ts +0 -47
- package/src/webhook/index.ts +0 -15
- package/src/webhook/server.test.ts +0 -253
- package/src/webhook/server.ts +0 -389
- package/src/webhook/store.ts +0 -239
- package/src/webhook/types.ts +0 -93
- package/tsconfig.json +0 -17
- package/vitest.config.ts +0 -39
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { readFile,
|
|
1
|
+
import { readFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { writeFileAtomic } from '../utils/file.js';
|
|
3
4
|
import { MissionExecutor } from '../interpreter/executor.js';
|
|
4
5
|
import { getNextRunTime, shouldRunNow } from './cron-parser.js';
|
|
6
|
+
import { setLongTimeout } from '../utils/long-timeout.js';
|
|
5
7
|
/**
|
|
6
8
|
* Scheduler for running missions on a schedule
|
|
7
9
|
*/
|
|
@@ -35,9 +37,18 @@ export class Scheduler {
|
|
|
35
37
|
throw new Error(`Mission '${mission.name}' has no schedule defined`);
|
|
36
38
|
}
|
|
37
39
|
this.missions.set(mission.name, { mission, filePath });
|
|
38
|
-
// Create or update job state
|
|
40
|
+
// Create or update job state. A schedule that can never produce a next run
|
|
41
|
+
// (e.g. an impossible cron like Feb 31) must not abort registration — the
|
|
42
|
+
// job is registered with an undefined nextRun and the check loop isolates
|
|
43
|
+
// it so it can't starve sibling jobs.
|
|
39
44
|
const existingJob = this.state.jobs[mission.name];
|
|
40
|
-
|
|
45
|
+
let nextRun = null;
|
|
46
|
+
try {
|
|
47
|
+
nextRun = getNextRunTime(mission.schedule);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
this.log(`Mission '${mission.name}' has an unschedulable cron: ${error.message}`);
|
|
51
|
+
}
|
|
41
52
|
this.state.jobs[mission.name] = {
|
|
42
53
|
id: mission.name,
|
|
43
54
|
missionName: mission.name,
|
|
@@ -97,7 +108,7 @@ export class Scheduler {
|
|
|
97
108
|
}
|
|
98
109
|
// Clear all pending retry timers to prevent memory leaks
|
|
99
110
|
for (const timer of this.retryTimers) {
|
|
100
|
-
|
|
111
|
+
timer.clear();
|
|
101
112
|
}
|
|
102
113
|
this.retryTimers.clear();
|
|
103
114
|
// Save state
|
|
@@ -109,19 +120,25 @@ export class Scheduler {
|
|
|
109
120
|
*/
|
|
110
121
|
async checkAndRun() {
|
|
111
122
|
const now = new Date();
|
|
123
|
+
// Each job is isolated: a throw while evaluating one schedule (e.g. an
|
|
124
|
+
// impossible cron) must not break the loop and starve siblings. Due jobs
|
|
125
|
+
// are dispatched without awaiting so a slow mission can't head-of-line
|
|
126
|
+
// block the rest of the tick.
|
|
112
127
|
for (const [name, job] of Object.entries(this.state.jobs)) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
128
|
+
try {
|
|
129
|
+
if (!job.enabled)
|
|
130
|
+
continue;
|
|
131
|
+
const scheduledMission = this.missions.get(name);
|
|
132
|
+
if (!scheduledMission)
|
|
133
|
+
continue;
|
|
134
|
+
const schedule = scheduledMission.mission.schedule;
|
|
135
|
+
if (!schedule)
|
|
136
|
+
continue; // Mission must have schedule
|
|
137
|
+
// Check if job should run
|
|
138
|
+
if (!shouldRunNow(schedule, job.lastRun, this.config.checkInterval))
|
|
139
|
+
continue;
|
|
123
140
|
// Check if already running
|
|
124
|
-
if (job.isRunning &&
|
|
141
|
+
if (job.isRunning && schedule.skipIfRunning !== false) {
|
|
125
142
|
this.emitEvent({
|
|
126
143
|
type: 'skipped',
|
|
127
144
|
jobId: job.id,
|
|
@@ -131,8 +148,14 @@ export class Scheduler {
|
|
|
131
148
|
});
|
|
132
149
|
continue;
|
|
133
150
|
}
|
|
134
|
-
//
|
|
135
|
-
|
|
151
|
+
// Dispatch without awaiting: the loop keeps checking other jobs while
|
|
152
|
+
// this mission runs. Failures are handled inside runJob.
|
|
153
|
+
void this.runJob(job, scheduledMission).catch((error) => {
|
|
154
|
+
this.log(`Job '${name}' run error: ${error.message}`);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.log(`Error checking job '${name}': ${error.message}`);
|
|
136
159
|
}
|
|
137
160
|
}
|
|
138
161
|
}
|
|
@@ -206,8 +229,16 @@ export class Scheduler {
|
|
|
206
229
|
}
|
|
207
230
|
finally {
|
|
208
231
|
job.isRunning = false;
|
|
209
|
-
// Calculate next run time
|
|
210
|
-
|
|
232
|
+
// Calculate next run time; never let an unschedulable cron throw out of
|
|
233
|
+
// the finally block and mask the run's real outcome.
|
|
234
|
+
try {
|
|
235
|
+
job.nextRun =
|
|
236
|
+
getNextRunTime(scheduledMission.mission.schedule, new Date()) ?? undefined;
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
job.nextRun = undefined;
|
|
240
|
+
this.log(`Could not compute next run for '${job.missionName}': ${error.message}`);
|
|
241
|
+
}
|
|
211
242
|
await this.saveState();
|
|
212
243
|
}
|
|
213
244
|
}
|
|
@@ -221,8 +252,9 @@ export class Scheduler {
|
|
|
221
252
|
if (job.consecutiveFailures <= retryConfig.maxRetries) {
|
|
222
253
|
this.log(`Job '${job.missionName}' failed, retrying in ${retryConfig.delaySeconds}s ` +
|
|
223
254
|
`(attempt ${job.consecutiveFailures}/${retryConfig.maxRetries})`);
|
|
224
|
-
// Schedule retry and track the timer to prevent memory leaks
|
|
225
|
-
|
|
255
|
+
// Schedule retry and track the timer to prevent memory leaks. Use a
|
|
256
|
+
// long-delay-safe timer so a large retry delay can't overflow setTimeout.
|
|
257
|
+
const timer = setLongTimeout(() => {
|
|
226
258
|
this.retryTimers.delete(timer);
|
|
227
259
|
const scheduledMission = this.missions.get(job.missionName);
|
|
228
260
|
if (scheduledMission && this.running) {
|
|
@@ -318,7 +350,9 @@ export class Scheduler {
|
|
|
318
350
|
try {
|
|
319
351
|
await mkdir(this.config.stateDir, { recursive: true });
|
|
320
352
|
const statePath = join(this.config.stateDir, 'state.json');
|
|
321
|
-
|
|
353
|
+
// Atomic write (temp file + fsync + rename) so a crash mid-write can't
|
|
354
|
+
// truncate or corrupt state.json.
|
|
355
|
+
await writeFileAtomic(statePath, JSON.stringify(this.state, null, 2));
|
|
322
356
|
}
|
|
323
357
|
catch (error) {
|
|
324
358
|
this.log(`Failed to save scheduler state: ${error.message}`);
|
package/dist/stores/factory.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ export interface CreateStoreOptions {
|
|
|
16
16
|
postgrest?: Omit<PostgRESTOptions, 'table'>;
|
|
17
17
|
/** Logger instance */
|
|
18
18
|
logger?: Logger;
|
|
19
|
+
/**
|
|
20
|
+
* Explicitly allow sql/nosql to fall back to a local file store. Without
|
|
21
|
+
* this, an unimplemented sql/nosql store hard-errors rather than silently
|
|
22
|
+
* writing JSON to disk (a data-loss trap).
|
|
23
|
+
*/
|
|
24
|
+
allowFileFallback?: boolean;
|
|
19
25
|
}
|
|
20
26
|
/**
|
|
21
27
|
* Create a store adapter based on type
|
|
@@ -33,4 +39,4 @@ export declare function createStore(options: CreateStoreOptions): StoreAdapter;
|
|
|
33
39
|
* Map DSL store type to adapter type
|
|
34
40
|
* In development mode, sql/nosql fall back to file stores
|
|
35
41
|
*/
|
|
36
|
-
export declare function resolveStoreType(dslType: 'sql' | 'nosql' | 'memory', developmentMode?: boolean): StoreType;
|
|
42
|
+
export declare function resolveStoreType(dslType: 'sql' | 'nosql' | 'memory' | 'file' | 'postgrest', developmentMode?: boolean): StoreType;
|
package/dist/stores/factory.js
CHANGED
|
@@ -40,6 +40,11 @@ export function createStore(options) {
|
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
// TODO: Implement raw SQL adapter (pg, mysql2, etc.)
|
|
43
|
+
if (!options.allowFileFallback) {
|
|
44
|
+
throw new Error(`SQL store is not implemented. Configure a PostgREST/Supabase backend, or ` +
|
|
45
|
+
`opt into the local file fallback (enable development mode / allowFileFallback) ` +
|
|
46
|
+
`for store '${options.name}'.`);
|
|
47
|
+
}
|
|
43
48
|
logger.warn(`SQL store not yet implemented, falling back to file store for '${options.name}'`);
|
|
44
49
|
return new FileStore(options.name, {
|
|
45
50
|
...options.fileOptions,
|
|
@@ -47,6 +52,11 @@ export function createStore(options) {
|
|
|
47
52
|
});
|
|
48
53
|
case 'nosql':
|
|
49
54
|
// TODO: Implement NoSQL adapter
|
|
55
|
+
if (!options.allowFileFallback) {
|
|
56
|
+
throw new Error(`NoSQL store is not implemented. Configure a real backend, or opt into the ` +
|
|
57
|
+
`local file fallback (enable development mode / allowFileFallback) for ` +
|
|
58
|
+
`store '${options.name}'.`);
|
|
59
|
+
}
|
|
50
60
|
logger.warn(`NoSQL store not yet implemented, falling back to file store for '${options.name}'`);
|
|
51
61
|
return new FileStore(options.name, {
|
|
52
62
|
...options.fileOptions,
|
|
@@ -60,9 +70,10 @@ export function createStore(options) {
|
|
|
60
70
|
* Map DSL store type to adapter type
|
|
61
71
|
* In development mode, sql/nosql fall back to file stores
|
|
62
72
|
*/
|
|
63
|
-
export function resolveStoreType(dslType, developmentMode =
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
export function resolveStoreType(dslType, developmentMode = false) {
|
|
74
|
+
// These types are used directly
|
|
75
|
+
if (dslType === 'memory' || dslType === 'file' || dslType === 'postgrest') {
|
|
76
|
+
return dslType;
|
|
66
77
|
}
|
|
67
78
|
if (developmentMode) {
|
|
68
79
|
// Use file stores for local development
|
package/dist/stores/file.d.ts
CHANGED
|
@@ -12,6 +12,9 @@ export interface FileStoreOptions {
|
|
|
12
12
|
/**
|
|
13
13
|
* File-based JSON store for local development
|
|
14
14
|
* Persists data to .reqon-data/{name}.json
|
|
15
|
+
*
|
|
16
|
+
* Use FileStore.create() for async initialization (recommended),
|
|
17
|
+
* or new FileStore() for lazy initialization (backward compatible).
|
|
15
18
|
*/
|
|
16
19
|
export declare class FileStore implements StoreAdapter {
|
|
17
20
|
private data;
|
|
@@ -19,9 +22,28 @@ export declare class FileStore implements StoreAdapter {
|
|
|
19
22
|
private options;
|
|
20
23
|
private dirty;
|
|
21
24
|
private initialized;
|
|
25
|
+
private initError;
|
|
22
26
|
private debounceTimer;
|
|
23
27
|
private pendingWrite;
|
|
28
|
+
/**
|
|
29
|
+
* Create a FileStore with async initialization (recommended).
|
|
30
|
+
* The store is fully initialized when the promise resolves.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const store = await FileStore.create('my-store', { baseDir: '.data' });
|
|
34
|
+
*/
|
|
35
|
+
static create(name: string, options?: FileStoreOptions): Promise<FileStore>;
|
|
36
|
+
/**
|
|
37
|
+
* Constructor for lazy initialization (backward compatible).
|
|
38
|
+
* Each operation will wait for initialization to complete.
|
|
39
|
+
* Prefer FileStore.create() for explicit async initialization.
|
|
40
|
+
*/
|
|
24
41
|
constructor(name: string, options?: FileStoreOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Ensure the store is initialized. Safe to call multiple times.
|
|
44
|
+
* Throws if initialization previously failed.
|
|
45
|
+
*/
|
|
46
|
+
private ensureInitialized;
|
|
25
47
|
private init;
|
|
26
48
|
private load;
|
|
27
49
|
private persist;
|
|
@@ -35,6 +57,10 @@ export declare class FileStore implements StoreAdapter {
|
|
|
35
57
|
key: string;
|
|
36
58
|
value: Record<string, unknown>;
|
|
37
59
|
}>): Promise<void>;
|
|
60
|
+
bulkUpsert(records: Array<{
|
|
61
|
+
key: string;
|
|
62
|
+
value: Record<string, unknown>;
|
|
63
|
+
}>): Promise<void>;
|
|
38
64
|
update(key: string, value: Partial<Record<string, unknown>>): Promise<void>;
|
|
39
65
|
delete(key: string): Promise<void>;
|
|
40
66
|
list(filter?: StoreFilter): Promise<Record<string, unknown>[]>;
|
package/dist/stores/file.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { writeFile } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
4
|
import { applyStoreFilter } from './types.js';
|
|
5
|
-
import { ensureDirectory, readJsonFile, serialize, } from '../utils/file.js';
|
|
5
|
+
import { ensureDirectory, readJsonFile, serialize, writeFileAtomic, writeFileAtomicSync, } from '../utils/file.js';
|
|
6
|
+
import { safeJoin } from '../utils/path.js';
|
|
7
|
+
import { deepMerge } from '../utils/deep-merge.js';
|
|
6
8
|
const DEFAULT_OPTIONS = {
|
|
7
9
|
baseDir: '.reqon-data',
|
|
8
10
|
persist: 'immediate',
|
|
@@ -12,19 +14,58 @@ const DEFAULT_OPTIONS = {
|
|
|
12
14
|
/**
|
|
13
15
|
* File-based JSON store for local development
|
|
14
16
|
* Persists data to .reqon-data/{name}.json
|
|
17
|
+
*
|
|
18
|
+
* Use FileStore.create() for async initialization (recommended),
|
|
19
|
+
* or new FileStore() for lazy initialization (backward compatible).
|
|
15
20
|
*/
|
|
16
21
|
export class FileStore {
|
|
17
22
|
data = new Map();
|
|
18
23
|
filePath;
|
|
19
24
|
options;
|
|
20
25
|
dirty = false;
|
|
21
|
-
initialized;
|
|
26
|
+
initialized = null;
|
|
27
|
+
initError = null;
|
|
22
28
|
debounceTimer = null;
|
|
23
29
|
pendingWrite = null;
|
|
30
|
+
/**
|
|
31
|
+
* Create a FileStore with async initialization (recommended).
|
|
32
|
+
* The store is fully initialized when the promise resolves.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const store = await FileStore.create('my-store', { baseDir: '.data' });
|
|
36
|
+
*/
|
|
37
|
+
static async create(name, options = {}) {
|
|
38
|
+
const store = new FileStore(name, options);
|
|
39
|
+
await store.ensureInitialized();
|
|
40
|
+
return store;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Constructor for lazy initialization (backward compatible).
|
|
44
|
+
* Each operation will wait for initialization to complete.
|
|
45
|
+
* Prefer FileStore.create() for explicit async initialization.
|
|
46
|
+
*/
|
|
24
47
|
constructor(name, options = {}) {
|
|
25
48
|
this.options = { ...DEFAULT_OPTIONS, ...options };
|
|
26
|
-
this.filePath =
|
|
27
|
-
|
|
49
|
+
this.filePath = safeJoin(this.options.baseDir, `${name}.json`);
|
|
50
|
+
// Lazy initialization - init() is called on first operation
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Ensure the store is initialized. Safe to call multiple times.
|
|
54
|
+
* Throws if initialization previously failed.
|
|
55
|
+
*/
|
|
56
|
+
async ensureInitialized() {
|
|
57
|
+
// If init previously failed, throw the cached error
|
|
58
|
+
if (this.initError) {
|
|
59
|
+
throw this.initError;
|
|
60
|
+
}
|
|
61
|
+
// If not yet started, start initialization
|
|
62
|
+
if (this.initialized === null) {
|
|
63
|
+
this.initialized = this.init().catch((error) => {
|
|
64
|
+
this.initError = error instanceof Error ? error : new Error(String(error));
|
|
65
|
+
throw this.initError;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
await this.initialized;
|
|
28
69
|
}
|
|
29
70
|
async init() {
|
|
30
71
|
const dir = dirname(this.filePath);
|
|
@@ -72,27 +113,27 @@ export class FileStore {
|
|
|
72
113
|
async writeToDisk() {
|
|
73
114
|
const obj = Object.fromEntries(this.data);
|
|
74
115
|
const content = serialize(obj, this.options.pretty);
|
|
75
|
-
await
|
|
116
|
+
await writeFileAtomic(this.filePath, content);
|
|
76
117
|
this.dirty = false;
|
|
77
118
|
}
|
|
78
119
|
/** Synchronous write for flush/close operations */
|
|
79
120
|
writeToDiskSync() {
|
|
80
121
|
const obj = Object.fromEntries(this.data);
|
|
81
122
|
const content = serialize(obj, this.options.pretty);
|
|
82
|
-
|
|
123
|
+
writeFileAtomicSync(this.filePath, content);
|
|
83
124
|
this.dirty = false;
|
|
84
125
|
}
|
|
85
126
|
async get(key) {
|
|
86
|
-
await this.
|
|
127
|
+
await this.ensureInitialized();
|
|
87
128
|
return this.data.get(key) ?? null;
|
|
88
129
|
}
|
|
89
130
|
async set(key, value) {
|
|
90
|
-
await this.
|
|
131
|
+
await this.ensureInitialized();
|
|
91
132
|
this.data.set(key, { ...value });
|
|
92
133
|
await this.persist();
|
|
93
134
|
}
|
|
94
135
|
async bulkSet(records) {
|
|
95
|
-
await this.
|
|
136
|
+
await this.ensureInitialized();
|
|
96
137
|
// Set all records in memory first (no disk I/O per record)
|
|
97
138
|
for (const { key, value } of records) {
|
|
98
139
|
this.data.set(key, { ...value });
|
|
@@ -100,28 +141,33 @@ export class FileStore {
|
|
|
100
141
|
// Single persist operation for all records
|
|
101
142
|
await this.persist();
|
|
102
143
|
}
|
|
144
|
+
async bulkUpsert(records) {
|
|
145
|
+
await this.ensureInitialized();
|
|
146
|
+
// Upsert all records in memory first (no disk I/O per record)
|
|
147
|
+
for (const { key, value } of records) {
|
|
148
|
+
const existing = this.data.get(key);
|
|
149
|
+
this.data.set(key, existing ? deepMerge(existing, value) : { ...value });
|
|
150
|
+
}
|
|
151
|
+
// Single persist operation for all records
|
|
152
|
+
await this.persist();
|
|
153
|
+
}
|
|
103
154
|
async update(key, value) {
|
|
104
|
-
await this.
|
|
155
|
+
await this.ensureInitialized();
|
|
105
156
|
const existing = this.data.get(key);
|
|
106
|
-
|
|
107
|
-
this.data.set(key, { ...existing, ...value });
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
this.data.set(key, value);
|
|
111
|
-
}
|
|
157
|
+
this.data.set(key, existing ? deepMerge(existing, value) : { ...value });
|
|
112
158
|
await this.persist();
|
|
113
159
|
}
|
|
114
160
|
async delete(key) {
|
|
115
|
-
await this.
|
|
161
|
+
await this.ensureInitialized();
|
|
116
162
|
this.data.delete(key);
|
|
117
163
|
await this.persist();
|
|
118
164
|
}
|
|
119
165
|
async list(filter) {
|
|
120
|
-
await this.
|
|
166
|
+
await this.ensureInitialized();
|
|
121
167
|
return applyStoreFilter(Array.from(this.data.values()), filter);
|
|
122
168
|
}
|
|
123
169
|
async count(filter) {
|
|
124
|
-
await this.
|
|
170
|
+
await this.ensureInitialized();
|
|
125
171
|
// Apply only the where clause for counting (ignore limit/offset)
|
|
126
172
|
const filtered = applyStoreFilter(Array.from(this.data.values()), {
|
|
127
173
|
where: filter?.where,
|
|
@@ -129,7 +175,7 @@ export class FileStore {
|
|
|
129
175
|
return filtered.length;
|
|
130
176
|
}
|
|
131
177
|
async clear() {
|
|
132
|
-
await this.
|
|
178
|
+
await this.ensureInitialized();
|
|
133
179
|
this.data.clear();
|
|
134
180
|
await this.persist();
|
|
135
181
|
}
|
package/dist/stores/index.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ---
|
|
3
|
+
* purpose: Store adapters - pluggable storage backends for pipeline data
|
|
4
|
+
* exports:
|
|
5
|
+
* - StoreAdapter - interface for all stores
|
|
6
|
+
* - MemoryStore, FileStore, PostgRESTStore - implementations
|
|
7
|
+
* - createStore - factory function
|
|
8
|
+
* related:
|
|
9
|
+
* - ./types.ts - StoreAdapter interface definition
|
|
10
|
+
* - ./memory.ts - in-memory store (default)
|
|
11
|
+
* - ./file.ts - JSON/CSV file store
|
|
12
|
+
* - ./postgrest.ts - PostgREST API store
|
|
13
|
+
* - ../interpreter/context.ts - stores registered in context
|
|
14
|
+
* ---
|
|
15
|
+
*/
|
|
1
16
|
export type { StoreAdapter, StoreFilter, StoreConfig } from './types.js';
|
|
2
17
|
export { applyStoreFilter } from './types.js';
|
|
3
18
|
export { MemoryStore } from './memory.js';
|
|
4
19
|
export { FileStore, type FileStoreOptions } from './file.js';
|
|
5
20
|
export { PostgRESTStore, PostgRESTError, type PostgRESTOptions } from './postgrest.js';
|
|
6
|
-
export { createStore, resolveStoreType, type StoreType, type CreateStoreOptions } from './factory.js';
|
|
21
|
+
export { createStore, resolveStoreType, type StoreType, type CreateStoreOptions, } from './factory.js';
|
package/dist/stores/index.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ---
|
|
3
|
+
* purpose: Store adapters - pluggable storage backends for pipeline data
|
|
4
|
+
* exports:
|
|
5
|
+
* - StoreAdapter - interface for all stores
|
|
6
|
+
* - MemoryStore, FileStore, PostgRESTStore - implementations
|
|
7
|
+
* - createStore - factory function
|
|
8
|
+
* related:
|
|
9
|
+
* - ./types.ts - StoreAdapter interface definition
|
|
10
|
+
* - ./memory.ts - in-memory store (default)
|
|
11
|
+
* - ./file.ts - JSON/CSV file store
|
|
12
|
+
* - ./postgrest.ts - PostgREST API store
|
|
13
|
+
* - ../interpreter/context.ts - stores registered in context
|
|
14
|
+
* ---
|
|
15
|
+
*/
|
|
1
16
|
export { applyStoreFilter } from './types.js';
|
|
2
17
|
export { MemoryStore } from './memory.js';
|
|
3
18
|
export { FileStore } from './file.js';
|
|
4
19
|
export { PostgRESTStore, PostgRESTError } from './postgrest.js';
|
|
5
|
-
export { createStore, resolveStoreType } from './factory.js';
|
|
20
|
+
export { createStore, resolveStoreType, } from './factory.js';
|
package/dist/stores/memory.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export declare class MemoryStore implements StoreAdapter {
|
|
|
9
9
|
key: string;
|
|
10
10
|
value: Record<string, unknown>;
|
|
11
11
|
}>): Promise<void>;
|
|
12
|
+
bulkUpsert(records: Array<{
|
|
13
|
+
key: string;
|
|
14
|
+
value: Record<string, unknown>;
|
|
15
|
+
}>): Promise<void>;
|
|
12
16
|
update(key: string, value: Partial<Record<string, unknown>>): Promise<void>;
|
|
13
17
|
delete(key: string): Promise<void>;
|
|
14
18
|
list(filter?: StoreFilter): Promise<Record<string, unknown>[]>;
|
package/dist/stores/memory.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { applyStoreFilter } from './types.js';
|
|
2
|
+
import { deepMerge } from '../utils/deep-merge.js';
|
|
2
3
|
export class MemoryStore {
|
|
3
4
|
data = new Map();
|
|
4
5
|
name;
|
|
@@ -16,14 +17,15 @@ export class MemoryStore {
|
|
|
16
17
|
this.data.set(key, { ...value });
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
async bulkUpsert(records) {
|
|
21
|
+
for (const { key, value } of records) {
|
|
22
|
+
const existing = this.data.get(key);
|
|
23
|
+
this.data.set(key, existing ? deepMerge(existing, value) : { ...value });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
19
26
|
async update(key, value) {
|
|
20
27
|
const existing = this.data.get(key);
|
|
21
|
-
|
|
22
|
-
this.data.set(key, { ...existing, ...value });
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
this.data.set(key, value);
|
|
26
|
-
}
|
|
28
|
+
this.data.set(key, existing ? deepMerge(existing, value) : { ...value });
|
|
27
29
|
}
|
|
28
30
|
async delete(key) {
|
|
29
31
|
this.data.delete(key);
|
|
@@ -10,6 +10,17 @@ export interface PostgRESTOptions {
|
|
|
10
10
|
primaryKey?: string;
|
|
11
11
|
/** Optional schema (for Supabase, typically 'public') */
|
|
12
12
|
schema?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Per-request timeout in milliseconds (default: 30000). Every request is
|
|
15
|
+
* aborted after this elapses so a hung connection can't stall a mission.
|
|
16
|
+
*/
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Opt-in guard for {@link PostgRESTStore.clear}, which issues a full-table
|
|
20
|
+
* DELETE. Defaults to false so a misconfigured store (e.g. a `sql` type
|
|
21
|
+
* resolving here by mistake) can't wipe a table.
|
|
22
|
+
*/
|
|
23
|
+
allowFullTableClear?: boolean;
|
|
13
24
|
}
|
|
14
25
|
/**
|
|
15
26
|
* PostgREST-compatible store adapter.
|
|
@@ -29,7 +40,24 @@ export declare class PostgRESTStore implements StoreAdapter {
|
|
|
29
40
|
private baseUrl;
|
|
30
41
|
private headers;
|
|
31
42
|
private primaryKey;
|
|
43
|
+
private timeoutMs;
|
|
32
44
|
constructor(options: PostgRESTOptions);
|
|
45
|
+
/** fetch wrapper that aborts the request once {@link timeoutMs} elapses. */
|
|
46
|
+
private request;
|
|
47
|
+
/**
|
|
48
|
+
* Reject a where-clause field unless it is a plain column identifier. This
|
|
49
|
+
* stops a key such as `or` or `id,or=(...)` from being concatenated into the
|
|
50
|
+
* query string and reinterpreted as a PostgREST operator.
|
|
51
|
+
*/
|
|
52
|
+
private validateField;
|
|
53
|
+
/**
|
|
54
|
+
* Render a where-clause value as a PostgREST operand. Strings containing
|
|
55
|
+
* reserved characters are wrapped in a quoted operand (with `"` and `\`
|
|
56
|
+
* escaped) so they can't be parsed as list/group syntax.
|
|
57
|
+
*/
|
|
58
|
+
private formatFilterValue;
|
|
59
|
+
/** Append a validated, escaped where clause to the given params. */
|
|
60
|
+
private applyWhere;
|
|
33
61
|
get(key: string): Promise<Record<string, unknown> | null>;
|
|
34
62
|
set(key: string, value: Record<string, unknown>): Promise<void>;
|
|
35
63
|
update(key: string, value: Partial<Record<string, unknown>>): Promise<void>;
|