Spaces:
Sleeping
Sleeping
File size: 7,214 Bytes
3ae68d6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | # Code Generation & Output Format Specification
This document details how the Smart API DevTool packages, displays, and delivers generated code assets and test files to the developer.
---
## 1. User Interface Display (Tabbed Preview)
When the LangGraph self-healing agent completes generation, the Web UI renders a tabbed workspace containing five distinct views:
1. **Overview & Auth Tab**: Displays extracted auth methods and the integration path recommendation (REST vs. SDK).
2. **Endpoints Explorer Tab**: Shows an interactive dictionary of endpoints (GET, POST, DELETE), headers, query params, and request payloads.
3. **Wrapper Class Tab**: Displays the syntax-highlighted source code of the generated client wrapper.
4. **Unit Tests Tab**: Displays the generated testing suite script.
5. **README Guide Tab**: Displays markdown usage instructions, library dependencies, and instantiation examples.
---
## 2. Download Deliverables & File Structure
Developers can download files individually or as a unified bundle.
### Option A: The Integration Bundle (ZIP)
Clicking the **"Download Integration Bundle (ZIP)"** button packages all generated files into a single ZIP file dynamically in the browser using `JSZip`. The extracted bundle structure varies by language:
#### Python
```text
my-api-integration/
βββ README.md # Setup instructions, dependencies, and code import examples
βββ client.py # The generated, type-safe wrapper class
βββ test_client.py # The Pytest test suite for validation (unittest.mock)
```
#### JavaScript
```text
my-api-integration/
βββ README.md # Setup instructions and CommonJS import examples
βββ client.js # The client class (exported via module.exports = { MyClientClass };)
βββ test_client.test.js # Standalone Node test script using named require and global fetch patch
```
#### TypeScript
```text
my-api-integration/
βββ README.md # Setup instructions and TS import examples
βββ client.ts # The client class (exported via export class MyClientClass { ... })
βββ test_client.test.ts # Standalone TS test script using named imports
βββ tsconfig.json # Minimal TypeScript config for sandbox/ts-node runtimes
```
#### Go
```text
my-api-integration/
βββ README.md # Setup instructions and go package import examples
βββ client.go # Go package source file defining the client struct
βββ client_test.go # Native Go test suite using testing package and httptest.NewServer
βββ go.mod # Temporary Go module name definition
```
#### Java
```text
my-api-integration/
βββ README.md # Setup instructions and compilation steps
βββ MyAPIClient.java # The Java client class (using java.net.http.HttpClient)
βββ TestClient.java # Standalone Java class with main() method running assertions (-ea)
```
---
## 3. Reference Output Code Structures
Below are the standard, production-ready structures of generated client wrappers and test suites.
### Python Client (Requests + Tenacity Retry)
The Python client utilizes `requests.Session` for connection pooling, type hints, custom error wrappers, and `tenacity.Retrying` dynamically at runtime to respect user configurations:
```python
import requests
from tenacity import Retrying, stop_after_attempt, wait_exponential, retry_if_exception_type
from typing import Dict, Any, Optional
class APIError(Exception):
"""Base exception for API errors."""
pass
class APIRateLimitError(APIError):
"""Exception for rate limits (429)."""
pass
class APIServerError(APIError):
"""Exception for server-side downtime (5xx)."""
pass
class APIClient:
def __init__(self, api_key: str, base_url: str = "https://api.example.com/v1", max_retries: int = 3):
if not api_key:
raise ValueError("API key cannot be empty.")
self.api_key = api_key
self.base_url = base_url.rstrip("/")
self.max_retries = max_retries
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
})
def _retry_request(self, func):
"""Dynamic tenacity runner to enforce instance-level retry limits."""
retrier = Retrying(
stop=stop_after_attempt(self.max_retries + 1),
wait=wait_exponential(multiplier=0.5, min=1, max=30),
retry=(
retry_if_exception_type(APIRateLimitError) |
retry_if_exception_type(APIServerError)
),
reraise=True
)
return retrier(func)
def _make_request(self, method: str, path: str, json_data=None) -> Dict[str, Any]:
url = f"{self.base_url}/{path.lstrip('/')}"
response = self.session.request(method, url, json=json_data, timeout=10)
if response.status_code == 429:
raise APIRateLimitError(f"Rate limited: {response.text}")
elif response.status_code >= 500:
raise APIServerError(f"Server error: {response.status_code}")
response.raise_for_status()
return response.json()
def get_resource(self, resource_id: str) -> Dict[str, Any]:
return self._retry_request(lambda: self._make_request("GET", f"/resources/{resource_id}"))
```
### JavaScript Client & Test (CommonJS + Async IIFE Test Harness)
The JavaScript client uses named exports, the global `fetch` API, and standard Node.js assertions inside a self-contained sequential test block:
```javascript
// client.js
class APIClient {
constructor(apiKey) {
if (!apiKey) throw new Error('API key cannot be empty.');
this.apiKey = apiKey;
this.baseUrl = 'https://api.example.com/v1';
}
async getResource(resourceId) {
const response = await fetch(`${this.baseUrl}/resources/${resourceId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) throw new Error(`HTTP Error ${response.status}`);
return await response.json();
}
}
module.exports = { APIClient };
```
```javascript
// test_client.test.js
const assert = require('assert');
const { APIClient } = require('./client');
async function runTests() {
const originalFetch = globalThis.fetch;
try {
// Setup local request mock
globalThis.fetch = async (url, options) => {
assert.strictEqual(options.headers['Authorization'], 'Bearer test-key');
return {
ok: true,
json: async () => ({ id: '123', name: 'Sample' })
};
};
const client = new APIClient('test-key');
const data = await client.getResource('123');
assert.deepStrictEqual(data, { id: '123', name: 'Sample' });
console.log('All tests passed successfully.');
} catch (error) {
console.error('Test execution failed:', error);
process.exit(1);
} finally {
globalThis.fetch = originalFetch;
}
process.exit(0);
}
runTests();
```
|