@http-forge/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +500 -0
- package/dist/container.d.ts +146 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/implementations/cookie-jar.d.ts +97 -0
- package/dist/implementations/cookie-jar.d.ts.map +1 -0
- package/dist/implementations/cookie-utils.d.ts +78 -0
- package/dist/implementations/cookie-utils.d.ts.map +1 -0
- package/dist/implementations/data-file-parser.d.ts +71 -0
- package/dist/implementations/data-file-parser.d.ts.map +1 -0
- package/dist/implementations/fetch-http-client.d.ts +19 -0
- package/dist/implementations/fetch-http-client.d.ts.map +1 -0
- package/dist/implementations/index.d.ts +22 -0
- package/dist/implementations/index.d.ts.map +1 -0
- package/dist/implementations/interceptor-chain.d.ts +262 -0
- package/dist/implementations/interceptor-chain.d.ts.map +1 -0
- package/dist/implementations/module-loader.d.ts +74 -0
- package/dist/implementations/module-loader.d.ts.map +1 -0
- package/dist/implementations/native-http-client.d.ts +72 -0
- package/dist/implementations/native-http-client.d.ts.map +1 -0
- package/dist/implementations/node-file-system.d.ts +52 -0
- package/dist/implementations/node-file-system.d.ts.map +1 -0
- package/dist/implementations/request-history.d.ts +73 -0
- package/dist/implementations/request-history.d.ts.map +1 -0
- package/dist/implementations/request-preprocessor.d.ts +78 -0
- package/dist/implementations/request-preprocessor.d.ts.map +1 -0
- package/dist/implementations/variable-interpolator.d.ts +55 -0
- package/dist/implementations/variable-interpolator.d.ts.map +1 -0
- package/dist/implementations/vm2-script-runner.d.ts +76 -0
- package/dist/implementations/vm2-script-runner.d.ts.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.mjs +46 -0
- package/dist/interfaces/cookie.d.ts +101 -0
- package/dist/interfaces/cookie.d.ts.map +1 -0
- package/dist/interfaces/history.d.ts +117 -0
- package/dist/interfaces/history.d.ts.map +1 -0
- package/dist/interfaces/index.d.ts +170 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/types.d.ts +308 -0
- package/dist/interfaces/types.d.ts.map +1 -0
- package/dist/parsers/http-forge-parser.d.ts +35 -0
- package/dist/parsers/http-forge-parser.d.ts.map +1 -0
- package/dist/parsers/index.d.ts +7 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/services/collection-loader.d.ts +52 -0
- package/dist/services/collection-loader.d.ts.map +1 -0
- package/dist/services/environment-resolver.d.ts +91 -0
- package/dist/services/environment-resolver.d.ts.map +1 -0
- package/dist/services/folder-collection-loader.d.ts +91 -0
- package/dist/services/folder-collection-loader.d.ts.map +1 -0
- package/dist/services/forge-env.d.ts +166 -0
- package/dist/services/forge-env.d.ts.map +1 -0
- package/dist/services/index.d.ts +20 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/parser-registry.d.ts +49 -0
- package/dist/services/parser-registry.d.ts.map +1 -0
- package/dist/services/request-executor.d.ts +86 -0
- package/dist/services/request-executor.d.ts.map +1 -0
- package/dist/services/script-pipeline.d.ts +43 -0
- package/dist/services/script-pipeline.d.ts.map +1 -0
- package/dist/services/script-session.d.ts +66 -0
- package/dist/services/script-session.d.ts.map +1 -0
- package/dist/services/url-builder.d.ts +60 -0
- package/dist/services/url-builder.d.ts.map +1 -0
- package/package.json +65 -0
package/README.md
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
# @http-forge/core
|
|
2
|
+
|
|
3
|
+
**Lightweight, VS Code-independent HTTP API testing engine** - The execution core of HTTP Forge.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@http-forge/core)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## 📦 What is @http-forge/core?
|
|
9
|
+
|
|
10
|
+
`@http-forge/core` is a standalone, dependency-injection-based HTTP execution engine that powers HTTP Forge. It provides a clean API for:
|
|
11
|
+
|
|
12
|
+
- 🚀 Executing HTTP requests with full HTTP Forge collection support
|
|
13
|
+
- 🔄 Running pre-request and post-response scripts
|
|
14
|
+
- 🌍 Managing environments and variables
|
|
15
|
+
- 🍪 Automatic cookie handling
|
|
16
|
+
- 📊 Test assertions and validations
|
|
17
|
+
- 🔌 Extensible via interceptors and custom implementations
|
|
18
|
+
|
|
19
|
+
**Perfect for:**
|
|
20
|
+
- Building custom API testing tools
|
|
21
|
+
- Integrating HTTP Forge into CI/CD pipelines
|
|
22
|
+
- Creating CLI tools for API testing
|
|
23
|
+
- Headless API testing automation
|
|
24
|
+
|
|
25
|
+
## 🎯 Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @http-forge/core
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or using the tarball:
|
|
32
|
+
```bash
|
|
33
|
+
npm install ./http-forge-core-0.1.0.tgz
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## ⚡ Quick Start
|
|
37
|
+
|
|
38
|
+
### Basic Usage
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { ForgeContainer } from '@http-forge/core';
|
|
42
|
+
|
|
43
|
+
// Create a container with default settings
|
|
44
|
+
const forge = new ForgeContainer();
|
|
45
|
+
|
|
46
|
+
// Load a collection
|
|
47
|
+
const collection = await forge.loadCollection('./my-api.forge.json');
|
|
48
|
+
|
|
49
|
+
// Execute a request
|
|
50
|
+
const result = await forge.execute(collection.items[0], collection);
|
|
51
|
+
|
|
52
|
+
console.log(result.response.status); // 200
|
|
53
|
+
console.log(result.response.body); // Response data
|
|
54
|
+
console.log(result.postResponseResult?.assertions); // Test results
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### With Environment Variables
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const forge = new ForgeContainer();
|
|
61
|
+
|
|
62
|
+
// Set environment variables
|
|
63
|
+
forge.setEnvironment({
|
|
64
|
+
baseUrl: 'https://api.example.com',
|
|
65
|
+
apiKey: 'your-api-key',
|
|
66
|
+
timeout: '5000'
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Variables are automatically interpolated in requests
|
|
70
|
+
// URL: {{baseUrl}}/users -> https://api.example.com/users
|
|
71
|
+
const result = await forge.execute(request, collection);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### With Custom Configuration
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const forge = new ForgeContainer({
|
|
78
|
+
// Use native Node.js http/https instead of fetch
|
|
79
|
+
useNativeHttp: true,
|
|
80
|
+
|
|
81
|
+
// Enable automatic cookie management
|
|
82
|
+
enableCookies: true,
|
|
83
|
+
|
|
84
|
+
// Set request timeout
|
|
85
|
+
requestTimeout: 10000,
|
|
86
|
+
|
|
87
|
+
// Enable request history
|
|
88
|
+
enableHistory: true,
|
|
89
|
+
maxHistoryEntries: 50,
|
|
90
|
+
|
|
91
|
+
// Storage format
|
|
92
|
+
storageFormat: 'folder' // or 'file'
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 📚 Core Concepts
|
|
97
|
+
|
|
98
|
+
### ForgeContainer
|
|
99
|
+
|
|
100
|
+
The main entry point - a dependency injection container that wires up all components.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
const forge = new ForgeContainer(options);
|
|
104
|
+
|
|
105
|
+
// Load collections
|
|
106
|
+
const collection = await forge.loadCollection(path);
|
|
107
|
+
const folderCollection = await forge.loadFolderCollection(path);
|
|
108
|
+
|
|
109
|
+
// Execute requests
|
|
110
|
+
const result = await forge.execute(request, collection, options);
|
|
111
|
+
|
|
112
|
+
// Manage environments
|
|
113
|
+
forge.setEnvironment(variables);
|
|
114
|
+
forge.setActiveEnvironment(name);
|
|
115
|
+
const resolved = forge.getResolvedEnvironment();
|
|
116
|
+
|
|
117
|
+
// Access services
|
|
118
|
+
const executor = forge.getRequestExecutor();
|
|
119
|
+
const loader = forge.getCollectionLoader();
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Request Execution
|
|
123
|
+
|
|
124
|
+
Execute requests with full control over the execution pipeline:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const result = await forge.execute(request, collection, {
|
|
128
|
+
environment: 'production',
|
|
129
|
+
overrides: {
|
|
130
|
+
url: 'https://override.com/api',
|
|
131
|
+
headers: { 'X-Custom': 'value' }
|
|
132
|
+
},
|
|
133
|
+
skipPreRequest: false,
|
|
134
|
+
skipPostResponse: false,
|
|
135
|
+
timeout: 5000
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Access results
|
|
139
|
+
console.log(result.response); // HTTP response
|
|
140
|
+
console.log(result.preRequestResult); // Pre-request script output
|
|
141
|
+
console.log(result.postResponseResult); // Test results
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Script Execution
|
|
145
|
+
|
|
146
|
+
Run pre-request and post-response scripts:
|
|
147
|
+
|
|
148
|
+
**Pre-request script:**
|
|
149
|
+
```javascript
|
|
150
|
+
// Set variables before request
|
|
151
|
+
forge.env.set('timestamp', Date.now());
|
|
152
|
+
forge.env.set('requestId', forge.uuid());
|
|
153
|
+
|
|
154
|
+
// Modify request
|
|
155
|
+
forge.request.headers['X-Request-ID'] = forge.env.get('requestId');
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Post-response script:**
|
|
159
|
+
```javascript
|
|
160
|
+
// Run tests
|
|
161
|
+
forge.expect(forge.response.status).toBe(200);
|
|
162
|
+
forge.expect(forge.response.body.success).toBeTruthy();
|
|
163
|
+
|
|
164
|
+
// Extract data from response
|
|
165
|
+
const token = forge.response.body.token;
|
|
166
|
+
forge.env.set('authToken', token);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Environment Management
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// Define multiple environments
|
|
173
|
+
forge.setEnvironmentConfig({
|
|
174
|
+
dev: { baseUrl: 'https://dev.api.com', apiKey: 'dev-key' },
|
|
175
|
+
staging: { baseUrl: 'https://staging.api.com', apiKey: 'staging-key' },
|
|
176
|
+
prod: { baseUrl: 'https://api.com', apiKey: 'prod-key' }
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Switch environments
|
|
180
|
+
forge.setActiveEnvironment('prod');
|
|
181
|
+
|
|
182
|
+
// Get resolved variables (with inheritance and overrides)
|
|
183
|
+
const vars = forge.getResolvedEnvironment('prod');
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 🔧 Advanced Features
|
|
187
|
+
|
|
188
|
+
### Custom HTTP Client
|
|
189
|
+
|
|
190
|
+
Implement your own HTTP client:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { IHttpClient, HttpRequest, HttpResponse } from '@http-forge/core';
|
|
194
|
+
|
|
195
|
+
class CustomHttpClient implements IHttpClient {
|
|
196
|
+
async send(request: HttpRequest): Promise<HttpResponse> {
|
|
197
|
+
// Your custom HTTP logic
|
|
198
|
+
return {
|
|
199
|
+
status: 200,
|
|
200
|
+
statusText: 'OK',
|
|
201
|
+
headers: {},
|
|
202
|
+
body: {},
|
|
203
|
+
duration: 100,
|
|
204
|
+
size: 1024
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const forge = new ForgeContainer({
|
|
210
|
+
httpClient: new CustomHttpClient()
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Request/Response Interceptors
|
|
215
|
+
|
|
216
|
+
Add custom interceptors to modify requests and responses:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { IRequestInterceptor, IResponseInterceptor } from '@http-forge/core';
|
|
220
|
+
|
|
221
|
+
// Request interceptor
|
|
222
|
+
class AuthInterceptor implements IRequestInterceptor {
|
|
223
|
+
async intercept(request: HttpRequest): Promise<HttpRequest> {
|
|
224
|
+
request.headers['Authorization'] = `Bearer ${getToken()}`;
|
|
225
|
+
return request;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Response interceptor
|
|
230
|
+
class LoggingInterceptor implements IResponseInterceptor {
|
|
231
|
+
async intercept(response: HttpResponse, request: HttpRequest): Promise<HttpResponse> {
|
|
232
|
+
console.log(`${request.method} ${request.url} -> ${response.status}`);
|
|
233
|
+
return response;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const forge = new ForgeContainer({
|
|
238
|
+
requestInterceptors: [new AuthInterceptor()],
|
|
239
|
+
responseInterceptors: [new LoggingInterceptor()]
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Cookie Management
|
|
244
|
+
|
|
245
|
+
Automatic cookie handling across requests:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
const forge = new ForgeContainer({
|
|
249
|
+
enableCookies: true
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
// Cookies are automatically stored and sent
|
|
253
|
+
const loginResult = await forge.execute(loginRequest, collection);
|
|
254
|
+
// Session cookie from login is automatically included in next request
|
|
255
|
+
const dataResult = await forge.execute(dataRequest, collection);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Request History
|
|
259
|
+
|
|
260
|
+
Track all executed requests:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const forge = new ForgeContainer({
|
|
264
|
+
enableHistory: true,
|
|
265
|
+
maxHistoryEntries: 100
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// Execute requests
|
|
269
|
+
await forge.execute(request1, collection);
|
|
270
|
+
await forge.execute(request2, collection);
|
|
271
|
+
|
|
272
|
+
// Access history
|
|
273
|
+
const history = forge.getRequestHistory();
|
|
274
|
+
const entries = history.getAll(); // All requests
|
|
275
|
+
const byId = history.getByRequestId(id); // Specific request history
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## 📖 API Reference
|
|
279
|
+
|
|
280
|
+
### ForgeContainer
|
|
281
|
+
|
|
282
|
+
**Constructor Options:**
|
|
283
|
+
```typescript
|
|
284
|
+
interface ForgeContainerOptions {
|
|
285
|
+
forgeRoot?: string; // Path to http-forge folder
|
|
286
|
+
storageFormat?: 'file' | 'folder'; // Collection storage format
|
|
287
|
+
|
|
288
|
+
// HTTP Settings
|
|
289
|
+
useNativeHttp?: boolean; // Use native http/https
|
|
290
|
+
httpClient?: IHttpClient; // Custom HTTP client
|
|
291
|
+
httpSettings?: RequestSettings; // Default HTTP settings
|
|
292
|
+
requestTimeout?: number; // Request timeout (ms)
|
|
293
|
+
|
|
294
|
+
// Cookie Settings
|
|
295
|
+
enableCookies?: boolean; // Enable cookie jar
|
|
296
|
+
cookieJar?: ICookieJar; // Custom cookie jar
|
|
297
|
+
|
|
298
|
+
// Interceptors
|
|
299
|
+
requestInterceptors?: IRequestInterceptor[];
|
|
300
|
+
responseInterceptors?: IResponseInterceptor[];
|
|
301
|
+
errorInterceptors?: IErrorInterceptor[];
|
|
302
|
+
|
|
303
|
+
// Script Settings
|
|
304
|
+
scriptRunner?: IScriptRunner; // Custom script runner
|
|
305
|
+
scriptTimeout?: number; // Script timeout (ms)
|
|
306
|
+
|
|
307
|
+
// History
|
|
308
|
+
enableHistory?: boolean; // Enable request history
|
|
309
|
+
maxHistoryEntries?: number; // Max history size
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Methods:**
|
|
314
|
+
```typescript
|
|
315
|
+
// Collection loading
|
|
316
|
+
loadCollection(path: string): Promise<UnifiedCollection>
|
|
317
|
+
loadFolderCollection(path: string): Promise<UnifiedCollection>
|
|
318
|
+
|
|
319
|
+
// Request execution
|
|
320
|
+
execute(
|
|
321
|
+
request: UnifiedRequest,
|
|
322
|
+
collection: UnifiedCollection,
|
|
323
|
+
options?: ExecuteOptions
|
|
324
|
+
): Promise<ExecuteResult>
|
|
325
|
+
|
|
326
|
+
// Environment management
|
|
327
|
+
setEnvironment(variables: Record<string, string>): void
|
|
328
|
+
setEnvironmentConfig(config: EnvironmentConfig): void
|
|
329
|
+
setActiveEnvironment(name: string): void
|
|
330
|
+
getResolvedEnvironment(name?: string): Record<string, string>
|
|
331
|
+
|
|
332
|
+
// Service access
|
|
333
|
+
getRequestExecutor(): RequestExecutor
|
|
334
|
+
getCollectionLoader(): ICollectionLoader
|
|
335
|
+
getEnvironmentResolver(): EnvironmentResolver
|
|
336
|
+
getRequestHistory(): IRequestHistory
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### ExecuteResult
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
interface ExecuteResult {
|
|
343
|
+
response: HttpResponse; // HTTP response
|
|
344
|
+
preRequestResult?: ScriptResult; // Pre-request script output
|
|
345
|
+
postResponseResult?: ScriptResult; // Test results
|
|
346
|
+
requestId: string; // Unique request ID
|
|
347
|
+
timestamp: number; // Execution timestamp
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### HttpResponse
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
interface HttpResponse {
|
|
355
|
+
status: number; // HTTP status code
|
|
356
|
+
statusText: string; // Status text
|
|
357
|
+
headers: Record<string, string>; // Response headers
|
|
358
|
+
body: any; // Parsed response body
|
|
359
|
+
cookies?: Cookie[]; // Response cookies
|
|
360
|
+
duration: number; // Request duration (ms)
|
|
361
|
+
size: number; // Response size (bytes)
|
|
362
|
+
redirected?: boolean; // Whether redirected
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## 🛠️ Use Cases
|
|
367
|
+
|
|
368
|
+
### CLI Tool
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
#!/usr/bin/env node
|
|
372
|
+
import { ForgeContainer } from '@http-forge/core';
|
|
373
|
+
|
|
374
|
+
async function runTests(collectionPath: string) {
|
|
375
|
+
const forge = new ForgeContainer();
|
|
376
|
+
const collection = await forge.loadCollection(collectionPath);
|
|
377
|
+
|
|
378
|
+
for (const request of collection.items) {
|
|
379
|
+
const result = await forge.execute(request, collection);
|
|
380
|
+
const tests = result.postResponseResult?.assertions || [];
|
|
381
|
+
|
|
382
|
+
console.log(`\n${request.name}: ${result.response.status}`);
|
|
383
|
+
tests.forEach(test => {
|
|
384
|
+
console.log(` ${test.passed ? '✓' : '✗'} ${test.name}`);
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
runTests(process.argv[2]);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### CI/CD Integration
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import { ForgeContainer } from '@http-forge/core';
|
|
396
|
+
|
|
397
|
+
async function ciTest() {
|
|
398
|
+
const forge = new ForgeContainer({
|
|
399
|
+
enableCookies: true,
|
|
400
|
+
requestTimeout: 30000
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
forge.setEnvironment({
|
|
404
|
+
baseUrl: process.env.API_URL,
|
|
405
|
+
apiKey: process.env.API_KEY
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
const collection = await forge.loadCollection('./api-tests.forge.json');
|
|
409
|
+
|
|
410
|
+
let failedTests = 0;
|
|
411
|
+
for (const request of collection.items) {
|
|
412
|
+
const result = await forge.execute(request, collection);
|
|
413
|
+
const failed = result.postResponseResult?.assertions?.filter(t => !t.passed) || [];
|
|
414
|
+
failedTests += failed.length;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
process.exit(failedTests > 0 ? 1 : 0);
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Custom Testing Framework
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
import { ForgeContainer } from '@http-forge/core';
|
|
425
|
+
|
|
426
|
+
class ApiTestRunner {
|
|
427
|
+
private forge: ForgeContainer;
|
|
428
|
+
|
|
429
|
+
constructor() {
|
|
430
|
+
this.forge = new ForgeContainer({
|
|
431
|
+
enableCookies: true,
|
|
432
|
+
enableHistory: true
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
async runSuite(suites: TestSuite[]) {
|
|
437
|
+
for (const suite of suites) {
|
|
438
|
+
await this.runTests(suite);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async runTests(suite: TestSuite) {
|
|
443
|
+
const collection = await this.forge.loadCollection(suite.collection);
|
|
444
|
+
|
|
445
|
+
for (const request of collection.items) {
|
|
446
|
+
const result = await this.forge.execute(request, collection);
|
|
447
|
+
suite.results.push(result);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
## 📦 Storage Formats
|
|
454
|
+
|
|
455
|
+
### File Format (Single JSON)
|
|
456
|
+
```
|
|
457
|
+
my-api.forge.json
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Folder Format (Directory Structure)
|
|
461
|
+
```
|
|
462
|
+
my-api/
|
|
463
|
+
collection.json
|
|
464
|
+
requests/
|
|
465
|
+
login/
|
|
466
|
+
request.json
|
|
467
|
+
users/
|
|
468
|
+
get-users/
|
|
469
|
+
request.json
|
|
470
|
+
create-user/
|
|
471
|
+
request.json
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
## 🤝 Contributing
|
|
475
|
+
|
|
476
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
477
|
+
|
|
478
|
+
## 📄 License
|
|
479
|
+
|
|
480
|
+
MIT © Henry Huang
|
|
481
|
+
|
|
482
|
+
## 🔗 Links
|
|
483
|
+
|
|
484
|
+
- [HTTP Forge Extension](https://marketplace.visualstudio.com/items?itemName=your-publisher.http-forge)
|
|
485
|
+
- [GitHub Repository](https://github.com/hsl1230/http-forge)
|
|
486
|
+
- [Issues](https://github.com/hsl1230/http-forge/issues)
|
|
487
|
+
|
|
488
|
+
## 📝 Changelog
|
|
489
|
+
|
|
490
|
+
### 0.1.0 (Initial Release)
|
|
491
|
+
|
|
492
|
+
- ✅ Core request execution engine
|
|
493
|
+
- ✅ Environment and variable management
|
|
494
|
+
- ✅ Pre-request and post-response scripts
|
|
495
|
+
- ✅ Cookie jar support
|
|
496
|
+
- ✅ Request/response interceptors
|
|
497
|
+
- ✅ Request history tracking
|
|
498
|
+
- ✅ File and folder collection formats
|
|
499
|
+
- ✅ Full TypeScript support
|
|
500
|
+
- ✅ Comprehensive test coverage
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forge Container - Dependency Injection Container
|
|
3
|
+
*
|
|
4
|
+
* Single Responsibility: Wire up all components with proper dependencies
|
|
5
|
+
* Factory Pattern: Creates configured instances of services
|
|
6
|
+
*/
|
|
7
|
+
import { IDataFileParser, IErrorInterceptor, IInterceptorChain, IRequestInterceptor, IRequestPreprocessor, IResponseInterceptor } from './implementations';
|
|
8
|
+
import { ICollectionLoader, ICookieJar, IFileSystem, IHttpClient, IRequestHistory, IScriptRunner, IVariableInterpolator } from './interfaces';
|
|
9
|
+
import { HttpRequest, HttpResponse, RequestSettings, UnifiedCollection, UnifiedRequest } from './interfaces/types';
|
|
10
|
+
import { EnvironmentConfig, EnvironmentResolver, ForgeEnv, ParserRegistry, RequestExecutor, ScriptPipeline } from './services';
|
|
11
|
+
/**
|
|
12
|
+
* Container configuration options
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Storage format for collections
|
|
16
|
+
*/
|
|
17
|
+
export type StorageFormat = 'file' | 'folder';
|
|
18
|
+
export interface ForgeContainerOptions {
|
|
19
|
+
/** Path to http-forge folder (enables custom modules from modules/ folder) */
|
|
20
|
+
forgeRoot?: string;
|
|
21
|
+
/** Storage format: 'file' for single JSON files, 'folder' for directory structure (default: 'folder') */
|
|
22
|
+
storageFormat?: StorageFormat;
|
|
23
|
+
/** Use native http/https instead of fetch (recommended for full control) */
|
|
24
|
+
useNativeHttp?: boolean;
|
|
25
|
+
/** Custom HTTP client implementation (overrides useNativeHttp) */
|
|
26
|
+
httpClient?: IHttpClient;
|
|
27
|
+
/** Default HTTP request settings */
|
|
28
|
+
httpSettings?: Partial<RequestSettings>;
|
|
29
|
+
/** HTTP request timeout (ms) - shorthand for httpSettings.timeout */
|
|
30
|
+
requestTimeout?: number;
|
|
31
|
+
/** Enable cookie jar for automatic cookie management */
|
|
32
|
+
enableCookies?: boolean;
|
|
33
|
+
/** Custom cookie jar implementation */
|
|
34
|
+
cookieJar?: ICookieJar;
|
|
35
|
+
/** Request interceptors to register */
|
|
36
|
+
requestInterceptors?: IRequestInterceptor[];
|
|
37
|
+
/** Response interceptors to register */
|
|
38
|
+
responseInterceptors?: IResponseInterceptor[];
|
|
39
|
+
/** Error interceptors to register */
|
|
40
|
+
errorInterceptors?: IErrorInterceptor[];
|
|
41
|
+
/** Custom interceptor chain (overrides individual interceptors) */
|
|
42
|
+
interceptorChain?: IInterceptorChain;
|
|
43
|
+
/** Custom script runner implementation */
|
|
44
|
+
scriptRunner?: IScriptRunner;
|
|
45
|
+
/** Script execution timeout (ms) */
|
|
46
|
+
scriptTimeout?: number;
|
|
47
|
+
/** Custom file system implementation */
|
|
48
|
+
fileSystem?: IFileSystem;
|
|
49
|
+
/** Custom variable interpolator implementation */
|
|
50
|
+
interpolator?: IVariableInterpolator;
|
|
51
|
+
/** Custom request preprocessor implementation */
|
|
52
|
+
preprocessor?: IRequestPreprocessor;
|
|
53
|
+
/** Custom data file parser implementation */
|
|
54
|
+
dataFileParser?: IDataFileParser;
|
|
55
|
+
/** Enable request history recording */
|
|
56
|
+
enableHistory?: boolean;
|
|
57
|
+
/** Maximum history entries per request (default: 100) */
|
|
58
|
+
maxHistoryEntries?: number;
|
|
59
|
+
/** Custom request history implementation */
|
|
60
|
+
requestHistory?: IRequestHistory;
|
|
61
|
+
/** Environment configuration */
|
|
62
|
+
environmentConfig?: EnvironmentConfig;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Forge Container - Main entry point for HTTP Forge Core
|
|
66
|
+
*
|
|
67
|
+
* Usage:
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const forge = new ForgeContainer();
|
|
70
|
+
* const collection = await forge.loadCollection('./api.forge.json');
|
|
71
|
+
* const result = await forge.execute(collection.items[0], collection);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare class ForgeContainer {
|
|
75
|
+
readonly httpClient: IHttpClient;
|
|
76
|
+
readonly fileSystem: IFileSystem;
|
|
77
|
+
readonly scriptRunner: IScriptRunner;
|
|
78
|
+
readonly interpolator: IVariableInterpolator;
|
|
79
|
+
readonly cookieJar: ICookieJar;
|
|
80
|
+
readonly interceptorChain: IInterceptorChain;
|
|
81
|
+
readonly preprocessor: IRequestPreprocessor;
|
|
82
|
+
readonly dataFileParser: IDataFileParser;
|
|
83
|
+
readonly requestHistory: IRequestHistory | null;
|
|
84
|
+
readonly parserRegistry: ParserRegistry;
|
|
85
|
+
readonly collectionLoader: ICollectionLoader;
|
|
86
|
+
readonly environmentStore: EnvironmentResolver;
|
|
87
|
+
readonly forgeEnv: ForgeEnv;
|
|
88
|
+
readonly scriptPipeline: ScriptPipeline;
|
|
89
|
+
readonly requestExecutor: RequestExecutor;
|
|
90
|
+
private readonly options;
|
|
91
|
+
constructor(options?: ForgeContainerOptions);
|
|
92
|
+
/**
|
|
93
|
+
* Create interceptor chain from options
|
|
94
|
+
*/
|
|
95
|
+
private createInterceptorChain;
|
|
96
|
+
/**
|
|
97
|
+
* Load a collection from file (only works with file storage format)
|
|
98
|
+
* @deprecated Use loadAllCollections() for folder format
|
|
99
|
+
*/
|
|
100
|
+
loadCollection(filePath: string): Promise<UnifiedCollection>;
|
|
101
|
+
/**
|
|
102
|
+
* Load all collections from the configured storage
|
|
103
|
+
* Works with both file and folder storage formats
|
|
104
|
+
*/
|
|
105
|
+
loadAllCollections(): Promise<UnifiedCollection[]>;
|
|
106
|
+
/**
|
|
107
|
+
* Execute a request with full pipeline
|
|
108
|
+
*/
|
|
109
|
+
execute(request: UnifiedRequest, collection: UnifiedCollection, options?: any): Promise<import("./services").ExecuteResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Execute a simple HTTP request
|
|
112
|
+
*/
|
|
113
|
+
executeSimple(request: HttpRequest, options?: any): Promise<HttpResponse>;
|
|
114
|
+
/**
|
|
115
|
+
* Register a custom collection parser
|
|
116
|
+
*/
|
|
117
|
+
registerParser(format: string, parser: any): void;
|
|
118
|
+
/**
|
|
119
|
+
* Set environment configuration
|
|
120
|
+
*/
|
|
121
|
+
setEnvironmentConfig(config: EnvironmentConfig): void;
|
|
122
|
+
/**
|
|
123
|
+
* Create a new container with custom options
|
|
124
|
+
*/
|
|
125
|
+
static create(options?: ForgeContainerOptions): ForgeContainer;
|
|
126
|
+
/**
|
|
127
|
+
* Create a container by auto-loading environments from forgeRoot
|
|
128
|
+
*
|
|
129
|
+
* Reads `{forgeRoot}/environments/environments.json` and creates
|
|
130
|
+
* a container with the environment configuration pre-loaded.
|
|
131
|
+
*
|
|
132
|
+
* @param forgeRoot - Path to http-forge folder (default: './http-forge')
|
|
133
|
+
* @param options - Additional container options
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* // Auto-load environments from ./http-forge/environments/environments.json
|
|
138
|
+
* const forge = ForgeContainer.fromForgeRoot('./http-forge');
|
|
139
|
+
*
|
|
140
|
+
* // Switch environment
|
|
141
|
+
* forge.forgeEnv.setActiveEnvironment('sit');
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
static fromForgeRoot(forgeRoot?: string, options?: Omit<ForgeContainerOptions, 'forgeRoot' | 'environmentConfig'>): ForgeContainer;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=container.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
|