@ioka-technologies/asyncapi-rust-client-template 0.0.20 → 0.0.22
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/dist/common/index.js +2004 -0
- package/package.json +12 -3
- package/template/Cargo.toml.js +13 -38
- package/template/dist/common/index.js +2004 -0
- package/template/helpers/index.js +56 -441
- package/template/helpers/index.js.dev +116 -0
- package/template/package.json +2 -1
- package/template/src/client.rs.js +3 -15
- package/template/src/lib.rs.js +10 -14
|
@@ -0,0 +1,2004 @@
|
|
|
1
|
+
/******/ // The require scope
|
|
2
|
+
/******/ var __webpack_require__ = {};
|
|
3
|
+
/******/
|
|
4
|
+
/************************************************************************/
|
|
5
|
+
/******/ /* webpack/runtime/define property getters */
|
|
6
|
+
/******/ (() => {
|
|
7
|
+
/******/ // define getter functions for harmony exports
|
|
8
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
9
|
+
/******/ for(var key in definition) {
|
|
10
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
11
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
12
|
+
/******/ }
|
|
13
|
+
/******/ }
|
|
14
|
+
/******/ };
|
|
15
|
+
/******/ })();
|
|
16
|
+
/******/
|
|
17
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
18
|
+
/******/ (() => {
|
|
19
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
20
|
+
/******/ })();
|
|
21
|
+
/******/
|
|
22
|
+
/************************************************************************/
|
|
23
|
+
var __webpack_exports__ = {};
|
|
24
|
+
|
|
25
|
+
;// ../common/src/string-utils.js
|
|
26
|
+
/**
|
|
27
|
+
* String conversion utilities for AsyncAPI template generation
|
|
28
|
+
*
|
|
29
|
+
* This module provides consistent string conversion functions used across
|
|
30
|
+
* multiple AsyncAPI templates to ensure naming conventions are standardized.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Converts a string to a valid Rust identifier
|
|
35
|
+
* Handles special characters, keywords, and ensures valid Rust naming conventions
|
|
36
|
+
*
|
|
37
|
+
* @param {string} str - Input string to convert
|
|
38
|
+
* @returns {string} Valid Rust identifier
|
|
39
|
+
*/
|
|
40
|
+
function toRustIdentifier(str) {
|
|
41
|
+
if (!str) return 'unknown';
|
|
42
|
+
let identifier = str.replace(/[^a-zA-Z0-9_]/g, '_').replace(/^[0-9]/, '_$&').replace(/_+/g, '_').replace(/^_+|_+$/g, '');
|
|
43
|
+
if (/^[0-9]/.test(identifier)) {
|
|
44
|
+
identifier = 'item_' + identifier;
|
|
45
|
+
}
|
|
46
|
+
if (!identifier) {
|
|
47
|
+
identifier = 'unknown';
|
|
48
|
+
}
|
|
49
|
+
const rustKeywords = ['as', 'break', 'const', 'continue', 'crate', 'else', 'enum', 'extern', 'false', 'fn', 'for', 'if', 'impl', 'in', 'let', 'loop', 'match', 'mod', 'move', 'mut', 'pub', 'ref', 'return', 'self', 'Self', 'static', 'struct', 'super', 'trait', 'true', 'type', 'unsafe', 'use', 'where', 'while', 'async', 'await', 'dyn'];
|
|
50
|
+
if (rustKeywords.includes(identifier)) {
|
|
51
|
+
identifier = identifier + '_';
|
|
52
|
+
}
|
|
53
|
+
return identifier;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Converts a string to PascalCase Rust type name
|
|
58
|
+
* Handles camelCase, snake_case, and kebab-case inputs
|
|
59
|
+
*
|
|
60
|
+
* @param {string} str - Input string to convert
|
|
61
|
+
* @returns {string} PascalCase Rust type name
|
|
62
|
+
*/
|
|
63
|
+
function toRustTypeName(str) {
|
|
64
|
+
if (!str) return 'Unknown';
|
|
65
|
+
|
|
66
|
+
// Ensure str is a string
|
|
67
|
+
const strValue = String(str);
|
|
68
|
+
const identifier = toRustIdentifier(strValue);
|
|
69
|
+
|
|
70
|
+
// Handle camelCase and PascalCase inputs by splitting on capital letters too
|
|
71
|
+
const parts = identifier.replace(/([a-z])([A-Z])/g, '$1_$2') // Insert underscore before capital letters
|
|
72
|
+
.split(/[_\s-]+/) // Split on underscores, spaces, and hyphens
|
|
73
|
+
.filter(part => part.length > 0);
|
|
74
|
+
return parts.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Converts a string to snake_case Rust field name
|
|
79
|
+
*
|
|
80
|
+
* @param {string} str - Input string to convert
|
|
81
|
+
* @returns {string} snake_case Rust field name
|
|
82
|
+
*/
|
|
83
|
+
function toRustFieldName(str) {
|
|
84
|
+
if (!str) return 'unknown';
|
|
85
|
+
const identifier = toRustIdentifier(str);
|
|
86
|
+
return identifier.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '').replace(/_+/g, '_');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Converts a string to Rust enum variant name (PascalCase)
|
|
91
|
+
*
|
|
92
|
+
* @param {string} str - Input string to convert
|
|
93
|
+
* @returns {string} PascalCase enum variant name
|
|
94
|
+
*/
|
|
95
|
+
function toRustEnumVariant(str) {
|
|
96
|
+
if (!str) return 'Unknown';
|
|
97
|
+
return str.split(/[-_\s]+/).map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Converts a string to Rust enum variant with serde rename for lowercase serialization
|
|
102
|
+
*
|
|
103
|
+
* @param {string} str - Input string to convert
|
|
104
|
+
* @returns {object} Object with rustName (PascalCase) and serializedName (lowercase)
|
|
105
|
+
*/
|
|
106
|
+
function toRustEnumVariantWithSerde(str) {
|
|
107
|
+
if (!str) return {
|
|
108
|
+
rustName: 'Unknown',
|
|
109
|
+
serializedName: 'unknown'
|
|
110
|
+
};
|
|
111
|
+
const rustName = str.split(/[-_\s]+/).map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
112
|
+
const serializedName = str.toLowerCase();
|
|
113
|
+
return {
|
|
114
|
+
rustName,
|
|
115
|
+
serializedName
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Converts a string to kebab-case
|
|
121
|
+
* Useful for package names and file names
|
|
122
|
+
*
|
|
123
|
+
* @param {string} str - Input string to convert
|
|
124
|
+
* @returns {string} kebab-case string
|
|
125
|
+
*/
|
|
126
|
+
function toKebabCase(str) {
|
|
127
|
+
if (!str) return '';
|
|
128
|
+
return str.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Converts a string to PascalCase
|
|
133
|
+
* Useful for class names and type names
|
|
134
|
+
*
|
|
135
|
+
* @param {string} str - Input string to convert
|
|
136
|
+
* @returns {string} PascalCase string
|
|
137
|
+
*/
|
|
138
|
+
function toPascalCase(str) {
|
|
139
|
+
if (!str) return '';
|
|
140
|
+
return str.replace(/[^a-zA-Z0-9]/g, ' ').split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join('');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Converts a string to snake_case
|
|
145
|
+
* Useful for Rust identifiers and file names
|
|
146
|
+
*
|
|
147
|
+
* @param {string} str - Input string to convert
|
|
148
|
+
* @returns {string} snake_case string
|
|
149
|
+
*/
|
|
150
|
+
function toSnakeCase(str) {
|
|
151
|
+
if (!str) return '';
|
|
152
|
+
return str.toLowerCase().replace(/[^a-z0-9]/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Converts a string to camelCase
|
|
157
|
+
* Useful for JavaScript/TypeScript identifiers
|
|
158
|
+
*
|
|
159
|
+
* @param {string} str - Input string to convert
|
|
160
|
+
* @returns {string} camelCase string
|
|
161
|
+
*/
|
|
162
|
+
function toCamelCase(str) {
|
|
163
|
+
if (!str) return '';
|
|
164
|
+
const pascalCase = toPascalCase(str);
|
|
165
|
+
return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);
|
|
166
|
+
}
|
|
167
|
+
;// ../common/src/message-utils.js
|
|
168
|
+
/**
|
|
169
|
+
* Message processing utilities for AsyncAPI template generation
|
|
170
|
+
*
|
|
171
|
+
* This module provides functions for extracting and processing message information
|
|
172
|
+
* from AsyncAPI specifications, handling various AsyncAPI versions and formats.
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Gets the message type name from a message object
|
|
179
|
+
*
|
|
180
|
+
* @param {object} message - AsyncAPI message object
|
|
181
|
+
* @returns {string|null} Message type name or null if not found
|
|
182
|
+
*/
|
|
183
|
+
function getMessageTypeName(message) {
|
|
184
|
+
if (!message) return null;
|
|
185
|
+
try {
|
|
186
|
+
// Try AsyncAPI 3.x format first - check _meta and _json properties
|
|
187
|
+
if (message._meta && message._meta.id) {
|
|
188
|
+
return message._meta.id;
|
|
189
|
+
}
|
|
190
|
+
if (message._json && message._json['x-parser-message-name']) {
|
|
191
|
+
return message._json['x-parser-message-name'];
|
|
192
|
+
}
|
|
193
|
+
if (message._json && message._json['x-parser-unique-object-id']) {
|
|
194
|
+
return message._json['x-parser-unique-object-id'];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Try different ways to get the message name
|
|
198
|
+
if (message.name && typeof message.name === 'function') {
|
|
199
|
+
return message.name();
|
|
200
|
+
}
|
|
201
|
+
if (message.name && typeof message.name === 'string') {
|
|
202
|
+
return message.name;
|
|
203
|
+
}
|
|
204
|
+
if (message.title && typeof message.title === 'function') {
|
|
205
|
+
return message.title();
|
|
206
|
+
}
|
|
207
|
+
if (message.title && typeof message.title === 'string') {
|
|
208
|
+
return message.title;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Try to extract from $ref
|
|
212
|
+
if (message.$ref) {
|
|
213
|
+
return message.$ref.split('/').pop();
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
} catch (e) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Gets the proper Rust type name from a message
|
|
223
|
+
*
|
|
224
|
+
* @param {object} message - AsyncAPI message object
|
|
225
|
+
* @returns {string} Rust type name
|
|
226
|
+
*/
|
|
227
|
+
function getMessageRustTypeName(message) {
|
|
228
|
+
const messageName = getMessageTypeName(message);
|
|
229
|
+
return messageName ? toRustTypeName(messageName) : 'UnknownMessage';
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Gets the payload component schema Rust type name from a message
|
|
234
|
+
* This extracts the actual payload type (component schema) rather than the message wrapper
|
|
235
|
+
*
|
|
236
|
+
* @param {object} message - AsyncAPI message object
|
|
237
|
+
* @returns {string} Rust type name for the payload component schema
|
|
238
|
+
*/
|
|
239
|
+
function getPayloadRustTypeName(message) {
|
|
240
|
+
if (!message) return 'UnknownPayload';
|
|
241
|
+
try {
|
|
242
|
+
// First priority: For inline message schemas, get the message name itself
|
|
243
|
+
// This handles cases where the message is defined inline in channels
|
|
244
|
+
const messageName = getMessageTypeName(message);
|
|
245
|
+
if (messageName) {
|
|
246
|
+
// Check if this is a component message reference (has payload.$ref)
|
|
247
|
+
let payload = null;
|
|
248
|
+
if (message.payload && typeof message.payload === 'function') {
|
|
249
|
+
payload = message.payload();
|
|
250
|
+
} else if (message.payload) {
|
|
251
|
+
payload = message.payload;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Check the message's _json for payload information
|
|
255
|
+
const messageJson = message._json || message;
|
|
256
|
+
if (!payload && messageJson.payload) {
|
|
257
|
+
payload = messageJson.payload;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// If payload has a $ref, this is a component message - extract the schema name
|
|
261
|
+
if (payload && payload.$ref) {
|
|
262
|
+
const refParts = payload.$ref.split('/');
|
|
263
|
+
const schemaName = refParts[refParts.length - 1];
|
|
264
|
+
return toRustTypeName(schemaName);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// For inline message schemas, use the message name directly as the payload type
|
|
268
|
+
// This is the correct approach for messages defined inline in channels
|
|
269
|
+
return toRustTypeName(messageName);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Second priority: Try to get the payload schema reference from the message
|
|
273
|
+
let payload = null;
|
|
274
|
+
|
|
275
|
+
// Try different ways to access the payload
|
|
276
|
+
if (message.payload && typeof message.payload === 'function') {
|
|
277
|
+
payload = message.payload();
|
|
278
|
+
} else if (message.payload) {
|
|
279
|
+
payload = message.payload;
|
|
280
|
+
}
|
|
281
|
+
if (payload) {
|
|
282
|
+
// Check for $ref in the payload (direct reference to component schema)
|
|
283
|
+
if (payload.$ref) {
|
|
284
|
+
const refParts = payload.$ref.split('/');
|
|
285
|
+
const schemaName = refParts[refParts.length - 1];
|
|
286
|
+
return toRustTypeName(schemaName);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Check for resolved $ref using x-parser-schema-id
|
|
290
|
+
if (payload['x-parser-schema-id']) {
|
|
291
|
+
return toRustTypeName(payload['x-parser-schema-id']);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Check for x-parser-schema-id in _json
|
|
295
|
+
if (payload._json && payload._json['x-parser-schema-id']) {
|
|
296
|
+
return toRustTypeName(payload._json['x-parser-schema-id']);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Check for title or name in the payload schema
|
|
300
|
+
if (payload.title) {
|
|
301
|
+
const title = typeof payload.title === 'function' ? payload.title() : payload.title;
|
|
302
|
+
if (title) return toRustTypeName(title);
|
|
303
|
+
}
|
|
304
|
+
if (payload.name) {
|
|
305
|
+
const name = typeof payload.name === 'function' ? payload.name() : payload.name;
|
|
306
|
+
if (name) return toRustTypeName(name);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Check the message's _json for payload information
|
|
311
|
+
const messageJson = message._json || message;
|
|
312
|
+
if (messageJson.payload) {
|
|
313
|
+
if (messageJson.payload.$ref) {
|
|
314
|
+
const refParts = messageJson.payload.$ref.split('/');
|
|
315
|
+
const schemaName = refParts[refParts.length - 1];
|
|
316
|
+
return toRustTypeName(schemaName);
|
|
317
|
+
}
|
|
318
|
+
if (messageJson.payload['x-parser-schema-id']) {
|
|
319
|
+
return toRustTypeName(messageJson.payload['x-parser-schema-id']);
|
|
320
|
+
}
|
|
321
|
+
if (messageJson.payload.title) {
|
|
322
|
+
return toRustTypeName(messageJson.payload.title);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Final fallback: try to extract from message title or name directly
|
|
327
|
+
if (message.title && typeof message.title === 'function') {
|
|
328
|
+
const title = message.title();
|
|
329
|
+
if (title && typeof title === 'string') {
|
|
330
|
+
return toRustTypeName(title);
|
|
331
|
+
}
|
|
332
|
+
} else if (message.title && typeof message.title === 'string') {
|
|
333
|
+
return toRustTypeName(message.title);
|
|
334
|
+
}
|
|
335
|
+
if (message.name && typeof message.name === 'function') {
|
|
336
|
+
const name = message.name();
|
|
337
|
+
if (name && typeof name === 'string') {
|
|
338
|
+
return toRustTypeName(name);
|
|
339
|
+
}
|
|
340
|
+
} else if (message.name && typeof message.name === 'string') {
|
|
341
|
+
return toRustTypeName(message.name);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Check message._json for title/name
|
|
345
|
+
if (messageJson.title && typeof messageJson.title === 'string') {
|
|
346
|
+
return toRustTypeName(messageJson.title);
|
|
347
|
+
}
|
|
348
|
+
if (messageJson.name && typeof messageJson.name === 'string') {
|
|
349
|
+
return toRustTypeName(messageJson.name);
|
|
350
|
+
}
|
|
351
|
+
return 'UnknownPayload';
|
|
352
|
+
} catch (e) {
|
|
353
|
+
console.warn('Error extracting payload type name:', e.message);
|
|
354
|
+
return 'UnknownPayload';
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Gets the TypeScript type name from a message for TypeScript templates
|
|
360
|
+
*
|
|
361
|
+
* @param {object} message - AsyncAPI message object
|
|
362
|
+
* @returns {string} TypeScript type name
|
|
363
|
+
*/
|
|
364
|
+
function getMessageTypeScriptTypeName(message) {
|
|
365
|
+
const messageName = getMessageTypeName(message);
|
|
366
|
+
if (!messageName) return 'UnknownMessage';
|
|
367
|
+
|
|
368
|
+
// Convert to PascalCase for TypeScript interfaces
|
|
369
|
+
return messageName.split(/[-_\s]+/).map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Gets the payload TypeScript type name from a message
|
|
374
|
+
*
|
|
375
|
+
* @param {object} message - AsyncAPI message object
|
|
376
|
+
* @returns {string} TypeScript type name for the payload
|
|
377
|
+
*/
|
|
378
|
+
function getPayloadTypeScriptTypeName(message) {
|
|
379
|
+
if (!message) return 'unknown';
|
|
380
|
+
try {
|
|
381
|
+
// Similar logic to getPayloadRustTypeName but for TypeScript naming
|
|
382
|
+
const messageName = getMessageTypeName(message);
|
|
383
|
+
if (messageName) {
|
|
384
|
+
let payload = null;
|
|
385
|
+
if (message.payload && typeof message.payload === 'function') {
|
|
386
|
+
payload = message.payload();
|
|
387
|
+
} else if (message.payload) {
|
|
388
|
+
payload = message.payload;
|
|
389
|
+
}
|
|
390
|
+
const messageJson = message._json || message;
|
|
391
|
+
if (!payload && messageJson.payload) {
|
|
392
|
+
payload = messageJson.payload;
|
|
393
|
+
}
|
|
394
|
+
if (payload && payload.$ref) {
|
|
395
|
+
const refParts = payload.$ref.split('/');
|
|
396
|
+
const schemaName = refParts[refParts.length - 1];
|
|
397
|
+
return schemaName.split(/[-_\s]+/).map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
398
|
+
}
|
|
399
|
+
return messageName.split(/[-_\s]+/).map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join('');
|
|
400
|
+
}
|
|
401
|
+
return 'unknown';
|
|
402
|
+
} catch (e) {
|
|
403
|
+
console.warn('Error extracting TypeScript payload type name:', e.message);
|
|
404
|
+
return 'unknown';
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Checks if a message has a payload schema defined
|
|
410
|
+
*
|
|
411
|
+
* @param {object} message - AsyncAPI message object
|
|
412
|
+
* @returns {boolean} True if message has a payload schema
|
|
413
|
+
*/
|
|
414
|
+
function messageHasPayload(message) {
|
|
415
|
+
if (!message) return false;
|
|
416
|
+
try {
|
|
417
|
+
// Check for payload function
|
|
418
|
+
if (message.payload && typeof message.payload === 'function') {
|
|
419
|
+
const payload = message.payload();
|
|
420
|
+
return payload !== null && payload !== undefined;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Check for payload property
|
|
424
|
+
if (message.payload) {
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Check _json for payload
|
|
429
|
+
const messageJson = message._json || message;
|
|
430
|
+
return !!messageJson.payload;
|
|
431
|
+
} catch (e) {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Gets the content type of a message
|
|
438
|
+
*
|
|
439
|
+
* @param {object} message - AsyncAPI message object
|
|
440
|
+
* @returns {string} Content type (e.g., 'application/json')
|
|
441
|
+
*/
|
|
442
|
+
function getMessageContentType(message) {
|
|
443
|
+
if (!message) return 'application/json';
|
|
444
|
+
try {
|
|
445
|
+
// Check for contentType function
|
|
446
|
+
if (message.contentType && typeof message.contentType === 'function') {
|
|
447
|
+
return message.contentType() || 'application/json';
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Check for contentType property
|
|
451
|
+
if (message.contentType) {
|
|
452
|
+
return message.contentType;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Check _json for contentType
|
|
456
|
+
const messageJson = message._json || message;
|
|
457
|
+
if (messageJson.contentType) {
|
|
458
|
+
return messageJson.contentType;
|
|
459
|
+
}
|
|
460
|
+
return 'application/json';
|
|
461
|
+
} catch (e) {
|
|
462
|
+
return 'application/json';
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
;// ../common/src/channel-utils.js
|
|
466
|
+
/**
|
|
467
|
+
* Channel processing utilities for AsyncAPI template generation
|
|
468
|
+
*
|
|
469
|
+
* This module provides functions for handling channels, parameters, and
|
|
470
|
+
* dynamic channel address resolution across different AsyncAPI templates.
|
|
471
|
+
*/
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Gets the NATS subject from a channel address
|
|
477
|
+
*
|
|
478
|
+
* @param {object} channel - AsyncAPI channel object
|
|
479
|
+
* @returns {string} NATS subject
|
|
480
|
+
*/
|
|
481
|
+
function getNatsSubject(channel) {
|
|
482
|
+
try {
|
|
483
|
+
if (channel.address && typeof channel.address === 'function') {
|
|
484
|
+
return channel.address();
|
|
485
|
+
} else if (channel.address) {
|
|
486
|
+
return channel.address;
|
|
487
|
+
} else if (channel.id && typeof channel.id === 'function') {
|
|
488
|
+
return channel.id();
|
|
489
|
+
} else if (channel.id) {
|
|
490
|
+
return channel.id;
|
|
491
|
+
}
|
|
492
|
+
return 'unknown.subject';
|
|
493
|
+
} catch (e) {
|
|
494
|
+
return 'unknown.subject';
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Gets the channel address from a channel object
|
|
500
|
+
* This is a more generic version of getNatsSubject that works for any protocol
|
|
501
|
+
*
|
|
502
|
+
* @param {object} channel - AsyncAPI channel object
|
|
503
|
+
* @returns {string} Channel address
|
|
504
|
+
*/
|
|
505
|
+
function getChannelAddress(channel) {
|
|
506
|
+
try {
|
|
507
|
+
if (channel.address && typeof channel.address === 'function') {
|
|
508
|
+
return channel.address();
|
|
509
|
+
} else if (channel.address) {
|
|
510
|
+
return channel.address;
|
|
511
|
+
} else if (channel.id && typeof channel.id === 'function') {
|
|
512
|
+
return channel.id();
|
|
513
|
+
} else if (channel.id) {
|
|
514
|
+
return channel.id;
|
|
515
|
+
}
|
|
516
|
+
return 'unknown.address';
|
|
517
|
+
} catch (e) {
|
|
518
|
+
return 'unknown.address';
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Checks if a channel address contains variables (dynamic channel)
|
|
524
|
+
*
|
|
525
|
+
* @param {string} address - Channel address
|
|
526
|
+
* @returns {boolean} True if the address contains variables
|
|
527
|
+
*/
|
|
528
|
+
function isDynamicChannel(address) {
|
|
529
|
+
if (!address || typeof address !== 'string') return false;
|
|
530
|
+
return /\{[^}]+\}/.test(address);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Extracts variable names from a channel address
|
|
535
|
+
*
|
|
536
|
+
* @param {string} address - Channel address with variables
|
|
537
|
+
* @returns {Array<string>} Array of variable names
|
|
538
|
+
*/
|
|
539
|
+
function extractChannelVariables(address) {
|
|
540
|
+
if (!address || typeof address !== 'string') return [];
|
|
541
|
+
const matches = address.match(/\{([^}]+)\}/g);
|
|
542
|
+
if (!matches) return [];
|
|
543
|
+
return matches.map(match => match.slice(1, -1)); // Remove { and }
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Extracts channel parameters from a dynamic channel address
|
|
548
|
+
*
|
|
549
|
+
* @param {string} channelAddress - Channel address like "device.{device_id}" or "user.{user_id}.notifications"
|
|
550
|
+
* @returns {Array} Array of parameter objects with name and rustName
|
|
551
|
+
*/
|
|
552
|
+
function extractChannelParameters(channelAddress) {
|
|
553
|
+
if (!channelAddress) return [];
|
|
554
|
+
const parameterRegex = /\{([^}]+)\}/g;
|
|
555
|
+
const parameters = [];
|
|
556
|
+
let match;
|
|
557
|
+
while ((match = parameterRegex.exec(channelAddress)) !== null) {
|
|
558
|
+
const paramName = match[1];
|
|
559
|
+
parameters.push({
|
|
560
|
+
name: paramName,
|
|
561
|
+
rustName: toRustFieldName(paramName),
|
|
562
|
+
placeholder: match[0] // The full {param_name} string
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
return parameters;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Gets channel parameters from a channel object
|
|
570
|
+
*
|
|
571
|
+
* @param {object} channel - AsyncAPI channel object
|
|
572
|
+
* @returns {Array<object>} Array of parameter objects with name and description
|
|
573
|
+
*/
|
|
574
|
+
function getChannelParameters(channel) {
|
|
575
|
+
try {
|
|
576
|
+
const parameters = [];
|
|
577
|
+
|
|
578
|
+
// Try to get parameters from the channel
|
|
579
|
+
let channelParams = null;
|
|
580
|
+
if (channel.parameters && typeof channel.parameters === 'function') {
|
|
581
|
+
channelParams = channel.parameters();
|
|
582
|
+
} else if (channel.parameters) {
|
|
583
|
+
channelParams = channel.parameters;
|
|
584
|
+
} else if (channel._json && channel._json.parameters) {
|
|
585
|
+
channelParams = channel._json.parameters;
|
|
586
|
+
}
|
|
587
|
+
if (channelParams) {
|
|
588
|
+
// Handle different parameter formats
|
|
589
|
+
if (typeof channelParams === 'object') {
|
|
590
|
+
for (const [paramName, paramDef] of Object.entries(channelParams)) {
|
|
591
|
+
// Skip internal AsyncAPI parser properties
|
|
592
|
+
if (paramName.startsWith('_') || paramName === 'collections' || paramName === 'meta') {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
let description = 'Channel parameter';
|
|
596
|
+
if (paramDef && typeof paramDef === 'object') {
|
|
597
|
+
if (typeof paramDef.description === 'string') {
|
|
598
|
+
description = paramDef.description;
|
|
599
|
+
} else if (typeof paramDef.description === 'function') {
|
|
600
|
+
try {
|
|
601
|
+
description = paramDef.description();
|
|
602
|
+
} catch (e) {
|
|
603
|
+
description = 'Channel parameter';
|
|
604
|
+
}
|
|
605
|
+
} else if (paramDef._json && paramDef._json.description) {
|
|
606
|
+
description = paramDef._json.description;
|
|
607
|
+
}
|
|
608
|
+
} else if (typeof paramDef === 'string') {
|
|
609
|
+
description = paramDef;
|
|
610
|
+
}
|
|
611
|
+
parameters.push({
|
|
612
|
+
name: paramName,
|
|
613
|
+
description: description,
|
|
614
|
+
rustName: toRustFieldName(paramName),
|
|
615
|
+
rustType: 'String' // For now, assume all parameters are strings
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return parameters;
|
|
621
|
+
} catch (e) {
|
|
622
|
+
console.warn('Error extracting channel parameters:', e.message);
|
|
623
|
+
return [];
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Resolves a dynamic channel address with provided variable values
|
|
629
|
+
*
|
|
630
|
+
* @param {string} address - Channel address template with variables
|
|
631
|
+
* @param {object} variables - Object mapping variable names to values
|
|
632
|
+
* @returns {string} Resolved channel address
|
|
633
|
+
*/
|
|
634
|
+
function resolveChannelAddress(address, variables) {
|
|
635
|
+
if (!address || typeof address !== 'string') return address;
|
|
636
|
+
if (!variables || typeof variables !== 'object') return address;
|
|
637
|
+
let resolved = address;
|
|
638
|
+
for (const [varName, varValue] of Object.entries(variables)) {
|
|
639
|
+
const placeholder = `{${varName}}`;
|
|
640
|
+
resolved = resolved.replace(new RegExp(placeholder.replace(/[{}]/g, '\\$&'), 'g'), varValue);
|
|
641
|
+
}
|
|
642
|
+
return resolved;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/**
|
|
646
|
+
* Checks if a channel has dynamic parameters
|
|
647
|
+
*
|
|
648
|
+
* @param {object} channel - AsyncAPI channel object
|
|
649
|
+
* @returns {boolean} True if the channel has parameters
|
|
650
|
+
*/
|
|
651
|
+
function channelHasParameters(channel) {
|
|
652
|
+
const address = getChannelAddress(channel);
|
|
653
|
+
return isDynamicChannel(address);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Generates Rust function parameters for dynamic channel parameters
|
|
658
|
+
*
|
|
659
|
+
* @param {Array} channelParameters - Array of channel parameter objects
|
|
660
|
+
* @returns {string} Rust function parameter string
|
|
661
|
+
*/
|
|
662
|
+
function generateChannelParameterArgs(channelParameters) {
|
|
663
|
+
if (!channelParameters || channelParameters.length === 0) {
|
|
664
|
+
return '';
|
|
665
|
+
}
|
|
666
|
+
return channelParameters.map(param => `${param.rustName}: String`).join(', ') + ', ';
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Generates Rust format string and arguments for dynamic channel resolution
|
|
671
|
+
*
|
|
672
|
+
* @param {string} channelAddress - Original channel address with parameters
|
|
673
|
+
* @param {Array} channelParameters - Array of channel parameter objects
|
|
674
|
+
* @returns {object} Object with formatString and formatArgs
|
|
675
|
+
*/
|
|
676
|
+
function generateChannelFormatting(channelAddress, channelParameters) {
|
|
677
|
+
if (!channelParameters || channelParameters.length === 0) {
|
|
678
|
+
return {
|
|
679
|
+
formatString: `"${channelAddress}".to_string()`,
|
|
680
|
+
formatArgs: ''
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Replace parameter placeholders with format placeholders
|
|
685
|
+
let formatString = channelAddress;
|
|
686
|
+
const formatArgs = [];
|
|
687
|
+
for (const param of channelParameters) {
|
|
688
|
+
formatString = formatString.replace(param.placeholder, '{}');
|
|
689
|
+
formatArgs.push(param.rustName);
|
|
690
|
+
}
|
|
691
|
+
return {
|
|
692
|
+
formatString: `format!("${formatString}", ${formatArgs.join(', ')})`,
|
|
693
|
+
formatArgs: formatArgs.join(', ')
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Generates TypeScript function parameters for dynamic channel parameters
|
|
699
|
+
*
|
|
700
|
+
* @param {Array} channelParameters - Array of channel parameter objects
|
|
701
|
+
* @returns {string} TypeScript function parameter string
|
|
702
|
+
*/
|
|
703
|
+
function generateTypeScriptChannelParameterArgs(channelParameters) {
|
|
704
|
+
if (!channelParameters || channelParameters.length === 0) {
|
|
705
|
+
return '';
|
|
706
|
+
}
|
|
707
|
+
return channelParameters.map(param => `${param.name}: string`).join(', ') + ', ';
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Generates TypeScript template literal for dynamic channel resolution
|
|
712
|
+
*
|
|
713
|
+
* @param {string} channelAddress - Original channel address with parameters
|
|
714
|
+
* @param {Array} channelParameters - Array of channel parameter objects
|
|
715
|
+
* @returns {string} TypeScript template literal string
|
|
716
|
+
*/
|
|
717
|
+
function generateTypeScriptChannelFormatting(channelAddress, channelParameters) {
|
|
718
|
+
if (!channelParameters || channelParameters.length === 0) {
|
|
719
|
+
return `'${channelAddress}'`;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// Replace parameter placeholders with template literal placeholders
|
|
723
|
+
let templateString = channelAddress;
|
|
724
|
+
for (const param of channelParameters) {
|
|
725
|
+
templateString = templateString.replace(param.placeholder, `\${${param.name}}`);
|
|
726
|
+
}
|
|
727
|
+
return `\`${templateString}\``;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Extracts server name from a $ref string
|
|
732
|
+
*
|
|
733
|
+
* @param {string} serverRef - Server reference like "#/servers/mqtt-server"
|
|
734
|
+
* @returns {string|null} Server name or null if invalid
|
|
735
|
+
*/
|
|
736
|
+
function extractServerNameFromRef(serverRef) {
|
|
737
|
+
if (!serverRef || typeof serverRef !== 'string') return null;
|
|
738
|
+
|
|
739
|
+
// Handle $ref format: "#/servers/server-name"
|
|
740
|
+
const refMatch = serverRef.match(/^#\/servers\/(.+)$/);
|
|
741
|
+
if (refMatch) {
|
|
742
|
+
return refMatch[1];
|
|
743
|
+
}
|
|
744
|
+
return null;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Analyzes channel server restrictions from AsyncAPI specification
|
|
749
|
+
*
|
|
750
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
751
|
+
* @returns {Array} Array of channel server mapping objects
|
|
752
|
+
*/
|
|
753
|
+
function analyzeChannelServerMappings(asyncapi) {
|
|
754
|
+
const mappings = [];
|
|
755
|
+
try {
|
|
756
|
+
const channels = asyncapi.channels();
|
|
757
|
+
if (!channels) return mappings;
|
|
758
|
+
for (const channel of channels) {
|
|
759
|
+
const channelName = channel.id();
|
|
760
|
+
let allowedServers = null; // null means available on all servers
|
|
761
|
+
|
|
762
|
+
// Try to get servers from the channel object
|
|
763
|
+
let channelServers = null;
|
|
764
|
+
|
|
765
|
+
// Method 1: Try channel.servers() function
|
|
766
|
+
if (channel.servers && typeof channel.servers === 'function') {
|
|
767
|
+
try {
|
|
768
|
+
channelServers = channel.servers();
|
|
769
|
+
} catch (e) {
|
|
770
|
+
// Ignore errors and try other methods
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Method 2: Try channel._json.servers (raw JSON data)
|
|
775
|
+
if (!channelServers && channel._json && channel._json.servers) {
|
|
776
|
+
channelServers = channel._json.servers;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Method 3: Try direct property access
|
|
780
|
+
if (!channelServers && channel.servers && Array.isArray(channel.servers)) {
|
|
781
|
+
channelServers = channel.servers;
|
|
782
|
+
}
|
|
783
|
+
if (channelServers && Array.isArray(channelServers) && channelServers.length > 0) {
|
|
784
|
+
// Extract server names from $ref strings
|
|
785
|
+
allowedServers = [];
|
|
786
|
+
for (const serverRef of channelServers) {
|
|
787
|
+
let serverName = null;
|
|
788
|
+
|
|
789
|
+
// Handle different ways the server reference might be provided
|
|
790
|
+
if (typeof serverRef === 'string') {
|
|
791
|
+
serverName = extractServerNameFromRef(serverRef);
|
|
792
|
+
} else if (serverRef && serverRef.$ref) {
|
|
793
|
+
serverName = extractServerNameFromRef(serverRef.$ref);
|
|
794
|
+
} else if (serverRef && typeof serverRef.id === 'function') {
|
|
795
|
+
serverName = serverRef.id();
|
|
796
|
+
} else if (serverRef && typeof serverRef.id === 'string') {
|
|
797
|
+
serverName = serverRef.id;
|
|
798
|
+
}
|
|
799
|
+
if (serverName) {
|
|
800
|
+
allowedServers.push(serverName);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// If no valid server names were extracted, treat as available on all servers
|
|
805
|
+
if (allowedServers.length === 0) {
|
|
806
|
+
allowedServers = null;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
mappings.push({
|
|
810
|
+
channelName: channelName,
|
|
811
|
+
allowedServers: allowedServers,
|
|
812
|
+
rustChannelName: toRustIdentifier(channelName),
|
|
813
|
+
description: channel.description && channel.description() || ''
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
} catch (e) {
|
|
817
|
+
console.warn('Error analyzing channel server mappings:', e.message);
|
|
818
|
+
}
|
|
819
|
+
return mappings;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Checks if a channel is allowed on a specific server
|
|
824
|
+
*
|
|
825
|
+
* @param {string} channelName - Name of the channel
|
|
826
|
+
* @param {string} serverName - Name of the server
|
|
827
|
+
* @param {Array} channelMappings - Array of channel server mappings
|
|
828
|
+
* @returns {boolean} True if channel is allowed on the server
|
|
829
|
+
*/
|
|
830
|
+
function isChannelAllowedOnServer(channelName, serverName, channelMappings) {
|
|
831
|
+
const mapping = channelMappings.find(m => m.channelName === channelName);
|
|
832
|
+
if (!mapping) {
|
|
833
|
+
// If no mapping found, assume channel is allowed on all servers
|
|
834
|
+
return true;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// If allowedServers is null, channel is available on all servers
|
|
838
|
+
if (mapping.allowedServers === null) {
|
|
839
|
+
return true;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// Check if server is in the allowed list
|
|
843
|
+
return mapping.allowedServers.includes(serverName);
|
|
844
|
+
}
|
|
845
|
+
;// ../common/src/security-utils.js
|
|
846
|
+
/**
|
|
847
|
+
* Security analysis utilities for AsyncAPI template generation
|
|
848
|
+
*
|
|
849
|
+
* This module provides functions for analyzing security requirements and
|
|
850
|
+
* authentication schemes across different AsyncAPI templates.
|
|
851
|
+
*/
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Analyzes operation security requirements from AsyncAPI specification
|
|
855
|
+
*
|
|
856
|
+
* @param {object} operation - AsyncAPI operation object
|
|
857
|
+
* @returns {object} Security analysis result
|
|
858
|
+
*/
|
|
859
|
+
function analyzeOperationSecurity(operation) {
|
|
860
|
+
try {
|
|
861
|
+
// Check AsyncAPI security field
|
|
862
|
+
const security = operation.security && operation.security();
|
|
863
|
+
if (security && Array.isArray(security) && security.length > 0) {
|
|
864
|
+
return {
|
|
865
|
+
hasSecurityRequirements: true,
|
|
866
|
+
securitySchemes: security,
|
|
867
|
+
requiresAuthentication: true
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// Check if operation has security defined in AsyncAPI spec
|
|
872
|
+
const operationJson = operation._json || operation;
|
|
873
|
+
if (operationJson.security && Array.isArray(operationJson.security) && operationJson.security.length > 0) {
|
|
874
|
+
return {
|
|
875
|
+
hasSecurityRequirements: true,
|
|
876
|
+
securitySchemes: operationJson.security,
|
|
877
|
+
requiresAuthentication: true
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
hasSecurityRequirements: false,
|
|
882
|
+
securitySchemes: [],
|
|
883
|
+
requiresAuthentication: false
|
|
884
|
+
};
|
|
885
|
+
} catch (e) {
|
|
886
|
+
return {
|
|
887
|
+
hasSecurityRequirements: false,
|
|
888
|
+
securitySchemes: [],
|
|
889
|
+
requiresAuthentication: false
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* Checks if an operation has security requirements
|
|
896
|
+
*
|
|
897
|
+
* @param {object} operation - AsyncAPI operation object
|
|
898
|
+
* @returns {boolean} True if operation has security requirements
|
|
899
|
+
*/
|
|
900
|
+
function operationHasSecurity(operation) {
|
|
901
|
+
const analysis = analyzeOperationSecurity(operation);
|
|
902
|
+
return analysis.hasSecurityRequirements;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Alias for operationHasSecurity for TypeScript templates
|
|
907
|
+
*
|
|
908
|
+
* @param {object} operation - AsyncAPI operation object
|
|
909
|
+
* @returns {boolean} True if operation requires authentication
|
|
910
|
+
*/
|
|
911
|
+
function operationRequiresAuth(operation) {
|
|
912
|
+
return operationHasSecurity(operation);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Checks if the AsyncAPI specification has security schemes defined
|
|
917
|
+
*
|
|
918
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
919
|
+
* @param {boolean} enableAuth - Whether auth feature is enabled (optional, defaults to true)
|
|
920
|
+
* @returns {boolean} True if security schemes are present and auth is enabled
|
|
921
|
+
*/
|
|
922
|
+
function hasSecuritySchemes(asyncapi, enableAuth = true) {
|
|
923
|
+
if (!enableAuth) return false;
|
|
924
|
+
try {
|
|
925
|
+
const components = asyncapi.components();
|
|
926
|
+
if (!components) return false;
|
|
927
|
+
const securitySchemes = components.securitySchemes();
|
|
928
|
+
return securitySchemes && Object.keys(securitySchemes).length > 0;
|
|
929
|
+
} catch (e) {
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Get security scheme type from AsyncAPI security scheme definition
|
|
936
|
+
*
|
|
937
|
+
* @param {object} securityScheme - AsyncAPI security scheme object
|
|
938
|
+
* @returns {string} Security scheme type ('jwt', 'basic', 'apikey', etc.)
|
|
939
|
+
*/
|
|
940
|
+
function getSecuritySchemeType(securityScheme) {
|
|
941
|
+
try {
|
|
942
|
+
if (securityScheme.type && typeof securityScheme.type === 'function') {
|
|
943
|
+
return securityScheme.type();
|
|
944
|
+
}
|
|
945
|
+
if (securityScheme.type) {
|
|
946
|
+
return securityScheme.type;
|
|
947
|
+
}
|
|
948
|
+
if (securityScheme._json && securityScheme._json.type) {
|
|
949
|
+
return securityScheme._json.type;
|
|
950
|
+
}
|
|
951
|
+
return 'unknown';
|
|
952
|
+
} catch (e) {
|
|
953
|
+
return 'unknown';
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Gets the security scheme name from a security scheme object
|
|
959
|
+
*
|
|
960
|
+
* @param {object} securityScheme - AsyncAPI security scheme object
|
|
961
|
+
* @returns {string} Security scheme name
|
|
962
|
+
*/
|
|
963
|
+
function getSecuritySchemeName(securityScheme) {
|
|
964
|
+
try {
|
|
965
|
+
if (securityScheme.name && typeof securityScheme.name === 'function') {
|
|
966
|
+
return securityScheme.name();
|
|
967
|
+
}
|
|
968
|
+
if (securityScheme.name) {
|
|
969
|
+
return securityScheme.name;
|
|
970
|
+
}
|
|
971
|
+
if (securityScheme._json && securityScheme._json.name) {
|
|
972
|
+
return securityScheme._json.name;
|
|
973
|
+
}
|
|
974
|
+
return 'unknown';
|
|
975
|
+
} catch (e) {
|
|
976
|
+
return 'unknown';
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/**
|
|
981
|
+
* Gets the security scheme location (header, query, cookie) for API key schemes
|
|
982
|
+
*
|
|
983
|
+
* @param {object} securityScheme - AsyncAPI security scheme object
|
|
984
|
+
* @returns {string} Security scheme location ('header', 'query', 'cookie')
|
|
985
|
+
*/
|
|
986
|
+
function getSecuritySchemeLocation(securityScheme) {
|
|
987
|
+
try {
|
|
988
|
+
if (securityScheme.in && typeof securityScheme.in === 'function') {
|
|
989
|
+
return securityScheme.in();
|
|
990
|
+
}
|
|
991
|
+
if (securityScheme.in) {
|
|
992
|
+
return securityScheme.in;
|
|
993
|
+
}
|
|
994
|
+
if (securityScheme._json && securityScheme._json.in) {
|
|
995
|
+
return securityScheme._json.in;
|
|
996
|
+
}
|
|
997
|
+
return 'header'; // Default to header
|
|
998
|
+
} catch (e) {
|
|
999
|
+
return 'header';
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Extract security requirements for all operations in the AsyncAPI spec
|
|
1005
|
+
*
|
|
1006
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1007
|
+
* @returns {object} Map of operation names to their security requirements
|
|
1008
|
+
*/
|
|
1009
|
+
function extractOperationSecurityMap(asyncapi) {
|
|
1010
|
+
const securityMap = {};
|
|
1011
|
+
try {
|
|
1012
|
+
const operations = asyncapi.operations && asyncapi.operations();
|
|
1013
|
+
if (operations) {
|
|
1014
|
+
// Handle AsyncAPI parser collection - use .all() method to get array
|
|
1015
|
+
const operationArray = operations.all ? operations.all() : Object.values(operations);
|
|
1016
|
+
operationArray.forEach(operation => {
|
|
1017
|
+
// Get operation ID
|
|
1018
|
+
let operationId = null;
|
|
1019
|
+
if (operation._meta && operation._meta.id) {
|
|
1020
|
+
operationId = operation._meta.id;
|
|
1021
|
+
} else if (operation.id && typeof operation.id === 'function') {
|
|
1022
|
+
operationId = operation.id();
|
|
1023
|
+
} else if (operation.id) {
|
|
1024
|
+
operationId = operation.id;
|
|
1025
|
+
}
|
|
1026
|
+
if (operationId) {
|
|
1027
|
+
const securityAnalysis = analyzeOperationSecurity(operation);
|
|
1028
|
+
securityMap[operationId] = securityAnalysis;
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
} catch (e) {
|
|
1033
|
+
console.warn('Error extracting operation security map:', e.message);
|
|
1034
|
+
}
|
|
1035
|
+
return securityMap;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Gets all security schemes from the AsyncAPI specification
|
|
1040
|
+
*
|
|
1041
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1042
|
+
* @returns {object} Map of security scheme names to their definitions
|
|
1043
|
+
*/
|
|
1044
|
+
function getAllSecuritySchemes(asyncapi) {
|
|
1045
|
+
try {
|
|
1046
|
+
const components = asyncapi.components();
|
|
1047
|
+
if (!components) return {};
|
|
1048
|
+
const securitySchemes = components.securitySchemes();
|
|
1049
|
+
if (!securitySchemes) return {};
|
|
1050
|
+
|
|
1051
|
+
// Convert to plain object if it's a collection
|
|
1052
|
+
if (typeof securitySchemes === 'object' && securitySchemes.all) {
|
|
1053
|
+
const schemes = {};
|
|
1054
|
+
const schemeArray = securitySchemes.all();
|
|
1055
|
+
schemeArray.forEach(scheme => {
|
|
1056
|
+
const name = scheme.id ? scheme.id() : 'unknown';
|
|
1057
|
+
schemes[name] = scheme;
|
|
1058
|
+
});
|
|
1059
|
+
return schemes;
|
|
1060
|
+
}
|
|
1061
|
+
return securitySchemes;
|
|
1062
|
+
} catch (e) {
|
|
1063
|
+
console.warn('Error extracting security schemes:', e.message);
|
|
1064
|
+
return {};
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Checks if a security scheme is of a specific type
|
|
1070
|
+
*
|
|
1071
|
+
* @param {object} securityScheme - AsyncAPI security scheme object
|
|
1072
|
+
* @param {string} expectedType - Expected security scheme type
|
|
1073
|
+
* @returns {boolean} True if the scheme matches the expected type
|
|
1074
|
+
*/
|
|
1075
|
+
function isSecuritySchemeType(securityScheme, expectedType) {
|
|
1076
|
+
const actualType = getSecuritySchemeType(securityScheme);
|
|
1077
|
+
return actualType.toLowerCase() === expectedType.toLowerCase();
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
/**
|
|
1081
|
+
* Gets the default port for a given protocol
|
|
1082
|
+
*
|
|
1083
|
+
* @param {string} protocol - Protocol name
|
|
1084
|
+
* @returns {number} Default port number
|
|
1085
|
+
*/
|
|
1086
|
+
function getDefaultPort(protocol) {
|
|
1087
|
+
switch (protocol === null || protocol === void 0 ? void 0 : protocol.toLowerCase()) {
|
|
1088
|
+
case 'http':
|
|
1089
|
+
return 80;
|
|
1090
|
+
case 'https':
|
|
1091
|
+
return 443;
|
|
1092
|
+
case 'ws':
|
|
1093
|
+
case 'websocket':
|
|
1094
|
+
return 80;
|
|
1095
|
+
case 'wss':
|
|
1096
|
+
case 'websockets':
|
|
1097
|
+
return 443;
|
|
1098
|
+
case 'mqtt':
|
|
1099
|
+
return 1883;
|
|
1100
|
+
case 'mqtts':
|
|
1101
|
+
return 8883;
|
|
1102
|
+
case 'amqp':
|
|
1103
|
+
return 5672;
|
|
1104
|
+
case 'amqps':
|
|
1105
|
+
return 5671;
|
|
1106
|
+
case 'kafka':
|
|
1107
|
+
return 9092;
|
|
1108
|
+
case 'nats':
|
|
1109
|
+
return 4222;
|
|
1110
|
+
default:
|
|
1111
|
+
return 8080;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Validates that all server references in channels exist in the servers section
|
|
1117
|
+
*
|
|
1118
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1119
|
+
* @returns {object} Validation result with errors if any
|
|
1120
|
+
*/
|
|
1121
|
+
function validateChannelServerReferences(asyncapi) {
|
|
1122
|
+
const result = {
|
|
1123
|
+
valid: true,
|
|
1124
|
+
errors: []
|
|
1125
|
+
};
|
|
1126
|
+
try {
|
|
1127
|
+
// Try multiple ways to get servers
|
|
1128
|
+
let servers = null;
|
|
1129
|
+
let serverNames = [];
|
|
1130
|
+
|
|
1131
|
+
// Method 1: Try asyncapi.servers() function
|
|
1132
|
+
if (asyncapi.servers && typeof asyncapi.servers === 'function') {
|
|
1133
|
+
try {
|
|
1134
|
+
servers = asyncapi.servers();
|
|
1135
|
+
if (servers) {
|
|
1136
|
+
// Check if this is a collection object (has iterator methods)
|
|
1137
|
+
if (typeof servers[Symbol.iterator] === 'function') {
|
|
1138
|
+
// It's iterable - iterate through the servers
|
|
1139
|
+
serverNames = [];
|
|
1140
|
+
for (const server of servers) {
|
|
1141
|
+
const serverName = server.id && typeof server.id === 'function' ? server.id() : server.id;
|
|
1142
|
+
if (serverName) {
|
|
1143
|
+
serverNames.push(serverName);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
} else {
|
|
1147
|
+
// It's a plain object - use Object.keys
|
|
1148
|
+
serverNames = Object.keys(servers);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
} catch (e) {
|
|
1152
|
+
// Ignore and try other methods
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// Method 2: Try asyncapi._json.servers (raw JSON data)
|
|
1157
|
+
if (serverNames.length === 0 && asyncapi._json && asyncapi._json.servers) {
|
|
1158
|
+
servers = asyncapi._json.servers;
|
|
1159
|
+
serverNames = Object.keys(servers);
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// Method 3: Try direct property access
|
|
1163
|
+
if (serverNames.length === 0 && asyncapi.servers && typeof asyncapi.servers === 'object') {
|
|
1164
|
+
servers = asyncapi.servers;
|
|
1165
|
+
serverNames = Object.keys(servers);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// Method 4: Try json() method if available
|
|
1169
|
+
if (serverNames.length === 0 && asyncapi.json && typeof asyncapi.json === 'function') {
|
|
1170
|
+
try {
|
|
1171
|
+
const jsonDoc = asyncapi.json();
|
|
1172
|
+
if (jsonDoc && jsonDoc.servers) {
|
|
1173
|
+
servers = jsonDoc.servers;
|
|
1174
|
+
serverNames = Object.keys(servers);
|
|
1175
|
+
}
|
|
1176
|
+
} catch (e) {
|
|
1177
|
+
// Ignore and try other methods
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// Note: We'll skip channel validation here to avoid circular dependency
|
|
1182
|
+
// This function can be enhanced later if needed
|
|
1183
|
+
console.warn('Channel server validation skipped to avoid circular dependency');
|
|
1184
|
+
} catch (e) {
|
|
1185
|
+
result.valid = false;
|
|
1186
|
+
result.errors.push({
|
|
1187
|
+
message: `Error validating channel server references: ${e.message}`
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
return result;
|
|
1191
|
+
}
|
|
1192
|
+
;// ../common/src/template-utils.js
|
|
1193
|
+
/**
|
|
1194
|
+
* Template parameter utilities for AsyncAPI template generation
|
|
1195
|
+
*
|
|
1196
|
+
* This module provides functions for handling template parameters and
|
|
1197
|
+
* common template operations across different AsyncAPI templates.
|
|
1198
|
+
*/
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Checks if a parameter contains unresolved template variables
|
|
1204
|
+
*
|
|
1205
|
+
* @param {string} value - Parameter value to check
|
|
1206
|
+
* @returns {boolean} True if the value contains template variables
|
|
1207
|
+
*/
|
|
1208
|
+
function isTemplateVariable(value) {
|
|
1209
|
+
return typeof value === 'string' && value.includes('{{') && value.includes('}}');
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* Extracts information from AsyncAPI specification with fallbacks
|
|
1214
|
+
*
|
|
1215
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1216
|
+
* @returns {object} Object with title, version, and description
|
|
1217
|
+
*/
|
|
1218
|
+
function extractAsyncApiInfo(asyncapi) {
|
|
1219
|
+
let title, version, description;
|
|
1220
|
+
try {
|
|
1221
|
+
const info = asyncapi.info();
|
|
1222
|
+
title = info.title();
|
|
1223
|
+
version = info.version();
|
|
1224
|
+
description = info.description();
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
title = 'UnknownAPI';
|
|
1227
|
+
version = '1.0.0';
|
|
1228
|
+
description = 'Generated AsyncAPI client';
|
|
1229
|
+
}
|
|
1230
|
+
return {
|
|
1231
|
+
title,
|
|
1232
|
+
version,
|
|
1233
|
+
description
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Resolves template parameters with fallbacks based on AsyncAPI info
|
|
1239
|
+
*
|
|
1240
|
+
* @param {object} params - Template parameters
|
|
1241
|
+
* @param {object} asyncApiInfo - AsyncAPI info object from extractAsyncApiInfo
|
|
1242
|
+
* @returns {object} Resolved parameters
|
|
1243
|
+
*/
|
|
1244
|
+
function resolveTemplateParameters(params, asyncApiInfo) {
|
|
1245
|
+
const {
|
|
1246
|
+
title,
|
|
1247
|
+
version
|
|
1248
|
+
} = asyncApiInfo;
|
|
1249
|
+
|
|
1250
|
+
// Resolve parameters, falling back to extracted values if parameters contain template variables
|
|
1251
|
+
const clientName = params.clientName && !isTemplateVariable(params.clientName) ? params.clientName : `${toPascalCase(title)}Client`;
|
|
1252
|
+
const packageName = params.packageName && !isTemplateVariable(params.packageName) ? params.packageName : `${toKebabCase(title)}-client`;
|
|
1253
|
+
const packageVersion = params.packageVersion && !isTemplateVariable(params.packageVersion) ? params.packageVersion : version;
|
|
1254
|
+
const license = params.license && !isTemplateVariable(params.license) ? params.license : 'Apache-2.0';
|
|
1255
|
+
const author = params.author && !isTemplateVariable(params.author) ? params.author : 'AsyncAPI Generator';
|
|
1256
|
+
return {
|
|
1257
|
+
clientName,
|
|
1258
|
+
packageName,
|
|
1259
|
+
packageVersion,
|
|
1260
|
+
license,
|
|
1261
|
+
author
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* Generates package.json content for Node.js templates
|
|
1267
|
+
*
|
|
1268
|
+
* @param {object} resolvedParams - Resolved template parameters
|
|
1269
|
+
* @param {object} asyncApiInfo - AsyncAPI info object
|
|
1270
|
+
* @param {object} options - Additional options for package.json generation
|
|
1271
|
+
* @returns {object} Package.json object
|
|
1272
|
+
*/
|
|
1273
|
+
function generatePackageJson(resolvedParams, asyncApiInfo, options = {}) {
|
|
1274
|
+
const {
|
|
1275
|
+
title,
|
|
1276
|
+
description
|
|
1277
|
+
} = asyncApiInfo;
|
|
1278
|
+
const {
|
|
1279
|
+
packageName,
|
|
1280
|
+
packageVersion,
|
|
1281
|
+
license,
|
|
1282
|
+
author
|
|
1283
|
+
} = resolvedParams;
|
|
1284
|
+
const basePackage = {
|
|
1285
|
+
name: packageName,
|
|
1286
|
+
version: packageVersion,
|
|
1287
|
+
description: `${description || title} - AsyncAPI Client`,
|
|
1288
|
+
author: author,
|
|
1289
|
+
license: license,
|
|
1290
|
+
keywords: ['asyncapi', 'client', title.toLowerCase().replace(/[^a-z0-9]/g, '-'), ...(options.additionalKeywords || [])]
|
|
1291
|
+
};
|
|
1292
|
+
|
|
1293
|
+
// Merge with additional options
|
|
1294
|
+
return {
|
|
1295
|
+
...basePackage,
|
|
1296
|
+
...options.additionalFields
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Generates README.md content for templates
|
|
1302
|
+
*
|
|
1303
|
+
* @param {object} resolvedParams - Resolved template parameters
|
|
1304
|
+
* @param {object} asyncApiInfo - AsyncAPI info object
|
|
1305
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1306
|
+
* @param {object} options - Additional options for README generation
|
|
1307
|
+
* @returns {string} README.md content
|
|
1308
|
+
*/
|
|
1309
|
+
function generateReadmeContent(resolvedParams, asyncApiInfo, asyncapi, options = {}) {
|
|
1310
|
+
const {
|
|
1311
|
+
title,
|
|
1312
|
+
description
|
|
1313
|
+
} = asyncApiInfo;
|
|
1314
|
+
const {
|
|
1315
|
+
packageName,
|
|
1316
|
+
packageVersion,
|
|
1317
|
+
license
|
|
1318
|
+
} = resolvedParams;
|
|
1319
|
+
const sections = {
|
|
1320
|
+
title: `# ${title}`,
|
|
1321
|
+
description: description || 'Generated AsyncAPI client',
|
|
1322
|
+
overview: options.overview || 'This client provides type-safe access to your AsyncAPI service.',
|
|
1323
|
+
installation: options.installation || `\`\`\`bash\nnpm install ${packageName}\n\`\`\``,
|
|
1324
|
+
usage: options.usage || '// Usage examples will be added here',
|
|
1325
|
+
metadata: `## Generated from AsyncAPI
|
|
1326
|
+
|
|
1327
|
+
- **AsyncAPI Version**: ${asyncapi.version()}
|
|
1328
|
+
- **Generated**: ${new Date().toISOString()}
|
|
1329
|
+
- **Title**: ${title}
|
|
1330
|
+
- **Version**: ${packageVersion}`,
|
|
1331
|
+
license: `## License
|
|
1332
|
+
|
|
1333
|
+
${license}`
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1336
|
+
// Allow overriding sections
|
|
1337
|
+
const finalSections = {
|
|
1338
|
+
...sections,
|
|
1339
|
+
...options.sections
|
|
1340
|
+
};
|
|
1341
|
+
return Object.values(finalSections).join('\n\n');
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Validates template parameters
|
|
1346
|
+
*
|
|
1347
|
+
* @param {object} params - Template parameters to validate
|
|
1348
|
+
* @param {Array<string>} requiredParams - List of required parameter names
|
|
1349
|
+
* @returns {object} Validation result with errors if any
|
|
1350
|
+
*/
|
|
1351
|
+
function validateTemplateParameters(params, requiredParams = []) {
|
|
1352
|
+
const result = {
|
|
1353
|
+
valid: true,
|
|
1354
|
+
errors: [],
|
|
1355
|
+
warnings: []
|
|
1356
|
+
};
|
|
1357
|
+
|
|
1358
|
+
// Check required parameters
|
|
1359
|
+
for (const paramName of requiredParams) {
|
|
1360
|
+
if (!params[paramName] || isTemplateVariable(params[paramName])) {
|
|
1361
|
+
result.valid = false;
|
|
1362
|
+
result.errors.push(`Required parameter '${paramName}' is missing or contains unresolved template variables`);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// Check for common issues
|
|
1367
|
+
if (params.packageName && !/^[a-z0-9-]+$/.test(params.packageName)) {
|
|
1368
|
+
result.warnings.push('Package name should only contain lowercase letters, numbers, and hyphens');
|
|
1369
|
+
}
|
|
1370
|
+
if (params.packageVersion && !/^\d+\.\d+\.\d+/.test(params.packageVersion)) {
|
|
1371
|
+
result.warnings.push('Package version should follow semantic versioning (e.g., 1.0.0)');
|
|
1372
|
+
}
|
|
1373
|
+
return result;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
/**
|
|
1377
|
+
* Generates TypeScript configuration for TypeScript templates
|
|
1378
|
+
*
|
|
1379
|
+
* @param {object} options - TypeScript configuration options
|
|
1380
|
+
* @returns {object} TypeScript configuration object
|
|
1381
|
+
*/
|
|
1382
|
+
function generateTypeScriptConfig(options = {}) {
|
|
1383
|
+
const defaultConfig = {
|
|
1384
|
+
compilerOptions: {
|
|
1385
|
+
target: 'ES2020',
|
|
1386
|
+
module: 'ES2020',
|
|
1387
|
+
lib: ['ES2020', 'DOM'],
|
|
1388
|
+
outDir: './dist',
|
|
1389
|
+
rootDir: './src',
|
|
1390
|
+
strict: true,
|
|
1391
|
+
esModuleInterop: true,
|
|
1392
|
+
skipLibCheck: true,
|
|
1393
|
+
forceConsistentCasingInFileNames: true,
|
|
1394
|
+
declaration: true,
|
|
1395
|
+
declarationMap: true,
|
|
1396
|
+
sourceMap: true,
|
|
1397
|
+
moduleResolution: 'node',
|
|
1398
|
+
allowSyntheticDefaultImports: true,
|
|
1399
|
+
experimentalDecorators: true,
|
|
1400
|
+
emitDecoratorMetadata: true,
|
|
1401
|
+
resolveJsonModule: true,
|
|
1402
|
+
typeRoots: ['node_modules/@types']
|
|
1403
|
+
},
|
|
1404
|
+
include: ['src/**/*'],
|
|
1405
|
+
exclude: ['node_modules', 'dist', '**/*.test.ts', '**/*.spec.ts']
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
// Merge with custom options
|
|
1409
|
+
return {
|
|
1410
|
+
...defaultConfig,
|
|
1411
|
+
compilerOptions: {
|
|
1412
|
+
...defaultConfig.compilerOptions,
|
|
1413
|
+
...options.compilerOptions
|
|
1414
|
+
},
|
|
1415
|
+
include: options.include || defaultConfig.include,
|
|
1416
|
+
exclude: options.exclude || defaultConfig.exclude
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* Generates ESLint configuration for JavaScript/TypeScript templates
|
|
1422
|
+
*
|
|
1423
|
+
* @param {object} options - ESLint configuration options
|
|
1424
|
+
* @returns {object} ESLint configuration object
|
|
1425
|
+
*/
|
|
1426
|
+
function generateEslintConfig(options = {}) {
|
|
1427
|
+
const isTypeScript = options.typescript || false;
|
|
1428
|
+
const baseConfig = {
|
|
1429
|
+
env: {
|
|
1430
|
+
node: true,
|
|
1431
|
+
es2021: true
|
|
1432
|
+
},
|
|
1433
|
+
extends: ['eslint:recommended'],
|
|
1434
|
+
parserOptions: {
|
|
1435
|
+
ecmaVersion: 12,
|
|
1436
|
+
sourceType: 'module'
|
|
1437
|
+
},
|
|
1438
|
+
rules: {
|
|
1439
|
+
'indent': ['error', 4],
|
|
1440
|
+
'linebreak-style': ['error', 'unix'],
|
|
1441
|
+
'quotes': ['error', 'single'],
|
|
1442
|
+
'semi': ['error', 'always']
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
if (isTypeScript) {
|
|
1446
|
+
baseConfig.extends.push('@typescript-eslint/recommended');
|
|
1447
|
+
baseConfig.parser = '@typescript-eslint/parser';
|
|
1448
|
+
baseConfig.plugins = ['@typescript-eslint'];
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Merge with custom options
|
|
1452
|
+
return {
|
|
1453
|
+
...baseConfig,
|
|
1454
|
+
...options.additionalConfig
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Formats a date for use in generated files
|
|
1460
|
+
*
|
|
1461
|
+
* @param {Date} date - Date to format (defaults to current date)
|
|
1462
|
+
* @returns {string} Formatted date string
|
|
1463
|
+
*/
|
|
1464
|
+
function formatGenerationDate(date = new Date()) {
|
|
1465
|
+
return date.toISOString();
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
/**
|
|
1469
|
+
* Generates a comment header for generated files
|
|
1470
|
+
*
|
|
1471
|
+
* @param {object} options - Header options
|
|
1472
|
+
* @returns {string} Comment header
|
|
1473
|
+
*/
|
|
1474
|
+
function generateFileHeader(options = {}) {
|
|
1475
|
+
const {
|
|
1476
|
+
title = 'Generated AsyncAPI File',
|
|
1477
|
+
description = 'This file was automatically generated from an AsyncAPI specification.',
|
|
1478
|
+
generator = 'AsyncAPI Generator',
|
|
1479
|
+
date = new Date(),
|
|
1480
|
+
warning = 'Do not modify this file directly.'
|
|
1481
|
+
} = options;
|
|
1482
|
+
return `/**
|
|
1483
|
+
* ${title}
|
|
1484
|
+
*
|
|
1485
|
+
* ${description}
|
|
1486
|
+
*
|
|
1487
|
+
* Generated by: ${generator}
|
|
1488
|
+
* Generated on: ${formatGenerationDate(date)}
|
|
1489
|
+
*
|
|
1490
|
+
* WARNING: ${warning}
|
|
1491
|
+
*/`;
|
|
1492
|
+
}
|
|
1493
|
+
;// ../common/src/operation-utils.js
|
|
1494
|
+
/**
|
|
1495
|
+
* Operation processing utilities for AsyncAPI template generation
|
|
1496
|
+
*
|
|
1497
|
+
* This module provides functions for extracting and processing operation information
|
|
1498
|
+
* from AsyncAPI specifications, handling different operation types and patterns.
|
|
1499
|
+
*/
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
/**
|
|
1504
|
+
* Gets the operation name from an operation object
|
|
1505
|
+
*
|
|
1506
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1507
|
+
* @returns {string|null} Operation name or null if not found
|
|
1508
|
+
*/
|
|
1509
|
+
function getOperationName(operation) {
|
|
1510
|
+
if (!operation) return null;
|
|
1511
|
+
try {
|
|
1512
|
+
// Try AsyncAPI 3.x format first - check _meta and _json properties
|
|
1513
|
+
if (operation._meta && operation._meta.id) {
|
|
1514
|
+
return operation._meta.id;
|
|
1515
|
+
}
|
|
1516
|
+
if (operation._json && operation._json['x-parser-operation-id']) {
|
|
1517
|
+
return operation._json['x-parser-operation-id'];
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// Try different ways to get the operation name
|
|
1521
|
+
if (operation.id && typeof operation.id === 'function') {
|
|
1522
|
+
return operation.id();
|
|
1523
|
+
}
|
|
1524
|
+
if (operation.id && typeof operation.id === 'string') {
|
|
1525
|
+
return operation.id;
|
|
1526
|
+
}
|
|
1527
|
+
if (operation.operationId && typeof operation.operationId === 'function') {
|
|
1528
|
+
return operation.operationId();
|
|
1529
|
+
}
|
|
1530
|
+
if (operation.operationId && typeof operation.operationId === 'string') {
|
|
1531
|
+
return operation.operationId;
|
|
1532
|
+
}
|
|
1533
|
+
return null;
|
|
1534
|
+
} catch (e) {
|
|
1535
|
+
return null;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
/**
|
|
1540
|
+
* Gets the operation action (send/receive/publish/subscribe)
|
|
1541
|
+
*
|
|
1542
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1543
|
+
* @returns {string} Operation action
|
|
1544
|
+
*/
|
|
1545
|
+
function getOperationAction(operation) {
|
|
1546
|
+
if (!operation) return 'unknown';
|
|
1547
|
+
try {
|
|
1548
|
+
if (operation.action && typeof operation.action === 'function') {
|
|
1549
|
+
return operation.action();
|
|
1550
|
+
}
|
|
1551
|
+
if (operation.action && typeof operation.action === 'string') {
|
|
1552
|
+
return operation.action;
|
|
1553
|
+
}
|
|
1554
|
+
if (operation._json && operation._json.action) {
|
|
1555
|
+
return operation._json.action;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
// Fallback based on operation type
|
|
1559
|
+
if (operation.isSend && typeof operation.isSend === 'function' && operation.isSend()) {
|
|
1560
|
+
return 'send';
|
|
1561
|
+
}
|
|
1562
|
+
if (operation.isReceive && typeof operation.isReceive === 'function' && operation.isReceive()) {
|
|
1563
|
+
return 'receive';
|
|
1564
|
+
}
|
|
1565
|
+
return 'unknown';
|
|
1566
|
+
} catch (e) {
|
|
1567
|
+
return 'unknown';
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* Gets the channel associated with an operation
|
|
1573
|
+
*
|
|
1574
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1575
|
+
* @returns {object|null} Channel object or null if not found
|
|
1576
|
+
*/
|
|
1577
|
+
function getOperationChannel(operation) {
|
|
1578
|
+
if (!operation) return null;
|
|
1579
|
+
try {
|
|
1580
|
+
if (operation.channel && typeof operation.channel === 'function') {
|
|
1581
|
+
return operation.channel();
|
|
1582
|
+
}
|
|
1583
|
+
if (operation.channel && typeof operation.channel === 'object') {
|
|
1584
|
+
return operation.channel;
|
|
1585
|
+
}
|
|
1586
|
+
return null;
|
|
1587
|
+
} catch (e) {
|
|
1588
|
+
return null;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
/**
|
|
1593
|
+
* Gets the messages associated with an operation
|
|
1594
|
+
*
|
|
1595
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1596
|
+
* @returns {Array} Array of message objects
|
|
1597
|
+
*/
|
|
1598
|
+
function getOperationMessages(operation) {
|
|
1599
|
+
if (!operation) return [];
|
|
1600
|
+
try {
|
|
1601
|
+
const messages = [];
|
|
1602
|
+
|
|
1603
|
+
// Try to get messages from the operation
|
|
1604
|
+
if (operation.messages && typeof operation.messages === 'function') {
|
|
1605
|
+
const operationMessages = operation.messages();
|
|
1606
|
+
if (operationMessages && Array.isArray(operationMessages)) {
|
|
1607
|
+
messages.push(...operationMessages);
|
|
1608
|
+
} else if (operationMessages && typeof operationMessages === 'object') {
|
|
1609
|
+
// Handle collection object
|
|
1610
|
+
if (operationMessages.all && typeof operationMessages.all === 'function') {
|
|
1611
|
+
messages.push(...operationMessages.all());
|
|
1612
|
+
} else {
|
|
1613
|
+
messages.push(...Object.values(operationMessages));
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
} else if (operation.messages && Array.isArray(operation.messages)) {
|
|
1617
|
+
messages.push(...operation.messages);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
// Try to get message from _json
|
|
1621
|
+
if (messages.length === 0 && operation._json && operation._json.message) {
|
|
1622
|
+
if (Array.isArray(operation._json.message)) {
|
|
1623
|
+
messages.push(...operation._json.message);
|
|
1624
|
+
} else {
|
|
1625
|
+
messages.push(operation._json.message);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
return messages;
|
|
1629
|
+
} catch (e) {
|
|
1630
|
+
return [];
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
/**
|
|
1635
|
+
* Checks if an operation is a send operation
|
|
1636
|
+
*
|
|
1637
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1638
|
+
* @returns {boolean} True if operation is a send operation
|
|
1639
|
+
*/
|
|
1640
|
+
function isOperationSend(operation) {
|
|
1641
|
+
const action = getOperationAction(operation);
|
|
1642
|
+
return action === 'send' || action === 'publish';
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
/**
|
|
1646
|
+
* Checks if an operation is a receive operation
|
|
1647
|
+
*
|
|
1648
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1649
|
+
* @returns {boolean} True if operation is a receive operation
|
|
1650
|
+
*/
|
|
1651
|
+
function isOperationReceive(operation) {
|
|
1652
|
+
const action = getOperationAction(operation);
|
|
1653
|
+
return action === 'receive' || action === 'subscribe';
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
/**
|
|
1657
|
+
* Gets the Rust function name for an operation
|
|
1658
|
+
*
|
|
1659
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1660
|
+
* @returns {string} Rust function name
|
|
1661
|
+
*/
|
|
1662
|
+
function getOperationRustFunctionName(operation) {
|
|
1663
|
+
const operationName = getOperationName(operation);
|
|
1664
|
+
if (!operationName) return 'unknown_operation';
|
|
1665
|
+
return toRustIdentifier(operationName);
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
/**
|
|
1669
|
+
* Gets the TypeScript method name for an operation
|
|
1670
|
+
*
|
|
1671
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1672
|
+
* @returns {string} TypeScript method name
|
|
1673
|
+
*/
|
|
1674
|
+
function getOperationTypeScriptMethodName(operation) {
|
|
1675
|
+
const operationName = getOperationName(operation);
|
|
1676
|
+
if (!operationName) return 'unknownOperation';
|
|
1677
|
+
|
|
1678
|
+
// Convert to camelCase for TypeScript
|
|
1679
|
+
return operationName.split(/[-_\s]+/).map((part, index) => {
|
|
1680
|
+
if (index === 0) {
|
|
1681
|
+
return part.toLowerCase();
|
|
1682
|
+
}
|
|
1683
|
+
return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
|
1684
|
+
}).join('');
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
/**
|
|
1688
|
+
* Gets the operation description
|
|
1689
|
+
*
|
|
1690
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1691
|
+
* @returns {string} Operation description
|
|
1692
|
+
*/
|
|
1693
|
+
function getOperationDescription(operation) {
|
|
1694
|
+
if (!operation) return '';
|
|
1695
|
+
try {
|
|
1696
|
+
if (operation.description && typeof operation.description === 'function') {
|
|
1697
|
+
return operation.description() || '';
|
|
1698
|
+
}
|
|
1699
|
+
if (operation.description && typeof operation.description === 'string') {
|
|
1700
|
+
return operation.description;
|
|
1701
|
+
}
|
|
1702
|
+
if (operation._json && operation._json.description) {
|
|
1703
|
+
return operation._json.description;
|
|
1704
|
+
}
|
|
1705
|
+
return '';
|
|
1706
|
+
} catch (e) {
|
|
1707
|
+
return '';
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* Gets the operation summary
|
|
1713
|
+
*
|
|
1714
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1715
|
+
* @returns {string} Operation summary
|
|
1716
|
+
*/
|
|
1717
|
+
function getOperationSummary(operation) {
|
|
1718
|
+
if (!operation) return '';
|
|
1719
|
+
try {
|
|
1720
|
+
if (operation.summary && typeof operation.summary === 'function') {
|
|
1721
|
+
return operation.summary() || '';
|
|
1722
|
+
}
|
|
1723
|
+
if (operation.summary && typeof operation.summary === 'string') {
|
|
1724
|
+
return operation.summary;
|
|
1725
|
+
}
|
|
1726
|
+
if (operation._json && operation._json.summary) {
|
|
1727
|
+
return operation._json.summary;
|
|
1728
|
+
}
|
|
1729
|
+
return '';
|
|
1730
|
+
} catch (e) {
|
|
1731
|
+
return '';
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
/**
|
|
1736
|
+
* Extracts all operations from an AsyncAPI specification
|
|
1737
|
+
*
|
|
1738
|
+
* @param {object} asyncapi - AsyncAPI specification object
|
|
1739
|
+
* @returns {Array} Array of operation objects with metadata
|
|
1740
|
+
*/
|
|
1741
|
+
function extractAllOperations(asyncapi) {
|
|
1742
|
+
const operations = [];
|
|
1743
|
+
try {
|
|
1744
|
+
const asyncApiOperations = asyncapi.operations && asyncapi.operations();
|
|
1745
|
+
if (asyncApiOperations) {
|
|
1746
|
+
// Handle AsyncAPI parser collection - use .all() method to get array
|
|
1747
|
+
const operationArray = asyncApiOperations.all ? asyncApiOperations.all() : Object.values(asyncApiOperations);
|
|
1748
|
+
operationArray.forEach(operation => {
|
|
1749
|
+
const operationName = getOperationName(operation);
|
|
1750
|
+
if (operationName) {
|
|
1751
|
+
const channel = getOperationChannel(operation);
|
|
1752
|
+
const messages = getOperationMessages(operation);
|
|
1753
|
+
operations.push({
|
|
1754
|
+
name: operationName,
|
|
1755
|
+
operation: operation,
|
|
1756
|
+
action: getOperationAction(operation),
|
|
1757
|
+
channel: channel,
|
|
1758
|
+
messages: messages,
|
|
1759
|
+
description: getOperationDescription(operation),
|
|
1760
|
+
summary: getOperationSummary(operation),
|
|
1761
|
+
rustFunctionName: getOperationRustFunctionName(operation),
|
|
1762
|
+
typeScriptMethodName: getOperationTypeScriptMethodName(operation),
|
|
1763
|
+
isSend: isOperationSend(operation),
|
|
1764
|
+
isReceive: isOperationReceive(operation)
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
});
|
|
1768
|
+
}
|
|
1769
|
+
} catch (e) {
|
|
1770
|
+
console.warn('Error extracting operations:', e.message);
|
|
1771
|
+
}
|
|
1772
|
+
return operations;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
/**
|
|
1776
|
+
* Groups operations by their action type
|
|
1777
|
+
*
|
|
1778
|
+
* @param {Array} operations - Array of operation objects
|
|
1779
|
+
* @returns {object} Object with send and receive operation arrays
|
|
1780
|
+
*/
|
|
1781
|
+
function groupOperationsByAction(operations) {
|
|
1782
|
+
const grouped = {
|
|
1783
|
+
send: [],
|
|
1784
|
+
receive: [],
|
|
1785
|
+
publish: [],
|
|
1786
|
+
subscribe: [],
|
|
1787
|
+
unknown: []
|
|
1788
|
+
};
|
|
1789
|
+
operations.forEach(operation => {
|
|
1790
|
+
const action = operation.action || 'unknown';
|
|
1791
|
+
if (grouped[action]) {
|
|
1792
|
+
grouped[action].push(operation);
|
|
1793
|
+
} else {
|
|
1794
|
+
grouped.unknown.push(operation);
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
return grouped;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
/**
|
|
1801
|
+
* Gets the operation trait information
|
|
1802
|
+
*
|
|
1803
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1804
|
+
* @returns {Array} Array of trait objects
|
|
1805
|
+
*/
|
|
1806
|
+
function getOperationTraits(operation) {
|
|
1807
|
+
if (!operation) return [];
|
|
1808
|
+
try {
|
|
1809
|
+
const traits = [];
|
|
1810
|
+
if (operation.traits && typeof operation.traits === 'function') {
|
|
1811
|
+
const operationTraits = operation.traits();
|
|
1812
|
+
if (operationTraits && Array.isArray(operationTraits)) {
|
|
1813
|
+
traits.push(...operationTraits);
|
|
1814
|
+
}
|
|
1815
|
+
} else if (operation.traits && Array.isArray(operation.traits)) {
|
|
1816
|
+
traits.push(...operation.traits);
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// Try to get traits from _json
|
|
1820
|
+
if (traits.length === 0 && operation._json && operation._json.traits) {
|
|
1821
|
+
if (Array.isArray(operation._json.traits)) {
|
|
1822
|
+
traits.push(...operation._json.traits);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
return traits;
|
|
1826
|
+
} catch (e) {
|
|
1827
|
+
return [];
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
/**
|
|
1832
|
+
* Checks if an operation has any traits defined
|
|
1833
|
+
*
|
|
1834
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1835
|
+
* @returns {boolean} True if operation has traits
|
|
1836
|
+
*/
|
|
1837
|
+
function operationHasTraits(operation) {
|
|
1838
|
+
const traits = getOperationTraits(operation);
|
|
1839
|
+
return traits.length > 0;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
/**
|
|
1843
|
+
* Gets the operation tags
|
|
1844
|
+
*
|
|
1845
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1846
|
+
* @returns {Array} Array of tag objects
|
|
1847
|
+
*/
|
|
1848
|
+
function getOperationTags(operation) {
|
|
1849
|
+
if (!operation) return [];
|
|
1850
|
+
try {
|
|
1851
|
+
const tags = [];
|
|
1852
|
+
if (operation.tags && typeof operation.tags === 'function') {
|
|
1853
|
+
const operationTags = operation.tags();
|
|
1854
|
+
if (operationTags && Array.isArray(operationTags)) {
|
|
1855
|
+
tags.push(...operationTags);
|
|
1856
|
+
}
|
|
1857
|
+
} else if (operation.tags && Array.isArray(operation.tags)) {
|
|
1858
|
+
tags.push(...operation.tags);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
// Try to get tags from _json
|
|
1862
|
+
if (tags.length === 0 && operation._json && operation._json.tags) {
|
|
1863
|
+
if (Array.isArray(operation._json.tags)) {
|
|
1864
|
+
tags.push(...operation._json.tags);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
return tags;
|
|
1868
|
+
} catch (e) {
|
|
1869
|
+
return [];
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
/**
|
|
1874
|
+
* Generates operation handler name for server templates
|
|
1875
|
+
*
|
|
1876
|
+
* @param {object} operation - AsyncAPI operation object
|
|
1877
|
+
* @param {string} suffix - Optional suffix to add to handler name
|
|
1878
|
+
* @returns {string} Handler function name
|
|
1879
|
+
*/
|
|
1880
|
+
function generateOperationHandlerName(operation, suffix = 'Handler') {
|
|
1881
|
+
const operationName = getOperationName(operation);
|
|
1882
|
+
if (!operationName) return `unknown${suffix}`;
|
|
1883
|
+
const pascalCaseName = toPascalCase(operationName);
|
|
1884
|
+
return `${pascalCaseName}${suffix}`;
|
|
1885
|
+
}
|
|
1886
|
+
;// ../common/src/index.js
|
|
1887
|
+
/**
|
|
1888
|
+
* AsyncAPI Common Template Utilities
|
|
1889
|
+
*
|
|
1890
|
+
* This package provides shared utilities for AsyncAPI template generation,
|
|
1891
|
+
* reducing code duplication across multiple templates.
|
|
1892
|
+
*/
|
|
1893
|
+
|
|
1894
|
+
// String utilities
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
// Message utilities
|
|
1898
|
+
|
|
1899
|
+
|
|
1900
|
+
// Channel utilities
|
|
1901
|
+
|
|
1902
|
+
|
|
1903
|
+
// Security utilities
|
|
1904
|
+
|
|
1905
|
+
|
|
1906
|
+
// Template utilities
|
|
1907
|
+
|
|
1908
|
+
|
|
1909
|
+
// Operation utilities
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
// Re-export all utilities
|
|
1913
|
+
|
|
1914
|
+
|
|
1915
|
+
// Version information
|
|
1916
|
+
const VERSION = '1.0.0';
|
|
1917
|
+
|
|
1918
|
+
// Convenience function to get all utilities in one object
|
|
1919
|
+
function getAllUtilities() {
|
|
1920
|
+
return {
|
|
1921
|
+
string: {
|
|
1922
|
+
toRustIdentifier: toRustIdentifier,
|
|
1923
|
+
toRustTypeName: toRustTypeName,
|
|
1924
|
+
toRustFieldName: toRustFieldName,
|
|
1925
|
+
toRustEnumVariant: toRustEnumVariant,
|
|
1926
|
+
toRustEnumVariantWithSerde: toRustEnumVariantWithSerde,
|
|
1927
|
+
toKebabCase: toKebabCase,
|
|
1928
|
+
toPascalCase: toPascalCase,
|
|
1929
|
+
toSnakeCase: toSnakeCase,
|
|
1930
|
+
toCamelCase: toCamelCase
|
|
1931
|
+
},
|
|
1932
|
+
message: {
|
|
1933
|
+
getMessageTypeName: getMessageTypeName,
|
|
1934
|
+
getMessageRustTypeName: getMessageRustTypeName,
|
|
1935
|
+
getPayloadRustTypeName: getPayloadRustTypeName,
|
|
1936
|
+
getMessageTypeScriptTypeName: getMessageTypeScriptTypeName,
|
|
1937
|
+
getPayloadTypeScriptTypeName: getPayloadTypeScriptTypeName,
|
|
1938
|
+
messageHasPayload: messageHasPayload,
|
|
1939
|
+
getMessageContentType: getMessageContentType
|
|
1940
|
+
},
|
|
1941
|
+
channel: {
|
|
1942
|
+
getNatsSubject: getNatsSubject,
|
|
1943
|
+
getChannelAddress: getChannelAddress,
|
|
1944
|
+
isDynamicChannel: isDynamicChannel,
|
|
1945
|
+
extractChannelVariables: extractChannelVariables,
|
|
1946
|
+
extractChannelParameters: extractChannelParameters,
|
|
1947
|
+
getChannelParameters: getChannelParameters,
|
|
1948
|
+
resolveChannelAddress: resolveChannelAddress,
|
|
1949
|
+
channelHasParameters: channelHasParameters,
|
|
1950
|
+
generateChannelParameterArgs: generateChannelParameterArgs,
|
|
1951
|
+
generateChannelFormatting: generateChannelFormatting,
|
|
1952
|
+
generateTypeScriptChannelParameterArgs: generateTypeScriptChannelParameterArgs,
|
|
1953
|
+
generateTypeScriptChannelFormatting: generateTypeScriptChannelFormatting,
|
|
1954
|
+
extractServerNameFromRef: extractServerNameFromRef,
|
|
1955
|
+
analyzeChannelServerMappings: analyzeChannelServerMappings,
|
|
1956
|
+
isChannelAllowedOnServer: isChannelAllowedOnServer
|
|
1957
|
+
},
|
|
1958
|
+
security: {
|
|
1959
|
+
analyzeOperationSecurity: analyzeOperationSecurity,
|
|
1960
|
+
operationHasSecurity: operationHasSecurity,
|
|
1961
|
+
operationRequiresAuth: operationRequiresAuth,
|
|
1962
|
+
hasSecuritySchemes: hasSecuritySchemes,
|
|
1963
|
+
getSecuritySchemeType: getSecuritySchemeType,
|
|
1964
|
+
getSecuritySchemeName: getSecuritySchemeName,
|
|
1965
|
+
getSecuritySchemeLocation: getSecuritySchemeLocation,
|
|
1966
|
+
extractOperationSecurityMap: extractOperationSecurityMap,
|
|
1967
|
+
getAllSecuritySchemes: getAllSecuritySchemes,
|
|
1968
|
+
isSecuritySchemeType: isSecuritySchemeType,
|
|
1969
|
+
getDefaultPort: getDefaultPort,
|
|
1970
|
+
validateChannelServerReferences: validateChannelServerReferences
|
|
1971
|
+
},
|
|
1972
|
+
template: {
|
|
1973
|
+
isTemplateVariable: isTemplateVariable,
|
|
1974
|
+
extractAsyncApiInfo: extractAsyncApiInfo,
|
|
1975
|
+
resolveTemplateParameters: resolveTemplateParameters,
|
|
1976
|
+
generatePackageJson: generatePackageJson,
|
|
1977
|
+
generateReadmeContent: generateReadmeContent,
|
|
1978
|
+
validateTemplateParameters: validateTemplateParameters,
|
|
1979
|
+
generateTypeScriptConfig: generateTypeScriptConfig,
|
|
1980
|
+
generateEslintConfig: generateEslintConfig,
|
|
1981
|
+
formatGenerationDate: formatGenerationDate,
|
|
1982
|
+
generateFileHeader: generateFileHeader
|
|
1983
|
+
},
|
|
1984
|
+
operation: {
|
|
1985
|
+
getOperationName: getOperationName,
|
|
1986
|
+
getOperationAction: getOperationAction,
|
|
1987
|
+
getOperationChannel: getOperationChannel,
|
|
1988
|
+
getOperationMessages: getOperationMessages,
|
|
1989
|
+
isOperationSend: isOperationSend,
|
|
1990
|
+
isOperationReceive: isOperationReceive,
|
|
1991
|
+
getOperationRustFunctionName: getOperationRustFunctionName,
|
|
1992
|
+
getOperationTypeScriptMethodName: getOperationTypeScriptMethodName,
|
|
1993
|
+
getOperationDescription: getOperationDescription,
|
|
1994
|
+
getOperationSummary: getOperationSummary,
|
|
1995
|
+
extractAllOperations: extractAllOperations,
|
|
1996
|
+
groupOperationsByAction: groupOperationsByAction,
|
|
1997
|
+
getOperationTraits: getOperationTraits,
|
|
1998
|
+
operationHasTraits: operationHasTraits,
|
|
1999
|
+
getOperationTags: getOperationTags,
|
|
2000
|
+
generateOperationHandlerName: generateOperationHandlerName
|
|
2001
|
+
}
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
export { VERSION, analyzeChannelServerMappings, analyzeOperationSecurity, channelHasParameters, extractAllOperations, extractAsyncApiInfo, extractChannelParameters, extractChannelVariables, extractOperationSecurityMap, extractServerNameFromRef, formatGenerationDate, generateChannelFormatting, generateChannelParameterArgs, generateEslintConfig, generateFileHeader, generateOperationHandlerName, generatePackageJson, generateReadmeContent, generateTypeScriptChannelFormatting, generateTypeScriptChannelParameterArgs, generateTypeScriptConfig, getAllSecuritySchemes, getAllUtilities, getChannelAddress, getChannelParameters, getDefaultPort, getMessageContentType, getMessageRustTypeName, getMessageTypeName, getMessageTypeScriptTypeName, getNatsSubject, getOperationAction, getOperationChannel, getOperationDescription, getOperationMessages, getOperationName, getOperationRustFunctionName, getOperationSummary, getOperationTags, getOperationTraits, getOperationTypeScriptMethodName, getPayloadRustTypeName, getPayloadTypeScriptTypeName, getSecuritySchemeLocation, getSecuritySchemeName, getSecuritySchemeType, groupOperationsByAction, hasSecuritySchemes, isChannelAllowedOnServer, isDynamicChannel, isOperationReceive, isOperationSend, isSecuritySchemeType, isTemplateVariable, messageHasPayload, operationHasSecurity, operationHasTraits, operationRequiresAuth, resolveChannelAddress, resolveTemplateParameters, toCamelCase, toKebabCase, toPascalCase, toRustEnumVariant, toRustEnumVariantWithSerde, toRustFieldName, toRustIdentifier, toRustTypeName, toSnakeCase, validateChannelServerReferences, validateTemplateParameters };
|