reqon-dsl 0.3.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.
Files changed (122) hide show
  1. package/README.md +23 -3
  2. package/dist/ast/nodes.d.ts +8 -0
  3. package/dist/auth/circuit-breaker.d.ts +11 -0
  4. package/dist/auth/circuit-breaker.js +83 -12
  5. package/dist/auth/credentials.d.ts +6 -1
  6. package/dist/auth/credentials.js +12 -4
  7. package/dist/auth/oauth2-provider.js +13 -3
  8. package/dist/auth/rate-limiter.d.ts +8 -1
  9. package/dist/auth/rate-limiter.js +30 -10
  10. package/dist/auth/token-store.js +8 -1
  11. package/dist/cli.d.ts +11 -1
  12. package/dist/cli.js +65 -6
  13. package/dist/config/constants.d.ts +15 -4
  14. package/dist/config/constants.js +15 -4
  15. package/dist/control/server.d.ts +17 -0
  16. package/dist/control/server.js +82 -5
  17. package/dist/control/types.d.ts +6 -0
  18. package/dist/debug/cli-debugger.js +8 -3
  19. package/dist/execution/store.js +2 -2
  20. package/dist/execution-log/events.d.ts +125 -0
  21. package/dist/execution-log/events.js +17 -0
  22. package/dist/execution-log/fold.d.ts +38 -0
  23. package/dist/execution-log/fold.js +54 -0
  24. package/dist/execution-log/index.d.ts +18 -0
  25. package/dist/execution-log/index.js +6 -0
  26. package/dist/execution-log/postgres-store.d.ts +36 -0
  27. package/dist/execution-log/postgres-store.js +108 -0
  28. package/dist/execution-log/resume.d.ts +11 -0
  29. package/dist/execution-log/resume.js +5 -0
  30. package/dist/execution-log/sqlite-store.d.ts +16 -0
  31. package/dist/execution-log/sqlite-store.js +101 -0
  32. package/dist/execution-log/store.d.ts +72 -0
  33. package/dist/execution-log/store.js +182 -0
  34. package/dist/index.d.ts +4 -3
  35. package/dist/index.js +4 -3
  36. package/dist/interpreter/context.d.ts +15 -0
  37. package/dist/interpreter/context.js +3 -0
  38. package/dist/interpreter/evaluator.js +38 -8
  39. package/dist/interpreter/executor.d.ts +63 -1
  40. package/dist/interpreter/executor.js +406 -30
  41. package/dist/interpreter/fetch-handler.d.ts +39 -1
  42. package/dist/interpreter/fetch-handler.js +84 -15
  43. package/dist/interpreter/http.d.ts +31 -2
  44. package/dist/interpreter/http.js +187 -26
  45. package/dist/interpreter/index.d.ts +3 -3
  46. package/dist/interpreter/index.js +3 -3
  47. package/dist/interpreter/pagination.d.ts +1 -1
  48. package/dist/interpreter/pagination.js +7 -1
  49. package/dist/interpreter/step-handlers/for-handler.d.ts +3 -0
  50. package/dist/interpreter/step-handlers/for-handler.js +18 -3
  51. package/dist/interpreter/step-handlers/match-handler.js +5 -2
  52. package/dist/interpreter/step-handlers/store-handler.d.ts +7 -1
  53. package/dist/interpreter/step-handlers/store-handler.js +25 -16
  54. package/dist/interpreter/step-handlers/validate-handler.js +4 -1
  55. package/dist/interpreter/step-handlers/webhook-handler.d.ts +1 -0
  56. package/dist/interpreter/step-handlers/webhook-handler.js +13 -3
  57. package/dist/interpreter/store-manager.d.ts +1 -1
  58. package/dist/interpreter/store-manager.js +5 -1
  59. package/dist/loader/index.js +5 -8
  60. package/dist/mcp/sandbox.d.ts +41 -0
  61. package/dist/mcp/sandbox.js +76 -0
  62. package/dist/mcp/server.js +62 -9
  63. package/dist/oas/loader.d.ts +13 -1
  64. package/dist/oas/loader.js +25 -3
  65. package/dist/oas/mock-generator.js +13 -4
  66. package/dist/oas/validator.js +45 -5
  67. package/dist/observability/events.d.ts +6 -2
  68. package/dist/observability/events.js +0 -5
  69. package/dist/observability/logger.js +17 -10
  70. package/dist/observability/otel.d.ts +8 -0
  71. package/dist/observability/otel.js +45 -10
  72. package/dist/parser/action-parser.js +2 -2
  73. package/dist/parser/base.d.ts +7 -0
  74. package/dist/parser/base.js +11 -0
  75. package/dist/parser/expressions.d.ts +1 -0
  76. package/dist/parser/expressions.js +17 -4
  77. package/dist/parser/fetch-parser.js +13 -2
  78. package/dist/pause/index.d.ts +1 -0
  79. package/dist/pause/index.js +1 -0
  80. package/dist/pause/log-store.d.ts +33 -0
  81. package/dist/pause/log-store.js +98 -0
  82. package/dist/pause/manager.d.ts +12 -0
  83. package/dist/pause/manager.js +77 -28
  84. package/dist/pause/store.js +5 -3
  85. package/dist/scheduler/cron-parser.d.ts +10 -3
  86. package/dist/scheduler/cron-parser.js +227 -48
  87. package/dist/scheduler/scheduler.js +56 -22
  88. package/dist/stores/factory.d.ts +6 -0
  89. package/dist/stores/factory.js +11 -1
  90. package/dist/stores/file.js +9 -17
  91. package/dist/stores/memory.js +3 -12
  92. package/dist/stores/postgrest.d.ts +28 -0
  93. package/dist/stores/postgrest.js +84 -37
  94. package/dist/sync/index.d.ts +3 -2
  95. package/dist/sync/index.js +2 -1
  96. package/dist/sync/log-store.d.ts +30 -0
  97. package/dist/sync/log-store.js +45 -0
  98. package/dist/sync/store.js +1 -1
  99. package/dist/trace/index.d.ts +2 -0
  100. package/dist/trace/index.js +1 -0
  101. package/dist/trace/log-view.d.ts +57 -0
  102. package/dist/trace/log-view.js +76 -0
  103. package/dist/trace/recorder.d.ts +5 -1
  104. package/dist/trace/recorder.js +19 -6
  105. package/dist/trace/store.d.ts +6 -0
  106. package/dist/trace/store.js +47 -22
  107. package/dist/utils/deep-merge.d.ts +10 -0
  108. package/dist/utils/deep-merge.js +23 -0
  109. package/dist/utils/file.d.ts +13 -4
  110. package/dist/utils/file.js +70 -12
  111. package/dist/utils/index.d.ts +1 -1
  112. package/dist/utils/index.js +1 -1
  113. package/dist/utils/long-timeout.d.ts +19 -0
  114. package/dist/utils/long-timeout.js +33 -0
  115. package/dist/utils/path.d.ts +22 -1
  116. package/dist/utils/path.js +46 -1
  117. package/dist/utils/redact.d.ts +22 -0
  118. package/dist/utils/redact.js +42 -0
  119. package/dist/webhook/server.d.ts +9 -0
  120. package/dist/webhook/server.js +115 -30
  121. package/dist/webhook/types.d.ts +9 -1
  122. package/package.json +22 -4
@@ -160,11 +160,14 @@ export function evaluate(expr, ctx, current) {
160
160
  }
161
161
  case 'LogicalExpression': {
162
162
  const left = evaluate(expr.left, ctx, current);
163
+ // Return operand values (like JS &&/||), not coerced booleans, so
164
+ // idioms like `x or default` work. Short-circuit: only evaluate the
165
+ // right operand when the left doesn't already decide the result.
163
166
  if (expr.operator === 'and') {
164
- return left ? evaluate(expr.right, ctx, current) : false;
167
+ return left ? evaluate(expr.right, ctx, current) : left;
165
168
  }
166
169
  else {
167
- return left ? true : evaluate(expr.right, ctx, current);
170
+ return left ? left : evaluate(expr.right, ctx, current);
168
171
  }
169
172
  }
170
173
  case 'NotExpression':
@@ -227,8 +230,16 @@ export function evaluate(expr, ctx, current) {
227
230
  return Math.ceil(toNumber(args[0], 'ceil'));
228
231
  case 'now':
229
232
  return new Date().toISOString();
230
- case 'env':
231
- return process.env[args[0]] ?? '';
233
+ case 'env': {
234
+ // The variable name must be a static string literal. A dynamic argument
235
+ // (e.g. env(response.field)) would let fetched/untrusted data choose
236
+ // which environment variable is read, exfiltrating secrets.
237
+ const nameExpr = expr.arguments[0];
238
+ if (!nameExpr || nameExpr.type !== 'Literal') {
239
+ throw new EvaluatorError(`env() requires a string-literal variable name, not a dynamic expression`, { expression: 'env' });
240
+ }
241
+ return process.env[String(args[0])] ?? '';
242
+ }
232
243
  default:
233
244
  throw new UnsupportedOperationError(`function: ${expr.callee}`, 'call expression');
234
245
  }
@@ -297,7 +308,11 @@ export function interpolatePath(path, ctx, current) {
297
308
  value = getVariable(ctx, part);
298
309
  }
299
310
  }
300
- return String(value ?? '');
311
+ // URL-encode each interpolated value so a path param can't inject path
312
+ // segments, query strings, or fragments into the request target. Path params
313
+ // are single segments, so encoding (which escapes '/', '?', '#', etc.) is the
314
+ // correct treatment.
315
+ return encodeURIComponent(String(value ?? ''));
301
316
  });
302
317
  }
303
318
  /**
@@ -324,12 +339,27 @@ function toNumber(value, operator) {
324
339
  expression: operator,
325
340
  });
326
341
  }
342
+ /** Coerce for comparison, yielding NaN (not a throw) for nullish/non-numeric. */
343
+ function toComparable(value) {
344
+ if (typeof value === 'number')
345
+ return value;
346
+ if (typeof value === 'boolean')
347
+ return value ? 1 : 0;
348
+ if (typeof value === 'string')
349
+ return Number(value);
350
+ return NaN;
351
+ }
327
352
  /**
328
- * Safely perform arithmetic comparison, with proper type coercion.
353
+ * Arithmetic comparison for `where`/`match`/`validate` guards. A missing or
354
+ * non-numeric operand makes the comparison false (the record is excluded) rather
355
+ * than throwing — real API data routinely omits fields, and one missing field
356
+ * shouldn't abort the whole stage.
329
357
  */
330
358
  function compareNumbers(left, right, operator) {
331
- const leftNum = toNumber(left, operator);
332
- const rightNum = toNumber(right, operator);
359
+ const leftNum = toComparable(left);
360
+ const rightNum = toComparable(right);
361
+ if (Number.isNaN(leftNum) || Number.isNaN(rightNum))
362
+ return false;
333
363
  switch (operator) {
334
364
  case '<':
335
365
  return leftNum < rightNum;
@@ -27,6 +27,7 @@ import type { DebugController } from '../debug/index.js';
27
27
  import type { ControlServer } from '../control/index.js';
28
28
  import { type TraceStore } from '../trace/index.js';
29
29
  import { type PauseManager, type PauseStore } from '../pause/index.js';
30
+ import type { ExecutionLogStore } from '../execution-log/index.js';
30
31
  export interface ExecutionResult {
31
32
  success: boolean;
32
33
  duration: number;
@@ -116,6 +117,13 @@ export interface ExecutorConfig {
116
117
  traceStore?: TraceStore;
117
118
  pauseStore?: PauseStore;
118
119
  pauseManager?: PauseManager;
120
+ executionLog?: ExecutionLogStore;
121
+ /**
122
+ * Max items a single run of a `backfill` paginated fetch accumulates before
123
+ * stopping cleanly (a later resume continues). Bounds memory per run for large
124
+ * backfills. Defaults to the handler's built-in cap.
125
+ */
126
+ backfillMaxItemsPerRun?: number;
119
127
  }
120
128
  export { type AuthConfig } from './source-manager.js';
121
129
  export declare class MissionExecutor {
@@ -123,6 +131,8 @@ export declare class MissionExecutor {
123
131
  private ctx;
124
132
  private errors;
125
133
  private actionsRun;
134
+ /** Monotonic key generator for queued values lacking an id. */
135
+ private queueCounter;
126
136
  private transforms;
127
137
  private rateLimiter;
128
138
  private circuitBreaker;
@@ -134,7 +144,15 @@ export declare class MissionExecutor {
134
144
  private missionName?;
135
145
  private eventEmitter?;
136
146
  private logger?;
137
- private stepIndex;
147
+ private executionLog?;
148
+ /** Stable id used for the execution event log (independent of persistState). */
149
+ private logExecutionId?;
150
+ /** Effect ids already applied (from the log) — replay skips these. */
151
+ private appliedEffects;
152
+ /** Backfill page progress per step id (from the log) — resumes pagination. */
153
+ private pageProgress;
154
+ /** The pause being resumed on this run — its step replays past, not into, a pause. */
155
+ private resumingPause?;
138
156
  private debugController?;
139
157
  private traceRecorder?;
140
158
  private traceStore?;
@@ -150,14 +168,58 @@ export declare class MissionExecutor {
150
168
  private executeMission;
151
169
  private getStageName;
152
170
  private executeSequentialStage;
171
+ /**
172
+ * Run all settled-style tasks with a bounded number in flight at once,
173
+ * preserving result order. Caps fan-out so a wide `run [...]` can't open an
174
+ * unbounded number of concurrent HTTP/store operations.
175
+ */
176
+ private settleWithLimit;
177
+ /**
178
+ * Execute a `run [A, B, ...]` stage.
179
+ *
180
+ * Failure semantics are **complete-then-fail**: every branch runs to
181
+ * completion (bounded by MAX_PARALLEL_ACTIONS in flight), then the stage
182
+ * fails if any branch failed. There is no cancellation of siblings and no
183
+ * rollback — a branch that committed store writes keeps them even if another
184
+ * branch failed. Each branch gets its own action scope (step counter +
185
+ * checkpoints); stores/sources/schemas are shared, so parallel branches that
186
+ * write the same key get last-writer-wins and should target disjoint keys.
187
+ */
153
188
  private executeParallelStage;
154
189
  private executeAction;
190
+ /** Compute a retry backoff delay from a RetrySignal's backoff config. */
191
+ private computeRetryDelay;
192
+ /** Push a queued value to its target store (queue directive). */
193
+ private handleQueue;
155
194
  private executeStep;
156
195
  private executeFetch;
196
+ /**
197
+ * Per-action mutable scope (step counter + deferred checkpoints). Lazily
198
+ * created so a step run with the bare mission context still works; normally
199
+ * executeAction installs a fresh scope that nested scopes inherit.
200
+ */
201
+ private scopeFor;
202
+ /**
203
+ * Append an event to the execution log. No-op (zero cost) when no log is
204
+ * configured. The executionId is supplied from this run's stable log id.
205
+ */
206
+ private logEvent;
207
+ /** Flush deferred sync checkpoints (called after a successful store / action). */
208
+ private flushPendingCheckpoints;
157
209
  private executeFor;
158
210
  private executeMap;
159
211
  private executeValidate;
160
212
  private executeStore;
213
+ /**
214
+ * A stable hash of the payload a store step will write, used to make the
215
+ * store-effect identity content-aware. Resolving the source is a pure read of
216
+ * the context (the same value the handler stores); on any evaluation failure we
217
+ * fall back to a constant so behaviour matches the old target-only identity
218
+ * rather than throwing inside the dedup path.
219
+ */
220
+ /** Load a pause's checkpoint into the shape the pause step uses to resume. */
221
+ private loadResumingPause;
222
+ private storeContentHash;
161
223
  private executeMatch;
162
224
  private executeLet;
163
225
  private executeApply;