@apiquest/types 1.0.2 → 1.0.4
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/README.md +54 -0
- package/package.json +27 -22
- package/src/index.ts +823 -823
- package/tsconfig.json +21 -21
package/src/index.ts
CHANGED
|
@@ -1,823 +1,823 @@
|
|
|
1
|
-
// Core Types and Interfaces for @apiquest/types
|
|
2
|
-
// Schema v1.0 - Updated 2026-01-05
|
|
3
|
-
|
|
4
|
-
// ============================================================================
|
|
5
|
-
// Collection & Items
|
|
6
|
-
// ============================================================================
|
|
7
|
-
|
|
8
|
-
export interface Collection {
|
|
9
|
-
$schema?: string;
|
|
10
|
-
info: CollectionInfo;
|
|
11
|
-
|
|
12
|
-
// Protocol (collection-level)
|
|
13
|
-
protocol: string; // "http", "graphql", "grpc", "websocket", etc.
|
|
14
|
-
|
|
15
|
-
auth?: Auth;
|
|
16
|
-
variables?: Record<string, string | Variable>;
|
|
17
|
-
|
|
18
|
-
// Collection lifecycle scripts
|
|
19
|
-
collectionPreScript?: string;
|
|
20
|
-
collectionPostScript?: string;
|
|
21
|
-
|
|
22
|
-
// Request lifecycle scripts (run before/after EACH request)
|
|
23
|
-
preRequestScript?: string;
|
|
24
|
-
postRequestScript?: string;
|
|
25
|
-
|
|
26
|
-
testData?: IterationData[];
|
|
27
|
-
options?: RuntimeOptions;
|
|
28
|
-
items: CollectionItem[];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface CollectionInfo {
|
|
32
|
-
id: string;
|
|
33
|
-
name: string;
|
|
34
|
-
version?: string;
|
|
35
|
-
description?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface Folder {
|
|
39
|
-
type: 'folder';
|
|
40
|
-
id: string;
|
|
41
|
-
name: string;
|
|
42
|
-
description?: string;
|
|
43
|
-
auth?: Auth;
|
|
44
|
-
|
|
45
|
-
// Execution control
|
|
46
|
-
dependsOn?: string[]; // Folder/Request IDs that must execute first
|
|
47
|
-
condition?: string; // JavaScript expression to evaluate
|
|
48
|
-
|
|
49
|
-
// Folder lifecycle scripts
|
|
50
|
-
folderPreScript?: string;
|
|
51
|
-
folderPostScript?: string;
|
|
52
|
-
|
|
53
|
-
// Request lifecycle scripts
|
|
54
|
-
preRequestScript?: string;
|
|
55
|
-
postRequestScript?: string;
|
|
56
|
-
|
|
57
|
-
options?: RuntimeOptions;
|
|
58
|
-
items: CollectionItem[];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface Request {
|
|
62
|
-
type: 'request';
|
|
63
|
-
id: string;
|
|
64
|
-
name: string;
|
|
65
|
-
description?: string;
|
|
66
|
-
|
|
67
|
-
// Execution control
|
|
68
|
-
dependsOn?: string[]; // Request IDs that must execute first
|
|
69
|
-
condition?: string; // JavaScript expression to evaluate
|
|
70
|
-
|
|
71
|
-
// Protocol is inherited from collection.protocol
|
|
72
|
-
auth?: Auth;
|
|
73
|
-
data: {
|
|
74
|
-
// Protocol-specific data
|
|
75
|
-
[key: string]: unknown;
|
|
76
|
-
|
|
77
|
-
// Plugin event scripts (e.g., for WebSocket: onMessage, onError, onComplete)
|
|
78
|
-
scripts?: ProtocolScript[];
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
preRequestScript?: string;
|
|
82
|
-
postRequestScript?: string; // Contains tests via quest.test()
|
|
83
|
-
|
|
84
|
-
options?: RuntimeOptions;
|
|
85
|
-
examples?: ResponseExample[];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export interface ProtocolScript {
|
|
89
|
-
event: string; // "onMessage", "onError", "onComplete", etc.
|
|
90
|
-
script: string;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export type CollectionItem = Request | Folder;
|
|
94
|
-
|
|
95
|
-
export interface ResponseExample {
|
|
96
|
-
name: string;
|
|
97
|
-
description?: string;
|
|
98
|
-
protocol: string;
|
|
99
|
-
data: unknown;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ============================================================================
|
|
103
|
-
// Authentication
|
|
104
|
-
// ============================================================================
|
|
105
|
-
|
|
106
|
-
export interface Auth {
|
|
107
|
-
type: string | 'inherit' | 'none';
|
|
108
|
-
data?: Record<string, unknown>;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// ============================================================================
|
|
112
|
-
// Variables
|
|
113
|
-
// ============================================================================
|
|
114
|
-
|
|
115
|
-
export interface Variable {
|
|
116
|
-
value: string;
|
|
117
|
-
enabled?: boolean;
|
|
118
|
-
type?: "string" | "number" | "boolean";
|
|
119
|
-
isSecret?: boolean;
|
|
120
|
-
isRequired?: boolean; // enforce presence at runtime
|
|
121
|
-
provider?: string; // "env", "vault:aws-secrets", etc., undefined for built-in
|
|
122
|
-
description?: string;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface Environment {
|
|
126
|
-
name: string;
|
|
127
|
-
variables: Record<string, string | Variable>;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface IterationData {
|
|
131
|
-
[key: string]: string | number | boolean;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// ============================================================================
|
|
135
|
-
// Runtime Options
|
|
136
|
-
// ============================================================================
|
|
137
|
-
|
|
138
|
-
export interface CollectionRunnerOptions {
|
|
139
|
-
pluginsDir?: string | string[]; // Optional path(s) to plugins folder(s) for dynamic loading
|
|
140
|
-
logLevel?: LogLevel; // Optional log level (default: INFO)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export interface RuntimeOptions {
|
|
144
|
-
// Validation
|
|
145
|
-
strictMode?: boolean; // Enable/disable conditional test validation (default: true)
|
|
146
|
-
|
|
147
|
-
// Execution control
|
|
148
|
-
execution?: ExecutionOptions;
|
|
149
|
-
|
|
150
|
-
// Filtering
|
|
151
|
-
filter?: string; // Path-based regex filter
|
|
152
|
-
excludeDeps?: boolean; // Exclude dependencies when filtering
|
|
153
|
-
|
|
154
|
-
// External libraries
|
|
155
|
-
libraries?: ExternalLibrary[];
|
|
156
|
-
|
|
157
|
-
// Cookies
|
|
158
|
-
cookies?: Cookie[];
|
|
159
|
-
jar?: CookieJarOptions;
|
|
160
|
-
|
|
161
|
-
// SSL/TLS
|
|
162
|
-
ssl?: SSLOptions;
|
|
163
|
-
|
|
164
|
-
// Proxy
|
|
165
|
-
proxy?: ProxyOptions;
|
|
166
|
-
|
|
167
|
-
// Timeouts
|
|
168
|
-
timeout?: TimeoutOptions;
|
|
169
|
-
|
|
170
|
-
// Redirects
|
|
171
|
-
followRedirects?: boolean;
|
|
172
|
-
maxRedirects?: number;
|
|
173
|
-
|
|
174
|
-
// Logging
|
|
175
|
-
logLevel?: LogLevel;
|
|
176
|
-
|
|
177
|
-
// Plugin-specific options
|
|
178
|
-
plugins?: Record<string, unknown>;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export interface ExecutionOptions {
|
|
182
|
-
allowParallel?: boolean; // Enable parallel execution
|
|
183
|
-
maxConcurrency?: number; // Max parallel requests
|
|
184
|
-
bail?: boolean; // Stop on first failure
|
|
185
|
-
delay?: number; // Delay between requests (ms)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export interface ExternalLibrary {
|
|
189
|
-
name: string;
|
|
190
|
-
source: LibrarySource;
|
|
191
|
-
version?: string;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export type LibrarySource =
|
|
195
|
-
| { type: 'npm'; package: string }
|
|
196
|
-
| { type: 'cdn'; url: string }
|
|
197
|
-
| { type: 'file'; path: string };
|
|
198
|
-
|
|
199
|
-
export interface Cookie {
|
|
200
|
-
name: string;
|
|
201
|
-
value: string;
|
|
202
|
-
domain: string;
|
|
203
|
-
path?: string;
|
|
204
|
-
expires?: string;
|
|
205
|
-
httpOnly?: boolean;
|
|
206
|
-
secure?: boolean;
|
|
207
|
-
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export interface CookieSetOptions {
|
|
211
|
-
domain: string;
|
|
212
|
-
path?: string;
|
|
213
|
-
expires?: string;
|
|
214
|
-
httpOnly?: boolean;
|
|
215
|
-
secure?: boolean;
|
|
216
|
-
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export interface CookieJarOptions {
|
|
220
|
-
persist: boolean; //default: false
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export interface SSLOptions {
|
|
224
|
-
validateCertificates?: boolean;
|
|
225
|
-
clientCertificate?: {
|
|
226
|
-
cert: string;
|
|
227
|
-
key: string;
|
|
228
|
-
passphrase?: string;
|
|
229
|
-
};
|
|
230
|
-
ca?: string;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export interface ProxyOptions {
|
|
234
|
-
enabled: boolean;
|
|
235
|
-
host: string;
|
|
236
|
-
port: number;
|
|
237
|
-
auth?: {
|
|
238
|
-
username: string;
|
|
239
|
-
password: string;
|
|
240
|
-
};
|
|
241
|
-
bypass?: string[];
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export interface TimeoutOptions {
|
|
245
|
-
request?: number;
|
|
246
|
-
connection?: number;
|
|
247
|
-
response?: number;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// ============================================================================
|
|
251
|
-
// Execution History
|
|
252
|
-
// ============================================================================
|
|
253
|
-
|
|
254
|
-
export interface ExecutionRecord {
|
|
255
|
-
// Identity
|
|
256
|
-
id: string;
|
|
257
|
-
name: string;
|
|
258
|
-
path: string; // "/folder1/folder2/request"
|
|
259
|
-
|
|
260
|
-
// Iteration metadata
|
|
261
|
-
iteration: number;
|
|
262
|
-
|
|
263
|
-
// Results
|
|
264
|
-
response: ProtocolResponse;
|
|
265
|
-
tests: TestResult[];
|
|
266
|
-
timestamp: string;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export interface ExecutionHistoryEntry {
|
|
270
|
-
requestId: string;
|
|
271
|
-
requestName: string;
|
|
272
|
-
response?: ProtocolResponse;
|
|
273
|
-
timestamp: Date;
|
|
274
|
-
collectionIteration: number;
|
|
275
|
-
requestIteration: number;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// ============================================================================
|
|
279
|
-
// Plugin Events
|
|
280
|
-
// ============================================================================
|
|
281
|
-
|
|
282
|
-
export interface PluginEvent {
|
|
283
|
-
eventName: string; // "onMessage", "onError", etc.
|
|
284
|
-
requestId: string; // Request that triggered the event
|
|
285
|
-
timestamp: Date;
|
|
286
|
-
data: unknown; // Plugin-specific event data
|
|
287
|
-
index: number; // Event sequence number (0-based, per event type)
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// ============================================================================
|
|
291
|
-
// Execution Context
|
|
292
|
-
// ============================================================================
|
|
293
|
-
|
|
294
|
-
export interface ScopeFrame {
|
|
295
|
-
level: 'collection' | 'folder' | 'request';
|
|
296
|
-
id: string;
|
|
297
|
-
vars: Record<string, string>;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export type IterationSource = 'collection' | 'cli' | 'none';
|
|
301
|
-
|
|
302
|
-
export interface ExecutionContext {
|
|
303
|
-
// Collection info
|
|
304
|
-
collectionInfo: CollectionInfo;
|
|
305
|
-
protocol: string; // Collection protocol (e.g., 'http', 'graphql')
|
|
306
|
-
|
|
307
|
-
// Variable scopes
|
|
308
|
-
collectionVariables: Record<string, string | Variable>;
|
|
309
|
-
globalVariables: Record<string, string | Variable>;
|
|
310
|
-
scopeStack: ScopeFrame[]; // Hierarchical scope stack
|
|
311
|
-
environment?: Environment;
|
|
312
|
-
|
|
313
|
-
// Current execution state
|
|
314
|
-
currentRequest?: Request;
|
|
315
|
-
currentResponse?: ProtocolResponse;
|
|
316
|
-
currentPath?: string; // Current folder/request path
|
|
317
|
-
|
|
318
|
-
// Plugin event tracking (for streaming protocols)
|
|
319
|
-
expectedMessages?: number; // Hint from quest.expectMessages() for plugin optimization
|
|
320
|
-
currentEvent?: PluginEvent; // Current plugin event (for eventScripts)
|
|
321
|
-
|
|
322
|
-
// Iteration state
|
|
323
|
-
iterationCurrent: number;
|
|
324
|
-
iterationCount: number;
|
|
325
|
-
iterationData?: IterationData[];
|
|
326
|
-
iterationSource: IterationSource; // Where iteration data comes from
|
|
327
|
-
|
|
328
|
-
// History
|
|
329
|
-
executionHistory: ExecutionRecord[];
|
|
330
|
-
|
|
331
|
-
// Runtime options
|
|
332
|
-
options: RuntimeOptions;
|
|
333
|
-
|
|
334
|
-
// Cookie jar - ICookieJar interface for type safety
|
|
335
|
-
cookieJar: ICookieJar;
|
|
336
|
-
|
|
337
|
-
// Event emitter for plugin callbacks
|
|
338
|
-
eventEmitter?: unknown; // EventEmitter instance
|
|
339
|
-
|
|
340
|
-
// Cached protocol plugin (loaded at collection initialization for fail-fast validation)
|
|
341
|
-
protocolPlugin: IProtocolPlugin;
|
|
342
|
-
|
|
343
|
-
// emitEvent - Allow plugins to emit custom events (websocket:message, sse:chunk, etc.)
|
|
344
|
-
// These events are protocol-specific and streamed to the UI
|
|
345
|
-
emitEvent?: (type: string, data: unknown) => void;
|
|
346
|
-
|
|
347
|
-
// Abort signal for execution cancellation
|
|
348
|
-
abortSignal: AbortSignal;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// ============================================================================
|
|
352
|
-
// Cookie Jar Interface
|
|
353
|
-
// ============================================================================
|
|
354
|
-
|
|
355
|
-
export interface ICookieJar {
|
|
356
|
-
get(name: string, domain?: string, path?: string): string | null;
|
|
357
|
-
set(name: string, value: string, options: CookieSetOptions): void;
|
|
358
|
-
has(name: string, domain?: string, path?: string): boolean;
|
|
359
|
-
remove(name: string, domain?: string, path?: string): void;
|
|
360
|
-
clear(): void;
|
|
361
|
-
toObject(): Record<string, string>;
|
|
362
|
-
getCookieHeader(url: string): string | null;
|
|
363
|
-
store(setCookieHeaders: string | string[] | null | undefined, requestUrl: string): void;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// ============================================================================
|
|
367
|
-
// Validation
|
|
368
|
-
// ============================================================================
|
|
369
|
-
|
|
370
|
-
export interface ValidationError {
|
|
371
|
-
message: string;
|
|
372
|
-
location: string; // Request path (e.g., "/Folder A/Request 1")
|
|
373
|
-
source: 'script' | 'protocol' | 'auth' | 'vault' | 'schema';
|
|
374
|
-
scriptType?: ScriptType;
|
|
375
|
-
details?: {
|
|
376
|
-
line?: number;
|
|
377
|
-
column?: number;
|
|
378
|
-
suggestion?: string;
|
|
379
|
-
[key: string]: unknown;
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// ============================================================================
|
|
384
|
-
// Logging
|
|
385
|
-
// ============================================================================
|
|
386
|
-
|
|
387
|
-
export enum LogLevel {
|
|
388
|
-
ERROR = 0,
|
|
389
|
-
WARN = 1,
|
|
390
|
-
INFO = 2,
|
|
391
|
-
DEBUG = 3,
|
|
392
|
-
TRACE = 4
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
export interface ILogger {
|
|
396
|
-
error(message: string, ...args: unknown[]): void;
|
|
397
|
-
warn(message: string, ...args: unknown[]): void;
|
|
398
|
-
info(message: string, ...args: unknown[]): void;
|
|
399
|
-
debug(message: string, ...args: unknown[]): void;
|
|
400
|
-
trace(message: string, ...args: unknown[]): void;
|
|
401
|
-
setLevel(level: LogLevel): void;
|
|
402
|
-
createLogger(component: string): ILogger;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// ============================================================================
|
|
406
|
-
// Run Options & Results
|
|
407
|
-
// ============================================================================
|
|
408
|
-
|
|
409
|
-
export interface RunOptions extends Omit<RuntimeOptions, 'logLevel'> {
|
|
410
|
-
// Additional CLI/API specific options not in RuntimeOptions
|
|
411
|
-
environment?: Environment;
|
|
412
|
-
globalVariables?: Record<string, string | Variable>;
|
|
413
|
-
data?: IterationData[]; // CLI --data override
|
|
414
|
-
iterations?: number; // Global iteration cap
|
|
415
|
-
filter?: string; // Path-based regex filter
|
|
416
|
-
excludeDeps?: boolean; // Exclude dependencies when filtering
|
|
417
|
-
signal?: AbortSignal; // External abort signal
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
export interface RunResult {
|
|
421
|
-
collectionId: string;
|
|
422
|
-
collectionName: string;
|
|
423
|
-
startTime: Date;
|
|
424
|
-
endTime: Date;
|
|
425
|
-
duration: number;
|
|
426
|
-
requestResults: RequestResult[];
|
|
427
|
-
totalTests: number;
|
|
428
|
-
passedTests: number;
|
|
429
|
-
failedTests: number;
|
|
430
|
-
skippedTests: number;
|
|
431
|
-
validationErrors?: ValidationError[]; // Pre-run validation errors
|
|
432
|
-
aborted?: boolean;
|
|
433
|
-
abortReason?: string;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
export interface RequestResult {
|
|
437
|
-
requestId: string;
|
|
438
|
-
requestName: string;
|
|
439
|
-
path: string;
|
|
440
|
-
success: boolean;
|
|
441
|
-
response?: ProtocolResponse;
|
|
442
|
-
tests: TestResult[];
|
|
443
|
-
duration: number;
|
|
444
|
-
scriptError?: string;
|
|
445
|
-
iteration: number;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
export interface TestResult {
|
|
449
|
-
name: string;
|
|
450
|
-
passed: boolean;
|
|
451
|
-
error?: string;
|
|
452
|
-
skipped: boolean;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// ============================================================================
|
|
456
|
-
// Plugin Package Metadata
|
|
457
|
-
// ============================================================================
|
|
458
|
-
|
|
459
|
-
export interface PluginPackageJson {
|
|
460
|
-
name: string;
|
|
461
|
-
version: string;
|
|
462
|
-
main?: string;
|
|
463
|
-
apiquest?: {
|
|
464
|
-
runtime?: string[] | string;
|
|
465
|
-
type: string;
|
|
466
|
-
capabilities?: {
|
|
467
|
-
provides?: {
|
|
468
|
-
protocols?: string[];
|
|
469
|
-
authTypes?: string[];
|
|
470
|
-
provider?: string;
|
|
471
|
-
};
|
|
472
|
-
};
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
// ============================================================================
|
|
477
|
-
// Protocol Plugin Interface
|
|
478
|
-
// ============================================================================
|
|
479
|
-
|
|
480
|
-
export interface IProtocolPlugin {
|
|
481
|
-
// Identity
|
|
482
|
-
name: string;
|
|
483
|
-
version: string;
|
|
484
|
-
description: string;
|
|
485
|
-
|
|
486
|
-
// What protocols does this plugin provide?
|
|
487
|
-
// Single-protocol: ['http']
|
|
488
|
-
// Multi-protocol bundle (rare): ['http', 'https', 'http2']
|
|
489
|
-
protocols: string[];
|
|
490
|
-
|
|
491
|
-
// Supported auth types for this protocol
|
|
492
|
-
// Example: HTTP supports ['bearer', 'basic', 'oauth2', 'apikey']
|
|
493
|
-
// SQL might support ['integrated', 'username-password']
|
|
494
|
-
supportedAuthTypes: string[];
|
|
495
|
-
|
|
496
|
-
// If true, ONLY supportedAuthTypes listed above are allowed
|
|
497
|
-
// If false/undefined, accept additional auth plugins that declare this protocol
|
|
498
|
-
strictAuthList?: boolean;
|
|
499
|
-
|
|
500
|
-
// Schema for request.data (defines what fields the UI should show)
|
|
501
|
-
// Example: HTTP has method, url, headers, body
|
|
502
|
-
dataSchema: unknown; // JSON Schema or custom schema format
|
|
503
|
-
|
|
504
|
-
// Schema for options.plugins[protocol] (runtime options)
|
|
505
|
-
// Example: HTTP has keepAlive, compression, maxSockets
|
|
506
|
-
optionsSchema?: PluginOptionsSchema;
|
|
507
|
-
|
|
508
|
-
// Plugin event definitions (e.g., WebSocket: onMessage, onError, onComplete)
|
|
509
|
-
events?: PluginEventDefinition[];
|
|
510
|
-
|
|
511
|
-
execute(
|
|
512
|
-
request: Request,
|
|
513
|
-
context: ExecutionContext,
|
|
514
|
-
options: RuntimeOptions, // Receives merged options
|
|
515
|
-
emitEvent?: (eventName: string, eventData: unknown) => Promise<void>, // Optional callback for plugin events
|
|
516
|
-
logger?: ILogger // Optional logger from fracture
|
|
517
|
-
): Promise<ProtocolResponse>;
|
|
518
|
-
|
|
519
|
-
validate(request: Request, options: RuntimeOptions): ValidationResult;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
export interface PluginOptionsSchema {
|
|
523
|
-
// Defines options that can be set in options.plugins[protocol]
|
|
524
|
-
// Example: options.plugins.http = { keepAlive: true, compression: "gzip" }
|
|
525
|
-
[optionKey: string]: {
|
|
526
|
-
type: 'boolean' | 'string' | 'number';
|
|
527
|
-
default?: unknown;
|
|
528
|
-
enum?: unknown[];
|
|
529
|
-
description?: string;
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
export interface PluginEventDefinition {
|
|
534
|
-
name: string; // "onMessage", "onError", "onComplete"
|
|
535
|
-
description: string;
|
|
536
|
-
canHaveTests: boolean; // Can this event script contain quest.test()?
|
|
537
|
-
required: boolean; // Is this event required or optional?
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
export interface ProtocolResponse {
|
|
541
|
-
status: number;
|
|
542
|
-
statusText: string;
|
|
543
|
-
body: string;
|
|
544
|
-
headers: Record<string, string | string[]>; // Headers can have multiple values (e.g., set-cookie)
|
|
545
|
-
duration: number;
|
|
546
|
-
error?: string;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
export interface ValidationResult {
|
|
550
|
-
valid: boolean;
|
|
551
|
-
errors?: ValidationError[];
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// ============================================================================
|
|
555
|
-
// Auth Plugin Interface
|
|
556
|
-
// ============================================================================
|
|
557
|
-
|
|
558
|
-
export interface IAuthPlugin {
|
|
559
|
-
// Identity
|
|
560
|
-
name: string;
|
|
561
|
-
version: string;
|
|
562
|
-
description: string;
|
|
563
|
-
|
|
564
|
-
// What auth types does this plugin provide?
|
|
565
|
-
// Single auth: ['bearer']
|
|
566
|
-
// Multi-auth bundle: ['bearer', 'basic', 'apikey', 'oauth2']
|
|
567
|
-
authTypes: string[];
|
|
568
|
-
|
|
569
|
-
// Which protocols does this auth work with? (REQUIRED)
|
|
570
|
-
// Example: ['http', 'grpc', 'graphql']
|
|
571
|
-
// No universal auth - must explicitly declare protocol support
|
|
572
|
-
protocols: string[];
|
|
573
|
-
|
|
574
|
-
// Schema for auth.data (defines what fields the UI should show)
|
|
575
|
-
// Example: bearer has { token: string }, basic has { username: string, password: string }
|
|
576
|
-
dataSchema: unknown; // JSON Schema or custom schema format
|
|
577
|
-
|
|
578
|
-
apply(
|
|
579
|
-
request: Request,
|
|
580
|
-
auth: Auth,
|
|
581
|
-
options: RuntimeOptions,
|
|
582
|
-
logger?: ILogger // Optional logger from fracture
|
|
583
|
-
): Promise<Request>;
|
|
584
|
-
|
|
585
|
-
validate(auth: Auth, options: RuntimeOptions): ValidationResult;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// ============================================================================
|
|
589
|
-
// Value Provider Plugin Interface
|
|
590
|
-
// ============================================================================
|
|
591
|
-
|
|
592
|
-
export interface IValueProviderPlugin {
|
|
593
|
-
provider: string; // "vault:aws-secrets", "vault:azure-keyvault", "vault:file"
|
|
594
|
-
name: string;
|
|
595
|
-
description: string;
|
|
596
|
-
|
|
597
|
-
// Configuration schema (if provider needs setup)
|
|
598
|
-
configSchema?: unknown;
|
|
599
|
-
|
|
600
|
-
// Retrieve a secret value by key
|
|
601
|
-
// Returns null if key doesn't exist
|
|
602
|
-
// Throws error if provider fails (network, auth, etc.)
|
|
603
|
-
getValue(
|
|
604
|
-
key: string,
|
|
605
|
-
config?: unknown,
|
|
606
|
-
context?: ExecutionContext,
|
|
607
|
-
logger?: ILogger // Optional logger from fracture
|
|
608
|
-
): Promise<string | null>;
|
|
609
|
-
|
|
610
|
-
// Validate provider configuration
|
|
611
|
-
validate(config?: unknown): ValidationResult;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// ============================================================================
|
|
615
|
-
// Script Engine
|
|
616
|
-
// ============================================================================
|
|
617
|
-
|
|
618
|
-
export interface ScriptResult {
|
|
619
|
-
success: boolean;
|
|
620
|
-
tests: TestResult[];
|
|
621
|
-
error?: string;
|
|
622
|
-
consoleOutput: string[];
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
export enum ScriptType {
|
|
626
|
-
CollectionPre = 'collection-pre',
|
|
627
|
-
CollectionPost = 'collection-post',
|
|
628
|
-
FolderPre = 'folder-pre',
|
|
629
|
-
FolderPost = 'folder-post',
|
|
630
|
-
PreRequest = 'request-pre',
|
|
631
|
-
PostRequest = 'request-post',
|
|
632
|
-
PluginEvent = 'plugin-event'
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// ============================================================================
|
|
636
|
-
// Reporter Interface
|
|
637
|
-
// ============================================================================
|
|
638
|
-
|
|
639
|
-
export interface IReporter {
|
|
640
|
-
// Identity
|
|
641
|
-
name: string;
|
|
642
|
-
version: string;
|
|
643
|
-
description: string;
|
|
644
|
-
|
|
645
|
-
// What report types does this plugin provide?
|
|
646
|
-
// Example: ['console'], ['json', 'json-summary'], ['html', 'junit']
|
|
647
|
-
reportTypes: string[];
|
|
648
|
-
|
|
649
|
-
// Reporter-specific options schema
|
|
650
|
-
// Defines what options can be passed to getOptions()
|
|
651
|
-
// Example: { outputFile: string, verbose: boolean, colors: boolean }
|
|
652
|
-
optionsSchema?: unknown;
|
|
653
|
-
|
|
654
|
-
// Get options for a specific report type
|
|
655
|
-
// Called before run starts to configure the reporter
|
|
656
|
-
getOptions?(reportType: string): unknown;
|
|
657
|
-
|
|
658
|
-
// Lifecycle hooks
|
|
659
|
-
onRunStarted(collection: Collection, options: RunOptions): void;
|
|
660
|
-
|
|
661
|
-
// @deprecated Use onBeforeRequest instead
|
|
662
|
-
onRequestStarted?(request: Request, path: string): void;
|
|
663
|
-
// @deprecated Use onAfterRequest + onAssertion instead
|
|
664
|
-
onRequestCompleted?(result: RequestResult): void;
|
|
665
|
-
// @deprecated Use onAssertion instead
|
|
666
|
-
onTestCompleted?(test: TestResult, request: string): void;
|
|
667
|
-
|
|
668
|
-
// New event-based hooks using EventPayloads types
|
|
669
|
-
onBeforeRequest?(payload: EventPayloads['beforeRequest']): void;
|
|
670
|
-
onAfterRequest?(payload: EventPayloads['afterRequest']): void;
|
|
671
|
-
onAssertion?(payload: EventPayloads['assertion']): void;
|
|
672
|
-
|
|
673
|
-
onRunCompleted(result: RunResult): void;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
// ============================================================================
|
|
677
|
-
// Events
|
|
678
|
-
// ============================================================================
|
|
679
|
-
|
|
680
|
-
/**
|
|
681
|
-
* Path type for EventEnvelope and ExecutionNode
|
|
682
|
-
*/
|
|
683
|
-
export type NodeType = 'collection' | 'folder' | 'request';
|
|
684
|
-
export type PathType = 'collection:/' | `folder:/${string}` | `request:/${string}`;
|
|
685
|
-
/**
|
|
686
|
-
* Event envelope that provides context for all events (except console)
|
|
687
|
-
*/
|
|
688
|
-
export type EventEnvelope = {
|
|
689
|
-
id: string; // Unique event ID
|
|
690
|
-
path: PathType;
|
|
691
|
-
pathType: NodeType;
|
|
692
|
-
collectionInfo: CollectionInfo;
|
|
693
|
-
iteration?: {
|
|
694
|
-
current: number;
|
|
695
|
-
total: number;
|
|
696
|
-
source: IterationSource;
|
|
697
|
-
rowIndex?: number;
|
|
698
|
-
rowKeys?: string[];
|
|
699
|
-
row?: Record<string, string | number | boolean>;
|
|
700
|
-
};
|
|
701
|
-
request?: Request;
|
|
702
|
-
};
|
|
703
|
-
|
|
704
|
-
export type RunnerEvent =
|
|
705
|
-
// Collection lifecycle
|
|
706
|
-
| 'beforeRun'
|
|
707
|
-
| 'afterRun'
|
|
708
|
-
| 'beforeCollectionPreScript'
|
|
709
|
-
| 'afterCollectionPreScript'
|
|
710
|
-
| 'beforeCollectionPostScript'
|
|
711
|
-
| 'afterCollectionPostScript'
|
|
712
|
-
|
|
713
|
-
// Folder lifecycle
|
|
714
|
-
| 'beforeFolder'
|
|
715
|
-
| 'afterFolder'
|
|
716
|
-
| 'beforeFolderPreScript'
|
|
717
|
-
| 'afterFolderPreScript'
|
|
718
|
-
| 'beforeFolderPostScript'
|
|
719
|
-
| 'afterFolderPostScript'
|
|
720
|
-
|
|
721
|
-
// Iteration
|
|
722
|
-
| 'beforeIteration'
|
|
723
|
-
| 'afterIteration'
|
|
724
|
-
|
|
725
|
-
// Request/Item
|
|
726
|
-
| 'beforeItem'
|
|
727
|
-
| 'afterItem'
|
|
728
|
-
| 'beforePreScript'
|
|
729
|
-
| 'afterPreScript'
|
|
730
|
-
| 'beforeRequest'
|
|
731
|
-
| 'afterRequest'
|
|
732
|
-
| 'beforePostScript'
|
|
733
|
-
| 'afterPostScript'
|
|
734
|
-
|
|
735
|
-
// Tests (run within postRequestScript via quest.test())
|
|
736
|
-
| 'assertion'
|
|
737
|
-
|
|
738
|
-
// Utilities
|
|
739
|
-
| 'console'
|
|
740
|
-
| 'exception';
|
|
741
|
-
|
|
742
|
-
export interface EventPayloads {
|
|
743
|
-
// Run Lifecycle
|
|
744
|
-
beforeRun: {
|
|
745
|
-
options: RunOptions;
|
|
746
|
-
validationResult?: ValidationResult;
|
|
747
|
-
expectedTestCount?: number;
|
|
748
|
-
} & Pick<EventEnvelope, 'collectionInfo'>;
|
|
749
|
-
|
|
750
|
-
afterRun: {
|
|
751
|
-
result: RunResult;
|
|
752
|
-
} & Pick<EventEnvelope, 'collectionInfo'>;
|
|
753
|
-
|
|
754
|
-
// Collection Scripts
|
|
755
|
-
beforeCollectionPreScript: EventEnvelope & { path: 'collection:/' };
|
|
756
|
-
afterCollectionPreScript: EventEnvelope & { path: 'collection:/'; result: ScriptResult };
|
|
757
|
-
beforeCollectionPostScript: EventEnvelope & { path: 'collection:/' };
|
|
758
|
-
afterCollectionPostScript: EventEnvelope & { path: 'collection:/'; result: ScriptResult };
|
|
759
|
-
|
|
760
|
-
// Iteration Lifecycle
|
|
761
|
-
beforeIteration: EventEnvelope & { iteration: Required<EventEnvelope['iteration']> };
|
|
762
|
-
afterIteration: EventEnvelope & { iteration: Required<EventEnvelope['iteration']>; duration: number };
|
|
763
|
-
|
|
764
|
-
// Folder Lifecycle
|
|
765
|
-
beforeFolder: EventEnvelope;
|
|
766
|
-
afterFolder: EventEnvelope & { duration: number };
|
|
767
|
-
|
|
768
|
-
// Folder Scripts
|
|
769
|
-
beforeFolderPreScript: EventEnvelope;
|
|
770
|
-
afterFolderPreScript: EventEnvelope & { result: ScriptResult };
|
|
771
|
-
beforeFolderPostScript: EventEnvelope;
|
|
772
|
-
afterFolderPostScript: EventEnvelope & { result: ScriptResult };
|
|
773
|
-
|
|
774
|
-
// Item Lifecycle
|
|
775
|
-
beforeItem: EventEnvelope & { request: Request; path: string };
|
|
776
|
-
afterItem: EventEnvelope & { request: Request; path: string; response?: ProtocolResponse; result: RequestResult };
|
|
777
|
-
|
|
778
|
-
// Pre-Request Script
|
|
779
|
-
beforePreScript: EventEnvelope & { request: Request; path: string };
|
|
780
|
-
afterPreScript: EventEnvelope & { request: Request; path: string; result: ScriptResult };
|
|
781
|
-
|
|
782
|
-
// Request
|
|
783
|
-
beforeRequest: EventEnvelope & { request: Request; path: string };
|
|
784
|
-
afterRequest: EventEnvelope & { request: Request; response: ProtocolResponse; duration: number };
|
|
785
|
-
|
|
786
|
-
// Post-Request Script
|
|
787
|
-
beforePostScript: EventEnvelope & { request: Request; path: string; response: ProtocolResponse };
|
|
788
|
-
afterPostScript: EventEnvelope & { request: Request; path: string; response: ProtocolResponse; result: ScriptResult };
|
|
789
|
-
|
|
790
|
-
// Test/Assertion
|
|
791
|
-
assertion: EventEnvelope & {
|
|
792
|
-
test: TestResult;
|
|
793
|
-
request?: Request;
|
|
794
|
-
path?: string;
|
|
795
|
-
response?: ProtocolResponse;
|
|
796
|
-
event?: {
|
|
797
|
-
name: string;
|
|
798
|
-
index: number;
|
|
799
|
-
timestamp: string;
|
|
800
|
-
data: unknown;
|
|
801
|
-
};
|
|
802
|
-
};
|
|
803
|
-
|
|
804
|
-
// Utility Events
|
|
805
|
-
console: {
|
|
806
|
-
id: string; // Unique event ID
|
|
807
|
-
message: string;
|
|
808
|
-
level: LogLevel;
|
|
809
|
-
levelName?: 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
|
810
|
-
component?: string;
|
|
811
|
-
timestamp?: string;
|
|
812
|
-
args?: unknown[];
|
|
813
|
-
};
|
|
814
|
-
|
|
815
|
-
exception: {
|
|
816
|
-
id: string; // Unique event ID
|
|
817
|
-
error: Error;
|
|
818
|
-
phase: 'collection-pre' | 'collection-post' | 'folder-pre' | 'folder-post' | 'prerequest' | 'postrequest' | 'request';
|
|
819
|
-
request?: Request;
|
|
820
|
-
path?: string;
|
|
821
|
-
response?: ProtocolResponse;
|
|
822
|
-
};
|
|
823
|
-
}
|
|
1
|
+
// Core Types and Interfaces for @apiquest/types
|
|
2
|
+
// Schema v1.0 - Updated 2026-01-05
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Collection & Items
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
export interface Collection {
|
|
9
|
+
$schema?: string;
|
|
10
|
+
info: CollectionInfo;
|
|
11
|
+
|
|
12
|
+
// Protocol (collection-level)
|
|
13
|
+
protocol: string; // "http", "graphql", "grpc", "websocket", etc.
|
|
14
|
+
|
|
15
|
+
auth?: Auth;
|
|
16
|
+
variables?: Record<string, string | Variable>;
|
|
17
|
+
|
|
18
|
+
// Collection lifecycle scripts
|
|
19
|
+
collectionPreScript?: string;
|
|
20
|
+
collectionPostScript?: string;
|
|
21
|
+
|
|
22
|
+
// Request lifecycle scripts (run before/after EACH request)
|
|
23
|
+
preRequestScript?: string;
|
|
24
|
+
postRequestScript?: string;
|
|
25
|
+
|
|
26
|
+
testData?: IterationData[];
|
|
27
|
+
options?: RuntimeOptions;
|
|
28
|
+
items: CollectionItem[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface CollectionInfo {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
version?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface Folder {
|
|
39
|
+
type: 'folder';
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
auth?: Auth;
|
|
44
|
+
|
|
45
|
+
// Execution control
|
|
46
|
+
dependsOn?: string[]; // Folder/Request IDs that must execute first
|
|
47
|
+
condition?: string; // JavaScript expression to evaluate
|
|
48
|
+
|
|
49
|
+
// Folder lifecycle scripts
|
|
50
|
+
folderPreScript?: string;
|
|
51
|
+
folderPostScript?: string;
|
|
52
|
+
|
|
53
|
+
// Request lifecycle scripts
|
|
54
|
+
preRequestScript?: string;
|
|
55
|
+
postRequestScript?: string;
|
|
56
|
+
|
|
57
|
+
options?: RuntimeOptions;
|
|
58
|
+
items: CollectionItem[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface Request {
|
|
62
|
+
type: 'request';
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
|
|
67
|
+
// Execution control
|
|
68
|
+
dependsOn?: string[]; // Request IDs that must execute first
|
|
69
|
+
condition?: string; // JavaScript expression to evaluate
|
|
70
|
+
|
|
71
|
+
// Protocol is inherited from collection.protocol
|
|
72
|
+
auth?: Auth;
|
|
73
|
+
data: {
|
|
74
|
+
// Protocol-specific data
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
|
|
77
|
+
// Plugin event scripts (e.g., for WebSocket: onMessage, onError, onComplete)
|
|
78
|
+
scripts?: ProtocolScript[];
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
preRequestScript?: string;
|
|
82
|
+
postRequestScript?: string; // Contains tests via quest.test()
|
|
83
|
+
|
|
84
|
+
options?: RuntimeOptions;
|
|
85
|
+
examples?: ResponseExample[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ProtocolScript {
|
|
89
|
+
event: string; // "onMessage", "onError", "onComplete", etc.
|
|
90
|
+
script: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type CollectionItem = Request | Folder;
|
|
94
|
+
|
|
95
|
+
export interface ResponseExample {
|
|
96
|
+
name: string;
|
|
97
|
+
description?: string;
|
|
98
|
+
protocol: string;
|
|
99
|
+
data: unknown;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Authentication
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
export interface Auth {
|
|
107
|
+
type: string | 'inherit' | 'none';
|
|
108
|
+
data?: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// Variables
|
|
113
|
+
// ============================================================================
|
|
114
|
+
|
|
115
|
+
export interface Variable {
|
|
116
|
+
value: string;
|
|
117
|
+
enabled?: boolean;
|
|
118
|
+
type?: "string" | "number" | "boolean";
|
|
119
|
+
isSecret?: boolean;
|
|
120
|
+
isRequired?: boolean; // enforce presence at runtime
|
|
121
|
+
provider?: string; // "env", "vault:aws-secrets", etc., undefined for built-in
|
|
122
|
+
description?: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface Environment {
|
|
126
|
+
name: string;
|
|
127
|
+
variables: Record<string, string | Variable>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface IterationData {
|
|
131
|
+
[key: string]: string | number | boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Runtime Options
|
|
136
|
+
// ============================================================================
|
|
137
|
+
|
|
138
|
+
export interface CollectionRunnerOptions {
|
|
139
|
+
pluginsDir?: string | string[]; // Optional path(s) to plugins folder(s) for dynamic loading
|
|
140
|
+
logLevel?: LogLevel; // Optional log level (default: INFO)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface RuntimeOptions {
|
|
144
|
+
// Validation
|
|
145
|
+
strictMode?: boolean; // Enable/disable conditional test validation (default: true)
|
|
146
|
+
|
|
147
|
+
// Execution control
|
|
148
|
+
execution?: ExecutionOptions;
|
|
149
|
+
|
|
150
|
+
// Filtering
|
|
151
|
+
filter?: string; // Path-based regex filter
|
|
152
|
+
excludeDeps?: boolean; // Exclude dependencies when filtering
|
|
153
|
+
|
|
154
|
+
// External libraries
|
|
155
|
+
libraries?: ExternalLibrary[];
|
|
156
|
+
|
|
157
|
+
// Cookies
|
|
158
|
+
cookies?: Cookie[];
|
|
159
|
+
jar?: CookieJarOptions;
|
|
160
|
+
|
|
161
|
+
// SSL/TLS
|
|
162
|
+
ssl?: SSLOptions;
|
|
163
|
+
|
|
164
|
+
// Proxy
|
|
165
|
+
proxy?: ProxyOptions;
|
|
166
|
+
|
|
167
|
+
// Timeouts
|
|
168
|
+
timeout?: TimeoutOptions;
|
|
169
|
+
|
|
170
|
+
// Redirects
|
|
171
|
+
followRedirects?: boolean;
|
|
172
|
+
maxRedirects?: number;
|
|
173
|
+
|
|
174
|
+
// Logging
|
|
175
|
+
logLevel?: LogLevel;
|
|
176
|
+
|
|
177
|
+
// Plugin-specific options
|
|
178
|
+
plugins?: Record<string, unknown>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface ExecutionOptions {
|
|
182
|
+
allowParallel?: boolean; // Enable parallel execution
|
|
183
|
+
maxConcurrency?: number; // Max parallel requests
|
|
184
|
+
bail?: boolean; // Stop on first failure
|
|
185
|
+
delay?: number; // Delay between requests (ms)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ExternalLibrary {
|
|
189
|
+
name: string;
|
|
190
|
+
source: LibrarySource;
|
|
191
|
+
version?: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export type LibrarySource =
|
|
195
|
+
| { type: 'npm'; package: string }
|
|
196
|
+
| { type: 'cdn'; url: string }
|
|
197
|
+
| { type: 'file'; path: string };
|
|
198
|
+
|
|
199
|
+
export interface Cookie {
|
|
200
|
+
name: string;
|
|
201
|
+
value: string;
|
|
202
|
+
domain: string;
|
|
203
|
+
path?: string;
|
|
204
|
+
expires?: string;
|
|
205
|
+
httpOnly?: boolean;
|
|
206
|
+
secure?: boolean;
|
|
207
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface CookieSetOptions {
|
|
211
|
+
domain: string;
|
|
212
|
+
path?: string;
|
|
213
|
+
expires?: string;
|
|
214
|
+
httpOnly?: boolean;
|
|
215
|
+
secure?: boolean;
|
|
216
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface CookieJarOptions {
|
|
220
|
+
persist: boolean; //default: false
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface SSLOptions {
|
|
224
|
+
validateCertificates?: boolean;
|
|
225
|
+
clientCertificate?: {
|
|
226
|
+
cert: string;
|
|
227
|
+
key: string;
|
|
228
|
+
passphrase?: string;
|
|
229
|
+
};
|
|
230
|
+
ca?: string;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface ProxyOptions {
|
|
234
|
+
enabled: boolean;
|
|
235
|
+
host: string;
|
|
236
|
+
port: number;
|
|
237
|
+
auth?: {
|
|
238
|
+
username: string;
|
|
239
|
+
password: string;
|
|
240
|
+
};
|
|
241
|
+
bypass?: string[];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export interface TimeoutOptions {
|
|
245
|
+
request?: number;
|
|
246
|
+
connection?: number;
|
|
247
|
+
response?: number;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ============================================================================
|
|
251
|
+
// Execution History
|
|
252
|
+
// ============================================================================
|
|
253
|
+
|
|
254
|
+
export interface ExecutionRecord {
|
|
255
|
+
// Identity
|
|
256
|
+
id: string;
|
|
257
|
+
name: string;
|
|
258
|
+
path: string; // "/folder1/folder2/request"
|
|
259
|
+
|
|
260
|
+
// Iteration metadata
|
|
261
|
+
iteration: number;
|
|
262
|
+
|
|
263
|
+
// Results
|
|
264
|
+
response: ProtocolResponse;
|
|
265
|
+
tests: TestResult[];
|
|
266
|
+
timestamp: string;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface ExecutionHistoryEntry {
|
|
270
|
+
requestId: string;
|
|
271
|
+
requestName: string;
|
|
272
|
+
response?: ProtocolResponse;
|
|
273
|
+
timestamp: Date;
|
|
274
|
+
collectionIteration: number;
|
|
275
|
+
requestIteration: number;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ============================================================================
|
|
279
|
+
// Plugin Events
|
|
280
|
+
// ============================================================================
|
|
281
|
+
|
|
282
|
+
export interface PluginEvent {
|
|
283
|
+
eventName: string; // "onMessage", "onError", etc.
|
|
284
|
+
requestId: string; // Request that triggered the event
|
|
285
|
+
timestamp: Date;
|
|
286
|
+
data: unknown; // Plugin-specific event data
|
|
287
|
+
index: number; // Event sequence number (0-based, per event type)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ============================================================================
|
|
291
|
+
// Execution Context
|
|
292
|
+
// ============================================================================
|
|
293
|
+
|
|
294
|
+
export interface ScopeFrame {
|
|
295
|
+
level: 'collection' | 'folder' | 'request';
|
|
296
|
+
id: string;
|
|
297
|
+
vars: Record<string, string>;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export type IterationSource = 'collection' | 'cli' | 'none';
|
|
301
|
+
|
|
302
|
+
export interface ExecutionContext {
|
|
303
|
+
// Collection info
|
|
304
|
+
collectionInfo: CollectionInfo;
|
|
305
|
+
protocol: string; // Collection protocol (e.g., 'http', 'graphql')
|
|
306
|
+
|
|
307
|
+
// Variable scopes
|
|
308
|
+
collectionVariables: Record<string, string | Variable>;
|
|
309
|
+
globalVariables: Record<string, string | Variable>;
|
|
310
|
+
scopeStack: ScopeFrame[]; // Hierarchical scope stack
|
|
311
|
+
environment?: Environment;
|
|
312
|
+
|
|
313
|
+
// Current execution state
|
|
314
|
+
currentRequest?: Request;
|
|
315
|
+
currentResponse?: ProtocolResponse;
|
|
316
|
+
currentPath?: string; // Current folder/request path
|
|
317
|
+
|
|
318
|
+
// Plugin event tracking (for streaming protocols)
|
|
319
|
+
expectedMessages?: number; // Hint from quest.expectMessages() for plugin optimization
|
|
320
|
+
currentEvent?: PluginEvent; // Current plugin event (for eventScripts)
|
|
321
|
+
|
|
322
|
+
// Iteration state
|
|
323
|
+
iterationCurrent: number;
|
|
324
|
+
iterationCount: number;
|
|
325
|
+
iterationData?: IterationData[];
|
|
326
|
+
iterationSource: IterationSource; // Where iteration data comes from
|
|
327
|
+
|
|
328
|
+
// History
|
|
329
|
+
executionHistory: ExecutionRecord[];
|
|
330
|
+
|
|
331
|
+
// Runtime options
|
|
332
|
+
options: RuntimeOptions;
|
|
333
|
+
|
|
334
|
+
// Cookie jar - ICookieJar interface for type safety
|
|
335
|
+
cookieJar: ICookieJar;
|
|
336
|
+
|
|
337
|
+
// Event emitter for plugin callbacks
|
|
338
|
+
eventEmitter?: unknown; // EventEmitter instance
|
|
339
|
+
|
|
340
|
+
// Cached protocol plugin (loaded at collection initialization for fail-fast validation)
|
|
341
|
+
protocolPlugin: IProtocolPlugin;
|
|
342
|
+
|
|
343
|
+
// emitEvent - Allow plugins to emit custom events (websocket:message, sse:chunk, etc.)
|
|
344
|
+
// These events are protocol-specific and streamed to the UI
|
|
345
|
+
emitEvent?: (type: string, data: unknown) => void;
|
|
346
|
+
|
|
347
|
+
// Abort signal for execution cancellation
|
|
348
|
+
abortSignal: AbortSignal;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// ============================================================================
|
|
352
|
+
// Cookie Jar Interface
|
|
353
|
+
// ============================================================================
|
|
354
|
+
|
|
355
|
+
export interface ICookieJar {
|
|
356
|
+
get(name: string, domain?: string, path?: string): string | null;
|
|
357
|
+
set(name: string, value: string, options: CookieSetOptions): void;
|
|
358
|
+
has(name: string, domain?: string, path?: string): boolean;
|
|
359
|
+
remove(name: string, domain?: string, path?: string): void;
|
|
360
|
+
clear(): void;
|
|
361
|
+
toObject(): Record<string, string>;
|
|
362
|
+
getCookieHeader(url: string): string | null;
|
|
363
|
+
store(setCookieHeaders: string | string[] | null | undefined, requestUrl: string): void;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// ============================================================================
|
|
367
|
+
// Validation
|
|
368
|
+
// ============================================================================
|
|
369
|
+
|
|
370
|
+
export interface ValidationError {
|
|
371
|
+
message: string;
|
|
372
|
+
location: string; // Request path (e.g., "/Folder A/Request 1")
|
|
373
|
+
source: 'script' | 'protocol' | 'auth' | 'vault' | 'schema';
|
|
374
|
+
scriptType?: ScriptType;
|
|
375
|
+
details?: {
|
|
376
|
+
line?: number;
|
|
377
|
+
column?: number;
|
|
378
|
+
suggestion?: string;
|
|
379
|
+
[key: string]: unknown;
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// ============================================================================
|
|
384
|
+
// Logging
|
|
385
|
+
// ============================================================================
|
|
386
|
+
|
|
387
|
+
export enum LogLevel {
|
|
388
|
+
ERROR = 0,
|
|
389
|
+
WARN = 1,
|
|
390
|
+
INFO = 2,
|
|
391
|
+
DEBUG = 3,
|
|
392
|
+
TRACE = 4
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export interface ILogger {
|
|
396
|
+
error(message: string, ...args: unknown[]): void;
|
|
397
|
+
warn(message: string, ...args: unknown[]): void;
|
|
398
|
+
info(message: string, ...args: unknown[]): void;
|
|
399
|
+
debug(message: string, ...args: unknown[]): void;
|
|
400
|
+
trace(message: string, ...args: unknown[]): void;
|
|
401
|
+
setLevel(level: LogLevel): void;
|
|
402
|
+
createLogger(component: string): ILogger;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// ============================================================================
|
|
406
|
+
// Run Options & Results
|
|
407
|
+
// ============================================================================
|
|
408
|
+
|
|
409
|
+
export interface RunOptions extends Omit<RuntimeOptions, 'logLevel'> {
|
|
410
|
+
// Additional CLI/API specific options not in RuntimeOptions
|
|
411
|
+
environment?: Environment;
|
|
412
|
+
globalVariables?: Record<string, string | Variable>;
|
|
413
|
+
data?: IterationData[]; // CLI --data override
|
|
414
|
+
iterations?: number; // Global iteration cap
|
|
415
|
+
filter?: string; // Path-based regex filter
|
|
416
|
+
excludeDeps?: boolean; // Exclude dependencies when filtering
|
|
417
|
+
signal?: AbortSignal; // External abort signal
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export interface RunResult {
|
|
421
|
+
collectionId: string;
|
|
422
|
+
collectionName: string;
|
|
423
|
+
startTime: Date;
|
|
424
|
+
endTime: Date;
|
|
425
|
+
duration: number;
|
|
426
|
+
requestResults: RequestResult[];
|
|
427
|
+
totalTests: number;
|
|
428
|
+
passedTests: number;
|
|
429
|
+
failedTests: number;
|
|
430
|
+
skippedTests: number;
|
|
431
|
+
validationErrors?: ValidationError[]; // Pre-run validation errors
|
|
432
|
+
aborted?: boolean;
|
|
433
|
+
abortReason?: string;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export interface RequestResult {
|
|
437
|
+
requestId: string;
|
|
438
|
+
requestName: string;
|
|
439
|
+
path: string;
|
|
440
|
+
success: boolean;
|
|
441
|
+
response?: ProtocolResponse;
|
|
442
|
+
tests: TestResult[];
|
|
443
|
+
duration: number;
|
|
444
|
+
scriptError?: string;
|
|
445
|
+
iteration: number;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export interface TestResult {
|
|
449
|
+
name: string;
|
|
450
|
+
passed: boolean;
|
|
451
|
+
error?: string;
|
|
452
|
+
skipped: boolean;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ============================================================================
|
|
456
|
+
// Plugin Package Metadata
|
|
457
|
+
// ============================================================================
|
|
458
|
+
|
|
459
|
+
export interface PluginPackageJson {
|
|
460
|
+
name: string;
|
|
461
|
+
version: string;
|
|
462
|
+
main?: string;
|
|
463
|
+
apiquest?: {
|
|
464
|
+
runtime?: string[] | string;
|
|
465
|
+
type: string;
|
|
466
|
+
capabilities?: {
|
|
467
|
+
provides?: {
|
|
468
|
+
protocols?: string[];
|
|
469
|
+
authTypes?: string[];
|
|
470
|
+
provider?: string;
|
|
471
|
+
};
|
|
472
|
+
};
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// ============================================================================
|
|
477
|
+
// Protocol Plugin Interface
|
|
478
|
+
// ============================================================================
|
|
479
|
+
|
|
480
|
+
export interface IProtocolPlugin {
|
|
481
|
+
// Identity
|
|
482
|
+
name: string;
|
|
483
|
+
version: string;
|
|
484
|
+
description: string;
|
|
485
|
+
|
|
486
|
+
// What protocols does this plugin provide?
|
|
487
|
+
// Single-protocol: ['http']
|
|
488
|
+
// Multi-protocol bundle (rare): ['http', 'https', 'http2']
|
|
489
|
+
protocols: string[];
|
|
490
|
+
|
|
491
|
+
// Supported auth types for this protocol
|
|
492
|
+
// Example: HTTP supports ['bearer', 'basic', 'oauth2', 'apikey']
|
|
493
|
+
// SQL might support ['integrated', 'username-password']
|
|
494
|
+
supportedAuthTypes: string[];
|
|
495
|
+
|
|
496
|
+
// If true, ONLY supportedAuthTypes listed above are allowed
|
|
497
|
+
// If false/undefined, accept additional auth plugins that declare this protocol
|
|
498
|
+
strictAuthList?: boolean;
|
|
499
|
+
|
|
500
|
+
// Schema for request.data (defines what fields the UI should show)
|
|
501
|
+
// Example: HTTP has method, url, headers, body
|
|
502
|
+
dataSchema: unknown; // JSON Schema or custom schema format
|
|
503
|
+
|
|
504
|
+
// Schema for options.plugins[protocol] (runtime options)
|
|
505
|
+
// Example: HTTP has keepAlive, compression, maxSockets
|
|
506
|
+
optionsSchema?: PluginOptionsSchema;
|
|
507
|
+
|
|
508
|
+
// Plugin event definitions (e.g., WebSocket: onMessage, onError, onComplete)
|
|
509
|
+
events?: PluginEventDefinition[];
|
|
510
|
+
|
|
511
|
+
execute(
|
|
512
|
+
request: Request,
|
|
513
|
+
context: ExecutionContext,
|
|
514
|
+
options: RuntimeOptions, // Receives merged options
|
|
515
|
+
emitEvent?: (eventName: string, eventData: unknown) => Promise<void>, // Optional callback for plugin events
|
|
516
|
+
logger?: ILogger // Optional logger from fracture
|
|
517
|
+
): Promise<ProtocolResponse>;
|
|
518
|
+
|
|
519
|
+
validate(request: Request, options: RuntimeOptions): ValidationResult;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export interface PluginOptionsSchema {
|
|
523
|
+
// Defines options that can be set in options.plugins[protocol]
|
|
524
|
+
// Example: options.plugins.http = { keepAlive: true, compression: "gzip" }
|
|
525
|
+
[optionKey: string]: {
|
|
526
|
+
type: 'boolean' | 'string' | 'number';
|
|
527
|
+
default?: unknown;
|
|
528
|
+
enum?: unknown[];
|
|
529
|
+
description?: string;
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export interface PluginEventDefinition {
|
|
534
|
+
name: string; // "onMessage", "onError", "onComplete"
|
|
535
|
+
description: string;
|
|
536
|
+
canHaveTests: boolean; // Can this event script contain quest.test()?
|
|
537
|
+
required: boolean; // Is this event required or optional?
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export interface ProtocolResponse {
|
|
541
|
+
status: number;
|
|
542
|
+
statusText: string;
|
|
543
|
+
body: string;
|
|
544
|
+
headers: Record<string, string | string[]>; // Headers can have multiple values (e.g., set-cookie)
|
|
545
|
+
duration: number;
|
|
546
|
+
error?: string;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
export interface ValidationResult {
|
|
550
|
+
valid: boolean;
|
|
551
|
+
errors?: ValidationError[];
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// ============================================================================
|
|
555
|
+
// Auth Plugin Interface
|
|
556
|
+
// ============================================================================
|
|
557
|
+
|
|
558
|
+
export interface IAuthPlugin {
|
|
559
|
+
// Identity
|
|
560
|
+
name: string;
|
|
561
|
+
version: string;
|
|
562
|
+
description: string;
|
|
563
|
+
|
|
564
|
+
// What auth types does this plugin provide?
|
|
565
|
+
// Single auth: ['bearer']
|
|
566
|
+
// Multi-auth bundle: ['bearer', 'basic', 'apikey', 'oauth2']
|
|
567
|
+
authTypes: string[];
|
|
568
|
+
|
|
569
|
+
// Which protocols does this auth work with? (REQUIRED)
|
|
570
|
+
// Example: ['http', 'grpc', 'graphql']
|
|
571
|
+
// No universal auth - must explicitly declare protocol support
|
|
572
|
+
protocols: string[];
|
|
573
|
+
|
|
574
|
+
// Schema for auth.data (defines what fields the UI should show)
|
|
575
|
+
// Example: bearer has { token: string }, basic has { username: string, password: string }
|
|
576
|
+
dataSchema: unknown; // JSON Schema or custom schema format
|
|
577
|
+
|
|
578
|
+
apply(
|
|
579
|
+
request: Request,
|
|
580
|
+
auth: Auth,
|
|
581
|
+
options: RuntimeOptions,
|
|
582
|
+
logger?: ILogger // Optional logger from fracture
|
|
583
|
+
): Promise<Request>;
|
|
584
|
+
|
|
585
|
+
validate(auth: Auth, options: RuntimeOptions): ValidationResult;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// ============================================================================
|
|
589
|
+
// Value Provider Plugin Interface
|
|
590
|
+
// ============================================================================
|
|
591
|
+
|
|
592
|
+
export interface IValueProviderPlugin {
|
|
593
|
+
provider: string; // "vault:aws-secrets", "vault:azure-keyvault", "vault:file"
|
|
594
|
+
name: string;
|
|
595
|
+
description: string;
|
|
596
|
+
|
|
597
|
+
// Configuration schema (if provider needs setup)
|
|
598
|
+
configSchema?: unknown;
|
|
599
|
+
|
|
600
|
+
// Retrieve a secret value by key
|
|
601
|
+
// Returns null if key doesn't exist
|
|
602
|
+
// Throws error if provider fails (network, auth, etc.)
|
|
603
|
+
getValue(
|
|
604
|
+
key: string,
|
|
605
|
+
config?: unknown,
|
|
606
|
+
context?: ExecutionContext,
|
|
607
|
+
logger?: ILogger // Optional logger from fracture
|
|
608
|
+
): Promise<string | null>;
|
|
609
|
+
|
|
610
|
+
// Validate provider configuration
|
|
611
|
+
validate(config?: unknown): ValidationResult;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// ============================================================================
|
|
615
|
+
// Script Engine
|
|
616
|
+
// ============================================================================
|
|
617
|
+
|
|
618
|
+
export interface ScriptResult {
|
|
619
|
+
success: boolean;
|
|
620
|
+
tests: TestResult[];
|
|
621
|
+
error?: string;
|
|
622
|
+
consoleOutput: string[];
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export enum ScriptType {
|
|
626
|
+
CollectionPre = 'collection-pre',
|
|
627
|
+
CollectionPost = 'collection-post',
|
|
628
|
+
FolderPre = 'folder-pre',
|
|
629
|
+
FolderPost = 'folder-post',
|
|
630
|
+
PreRequest = 'request-pre',
|
|
631
|
+
PostRequest = 'request-post',
|
|
632
|
+
PluginEvent = 'plugin-event'
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// ============================================================================
|
|
636
|
+
// Reporter Interface
|
|
637
|
+
// ============================================================================
|
|
638
|
+
|
|
639
|
+
export interface IReporter {
|
|
640
|
+
// Identity
|
|
641
|
+
name: string;
|
|
642
|
+
version: string;
|
|
643
|
+
description: string;
|
|
644
|
+
|
|
645
|
+
// What report types does this plugin provide?
|
|
646
|
+
// Example: ['console'], ['json', 'json-summary'], ['html', 'junit']
|
|
647
|
+
reportTypes: string[];
|
|
648
|
+
|
|
649
|
+
// Reporter-specific options schema
|
|
650
|
+
// Defines what options can be passed to getOptions()
|
|
651
|
+
// Example: { outputFile: string, verbose: boolean, colors: boolean }
|
|
652
|
+
optionsSchema?: unknown;
|
|
653
|
+
|
|
654
|
+
// Get options for a specific report type
|
|
655
|
+
// Called before run starts to configure the reporter
|
|
656
|
+
getOptions?(reportType: string): unknown;
|
|
657
|
+
|
|
658
|
+
// Lifecycle hooks
|
|
659
|
+
onRunStarted(collection: Collection, options: RunOptions): void;
|
|
660
|
+
|
|
661
|
+
// @deprecated Use onBeforeRequest instead
|
|
662
|
+
onRequestStarted?(request: Request, path: string): void;
|
|
663
|
+
// @deprecated Use onAfterRequest + onAssertion instead
|
|
664
|
+
onRequestCompleted?(result: RequestResult): void;
|
|
665
|
+
// @deprecated Use onAssertion instead
|
|
666
|
+
onTestCompleted?(test: TestResult, request: string): void;
|
|
667
|
+
|
|
668
|
+
// New event-based hooks using EventPayloads types
|
|
669
|
+
onBeforeRequest?(payload: EventPayloads['beforeRequest']): void;
|
|
670
|
+
onAfterRequest?(payload: EventPayloads['afterRequest']): void;
|
|
671
|
+
onAssertion?(payload: EventPayloads['assertion']): void;
|
|
672
|
+
|
|
673
|
+
onRunCompleted(result: RunResult): void;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// ============================================================================
|
|
677
|
+
// Events
|
|
678
|
+
// ============================================================================
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Path type for EventEnvelope and ExecutionNode
|
|
682
|
+
*/
|
|
683
|
+
export type NodeType = 'collection' | 'folder' | 'request';
|
|
684
|
+
export type PathType = 'collection:/' | `folder:/${string}` | `request:/${string}`;
|
|
685
|
+
/**
|
|
686
|
+
* Event envelope that provides context for all events (except console)
|
|
687
|
+
*/
|
|
688
|
+
export type EventEnvelope = {
|
|
689
|
+
id: string; // Unique event ID
|
|
690
|
+
path: PathType;
|
|
691
|
+
pathType: NodeType;
|
|
692
|
+
collectionInfo: CollectionInfo;
|
|
693
|
+
iteration?: {
|
|
694
|
+
current: number;
|
|
695
|
+
total: number;
|
|
696
|
+
source: IterationSource;
|
|
697
|
+
rowIndex?: number;
|
|
698
|
+
rowKeys?: string[];
|
|
699
|
+
row?: Record<string, string | number | boolean>;
|
|
700
|
+
};
|
|
701
|
+
request?: Request;
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
export type RunnerEvent =
|
|
705
|
+
// Collection lifecycle
|
|
706
|
+
| 'beforeRun'
|
|
707
|
+
| 'afterRun'
|
|
708
|
+
| 'beforeCollectionPreScript'
|
|
709
|
+
| 'afterCollectionPreScript'
|
|
710
|
+
| 'beforeCollectionPostScript'
|
|
711
|
+
| 'afterCollectionPostScript'
|
|
712
|
+
|
|
713
|
+
// Folder lifecycle
|
|
714
|
+
| 'beforeFolder'
|
|
715
|
+
| 'afterFolder'
|
|
716
|
+
| 'beforeFolderPreScript'
|
|
717
|
+
| 'afterFolderPreScript'
|
|
718
|
+
| 'beforeFolderPostScript'
|
|
719
|
+
| 'afterFolderPostScript'
|
|
720
|
+
|
|
721
|
+
// Iteration
|
|
722
|
+
| 'beforeIteration'
|
|
723
|
+
| 'afterIteration'
|
|
724
|
+
|
|
725
|
+
// Request/Item
|
|
726
|
+
| 'beforeItem'
|
|
727
|
+
| 'afterItem'
|
|
728
|
+
| 'beforePreScript'
|
|
729
|
+
| 'afterPreScript'
|
|
730
|
+
| 'beforeRequest'
|
|
731
|
+
| 'afterRequest'
|
|
732
|
+
| 'beforePostScript'
|
|
733
|
+
| 'afterPostScript'
|
|
734
|
+
|
|
735
|
+
// Tests (run within postRequestScript via quest.test())
|
|
736
|
+
| 'assertion'
|
|
737
|
+
|
|
738
|
+
// Utilities
|
|
739
|
+
| 'console'
|
|
740
|
+
| 'exception';
|
|
741
|
+
|
|
742
|
+
export interface EventPayloads {
|
|
743
|
+
// Run Lifecycle
|
|
744
|
+
beforeRun: {
|
|
745
|
+
options: RunOptions;
|
|
746
|
+
validationResult?: ValidationResult;
|
|
747
|
+
expectedTestCount?: number;
|
|
748
|
+
} & Pick<EventEnvelope, 'collectionInfo'>;
|
|
749
|
+
|
|
750
|
+
afterRun: {
|
|
751
|
+
result: RunResult;
|
|
752
|
+
} & Pick<EventEnvelope, 'collectionInfo'>;
|
|
753
|
+
|
|
754
|
+
// Collection Scripts
|
|
755
|
+
beforeCollectionPreScript: EventEnvelope & { path: 'collection:/' };
|
|
756
|
+
afterCollectionPreScript: EventEnvelope & { path: 'collection:/'; result: ScriptResult };
|
|
757
|
+
beforeCollectionPostScript: EventEnvelope & { path: 'collection:/' };
|
|
758
|
+
afterCollectionPostScript: EventEnvelope & { path: 'collection:/'; result: ScriptResult };
|
|
759
|
+
|
|
760
|
+
// Iteration Lifecycle
|
|
761
|
+
beforeIteration: EventEnvelope & { iteration: Required<EventEnvelope['iteration']> };
|
|
762
|
+
afterIteration: EventEnvelope & { iteration: Required<EventEnvelope['iteration']>; duration: number };
|
|
763
|
+
|
|
764
|
+
// Folder Lifecycle
|
|
765
|
+
beforeFolder: EventEnvelope;
|
|
766
|
+
afterFolder: EventEnvelope & { duration: number };
|
|
767
|
+
|
|
768
|
+
// Folder Scripts
|
|
769
|
+
beforeFolderPreScript: EventEnvelope;
|
|
770
|
+
afterFolderPreScript: EventEnvelope & { result: ScriptResult };
|
|
771
|
+
beforeFolderPostScript: EventEnvelope;
|
|
772
|
+
afterFolderPostScript: EventEnvelope & { result: ScriptResult };
|
|
773
|
+
|
|
774
|
+
// Item Lifecycle
|
|
775
|
+
beforeItem: EventEnvelope & { request: Request; path: string };
|
|
776
|
+
afterItem: EventEnvelope & { request: Request; path: string; response?: ProtocolResponse; result: RequestResult };
|
|
777
|
+
|
|
778
|
+
// Pre-Request Script
|
|
779
|
+
beforePreScript: EventEnvelope & { request: Request; path: string };
|
|
780
|
+
afterPreScript: EventEnvelope & { request: Request; path: string; result: ScriptResult };
|
|
781
|
+
|
|
782
|
+
// Request
|
|
783
|
+
beforeRequest: EventEnvelope & { request: Request; path: string };
|
|
784
|
+
afterRequest: EventEnvelope & { request: Request; response: ProtocolResponse; duration: number };
|
|
785
|
+
|
|
786
|
+
// Post-Request Script
|
|
787
|
+
beforePostScript: EventEnvelope & { request: Request; path: string; response: ProtocolResponse };
|
|
788
|
+
afterPostScript: EventEnvelope & { request: Request; path: string; response: ProtocolResponse; result: ScriptResult };
|
|
789
|
+
|
|
790
|
+
// Test/Assertion
|
|
791
|
+
assertion: EventEnvelope & {
|
|
792
|
+
test: TestResult;
|
|
793
|
+
request?: Request;
|
|
794
|
+
path?: string;
|
|
795
|
+
response?: ProtocolResponse;
|
|
796
|
+
event?: {
|
|
797
|
+
name: string;
|
|
798
|
+
index: number;
|
|
799
|
+
timestamp: string;
|
|
800
|
+
data: unknown;
|
|
801
|
+
};
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
// Utility Events
|
|
805
|
+
console: {
|
|
806
|
+
id: string; // Unique event ID
|
|
807
|
+
message: string;
|
|
808
|
+
level: LogLevel;
|
|
809
|
+
levelName?: 'error' | 'warn' | 'info' | 'debug' | 'trace';
|
|
810
|
+
component?: string;
|
|
811
|
+
timestamp?: string;
|
|
812
|
+
args?: unknown[];
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
exception: {
|
|
816
|
+
id: string; // Unique event ID
|
|
817
|
+
error: Error;
|
|
818
|
+
phase: 'collection-pre' | 'collection-post' | 'folder-pre' | 'folder-post' | 'prerequest' | 'postrequest' | 'request';
|
|
819
|
+
request?: Request;
|
|
820
|
+
path?: string;
|
|
821
|
+
response?: ProtocolResponse;
|
|
822
|
+
};
|
|
823
|
+
}
|