@powerduck/openapi-cli 0.2.6 → 0.2.9

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/dist/index.d.cts CHANGED
@@ -1,6 +1,64 @@
1
+ import { RequestValues, createClient } from '@powerduck/openapi-request';
2
+
3
+ /**
4
+ * Assertion engine. Supports two sources:
5
+ * 1. Declarative `x-tests` array on the operation (simple, JSON-serializable).
6
+ * 2. Postman `x-postman-scripts.test` string (full pm.* API, executed by
7
+ * @powerduck/openapi-request's script sandbox and surfaced via onAssertion).
8
+ */
9
+
10
+ interface DeclarativeAssertion {
11
+ name: string;
12
+ /** What to assert. */
13
+ assert: "status" | "header" | "bodyContains" | "jsonPath" | "responseTime" | "bodyEquals";
14
+ /** Expected status code (for assert=status). */
15
+ value?: number;
16
+ /** Header name (for assert=header). */
17
+ key?: string;
18
+ /** Substring to check (for assert=header / bodyContains). */
19
+ contains?: string;
20
+ /** JSONPath expression (for assert=jsonPath). Simple dot-notation supported. */
21
+ path?: string;
22
+ /** Expected value at path (for assert=jsonPath). */
23
+ equals?: unknown;
24
+ /** Whether the path must exist (for assert=jsonPath). */
25
+ exists?: boolean;
26
+ /** Max response time in ms (for assert=responseTime). */
27
+ max?: number;
28
+ /** Expected body string (for assert=bodyEquals). */
29
+ body?: string;
30
+ }
31
+ interface AssertionContext {
32
+ status?: number;
33
+ headers?: Record<string, string>;
34
+ body?: unknown;
35
+ bodyText?: string;
36
+ durationMs: number;
37
+ }
38
+ /**
39
+ * Run declarative assertions against a response context.
40
+ */
41
+ declare function runDeclarativeAssertions(assertions: DeclarativeAssertion[], ctx: AssertionContext): AssertionResult[];
42
+ /**
43
+ * Minimal JSONPath resolver supporting dot notation and array indices.
44
+ * e.g. "$.data.items[0].id" or "data.user.name"
45
+ */
46
+ declare function resolveJsonPath(obj: unknown, path: string): unknown;
47
+ /**
48
+ * Extract declarative assertions from an OpenAPI operation.
49
+ * Looks for `x-tests` on the operation or path item.
50
+ */
51
+ declare function extractAssertions(operation: any, pathItem?: any): DeclarativeAssertion[];
52
+ /**
53
+ * Extract Postman test scripts from an operation.
54
+ * Looks for `x-postman-scripts.test` on the operation.
55
+ */
56
+ declare function extractPostmanScripts(operation: any): string | undefined;
57
+
1
58
  /**
2
59
  * Public types for @powerduck/openapi-cli.
3
60
  */
61
+
4
62
  type ProtocolName = "http" | "sse" | "websocket" | "graphql" | "grpc" | "mcp";
5
63
  type ReportFormat = "json" | "cli" | "html";
6
64
  type TestStatus = "passed" | "failed" | "skipped" | "error";
@@ -80,6 +138,21 @@ interface AssertionResult {
80
138
  passed: boolean;
81
139
  error?: string;
82
140
  }
141
+ /**
142
+ * Best-effort snapshot of the request actually sent, after variable
143
+ * substitution and header merging. Secrets are included as sent; callers
144
+ * decide what to redact before persisting or displaying.
145
+ */
146
+ interface RequestSnapshot {
147
+ method?: string;
148
+ /** Fully resolved URL for HTTP-style protocols. */
149
+ url?: string;
150
+ headers?: Record<string, string>;
151
+ /** Request body, gRPC message, WS payload or MCP arguments. */
152
+ body?: unknown;
153
+ /** Protocol-specific target, e.g. "package.Service/Method" or an MCP tool. */
154
+ target?: string;
155
+ }
83
156
  interface TestResult {
84
157
  operationId: string;
85
158
  path: string;
@@ -87,6 +160,8 @@ interface TestResult {
87
160
  protocol: ProtocolName | string;
88
161
  status: TestStatus;
89
162
  durationMs: number;
163
+ /** Snapshot of the resolved request, when the protocol could capture it. */
164
+ request?: RequestSnapshot;
90
165
  response?: {
91
166
  status?: number;
92
167
  statusText?: string;
@@ -118,11 +193,185 @@ interface TestReport {
118
193
  generatedAt: string;
119
194
  version: string;
120
195
  }
196
+ /** Pull a value out of one step's response into the shared scenario scope. */
197
+ interface ScenarioExtract {
198
+ /** Variable name written into the scenario scope. */
199
+ name: string;
200
+ /** Response part to read from. */
201
+ from: "body" | "header" | "status";
202
+ /** Dot/JSONPath into the JSON body when from="body" (e.g. "$.data.token"). */
203
+ path?: string;
204
+ /** Response header name when from="header". */
205
+ key?: string;
206
+ }
207
+ /** Per-step request overrides and verification rules. */
208
+ interface ScenarioStepRequest {
209
+ /** Request values merged over the operation's sampled defaults. */
210
+ values?: RequestValues;
211
+ /** Override the resolved server URL for this step only. */
212
+ serverUrl?: string;
213
+ /** Declarative variables extracted after the response arrives. */
214
+ extract?: ScenarioExtract[];
215
+ /** Declarative assertions added on top of the operation's spec assertions. */
216
+ assertions?: DeclarativeAssertion[];
217
+ }
218
+ /** A single ordered operation invocation inside a scenario. */
219
+ interface ScenarioStep {
220
+ /** Reference as "METHOD /path" (e.g. "POST /login") or an operationId. */
221
+ ref?: string;
222
+ /** Explicit method, paired with `path`; an alternative to `ref`. */
223
+ method?: string;
224
+ /** Explicit path, paired with `method`; an alternative to `ref`. */
225
+ path?: string;
226
+ /** Human-readable step label shown in reports and live events. */
227
+ name?: string;
228
+ request?: ScenarioStepRequest;
229
+ /** Compile-time skip; the step is reported as skipped and never sent. */
230
+ skip?: boolean;
231
+ }
232
+ /** A named, ordered sequence of operations with shared variable scope. */
233
+ interface ScenarioDefinition {
234
+ name: string;
235
+ description?: string;
236
+ steps: ScenarioStep[];
237
+ /** Initial scenario variables, merged over CliConfig.variables. */
238
+ variables?: Record<string, string>;
239
+ /** Stop at the first failed/error step. Default: true. */
240
+ stopOnFailure?: boolean;
241
+ }
242
+ type ScenarioStatus = "passed" | "failed" | "error" | "cancelled";
243
+ /** Result of executing one scenario step. */
244
+ interface ScenarioStepResult extends TestResult {
245
+ /** Zero-based position in the scenario. */
246
+ index: number;
247
+ /** Resolved operation reference ("METHOD /path"). */
248
+ ref: string;
249
+ name?: string;
250
+ /** Variables written by this step (declarative extraction + scripts). */
251
+ extracted?: Record<string, string>;
252
+ /** Full scenario variable scope after this step completed. */
253
+ variablesAfter?: Record<string, string>;
254
+ /** True when the step never executed (explicit skip or halted by a prior failure). */
255
+ notRun?: boolean;
256
+ notRunReason?: string;
257
+ }
258
+ type ScenarioEventType = "scenario:start" | "step:start" | "step:finish" | "step:skip" | "scenario:finish" | "scenario:cancel";
259
+ /** Live progress event emitted while a scenario runs. */
260
+ interface ScenarioEvent {
261
+ type: ScenarioEventType;
262
+ scenario: string;
263
+ stepIndex?: number;
264
+ step?: ScenarioStepResult;
265
+ status?: ScenarioStatus;
266
+ message?: string;
267
+ }
268
+ /** Aggregate result of a full scenario execution. */
269
+ interface ScenarioReport {
270
+ name: string;
271
+ description?: string;
272
+ status: ScenarioStatus;
273
+ summary: TestSummary;
274
+ steps: ScenarioStepResult[];
275
+ /** Final shared variable scope. */
276
+ variables: Record<string, string>;
277
+ config: CliConfig;
278
+ startedAt: string;
279
+ durationMs: number;
280
+ generatedAt: string;
281
+ version: string;
282
+ }
283
+ /** Options for {@link runScenario}. */
284
+ interface RunScenarioOptions {
285
+ /** Runner configuration (server, auth, proxy, TLS, timeouts, ...). */
286
+ config: CliConfig;
287
+ /** Pre-parsed spec document; when omitted it is loaded from config.specPath. */
288
+ spec?: unknown;
289
+ /** Live progress callback, invoked defensively (a throw never aborts the run). */
290
+ onEvent?: (event: ScenarioEvent) => void;
291
+ /** Aborting cancels the scenario; remaining steps are reported as skipped. */
292
+ signal?: AbortSignal;
293
+ }
121
294
 
295
+ /**
296
+ * Batch test runner. Iterates over all operations in an OpenAPI spec,
297
+ * executes each via @powerduck/openapi-request, runs assertions, and collects
298
+ * results. Supports HTTP, SSE, GraphQL, gRPC (unary/server-streaming),
299
+ * MCP (one-shot), and WebSocket (connect-send-close).
300
+ */
301
+
302
+ interface OperationInfo {
303
+ path: string;
304
+ method: string;
305
+ operation: any;
306
+ pathItem: any;
307
+ operationId: string;
308
+ protocol: string;
309
+ }
310
+ /** Extract a readable message from any assertion error shape. */
311
+ declare function formatAssertionError(err: unknown): string | undefined;
312
+ /**
313
+ * Build implicit assertions when the user defined none.
314
+ *
315
+ * Conventional success criteria per protocol:
316
+ * HTTP / SSE : HTTP status 2xx (200-299)
317
+ * GraphQL : HTTP status 2xx AND no top-level "errors" array in the body
318
+ * gRPC : status code 0 (OK)
319
+ * MCP : JSON-RPC response has a "result" and no "error"
320
+ * WebSocket : connection reached the "open" state
321
+ */
322
+ declare function buildImplicitAssertions(protocol: string, response: TestResult["response"]): Array<{
323
+ name: string;
324
+ passed: boolean;
325
+ error?: string;
326
+ }>;
122
327
  /**
123
328
  * Run all tests defined in the spec.
124
329
  */
125
330
  declare function runTests(config: CliConfig): Promise<TestReport>;
331
+ declare function collectOperations(spec: any, config: CliConfig): OperationInfo[];
332
+ interface StepExecutionOptions {
333
+ config: CliConfig;
334
+ spec: any;
335
+ /** Active variable scope injected as {{name}} values. */
336
+ variables?: Record<string, string>;
337
+ /** Per-step request values (path/query/header/body). */
338
+ values?: any;
339
+ /** Override the resolved server URL for this invocation. */
340
+ serverUrl?: string;
341
+ /** Declarative assertions added beyond those declared on the operation. */
342
+ extraAssertions?: DeclarativeAssertion[];
343
+ }
344
+ interface StepExecution {
345
+ result: TestResult;
346
+ response: TestResult["response"];
347
+ /** Resolved request snapshot for the result card. */
348
+ request?: TestResult["request"];
349
+ /** Variable scope produced by Postman scripts during this step. */
350
+ env: Record<string, string>;
351
+ }
352
+ /**
353
+ * Execute a single operation with per-step overrides and return the result,
354
+ * the normalized response, and any variables produced by its scripts. Shared
355
+ * by the batch runner (runTests) and the ordered scenario engine (runScenario).
356
+ */
357
+ declare function executeStep(client: ReturnType<typeof createClient>, op: OperationInfo, options: StepExecutionOptions): Promise<StepExecution>;
358
+ declare function buildSummary(results: TestResult[], durationMs: number): TestSummary;
359
+
360
+ interface ResolvedStep {
361
+ step: ScenarioStep;
362
+ op: OperationInfo;
363
+ ref: string;
364
+ }
365
+ /** Normalize a step reference to "METHOD /path". */
366
+ declare function stepRef(step: ScenarioStep): string;
367
+ /** Resolve every step reference up front so a bad plan fails before any call. */
368
+ declare function resolveSteps(definition: ScenarioDefinition, operations: OperationInfo[]): ResolvedStep[];
369
+ /** Read declared extracts out of a normalized response. Missing values are omitted. */
370
+ declare function applyExtracts(extracts: ScenarioExtract[] | undefined, response: TestResult["response"]): Record<string, string>;
371
+ /**
372
+ * Execute a scenario in order with a shared variable scope.
373
+ */
374
+ declare function runScenario(definition: ScenarioDefinition, options: RunScenarioOptions): Promise<ScenarioReport>;
126
375
 
127
376
  declare const DEFAULT_CONFIG: Required<Pick<CliConfig, "outputDir" | "formats" | "concurrency" | "timeout" | "failOnError" | "grpcReflection" | "mcpTransport">>;
128
377
  interface CliArgs {
@@ -168,61 +417,6 @@ declare function isRemoteSpec(specPath: string): boolean;
168
417
  */
169
418
  declare function loadSpec(config: CliConfig): Promise<any>;
170
419
 
171
- /**
172
- * Assertion engine. Supports two sources:
173
- * 1. Declarative `x-tests` array on the operation (simple, JSON-serializable).
174
- * 2. Postman `x-postman-scripts.test` string (full pm.* API, executed by
175
- * @powerduck/openapi-request's script sandbox and surfaced via onAssertion).
176
- */
177
-
178
- interface DeclarativeAssertion {
179
- name: string;
180
- /** What to assert. */
181
- assert: "status" | "header" | "bodyContains" | "jsonPath" | "responseTime" | "bodyEquals";
182
- /** Expected status code (for assert=status). */
183
- value?: number;
184
- /** Header name (for assert=header). */
185
- key?: string;
186
- /** Substring to check (for assert=header / bodyContains). */
187
- contains?: string;
188
- /** JSONPath expression (for assert=jsonPath). Simple dot-notation supported. */
189
- path?: string;
190
- /** Expected value at path (for assert=jsonPath). */
191
- equals?: unknown;
192
- /** Whether the path must exist (for assert=jsonPath). */
193
- exists?: boolean;
194
- /** Max response time in ms (for assert=responseTime). */
195
- max?: number;
196
- /** Expected body string (for assert=bodyEquals). */
197
- body?: string;
198
- }
199
- interface AssertionContext {
200
- status?: number;
201
- headers?: Record<string, string>;
202
- body?: unknown;
203
- bodyText?: string;
204
- durationMs: number;
205
- }
206
- /**
207
- * Run declarative assertions against a response context.
208
- */
209
- declare function runDeclarativeAssertions(assertions: DeclarativeAssertion[], ctx: AssertionContext): AssertionResult[];
210
- /**
211
- * Minimal JSONPath resolver supporting dot notation and array indices.
212
- * e.g. "$.data.items[0].id" or "data.user.name"
213
- */
214
- declare function resolveJsonPath(obj: unknown, path: string): unknown;
215
- /**
216
- * Extract declarative assertions from an OpenAPI operation.
217
- * Looks for `x-tests` on the operation or path item.
218
- */
219
- declare function extractAssertions(operation: any, pathItem?: any): DeclarativeAssertion[];
220
- /**
221
- * Extract Postman test scripts from an operation.
222
- * Looks for `x-postman-scripts.test` on the operation.
223
- */
224
- declare function extractPostmanScripts(operation: any): string | undefined;
225
-
226
420
  declare function generateJsonReport(report: TestReport, outputDir: string): string;
227
421
 
228
422
  /**
@@ -238,4 +432,4 @@ declare function printCliReport(report: TestReport): string;
238
432
 
239
433
  declare function generateHtmlReport(report: TestReport, outputDir: string): string;
240
434
 
241
- export { type AssertionResult, type AuthConfig, type CliArgs, type CliConfig, DEFAULT_CONFIG, type DeclarativeAssertion, type FilterConfig, type ProtocolName, type ReportFormat, type TestReport, type TestResult, type TestStatus, type TestSummary, type TlsConfig, extractAssertions, extractPostmanScripts, generateCliReport, generateHtmlReport, generateJsonReport, isRemoteSpec, loadSpec, printCliReport, resolveConfig, resolveJsonPath, runDeclarativeAssertions, runTests };
435
+ export { type AssertionResult, type AuthConfig, type CliArgs, type CliConfig, DEFAULT_CONFIG, type DeclarativeAssertion, type FilterConfig, type ProtocolName, type ReportFormat, type RunScenarioOptions, type ScenarioDefinition, type ScenarioEvent, type ScenarioEventType, type ScenarioExtract, type ScenarioReport, type ScenarioStatus, type ScenarioStep, type ScenarioStepRequest, type ScenarioStepResult, type TestReport, type TestResult, type TestStatus, type TestSummary, type TlsConfig, applyExtracts, buildImplicitAssertions, buildSummary, collectOperations, executeStep, extractAssertions, extractPostmanScripts, formatAssertionError, generateCliReport, generateHtmlReport, generateJsonReport, isRemoteSpec, loadSpec, printCliReport, resolveConfig, resolveJsonPath, resolveSteps, runDeclarativeAssertions, runScenario, runTests, stepRef };