@ioka-technologies/asyncapi-ts-client-template 0.0.21 → 0.0.23

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/package.json CHANGED
@@ -1,14 +1,17 @@
1
1
  {
2
2
  "name": "@ioka-technologies/asyncapi-ts-client-template",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "TypeScript AsyncAPI client generator template compatible with rust-asyncapi patterns",
5
5
  "main": "template/index.js",
6
6
  "scripts": {
7
+ "build": "webpack --config ../webpack.config.js --env template=ts-client",
8
+ "build:dev": "webpack --config ../webpack.config.js --env template=ts-client --mode development",
9
+ "prepublishOnly": "npm run build",
7
10
  "test": "npm run test:generate",
8
- "test:generate": "asyncapi generate fromTemplate examples/auth-retry/asyncapi.yaml . -o test-output-auth-retry --force-write && cd test-output-auth-retry && npm install && npm run build",
9
- "test:realworld": "asyncapi generate fromTemplate ../examples/realworld/asyncapi.yaml . -o test-output-realworld --force-write",
10
- "test:simple": "asyncapi generate fromTemplate ../examples/simple/asyncapi.yaml . -o test-output-simple --force-write",
11
- "clean": "rm -rf test-output-*"
11
+ "test:generate": "asyncapi generate fromTemplate examples/auth-retry/asyncapi.yaml ./ -o test-output-auth-retry --force-write && cd test-output-auth-retry && npm install && npm run build",
12
+ "test:realworld": "asyncapi generate fromTemplate ../examples/realworld/asyncapi.yaml ./ -o test-output-realworld --force-write",
13
+ "test:simple": "asyncapi generate fromTemplate ../examples/simple/asyncapi.yaml ./ -o test-output-simple --force-write",
14
+ "clean": "rm -rf test-output-* dist"
12
15
  },
13
16
  "keywords": [
14
17
  "asyncapi",
@@ -22,6 +25,9 @@
22
25
  ],
23
26
  "author": "AsyncAPI TypeScript Generator",
24
27
  "license": "Apache-2.0",
28
+ "dependencies": {
29
+ "@asyncapi/generator-react-sdk": "^1.0.20"
30
+ },
25
31
  "devDependencies": {
26
32
  "@asyncapi/cli": "^1.18.0"
27
33
  },
@@ -86,6 +92,7 @@
86
92
  },
87
93
  "files": [
88
94
  "template/**/*",
95
+ "dist/common/**/*",
89
96
  "examples/**/*",
90
97
  "README.md",
91
98
  "USAGE.md",
@@ -1,78 +1,13 @@
1
1
  /**
2
2
  * Security analysis helper functions for TypeScript client template
3
- * Adapted from rust-server template helpers
3
+ * Most common security utilities have been moved to the shared @common package.
4
4
  */
5
5
 
6
- /**
7
- * Analyzes operation security requirements from AsyncAPI specification
8
- *
9
- * @param {object} operation - AsyncAPI operation object
10
- * @returns {object} Security analysis result
11
- */
12
- export function analyzeOperationSecurity(operation) {
13
- try {
14
- // Check AsyncAPI security field
15
- const security = operation.security && operation.security();
16
- if (security && Array.isArray(security) && security.length > 0) {
17
- return {
18
- hasSecurityRequirements: true,
19
- securitySchemes: security,
20
- requiresAuthentication: true
21
- };
22
- }
23
-
24
- // Check if operation has security defined in AsyncAPI spec
25
- const operationJson = operation._json || operation;
26
- if (operationJson.security && Array.isArray(operationJson.security) && operationJson.security.length > 0) {
27
- return {
28
- hasSecurityRequirements: true,
29
- securitySchemes: operationJson.security,
30
- requiresAuthentication: true
31
- };
32
- }
33
-
34
- return {
35
- hasSecurityRequirements: false,
36
- securitySchemes: [],
37
- requiresAuthentication: false
38
- };
39
- } catch (e) {
40
- return {
41
- hasSecurityRequirements: false,
42
- securitySchemes: [],
43
- requiresAuthentication: false
44
- };
45
- }
46
- }
47
-
48
- /**
49
- * Checks if an operation has security requirements
50
- *
51
- * @param {object} operation - AsyncAPI operation object
52
- * @returns {boolean} True if operation has security requirements
53
- */
54
- export function operationRequiresAuth(operation) {
55
- const analysis = analyzeOperationSecurity(operation);
56
- return analysis.hasSecurityRequirements;
57
- }
58
-
59
- /**
60
- * Checks if the AsyncAPI specification has security schemes defined
61
- *
62
- * @param {object} asyncapi - AsyncAPI specification object
63
- * @returns {boolean} True if security schemes are present
64
- */
65
- export function hasSecuritySchemes(asyncapi) {
66
- try {
67
- const components = asyncapi.components();
68
- if (!components) return false;
69
-
70
- const securitySchemes = components.securitySchemes();
71
- return securitySchemes && Object.keys(securitySchemes).length > 0;
72
- } catch (e) {
73
- return false;
74
- }
75
- }
6
+ import {
7
+ analyzeOperationSecurity,
8
+ operationHasSecurity,
9
+ hasSecuritySchemes
10
+ } from "../dist/common/index.js";
76
11
 
77
12
  /**
78
13
  * Get security scheme type from AsyncAPI security scheme definition
@@ -80,7 +15,7 @@ export function hasSecuritySchemes(asyncapi) {
80
15
  * @param {object} securityScheme - AsyncAPI security scheme object
81
16
  * @returns {string} Security scheme type ('jwt', 'basic', 'apikey', etc.)
82
17
  */
83
- export function getSecuritySchemeType(securityScheme) {
18
+ function getSecuritySchemeType(securityScheme) {
84
19
  try {
85
20
  if (securityScheme.type && typeof securityScheme.type === 'function') {
86
21
  return securityScheme.type();
@@ -103,7 +38,7 @@ export function getSecuritySchemeType(securityScheme) {
103
38
  * @param {object} asyncapi - AsyncAPI specification object
104
39
  * @returns {object} Map of operation names to their security requirements
105
40
  */
106
- export function extractOperationSecurityMap(asyncapi) {
41
+ function extractOperationSecurityMap(asyncapi) {
107
42
  const securityMap = {};
108
43
 
109
44
  try {
@@ -135,3 +70,15 @@ export function extractOperationSecurityMap(asyncapi) {
135
70
 
136
71
  return securityMap;
137
72
  }
73
+
74
+ // Export all functions
75
+ export {
76
+ // Re-export common security utilities for backward compatibility
77
+ analyzeOperationSecurity,
78
+ operationHasSecurity as operationRequiresAuth,
79
+ hasSecuritySchemes,
80
+
81
+ // TypeScript client specific functions
82
+ getSecuritySchemeType,
83
+ extractOperationSecurityMap
84
+ };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Security analysis helper functions for TypeScript client template
3
+ * Most common security utilities have been moved to the shared @common package.
4
+ */
5
+
6
+ import {
7
+ analyzeOperationSecurity,
8
+ operationHasSecurity,
9
+ hasSecuritySchemes
10
+ } from '../../../common/src/index.js';
11
+
12
+ /**
13
+ * Get security scheme type from AsyncAPI security scheme definition
14
+ *
15
+ * @param {object} securityScheme - AsyncAPI security scheme object
16
+ * @returns {string} Security scheme type ('jwt', 'basic', 'apikey', etc.)
17
+ */
18
+ function getSecuritySchemeType(securityScheme) {
19
+ try {
20
+ if (securityScheme.type && typeof securityScheme.type === 'function') {
21
+ return securityScheme.type();
22
+ }
23
+ if (securityScheme.type) {
24
+ return securityScheme.type;
25
+ }
26
+ if (securityScheme._json && securityScheme._json.type) {
27
+ return securityScheme._json.type;
28
+ }
29
+ return 'unknown';
30
+ } catch (e) {
31
+ return 'unknown';
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Extract security requirements for all operations in the AsyncAPI spec
37
+ *
38
+ * @param {object} asyncapi - AsyncAPI specification object
39
+ * @returns {object} Map of operation names to their security requirements
40
+ */
41
+ function extractOperationSecurityMap(asyncapi) {
42
+ const securityMap = {};
43
+
44
+ try {
45
+ const operations = asyncapi.operations && asyncapi.operations();
46
+ if (operations) {
47
+ // Handle AsyncAPI parser collection - use .all() method to get array
48
+ const operationArray = operations.all ? operations.all() : Object.values(operations);
49
+
50
+ operationArray.forEach((operation) => {
51
+ // Get operation ID
52
+ let operationId = null;
53
+ if (operation._meta && operation._meta.id) {
54
+ operationId = operation._meta.id;
55
+ } else if (operation.id && typeof operation.id === 'function') {
56
+ operationId = operation.id();
57
+ } else if (operation.id) {
58
+ operationId = operation.id;
59
+ }
60
+
61
+ if (operationId) {
62
+ const securityAnalysis = analyzeOperationSecurity(operation);
63
+ securityMap[operationId] = securityAnalysis;
64
+ }
65
+ });
66
+ }
67
+ } catch (e) {
68
+ console.warn('Error extracting operation security map:', e.message);
69
+ }
70
+
71
+ return securityMap;
72
+ }
73
+
74
+ // Export all functions
75
+ export {
76
+ // Re-export common security utilities for backward compatibility
77
+ analyzeOperationSecurity,
78
+ operationHasSecurity as operationRequiresAuth,
79
+ hasSecuritySchemes,
80
+
81
+ // TypeScript client specific functions
82
+ getSecuritySchemeType,
83
+ extractOperationSecurityMap
84
+ };
package/template/index.js CHANGED
@@ -1,7 +1,7 @@
1
- const { File } = require('@asyncapi/generator-react-sdk');
2
- const React = require('react');
1
+ import { File } from '@asyncapi/generator-react-sdk';
2
+ import React from 'react';
3
3
 
4
- module.exports = function ({ asyncapi, params }) {
4
+ export default function ({ asyncapi, params }) {
5
5
  // Extract info from AsyncAPI spec
6
6
  let title, version, description;
7
7
  try {
@@ -272,4 +272,4 @@ ${params.license || 'Apache-2.0'}
272
272
  `
273
273
  )
274
274
  ];
275
- };
275
+ }
@@ -806,7 +806,7 @@ export default ${clientName};
806
806
  return content;
807
807
  }
808
808
 
809
- module.exports = function ({ asyncapi, params }) {
809
+ export default function ({ asyncapi, params }) {
810
810
  const title = asyncapi.info().title();
811
811
 
812
812
  // Always use the processed title, ignore params.clientName if it contains template variables
@@ -824,4 +824,4 @@ module.exports = function ({ asyncapi, params }) {
824
824
  {generatedContent}
825
825
  </File>
826
826
  );
827
- };
827
+ }
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import { File } from '@asyncapi/generator-react-sdk';
3
3
 
4
- module.exports = function ({ asyncapi, params }) {
4
+ export default function ({ asyncapi, params }) {
5
5
  return (
6
6
  <File name="index.ts">
7
7
  {`export * from './client';
@@ -1,378 +1,21 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import { File } from '@asyncapi/generator-react-sdk';
3
+ import { generateTypeScriptModels } from '../../../common/src/index.js';
3
4
 
4
- function generateModels(asyncapi) {
5
- let content = '// Generated TypeScript models from AsyncAPI specification\n\n';
6
-
7
- // Helper functions for TypeScript identifier generation
8
- function toTypeScriptIdentifier(str) {
9
- if (!str) return 'unknown';
10
- let identifier = str
11
- .replace(/[^a-zA-Z0-9_]/g, '_')
12
- .replace(/^[0-9]/, '_$&')
13
- .replace(/_+/g, '_')
14
- .replace(/^_+|_+$/g, '');
15
- if (/^[0-9]/.test(identifier)) {
16
- identifier = 'item_' + identifier;
17
- }
18
- if (!identifier) {
19
- identifier = 'unknown';
20
- }
21
- return identifier;
22
- }
23
-
24
-
25
- function toTypeScriptTypeName(str) {
26
- if (!str) return 'Unknown';
27
- // Handle camelCase and PascalCase properly
28
- const identifier = str
29
- .replace(/[^a-zA-Z0-9]/g, '_')
30
- .replace(/^[0-9]/, '_$&')
31
- .replace(/_+/g, '_')
32
- .replace(/^_+|_+$/g, '');
33
-
34
- // Split on underscores and camelCase boundaries
35
- const parts = identifier.split(/[_\s]+|(?=[A-Z])/);
36
-
37
- return parts
38
- .filter(part => part.length > 0)
39
- .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
40
- .join('');
41
- }
42
-
43
- // Extract message schemas and build channel mapping
44
- const components = asyncapi.components();
45
- const messageSchemas = [];
46
- const componentSchemas = [];
47
- const messageToChannels = new Map();
48
- const generatedTypes = new Set();
49
- const schemaRegistry = new Map();
50
-
51
- // Build schema registry from components.schemas
52
- // Try to access the raw AsyncAPI document
53
- let rawDoc = null;
54
- try {
55
- if (asyncapi.json && typeof asyncapi.json === 'function') {
56
- rawDoc = asyncapi.json();
57
- } else if (asyncapi._json) {
58
- rawDoc = asyncapi._json;
59
- }
60
- } catch (e) {
61
- // Ignore
62
- }
63
-
64
- // Extract schemas from raw document if available
65
- if (rawDoc && rawDoc.components && rawDoc.components.schemas) {
66
- Object.entries(rawDoc.components.schemas).forEach(([name, schema]) => {
67
- if (name && typeof name === 'string' && schema && typeof schema === 'object') {
68
- schemaRegistry.set(name, schema);
69
- componentSchemas.push({
70
- name,
71
- typeName: toTypeScriptTypeName(name),
72
- schema: schema,
73
- description: schema.description
74
- });
75
- }
76
- });
77
- }
78
-
79
- // Fallback: try the components.schemas() method
80
- if (componentSchemas.length === 0 && components && components.schemas) {
81
- try {
82
- const schemas = components.schemas();
83
- if (schemas) {
84
- // Try different ways to access schemas
85
- let schemaEntries = [];
86
-
87
- if (schemas instanceof Map) {
88
- schemaEntries = Array.from(schemas.entries());
89
- } else if (typeof schemas === 'object') {
90
- schemaEntries = Object.entries(schemas);
91
- } else if (schemas.all && typeof schemas.all === 'function') {
92
- // AsyncAPI parser might have an all() method
93
- const allSchemas = schemas.all();
94
- if (Array.isArray(allSchemas)) {
95
- schemaEntries = allSchemas.map(schema => {
96
- const name = schema.uid ? schema.uid() : (schema.id ? schema.id() : null);
97
- return [name, schema];
98
- }).filter(([name]) => name);
99
- }
100
- }
101
-
102
- schemaEntries.forEach(([name, schema]) => {
103
- // Skip internal AsyncAPI parser objects and numeric keys
104
- if (!name || name === 'collections' || name === '_meta' || name.startsWith('_') || /^\d+$/.test(name)) {
105
- return;
106
- }
107
-
108
- let schemaData = null;
109
- let description = null;
110
-
111
- try {
112
- // Handle different schema object types
113
- if (schema && typeof schema.json === 'function') {
114
- schemaData = schema.json();
115
- } else if (schema && typeof schema === 'object') {
116
- schemaData = schema;
117
- }
118
-
119
- if (schema && typeof schema.description === 'function') {
120
- description = schema.description();
121
- } else if (schema && schema.description) {
122
- description = schema.description;
123
- }
124
- } catch (e) {
125
- // Ignore schema extraction errors
126
- console.warn(`Failed to extract schema for ${name}:`, e.message);
127
- }
128
-
129
- if (schemaData && typeof name === 'string' && name.length > 0) {
130
- schemaRegistry.set(name, schemaData);
131
- componentSchemas.push({
132
- name,
133
- typeName: toTypeScriptTypeName(name),
134
- schema: schemaData,
135
- description
136
- });
137
- }
138
- });
139
- }
140
- } catch (e) {
141
- console.warn('Failed to extract component schemas:', e.message);
142
- }
143
- }
144
-
145
- // First, build channel to message mapping
146
- if (asyncapi.channels) {
147
- const channels = asyncapi.channels();
148
- if (channels) {
149
- Object.entries(channels).forEach(([channelName, channel]) => {
150
- try {
151
- // Handle AsyncAPI 3.x format
152
- if (channel.messages) {
153
- const messages = channel.messages();
154
- if (messages) {
155
- Object.entries(messages).forEach(([msgKey, message]) => {
156
- if (message) {
157
- let messageName = null;
158
- if (message.$ref) {
159
- messageName = message.$ref.split('/').pop();
160
- } else if (message.name) {
161
- messageName = typeof message.name === 'function' ? message.name() : message.name;
162
- }
163
-
164
- if (messageName) {
165
- if (!messageToChannels.has(messageName)) {
166
- messageToChannels.set(messageName, []);
167
- }
168
- messageToChannels.get(messageName).push(channelName);
169
- }
170
- }
171
- });
172
- }
173
- }
174
- } catch (e) {
175
- // Ignore channel processing errors
176
- }
177
- });
178
- }
179
- }
180
-
181
- // Extract messages from components
182
- if (components && components.messages) {
183
- const messages = components.messages();
184
- if (messages) {
185
- Object.entries(messages).forEach(([name, message]) => {
186
- // Skip internal AsyncAPI parser objects
187
- if (name === 'collections' || name === '_meta' || name.startsWith('_')) {
188
- return;
189
- }
190
- let payload = null;
191
- let description = null;
192
- let title = null;
193
- let messageName = name;
194
-
195
- try {
196
- if (message.payload && typeof message.payload === 'function') {
197
- const payloadSchema = message.payload();
198
- payload = payloadSchema && payloadSchema.json ? payloadSchema.json() : payloadSchema;
199
- }
200
- description = message.description && typeof message.description === 'function' ? message.description() : message.description;
201
- title = message.title && typeof message.title === 'function' ? message.title() : message.title;
202
-
203
- // Try to get the actual message name
204
- if (message.name && typeof message.name === 'function') {
205
- messageName = message.name();
206
- } else if (message.name) {
207
- messageName = message.name;
208
- }
209
- } catch (e) {
210
- // Ignore payload extraction errors
211
- }
212
-
213
- const channels = messageToChannels.get(messageName) || messageToChannels.get(name) || [];
214
- messageSchemas.push({
215
- name: messageName,
216
- typeName: toTypeScriptTypeName(messageName),
217
- payload,
218
- description: description || title,
219
- channels
220
- });
221
- });
222
- }
223
- }
224
-
225
- // Helper function to convert JSON schema to TypeScript type
226
- function jsonSchemaToTypeScriptType(schema, fieldName = '') {
227
- if (!schema) return 'any';
228
-
229
- // Handle $ref - resolve from schema registry
230
- if (schema.$ref) {
231
- const refName = schema.$ref.split('/').pop();
232
- // Always return the type name for $ref, since we generate all component schemas
233
- const typeName = toTypeScriptTypeName(refName);
234
- return typeName;
235
- }
236
-
237
- // Handle resolved $ref - check for x-parser-schema-id which indicates original schema name
238
- if (schema['x-parser-schema-id'] && typeof schema['x-parser-schema-id'] === 'string') {
239
- const schemaId = schema['x-parser-schema-id'];
240
- // Check if this matches a known component schema
241
- if (schemaRegistry.has(schemaId)) {
242
- const typeName = toTypeScriptTypeName(schemaId);
243
- return typeName;
244
- }
245
- }
246
-
247
- if (!schema.type) {
248
- // If no type specified, check for properties (object) or items (array)
249
- if (schema.properties) {
250
- schema.type = 'object';
251
- } else if (schema.items) {
252
- schema.type = 'array';
253
- } else {
254
- return 'any';
255
- }
256
- }
257
-
258
- switch (schema.type) {
259
- case 'string':
260
- if (schema.enum && schema.enum.length > 0) {
261
- return schema.enum.map(val => `'${val}'`).join(' | ');
262
- }
263
- return 'string';
264
- case 'integer':
265
- case 'number':
266
- return 'number';
267
- case 'boolean':
268
- return 'boolean';
269
- case 'array': {
270
- if (schema.items) {
271
- const itemType = jsonSchemaToTypeScriptType(schema.items, fieldName);
272
- return `${itemType}[]`;
273
- }
274
- return 'any[]';
275
- }
276
- case 'object':
277
- // For objects with properties, we should generate inline types or check if it's a known schema
278
- if (schema.properties) {
279
- // This is a complex object - for now return Record<string, any>
280
- // In a more sophisticated implementation, we could generate inline types
281
- return 'Record<string, any>';
282
- }
283
- return 'Record<string, any>';
284
- default:
285
- return 'any';
286
- }
287
- }
288
-
289
- // Generate message interfaces
290
- function generateMessageInterface(schema, messageName) {
291
- if (!schema || !schema.properties) {
292
- return ' [key: string]: any;';
293
- }
294
-
295
- const fields = Object.entries(schema.properties).map(([fieldName, fieldSchema]) => {
296
- const tsType = jsonSchemaToTypeScriptType(fieldSchema, fieldName);
297
- const optional = !schema.required || !schema.required.includes(fieldName);
298
- const optionalMarker = optional ? '?' : '';
299
-
300
- let fieldDoc = '';
301
- if (fieldSchema.description) {
302
- fieldDoc = ` /** ${fieldSchema.description} */\n`;
303
- }
304
-
305
- return `${fieldDoc} ${fieldName}${optionalMarker}: ${tsType};`;
306
- }).join('\n');
307
-
308
- return fields;
309
- }
310
-
311
- // Generate interfaces for component schemas first (so they can be referenced by messages)
312
- componentSchemas.forEach(schema => {
313
- const doc = schema.description ? `/** ${schema.description} */\n` : `/** ${schema.name} */\n`;
314
-
315
- // Check if this is a standalone enum schema
316
- if (schema.schema.type === 'string' && schema.schema.enum && Array.isArray(schema.schema.enum)) {
317
- // Generate union type for enum
318
- const enumValues = schema.schema.enum.map(val => `'${val}'`).join(' | ');
319
- content += `${doc}export type ${schema.typeName} = ${enumValues};\n\n`;
320
- } else {
321
- // Generate interface for object schema
322
- content += `${doc}export interface ${schema.typeName} {\n`;
323
- content += generateMessageInterface(schema.schema, schema.typeName);
324
- content += '\n}\n\n';
325
- }
326
-
327
- // Track generated types to avoid duplicates
328
- generatedTypes.add(schema.typeName);
5
+ export default function ({ asyncapi, params }) {
6
+ // Generate models using the common helper
7
+ const models = generateTypeScriptModels(asyncapi, {
8
+ includeMessageTypes: true // TypeScript client includes message type constants
329
9
  });
330
10
 
331
- // Generate interfaces for each message (only if not already generated as component schema)
332
- messageSchemas.forEach(schema => {
333
- const interfaceName = `${schema.typeName}Payload`;
334
-
335
- // Check if this is a duplicate of a component schema
336
- // For message payloads that match component schema names, skip the payload version
337
- if (generatedTypes.has(schema.typeName) || generatedTypes.has(interfaceName)) {
338
- // Skip generating the payload version if we already have the component schema
339
- return;
340
- }
341
-
342
- const doc = schema.description ? `/** ${schema.description} */\n` : `/** ${schema.name} message payload */\n`;
343
-
344
- content += `${doc}export interface ${interfaceName} {\n`;
345
- content += generateMessageInterface(schema.payload, schema.typeName);
346
- content += '\n}\n\n';
347
-
348
- generatedTypes.add(interfaceName);
349
- });
350
-
351
- // Generate a union type for all message payloads
352
- if (messageSchemas.length > 0) {
353
- const payloadTypes = messageSchemas.map(schema => `${schema.typeName}Payload`).join(' | ');
354
- content += '/** Union type for all message payloads */\n';
355
- content += `export type MessagePayload = ${payloadTypes};\n\n`;
356
-
357
- // Generate message type constants
358
- content += '/** Message type constants */\n';
359
- content += 'export const MessageTypes = {\n';
360
- messageSchemas.forEach(schema => {
361
- content += ` ${schema.typeName.toUpperCase()}: '${schema.name}',\n`;
362
- });
363
- content += '} as const;\n\n';
364
-
365
- content += '/** Message type union */\n';
366
- content += 'export type MessageType = typeof MessageTypes[keyof typeof MessageTypes];\n\n';
367
- }
368
-
369
- return content;
370
- }
371
-
372
- module.exports = function ({ asyncapi, params }) {
373
11
  return (
374
12
  <File name="models.ts">
375
- {generateModels(asyncapi)}
13
+ {`// Generated TypeScript models from AsyncAPI specification
14
+
15
+ ${models.generateComponentSchemas()}
16
+ ${models.generateMessageSchemas()}
17
+ ${models.generateMessageTypes()}
18
+ `}
376
19
  </File>
377
20
  );
378
- };
21
+ }