@ioka-technologies/asyncapi-ts-client-template 0.0.7
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 +382 -0
- package/USAGE.md +586 -0
- package/examples/simple/asyncapi.yaml +256 -0
- package/package.json +97 -0
- package/template/index.js +284 -0
- package/template/src/client.ts.js +377 -0
- package/template/src/index.ts.js +13 -0
- package/template/src/models.ts.js +229 -0
- package/template/src/runtime/errors.ts.js +29 -0
- package/template/src/runtime/transports/factory.ts.js +33 -0
- package/template/src/runtime/transports/http.ts.js +122 -0
- package/template/src/runtime/transports/websocket.ts.js +329 -0
- package/template/src/runtime/types.ts.js +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# TypeScript AsyncAPI Client Generator Template
|
|
2
|
+
|
|
3
|
+
A production-ready AsyncAPI code generator template for TypeScript clients. This template generates fully-typed TypeScript clients from AsyncAPI specifications with support for WebSocket and HTTP transports, compatible with the rust-asyncapi patterns.
|
|
4
|
+
|
|
5
|
+
## ๐ฏ Key Features
|
|
6
|
+
|
|
7
|
+
- ๐ฆ **Rust-AsyncAPI Compatible**: Generated clients are type-compatible with rust-asyncapi servers
|
|
8
|
+
- ๐ **Multiple Transports**: WebSocket and HTTP support with automatic transport selection
|
|
9
|
+
- ๐ก๏ธ **Type Safe**: Full TypeScript support with generated interfaces from AsyncAPI schemas
|
|
10
|
+
- ๐ง **Smart Method Names**: Automatic sanitization of operation names to valid JavaScript identifiers
|
|
11
|
+
- ๐ **Auto Reconnection**: WebSocket reconnection with configurable retry logic
|
|
12
|
+
- ๐ **Authentication**: JWT, API Key, and custom authentication support
|
|
13
|
+
- โก **Promise Based**: Modern async/await API
|
|
14
|
+
- ๐ฆ **Zero Config**: Works out of the box with sensible defaults
|
|
15
|
+
- ๐งช **Well Tested**: Comprehensive examples and documentation
|
|
16
|
+
|
|
17
|
+
## ๐ Quick Start
|
|
18
|
+
|
|
19
|
+
### Prerequisites
|
|
20
|
+
|
|
21
|
+
- [AsyncAPI CLI](https://github.com/asyncapi/cli) installed
|
|
22
|
+
- [Node.js](https://nodejs.org/) 16+ installed
|
|
23
|
+
|
|
24
|
+
### Generate Your Client
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install AsyncAPI CLI
|
|
28
|
+
npm install -g @asyncapi/cli
|
|
29
|
+
|
|
30
|
+
# Generate TypeScript client from your AsyncAPI specification
|
|
31
|
+
asyncapi generate fromTemplate asyncapi.yaml ./template -o ./my-client
|
|
32
|
+
|
|
33
|
+
# Install dependencies and build
|
|
34
|
+
cd my-client
|
|
35
|
+
npm install
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ๐ Project Structure
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
ts-asyncapi/
|
|
43
|
+
โโโ README.md # This file
|
|
44
|
+
โโโ USAGE.md # Comprehensive usage guide
|
|
45
|
+
โโโ PROJECT_SUMMARY.md # Project summary and achievements
|
|
46
|
+
โโโ example-api.yaml # Example AsyncAPI specification
|
|
47
|
+
โโโ package.json # Project dependencies
|
|
48
|
+
โโโ template/ # AsyncAPI Generator Template
|
|
49
|
+
โโโ package.json # Template dependencies
|
|
50
|
+
โโโ index.jsx # Template entry point
|
|
51
|
+
โโโ README.md # Template documentation
|
|
52
|
+
โโโ test.js # Template testing script
|
|
53
|
+
โโโ components/ # Template components
|
|
54
|
+
โโโ PackageJson.js # Package.json generator
|
|
55
|
+
โโโ IndexFile.js # Main index.ts generator
|
|
56
|
+
โโโ ClientFile.js # Client class generator
|
|
57
|
+
โโโ ModelsFile.js # Type definitions generator
|
|
58
|
+
โโโ TransportsFile.js # Transport exports
|
|
59
|
+
โโโ TsConfigFile.js # TypeScript config generator
|
|
60
|
+
โโโ ReadmeFile.js # Generated README
|
|
61
|
+
โโโ UsageFile.js # Generated usage docs
|
|
62
|
+
โโโ examples/ # Example generators
|
|
63
|
+
โ โโโ WebSocketExample.js # WebSocket example generator
|
|
64
|
+
โ โโโ HttpExample.js # HTTP example generator
|
|
65
|
+
โโโ runtime/ # Runtime implementation generators
|
|
66
|
+
โโโ RuntimeTypes.js # Core type definitions
|
|
67
|
+
โโโ RuntimeErrors.js # Error classes
|
|
68
|
+
โโโ TransportFactory.js # Transport factory
|
|
69
|
+
โโโ WebSocketTransport.js # WebSocket implementation
|
|
70
|
+
โโโ HttpTransport.js # HTTP implementation
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## ๐ง Template Parameters
|
|
74
|
+
|
|
75
|
+
| Parameter | Type | Default | Description |
|
|
76
|
+
|-----------|------|---------|-------------|
|
|
77
|
+
| `clientName` | string | `"{{info.title}}Client"` | Name of the generated client class |
|
|
78
|
+
| `packageName` | string | `"{{info.title | kebabCase}}-client"` | Name of the generated npm package |
|
|
79
|
+
| `packageVersion` | string | `"{{info.version}}"` | Version of the generated package |
|
|
80
|
+
| `author` | string | `"AsyncAPI Generator"` | Package author |
|
|
81
|
+
| `license` | string | `"Apache-2.0"` | Package license |
|
|
82
|
+
| `generateTests` | boolean | `true` | Generate unit tests |
|
|
83
|
+
| `includeExamples` | boolean | `true` | Include usage examples |
|
|
84
|
+
| `transports` | string | `"websocket,http"` | Comma-separated list of transports |
|
|
85
|
+
|
|
86
|
+
### Example with Parameters
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
asyncapi generate fromTemplate asyncapi.yaml ./template \
|
|
90
|
+
-o ./my-client \
|
|
91
|
+
-p clientName=MyAwesomeClient \
|
|
92
|
+
-p packageName=my-awesome-client \
|
|
93
|
+
-p packageVersion=1.0.0 \
|
|
94
|
+
-p author="Your Name" \
|
|
95
|
+
-p transports=websocket
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## ๐จ Message Envelope Standard
|
|
99
|
+
|
|
100
|
+
This template implements a standardized message envelope format for all AsyncAPI communications, enabling operation-based routing and consistent message handling across transports.
|
|
101
|
+
|
|
102
|
+
### Message Envelope Structure
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
interface MessageEnvelope {
|
|
106
|
+
operation: string; // AsyncAPI operation ID
|
|
107
|
+
id?: string; // Correlation ID for request/response
|
|
108
|
+
channel?: string; // Optional channel context
|
|
109
|
+
payload: any; // Message payload
|
|
110
|
+
timestamp?: number; // Message timestamp
|
|
111
|
+
error?: { // Error information
|
|
112
|
+
code: string;
|
|
113
|
+
message: string;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Message Flow Examples
|
|
119
|
+
|
|
120
|
+
#### Request/Response Pattern
|
|
121
|
+
```typescript
|
|
122
|
+
// Client sends:
|
|
123
|
+
{
|
|
124
|
+
"operation": "getUserProfile",
|
|
125
|
+
"id": "uuid-1234",
|
|
126
|
+
"channel": "user/profile",
|
|
127
|
+
"payload": { "userId": "123" },
|
|
128
|
+
"timestamp": 1234567890
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Server responds:
|
|
132
|
+
{
|
|
133
|
+
"operation": "getUserProfile",
|
|
134
|
+
"id": "uuid-1234",
|
|
135
|
+
"payload": { "id": "123", "name": "John" },
|
|
136
|
+
"timestamp": 1234567891
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Subscription Pattern
|
|
141
|
+
```typescript
|
|
142
|
+
// Server publishes:
|
|
143
|
+
{
|
|
144
|
+
"operation": "onMessageReceived",
|
|
145
|
+
"channel": "chat/receive",
|
|
146
|
+
"payload": { "text": "Hello", "from": "Alice" },
|
|
147
|
+
"timestamp": 1234567892
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### Error Response
|
|
152
|
+
```typescript
|
|
153
|
+
{
|
|
154
|
+
"operation": "getUserProfile",
|
|
155
|
+
"id": "uuid-1234",
|
|
156
|
+
"error": {
|
|
157
|
+
"code": "USER_NOT_FOUND",
|
|
158
|
+
"message": "User with ID 123 not found"
|
|
159
|
+
},
|
|
160
|
+
"timestamp": 1234567893
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Transport-Specific Handling
|
|
165
|
+
|
|
166
|
+
#### WebSocket Transport
|
|
167
|
+
- **Sending**: All messages wrapped in MessageEnvelope
|
|
168
|
+
- **Receiving**: Automatic envelope parsing and operation-based routing
|
|
169
|
+
- **Subscriptions**: Client-side filtering by operation field
|
|
170
|
+
- **Correlation**: Built-in request/response correlation via `id` field
|
|
171
|
+
|
|
172
|
+
#### HTTP Transport
|
|
173
|
+
- **Sending**: Complete envelope in POST body
|
|
174
|
+
- **Headers**: Operation and correlation ID in HTTP headers
|
|
175
|
+
- **Error Handling**: Envelope-level errors parsed from response body
|
|
176
|
+
- **Subscriptions**: Warning logged (HTTP doesn't support real-time subscriptions)
|
|
177
|
+
|
|
178
|
+
### Server Implementation Guide
|
|
179
|
+
|
|
180
|
+
To implement a compatible server, ensure your server:
|
|
181
|
+
|
|
182
|
+
1. **Parses MessageEnvelope**: All incoming messages should be parsed as MessageEnvelope
|
|
183
|
+
2. **Routes by Operation**: Use the `operation` field to route messages to appropriate handlers
|
|
184
|
+
3. **Preserves Correlation**: Include the same `id` in response messages for request/response patterns
|
|
185
|
+
4. **Uses Error Format**: Return errors in the envelope `error` field with `code` and `message`
|
|
186
|
+
5. **Includes Timestamps**: Add `timestamp` field for message timing information
|
|
187
|
+
|
|
188
|
+
## ๐ Rust-AsyncAPI Compatibility
|
|
189
|
+
|
|
190
|
+
This template generates clients that work with AsyncAPI-compliant servers. The message envelope format provides a standard way to handle operation routing and correlation across different server implementations.
|
|
191
|
+
|
|
192
|
+
### Key Compatibility Features
|
|
193
|
+
|
|
194
|
+
- **Operation-Based Routing**: Servers can route messages based on the `operation` field
|
|
195
|
+
- **Request/Response Correlation**: Built-in correlation ID support for async request/response patterns
|
|
196
|
+
- **Standardized Error Format**: Consistent error structure across all operations
|
|
197
|
+
- **Transport Agnostic**: Same envelope format works across WebSocket and HTTP transports
|
|
198
|
+
- **Channel Context**: Optional channel information for debugging and routing
|
|
199
|
+
|
|
200
|
+
## ๐ Usage Examples
|
|
201
|
+
|
|
202
|
+
### WebSocket Client
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
import { MyServiceClient } from './my-client';
|
|
206
|
+
|
|
207
|
+
const client = new MyServiceClient({
|
|
208
|
+
transport: 'websocket',
|
|
209
|
+
websocket: {
|
|
210
|
+
url: 'ws://localhost:8080',
|
|
211
|
+
reconnect: true,
|
|
212
|
+
auth: {
|
|
213
|
+
token: 'your-jwt-token'
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await client.connect();
|
|
219
|
+
const response = await client.getUserProfile({ userId: '123' });
|
|
220
|
+
console.log(response);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### HTTP Client
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { MyServiceClient } from './my-client';
|
|
227
|
+
|
|
228
|
+
const client = new MyServiceClient({
|
|
229
|
+
transport: 'http',
|
|
230
|
+
http: {
|
|
231
|
+
baseUrl: 'http://localhost:8080',
|
|
232
|
+
retry: {
|
|
233
|
+
attempts: 3,
|
|
234
|
+
delay: 1000,
|
|
235
|
+
backoff: 'exponential'
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
await client.connect();
|
|
241
|
+
const response = await client.createUser({ name: 'John', email: 'john@example.com' });
|
|
242
|
+
console.log(response);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## ๐ก๏ธ Type Safety
|
|
246
|
+
|
|
247
|
+
The generated client provides full TypeScript type safety:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// All request/response types are generated from your AsyncAPI spec
|
|
251
|
+
const response = await client.getUserProfile({
|
|
252
|
+
userId: '123' // TypeScript knows this is required
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Response is fully typed
|
|
256
|
+
console.log(response.user.name); // TypeScript provides autocomplete
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## ๐ Authentication Support
|
|
260
|
+
|
|
261
|
+
### JWT Tokens
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
{
|
|
265
|
+
auth: {
|
|
266
|
+
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### API Keys
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
{
|
|
275
|
+
auth: {
|
|
276
|
+
apiKey: 'your-api-key'
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Custom Headers
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
{
|
|
285
|
+
auth: {
|
|
286
|
+
headers: {
|
|
287
|
+
'X-Custom-Auth': 'custom-value'
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## ๐ Error Handling
|
|
294
|
+
|
|
295
|
+
Comprehensive error types for robust error handling:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
import { ConnectionError, MessageTimeoutError, HttpError } from './my-client';
|
|
299
|
+
|
|
300
|
+
try {
|
|
301
|
+
await client.someOperation(data);
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error instanceof ConnectionError) {
|
|
304
|
+
console.error('Connection failed:', error.message);
|
|
305
|
+
} else if (error instanceof MessageTimeoutError) {
|
|
306
|
+
console.error('Request timed out');
|
|
307
|
+
} else if (error instanceof HttpError) {
|
|
308
|
+
console.error(`HTTP ${error.status}: ${error.message}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## ๐งช Testing the Template
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Test the template with the example API
|
|
317
|
+
cd template
|
|
318
|
+
npm install
|
|
319
|
+
node test.js
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## ๐๏ธ Generated Project Structure
|
|
323
|
+
|
|
324
|
+
When you generate a client, you'll get a complete TypeScript project:
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
my-client/
|
|
328
|
+
โโโ package.json # NPM package configuration
|
|
329
|
+
โโโ tsconfig.json # TypeScript configuration
|
|
330
|
+
โโโ README.md # Generated documentation
|
|
331
|
+
โโโ USAGE.md # Detailed usage instructions
|
|
332
|
+
โโโ src/
|
|
333
|
+
โ โโโ index.ts # Main exports
|
|
334
|
+
โ โโโ client.ts # Generated client class
|
|
335
|
+
โ โโโ models.ts # Generated TypeScript interfaces
|
|
336
|
+
โ โโโ transports.ts # Transport exports
|
|
337
|
+
โ โโโ runtime/ # Runtime implementation
|
|
338
|
+
โ โโโ types.ts # Core type definitions
|
|
339
|
+
โ โโโ errors.ts # Error classes
|
|
340
|
+
โ โโโ transports/ # Transport implementations
|
|
341
|
+
โ โโโ factory.ts # Transport factory
|
|
342
|
+
โ โโโ websocket.ts # WebSocket transport
|
|
343
|
+
โ โโโ http.ts # HTTP transport
|
|
344
|
+
โโโ examples/ # Usage examples
|
|
345
|
+
โโโ websocket-example.ts # WebSocket example
|
|
346
|
+
โโโ http-example.ts # HTTP example
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## ๐ Documentation
|
|
350
|
+
|
|
351
|
+
- **[USAGE.md](./USAGE.md)** - Comprehensive usage guide with examples
|
|
352
|
+
- **[PROJECT_SUMMARY.md](./PROJECT_SUMMARY.md)** - Complete project summary
|
|
353
|
+
- **[template/README.md](./template/README.md)** - Template-specific documentation
|
|
354
|
+
|
|
355
|
+
## ๐ค Contributing
|
|
356
|
+
|
|
357
|
+
1. Fork the repository
|
|
358
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
359
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
360
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
361
|
+
5. Submit a pull request
|
|
362
|
+
|
|
363
|
+
## ๐ Requirements
|
|
364
|
+
|
|
365
|
+
- **Node.js**: >= 16.0.0
|
|
366
|
+
- **TypeScript**: >= 4.5.0
|
|
367
|
+
- **AsyncAPI CLI**: Latest version
|
|
368
|
+
|
|
369
|
+
## ๐ License
|
|
370
|
+
|
|
371
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
372
|
+
|
|
373
|
+
## ๐ Related Projects
|
|
374
|
+
|
|
375
|
+
- [AsyncAPI Generator](https://github.com/asyncapi/generator)
|
|
376
|
+
- [AsyncAPI CLI](https://github.com/asyncapi/cli)
|
|
377
|
+
- [Rust AsyncAPI Template](https://github.com/asyncapi/rust-template)
|
|
378
|
+
- [AsyncAPI Specification](https://github.com/asyncapi/spec)
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
Generated with โค๏ธ by [AsyncAPI Generator](https://github.com/asyncapi/generator)
|