@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.
@@ -0,0 +1,256 @@
1
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/asyncapi/spec-json-schemas/refs/heads/master/schemas/all.schema-store.json
2
+ asyncapi: 3.0.0
3
+ info:
4
+ title: Simple Chat API
5
+ version: 1.0.0
6
+ description: A simple chat API for testing the TypeScript client generator
7
+
8
+ servers:
9
+ websocket:
10
+ host: localhost:8080
11
+ protocol: ws
12
+ description: WebSocket server for real-time chat
13
+ http:
14
+ host: localhost:8080
15
+ protocol: http
16
+ description: HTTP server for REST API
17
+
18
+ channels:
19
+ chatSend:
20
+ address: chat/send
21
+ messages:
22
+ SendMessage:
23
+ $ref: '#/components/messages/SendMessage'
24
+ MessageAck:
25
+ $ref: '#/components/messages/MessageAck'
26
+
27
+ chatReceive:
28
+ address: chat/receive
29
+ messages:
30
+ MessageReceived:
31
+ $ref: '#/components/messages/MessageReceived'
32
+
33
+ userProfile:
34
+ address: user/profile
35
+ messages:
36
+ GetUserProfile:
37
+ $ref: '#/components/messages/GetUserProfile'
38
+ UserProfile:
39
+ $ref: '#/components/messages/UserProfile'
40
+
41
+ userStatus:
42
+ address: user/status
43
+ messages:
44
+ UpdateStatus:
45
+ $ref: '#/components/messages/UpdateStatus'
46
+ StatusUpdated:
47
+ $ref: '#/components/messages/StatusUpdated'
48
+
49
+ operations:
50
+ # Request/Response pattern - send message and wait for acknowledgment
51
+ sendMessage:
52
+ action: send
53
+ channel:
54
+ $ref: '#/channels/chatSend'
55
+ messages:
56
+ - $ref: '#/channels/chatSend/messages/SendMessage'
57
+ reply:
58
+ channel:
59
+ $ref: '#/channels/chatSend'
60
+ messages:
61
+ - $ref: '#/channels/chatSend/messages/MessageAck'
62
+
63
+ # Regular receive operation - listen for incoming messages
64
+ onMessageReceived:
65
+ action: receive
66
+ channel:
67
+ $ref: '#/channels/chatReceive'
68
+ messages:
69
+ - $ref: '#/channels/chatReceive/messages/MessageReceived'
70
+
71
+ # Request/Response pattern - get user profile and wait for response
72
+ getUserProfile:
73
+ action: send
74
+ channel:
75
+ $ref: '#/channels/userProfile'
76
+ messages:
77
+ - $ref: '#/channels/userProfile/messages/GetUserProfile'
78
+ reply:
79
+ channel:
80
+ $ref: '#/channels/userProfile'
81
+ messages:
82
+ - $ref: '#/channels/userProfile/messages/UserProfile'
83
+
84
+ # Regular send operation - fire and forget status update
85
+ updateStatus:
86
+ action: send
87
+ channel:
88
+ $ref: '#/channels/userStatus'
89
+ messages:
90
+ - $ref: '#/channels/userStatus/messages/UpdateStatus'
91
+
92
+ # Regular receive operation - listen for status updates from other users
93
+ onStatusUpdated:
94
+ action: receive
95
+ channel:
96
+ $ref: '#/channels/userStatus'
97
+ messages:
98
+ - $ref: '#/channels/userStatus/messages/StatusUpdated'
99
+
100
+ components:
101
+ messages:
102
+ SendMessage:
103
+ name: SendMessage
104
+ title: Send Message
105
+ summary: Send a chat message
106
+ payload:
107
+ type: object
108
+ properties:
109
+ roomId:
110
+ type: string
111
+ description: The chat room ID
112
+ content:
113
+ type: string
114
+ description: The message content
115
+ timestamp:
116
+ type: string
117
+ format: date-time
118
+ description: When the message was sent
119
+ required:
120
+ - roomId
121
+ - content
122
+
123
+ MessageAck:
124
+ name: MessageAck
125
+ title: Message Acknowledgment
126
+ summary: Acknowledgment of a sent message
127
+ payload:
128
+ type: object
129
+ properties:
130
+ messageId:
131
+ type: string
132
+ description: The unique message ID
133
+ status:
134
+ type: string
135
+ enum: [sent, delivered, failed]
136
+ description: The message status
137
+ timestamp:
138
+ type: string
139
+ format: date-time
140
+ required:
141
+ - messageId
142
+ - status
143
+ - timestamp
144
+
145
+ MessageReceived:
146
+ name: MessageReceived
147
+ title: Message Received
148
+ summary: A message received in a chat room
149
+ payload:
150
+ type: object
151
+ properties:
152
+ messageId:
153
+ type: string
154
+ roomId:
155
+ type: string
156
+ senderId:
157
+ type: string
158
+ senderName:
159
+ type: string
160
+ content:
161
+ type: string
162
+ timestamp:
163
+ type: string
164
+ format: date-time
165
+ required:
166
+ - messageId
167
+ - roomId
168
+ - senderId
169
+ - senderName
170
+ - content
171
+ - timestamp
172
+
173
+ GetUserProfile:
174
+ name: GetUserProfile
175
+ title: Get User Profile
176
+ summary: Request to get a user's profile
177
+ payload:
178
+ type: object
179
+ properties:
180
+ userId:
181
+ type: string
182
+ description: The user ID to fetch
183
+ required:
184
+ - userId
185
+
186
+ UserProfile:
187
+ name: UserProfile
188
+ title: User Profile
189
+ summary: User profile information
190
+ payload:
191
+ type: object
192
+ properties:
193
+ id:
194
+ type: string
195
+ username:
196
+ type: string
197
+ displayName:
198
+ type: string
199
+ email:
200
+ type: string
201
+ status:
202
+ type: string
203
+ enum: [online, away, busy, offline]
204
+ avatar:
205
+ type: string
206
+ description: URL to user avatar
207
+ joinedAt:
208
+ type: string
209
+ format: date-time
210
+ lastSeen:
211
+ type: string
212
+ format: date-time
213
+ required:
214
+ - id
215
+ - username
216
+ - displayName
217
+ - status
218
+ - joinedAt
219
+
220
+ UpdateStatus:
221
+ name: UpdateStatus
222
+ title: Update Status
223
+ summary: Update user status
224
+ payload:
225
+ type: object
226
+ properties:
227
+ status:
228
+ type: string
229
+ enum: [online, away, busy, offline]
230
+ message:
231
+ type: string
232
+ description: Optional status message
233
+ required:
234
+ - status
235
+
236
+ StatusUpdated:
237
+ name: StatusUpdated
238
+ title: Status Updated
239
+ summary: User status has been updated
240
+ payload:
241
+ type: object
242
+ properties:
243
+ userId:
244
+ type: string
245
+ status:
246
+ type: string
247
+ enum: [online, away, busy, offline]
248
+ message:
249
+ type: string
250
+ updatedAt:
251
+ type: string
252
+ format: date-time
253
+ required:
254
+ - userId
255
+ - status
256
+ - updatedAt
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@ioka-technologies/asyncapi-ts-client-template",
3
+ "version": "0.0.7",
4
+ "description": "TypeScript AsyncAPI client generator template compatible with rust-asyncapi patterns",
5
+ "main": "template/index.js",
6
+ "scripts": {
7
+ "test": "npm run test:generate",
8
+ "test:generate": "asyncapi generate fromTemplate examples/simple/asyncapi.yaml . -o test-output-simple --force-write -p enableAuth=true",
9
+ "clean": "rm -rf test-output-*"
10
+ },
11
+ "keywords": [
12
+ "asyncapi",
13
+ "typescript",
14
+ "websocket",
15
+ "http",
16
+ "client",
17
+ "generator",
18
+ "template",
19
+ "rust-asyncapi"
20
+ ],
21
+ "author": "AsyncAPI TypeScript Generator",
22
+ "license": "Apache-2.0",
23
+ "devDependencies": {
24
+ "@asyncapi/cli": "^1.18.0"
25
+ },
26
+ "generator": {
27
+ "renderer": "react",
28
+ "apiVersion": "v3",
29
+ "supportedProtocols": [
30
+ "http",
31
+ "https",
32
+ "ws",
33
+ "wss"
34
+ ],
35
+ "parameters": {
36
+ "clientName": {
37
+ "description": "Name of the generated client class",
38
+ "default": "",
39
+ "required": false
40
+ },
41
+ "packageName": {
42
+ "description": "Name of the generated npm package",
43
+ "default": "",
44
+ "required": false
45
+ },
46
+ "packageVersion": {
47
+ "description": "Version of the generated package",
48
+ "default": "",
49
+ "required": false
50
+ },
51
+ "author": {
52
+ "description": "Package author",
53
+ "default": "AsyncAPI Generator",
54
+ "required": false
55
+ },
56
+ "license": {
57
+ "description": "Package license",
58
+ "default": "Apache-2.0",
59
+ "required": false
60
+ },
61
+ "enableAuth": {
62
+ "description": "Enable authentication middleware",
63
+ "default": true,
64
+ "required": false
65
+ },
66
+ "transports": {
67
+ "description": "Comma-separated list of transports to include",
68
+ "default": "websocket,http",
69
+ "required": false
70
+ },
71
+ "generateTests": {
72
+ "description": "Generate unit tests",
73
+ "default": true,
74
+ "required": false
75
+ },
76
+ "includeExamples": {
77
+ "description": "Include usage examples",
78
+ "default": true,
79
+ "required": false
80
+ }
81
+ },
82
+ "nonRenderableFiles": [
83
+ "examples/**/*",
84
+ "test-output-*/**/*",
85
+ "*.md",
86
+ "LICENSE"
87
+ ],
88
+ "generator": ">=1.15.0 <3.0.0"
89
+ },
90
+ "files": [
91
+ "template/**/*",
92
+ "examples/**/*",
93
+ "README.md",
94
+ "USAGE.md",
95
+ "PROJECT_SUMMARY.md"
96
+ ]
97
+ }
@@ -0,0 +1,284 @@
1
+ const { File } = require('@asyncapi/generator-react-sdk');
2
+ const React = require('react');
3
+
4
+ module.exports = function ({ asyncapi, params }) {
5
+ // Extract info from AsyncAPI spec
6
+ let title, version, description;
7
+ try {
8
+ const info = asyncapi.info();
9
+ title = info.title();
10
+ version = info.version();
11
+ description = info.description();
12
+ } catch (error) {
13
+ title = 'UnknownAPI';
14
+ version = '1.0.0';
15
+ description = 'Generated API client';
16
+ }
17
+
18
+ // Helper function to check if a parameter contains unresolved template variables
19
+ function isTemplateVariable(value) {
20
+ return typeof value === 'string' && value.includes('{{') && value.includes('}}');
21
+ }
22
+
23
+ // Helper function to convert title to kebab-case
24
+ function toKebabCase(str) {
25
+ return str.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
26
+ }
27
+
28
+ // Resolve parameters, falling back to extracted values if parameters contain template variables
29
+ const clientName = (params.clientName && !isTemplateVariable(params.clientName))
30
+ ? params.clientName
31
+ : `${title.replace(/[^a-zA-Z0-9]/g, '')}Client`;
32
+
33
+ const packageName = (params.packageName && !isTemplateVariable(params.packageName))
34
+ ? params.packageName
35
+ : `${toKebabCase(title)}-client`;
36
+
37
+ const packageVersion = (params.packageVersion && !isTemplateVariable(params.packageVersion))
38
+ ? params.packageVersion
39
+ : version;
40
+
41
+ const transports = (params.transports || 'websocket,http').split(',').map(t => t.trim());
42
+
43
+ // Generate all files from the main index.js
44
+ return [
45
+ React.createElement(File, { name: "package.json" },
46
+ JSON.stringify({
47
+ name: packageName,
48
+ version: packageVersion,
49
+ description: `${description || title} - TypeScript AsyncAPI Client`,
50
+ main: "dist/index.js",
51
+ types: "dist/index.d.ts",
52
+ scripts: {
53
+ build: "tsc",
54
+ dev: "tsc --watch",
55
+ test: "jest",
56
+ lint: "eslint src/**/*.ts",
57
+ prepare: "npm run build"
58
+ },
59
+ keywords: [
60
+ "asyncapi",
61
+ "websocket",
62
+ "http",
63
+ "client",
64
+ "typescript",
65
+ title.toLowerCase().replace(/[^a-z0-9]/g, '-')
66
+ ],
67
+ author: params.author || "AsyncAPI Generator",
68
+ license: params.license || "Apache-2.0",
69
+ dependencies: {
70
+ uuid: "^9.0.0"
71
+ },
72
+ optionalDependencies: {
73
+ ws: "^8.14.0"
74
+ },
75
+ devDependencies: {
76
+ "@types/ws": "^8.5.0",
77
+ "@types/uuid": "^9.0.0",
78
+ "@types/node": "^20.0.0",
79
+ typescript: "^5.0.0",
80
+ eslint: "^8.0.0",
81
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
82
+ "@typescript-eslint/parser": "^6.0.0",
83
+ ...(params.generateTests && {
84
+ jest: "^29.0.0",
85
+ "@types/jest": "^29.0.0",
86
+ "ts-jest": "^29.0.0"
87
+ })
88
+ },
89
+ files: [
90
+ "dist/**/*",
91
+ "README.md",
92
+ "USAGE.md"
93
+ ]
94
+ }, null, 2)
95
+ ),
96
+
97
+ React.createElement(File, { name: "tsconfig.json" },
98
+ JSON.stringify({
99
+ compilerOptions: {
100
+ target: "ES2020",
101
+ module: "ES2020",
102
+ lib: ["ES2020", "DOM"],
103
+ outDir: "./dist",
104
+ rootDir: "./src",
105
+ strict: true,
106
+ esModuleInterop: true,
107
+ skipLibCheck: true,
108
+ forceConsistentCasingInFileNames: true,
109
+ declaration: true,
110
+ declarationMap: true,
111
+ sourceMap: true,
112
+ moduleResolution: "node",
113
+ allowSyntheticDefaultImports: true,
114
+ experimentalDecorators: true,
115
+ emitDecoratorMetadata: true,
116
+ resolveJsonModule: true,
117
+ typeRoots: ["node_modules/@types"]
118
+ },
119
+ include: [
120
+ "src/**/*"
121
+ ],
122
+ exclude: [
123
+ "node_modules",
124
+ "dist",
125
+ "**/*.test.ts",
126
+ "**/*.spec.ts"
127
+ ]
128
+ }, null, 2)
129
+ ),
130
+
131
+ React.createElement(File, { name: "README.md" },
132
+ `# ${title}
133
+
134
+ ${description || 'Generated TypeScript AsyncAPI client'}
135
+
136
+ ## Installation
137
+
138
+ \`\`\`bash
139
+ npm install ${packageName}
140
+ \`\`\`
141
+
142
+ ## Quick Start
143
+
144
+ See [USAGE.md](./USAGE.md) for detailed usage instructions.
145
+
146
+ ## Generated from AsyncAPI
147
+
148
+ This client was generated from an AsyncAPI specification using the TypeScript AsyncAPI Client Generator.
149
+
150
+ - AsyncAPI Version: ${asyncapi.version()}
151
+ - Generated: ${new Date().toISOString()}
152
+ `
153
+ ),
154
+
155
+ React.createElement(File, { name: "USAGE.md" },
156
+ `# ${title} - Usage Guide
157
+
158
+ This document shows how to use the generated TypeScript AsyncAPI client.
159
+
160
+ ## Installation
161
+
162
+ ### Browser Usage
163
+ For browser environments, install the package normally:
164
+ \`\`\`bash
165
+ npm install ${packageName}
166
+ \`\`\`
167
+
168
+ ### Node.js Usage
169
+ For Node.js environments, you'll also need the WebSocket library:
170
+ \`\`\`bash
171
+ npm install ${packageName} ws
172
+ \`\`\`
173
+
174
+ ## Environment Compatibility
175
+
176
+ This client automatically detects the environment and uses the appropriate WebSocket implementation:
177
+ - **Browser**: Uses the native \`WebSocket\` API
178
+ - **Node.js**: Uses the \`ws\` library (must be installed separately)
179
+
180
+ ## WebSocket Usage
181
+
182
+ \`\`\`typescript
183
+ import { ${clientName} } from '${packageName}';
184
+
185
+ const client = new ${clientName}({
186
+ type: 'websocket',
187
+ url: 'ws://localhost:8080',
188
+ headers: {
189
+ 'Authorization': 'Bearer your-token'
190
+ }
191
+ });
192
+
193
+ // Connect to the WebSocket
194
+ await client.connect();
195
+
196
+ // Send a message and wait for response
197
+ try {
198
+ const response = await client.sendMessage({
199
+ text: 'Hello, World!',
200
+ userId: '123'
201
+ });
202
+ console.log('Response:', response);
203
+ } catch (error) {
204
+ console.error('Error:', error);
205
+ }
206
+
207
+ // Disconnect when done
208
+ await client.disconnect();
209
+ \`\`\`
210
+
211
+ ## HTTP Usage
212
+
213
+ \`\`\`typescript
214
+ import { ${clientName} } from '${packageName}';
215
+
216
+ const client = new ${clientName}({
217
+ type: 'http',
218
+ url: 'http://localhost:8080/api',
219
+ headers: {
220
+ 'Authorization': 'Bearer your-token'
221
+ }
222
+ });
223
+
224
+ // Send HTTP request
225
+ try {
226
+ const response = await client.sendMessage({
227
+ text: 'Hello, World!',
228
+ userId: '123'
229
+ });
230
+ console.log('Response:', response);
231
+ } catch (error) {
232
+ console.error('Error:', error);
233
+ }
234
+ \`\`\`
235
+
236
+ ## Configuration Options
237
+
238
+ \`\`\`typescript
239
+ interface TransportConfig {
240
+ type: 'websocket' | 'http';
241
+ url: string;
242
+ headers?: Record<string, string>;
243
+ timeout?: number;
244
+ }
245
+ \`\`\`
246
+
247
+ ## Error Handling
248
+
249
+ The client throws specific error types:
250
+
251
+ - \`TransportError\`: General transport errors
252
+ - \`ConnectionError\`: Connection-related errors
253
+ - \`TimeoutError\`: Request timeout errors
254
+
255
+ \`\`\`typescript
256
+ import { TransportError, ConnectionError, TimeoutError } from '${packageName}';
257
+
258
+ try {
259
+ await client.sendMessage(payload);
260
+ } catch (error) {
261
+ if (error instanceof ConnectionError) {
262
+ console.error('Connection failed:', error.message);
263
+ } else if (error instanceof TimeoutError) {
264
+ console.error('Request timed out:', error.message);
265
+ } else if (error instanceof TransportError) {
266
+ console.error('Transport error:', error.message);
267
+ }
268
+ }
269
+ \`\`\`
270
+
271
+ ## Troubleshooting
272
+
273
+ ### WebSocket Issues in Node.js
274
+ If you get an error like "WebSocket implementation not available", make sure you have installed the \`ws\` package:
275
+ \`\`\`bash
276
+ npm install ws
277
+ \`\`\`
278
+
279
+ ### Browser Compatibility
280
+ The client uses the native WebSocket API in browsers, which is supported in all modern browsers. No additional dependencies are required.
281
+ `
282
+ )
283
+ ];
284
+ };