Skip to content

Commit eff11fb

Browse files
jonaslagoniclaude
andcommitted
feat: Generate JSDoc comments from schema descriptions (including @deprecated)
Resolves #338 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cf6ae51 commit eff11fb

117 files changed

Lines changed: 2535 additions & 302 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/codegen/generators/typescript/channels/openapi.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ import {
1313
} from './types';
1414
import {ConstrainedObjectModel} from '@asyncapi/modelina';
1515
import {collectProtocolDependencies} from './utils';
16-
import {
17-
renderHttpFetchClient,
18-
renderHttpCommonTypes
19-
} from './protocols/http';
16+
import {renderHttpFetchClient, renderHttpCommonTypes} from './protocols/http';
2017
import {getMessageTypeAndModule} from './utils';
2118
import {pascalCase} from '../utils';
2219
import {createMissingInputDocumentError} from '../../../errors';
@@ -220,6 +217,10 @@ function processOperation(
220217
return undefined;
221218
}
222219

220+
// Extract operation metadata for JSDoc
221+
const description = operation.description ?? operation.summary;
222+
const deprecated = operation.deprecated === true;
223+
223224
// Generate the HTTP client function
224225
return renderHttpFetchClient({
225226
subName: pascalCase(operationId),
@@ -239,7 +240,9 @@ function processOperation(
239240
channelParameters: parameterModel?.model as
240241
| ConstrainedObjectModel
241242
| undefined,
242-
includesStatusCodes: replyIncludesStatusCodes
243+
includesStatusCodes: replyIncludesStatusCodes,
244+
description,
245+
deprecated
243246
});
244247
}
245248

src/codegen/generators/typescript/channels/protocols/amqp/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
ChannelFunctionTypes,
77
TypeScriptChannelsGeneratorContext
88
} from '../../types';
9-
import {findNameFromOperation, findOperationId} from '../../../../../utils';
9+
import {
10+
findNameFromOperation,
11+
findOperationId,
12+
getOperationMetadata
13+
} from '../../../../../utils';
1014
import {getMessageTypeAndModule} from '../../utils';
1115
import {
1216
shouldRenderFunctionType,
@@ -113,11 +117,15 @@ async function generateForOperations(
113117
`Could not find message type for channel typescript generator for AMQP`
114118
);
115119
}
120+
// Extract operation metadata for JSDoc
121+
const {description, deprecated} = getOperationMetadata(operation);
116122
const updatedContext = {
117123
...amqpContext,
118124
messageType,
119125
messageModule,
120-
subName: findNameFromOperation(operation, channel)
126+
subName: findNameFromOperation(operation, channel),
127+
description,
128+
deprecated
121129
};
122130

123131
renders.push(

src/codegen/generators/typescript/channels/protocols/amqp/publishExchange.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {ChannelFunctionTypes} from '../..';
33
import {SingleFunctionRenderType} from '../../../../../types';
44
import {pascalCase} from '../../../utils';
55
import {RenderRegularParameters} from '../../types';
6+
import {renderChannelJSDoc} from '../../utils';
67

78
export function renderPublishExchange({
89
topic,
@@ -12,7 +13,9 @@ export function renderPublishExchange({
1213
channelHeaders,
1314
subName = pascalCase(topic),
1415
functionName = `publishTo${subName}Exchange`,
15-
additionalProperties
16+
additionalProperties,
17+
description,
18+
deprecated
1619
}: RenderRegularParameters<{
1720
exchange: string | undefined;
1821
}>): SingleFunctionRenderType {
@@ -83,11 +86,17 @@ channel.publish(exchange, routingKey, Buffer.from(dataToSend), publishOptions);`
8386
}
8487
];
8588

86-
const code = `/**
87-
* AMQP publish operation for exchange \`${topic}\`
88-
*
89-
${functionParameters.map((param) => param.jsDoc).join('\n')}
90-
*/
89+
const jsDoc = renderChannelJSDoc({
90+
description,
91+
deprecated,
92+
fallbackDescription: `AMQP publish operation for exchange \`${topic}\``,
93+
parameters: functionParameters.map((param) => ({
94+
name: param.parameter,
95+
jsDoc: param.jsDoc
96+
}))
97+
});
98+
99+
const code = `${jsDoc}
91100
function ${functionName}({
92101
${functionParameters.map((param) => param.parameter).join(', \n ')}
93102
}: {

src/codegen/generators/typescript/channels/protocols/amqp/publishQueue.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {ChannelFunctionTypes} from '../..';
33
import {SingleFunctionRenderType} from '../../../../../types';
44
import {pascalCase} from '../../../utils';
55
import {RenderRegularParameters} from '../../types';
6+
import {renderChannelJSDoc} from '../../utils';
67

78
export function renderPublishQueue({
89
topic,
@@ -11,7 +12,9 @@ export function renderPublishQueue({
1112
channelParameters,
1213
channelHeaders,
1314
subName = pascalCase(topic),
14-
functionName = `publishTo${subName}Queue`
15+
functionName = `publishTo${subName}Queue`,
16+
description,
17+
deprecated
1518
}: RenderRegularParameters): SingleFunctionRenderType {
1619
const addressToUse = channelParameters
1720
? `parameters.getChannelWithParameters('${topic}')`
@@ -80,11 +83,17 @@ channel.sendToQueue(queue, Buffer.from(dataToSend), publishOptions);`;
8083
}
8184
];
8285

83-
const code = `/**
84-
* AMQP publish operation for queue \`${topic}\`
85-
*
86-
${functionParameters.map((param) => param.jsDoc).join('\n')}
87-
*/
86+
const jsDoc = renderChannelJSDoc({
87+
description,
88+
deprecated,
89+
fallbackDescription: `AMQP publish operation for queue \`${topic}\``,
90+
parameters: functionParameters.map((param) => ({
91+
name: param.parameter,
92+
jsDoc: param.jsDoc
93+
}))
94+
});
95+
96+
const code = `${jsDoc}
8897
function ${functionName}({
8998
${functionParameters.map((param) => param.parameter).join(', \n ')}
9099
}: {

src/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {ChannelFunctionTypes} from '../..';
22
import {SingleFunctionRenderType} from '../../../../../types';
33
import {pascalCase} from '../../../utils';
44
import {RenderRegularParameters} from '../../types';
5-
import {getValidationFunctions} from '../../utils';
5+
import {getValidationFunctions, renderChannelJSDoc} from '../../utils';
66

77
export function renderSubscribeQueue({
88
topic,
@@ -12,7 +12,9 @@ export function renderSubscribeQueue({
1212
channelHeaders,
1313
subName = pascalCase(topic),
1414
functionName = `subscribeTo${subName}Queue`,
15-
payloadGenerator
15+
payloadGenerator,
16+
description,
17+
deprecated
1618
}: RenderRegularParameters): SingleFunctionRenderType {
1719
const includeValidation = payloadGenerator.generator.includeValidation;
1820
const addressToUse = channelParameters
@@ -116,11 +118,17 @@ channel.consume(queue, (msg) => {
116118
}
117119
];
118120

119-
const code = `/**
120-
* AMQP subscribe operation for queue \`${topic}\`
121-
*
122-
${functionParameters.map((param) => param.jsDoc).join('\n')}
123-
*/
121+
const jsDoc = renderChannelJSDoc({
122+
description,
123+
deprecated,
124+
fallbackDescription: `AMQP subscribe operation for queue \`${topic}\``,
125+
parameters: functionParameters.map((param) => ({
126+
name: param.parameter,
127+
jsDoc: param.jsDoc
128+
}))
129+
});
130+
131+
const code = `${jsDoc}
124132
function ${functionName}({
125133
${functionParameters.map((param) => param.parameter).join(', \n ')}
126134
}: {

src/codegen/generators/typescript/channels/protocols/eventsource/express.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {ChannelFunctionTypes} from '../..';
33
import {SingleFunctionRenderType} from '../../../../../types';
44
import {findRegexFromChannel, pascalCase} from '../../../utils';
55
import {RenderRegularParameters} from '../../types';
6+
import {renderChannelJSDoc} from '../../utils';
67

78
export function renderExpress({
89
topic,
@@ -11,7 +12,9 @@ export function renderExpress({
1112
channelParameters,
1213
channelHeaders,
1314
subName = pascalCase(topic),
14-
functionName = `register${subName}`
15+
functionName = `register${subName}`,
16+
description,
17+
deprecated
1518
}: RenderRegularParameters): SingleFunctionRenderType {
1619
let addressToUse = topic.replace(/{([^}]+)}/g, ':$1');
1720
addressToUse = addressToUse.startsWith('/')
@@ -64,7 +67,18 @@ export function renderExpress({
6467
}
6568
];
6669

67-
const code = `function ${functionName}({
70+
const jsDoc = renderChannelJSDoc({
71+
description,
72+
deprecated,
73+
fallbackDescription: `Register EventSource endpoint for \`${topic}\``,
74+
parameters: functionParameters.map((param) => ({
75+
name: param.parameter,
76+
jsDoc: param.jsDoc
77+
}))
78+
});
79+
80+
const code = `${jsDoc}
81+
function ${functionName}({
6882
${functionParameters.map((param) => param.parameter).join(', \n ')}
6983
}: {
7084
${functionParameters.map((param) => param.parameterType).join(', \n ')}

src/codegen/generators/typescript/channels/protocols/eventsource/fetch.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
defaultTypeScriptChannelsGenerator,
77
RenderRegularParameters
88
} from '../../types';
9-
import {getValidationFunctions} from '../../utils';
9+
import {getValidationFunctions, renderChannelJSDoc} from '../../utils';
1010

1111
export function renderFetch({
1212
topic,
@@ -19,7 +19,9 @@ export function renderFetch({
1919
additionalProperties = {
2020
fetchDependency: defaultTypeScriptChannelsGenerator.eventSourceDependency
2121
},
22-
payloadGenerator
22+
payloadGenerator,
23+
description,
24+
deprecated
2325
}: RenderRegularParameters<{
2426
fetchDependency: string;
2527
}>): SingleFunctionRenderType {
@@ -75,12 +77,23 @@ export function renderFetch({
7577
}
7678
];
7779

78-
const code = `/**
79-
* Event source fetch for \`${topic}\`
80-
*
81-
${functionParameters.map((param) => param.jsDoc).join('\n')}
82-
* @returns A cleanup function to abort the connection
83-
*/
80+
const jsDoc = renderChannelJSDoc({
81+
description,
82+
deprecated,
83+
fallbackDescription: `Event source fetch for \`${topic}\``,
84+
parameters: [
85+
...functionParameters.map((param) => ({
86+
name: param.parameter,
87+
jsDoc: param.jsDoc
88+
})),
89+
{
90+
name: 'returns',
91+
jsDoc: ' * @returns A cleanup function to abort the connection'
92+
}
93+
]
94+
});
95+
96+
const code = `${jsDoc}
8497
function ${functionName}({
8598
${functionParameters.map((param) => param.parameter).join(', \n ')}
8699
}: {

src/codegen/generators/typescript/channels/protocols/eventsource/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
ChannelFunctionTypes,
77
TypeScriptChannelsGeneratorContext
88
} from '../../types';
9-
import {findNameFromOperation, findOperationId} from '../../../../../utils';
9+
import {
10+
findNameFromOperation,
11+
findOperationId,
12+
getOperationMetadata
13+
} from '../../../../../utils';
1014
import {getMessageTypeAndModule} from '../../utils';
1115
import {
1216
shouldRenderFunctionType,
@@ -112,11 +116,15 @@ async function generateForOperations(
112116
`Could not find message type for channel typescript generator for EventSource`
113117
);
114118
}
119+
// Extract operation metadata for JSDoc
120+
const {description, deprecated} = getOperationMetadata(operation);
115121
const updatedContext = {
116122
...eventSourceContext,
117123
messageType,
118124
messageModule,
119-
subName: findNameFromOperation(operation, channel)
125+
subName: findNameFromOperation(operation, channel),
126+
description,
127+
deprecated
120128
};
121129

122130
renders.push(

src/codegen/generators/typescript/channels/protocols/http/client.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import {HttpRenderType} from '../../../../../types';
66
import {pascalCase} from '../../../utils';
77
import {ChannelFunctionTypes, RenderHttpParameters} from '../../types';
8+
import {renderChannelJSDoc} from '../../utils';
89

910
/**
1011
* Renders an HTTP fetch client function for a specific API operation.
@@ -20,7 +21,9 @@ export function renderHttpFetchClient({
2021
servers = [],
2122
subName = pascalCase(requestTopic),
2223
functionName = `${method.toLowerCase()}${subName}`,
23-
includesStatusCodes = false
24+
includesStatusCodes = false,
25+
description,
26+
deprecated
2427
}: RenderHttpParameters): HttpRenderType {
2528
const messageType = requestMessageModule
2629
? `${requestMessageModule}.${requestMessageType}`
@@ -43,6 +46,13 @@ export function renderHttpFetchClient({
4346
method
4447
);
4548

49+
// Generate JSDoc for the function
50+
const jsDoc = renderChannelJSDoc({
51+
description,
52+
deprecated,
53+
fallbackDescription: `HTTP ${method} request to ${requestTopic}`
54+
});
55+
4656
// Generate the function implementation
4757
const functionCode = generateFunctionImplementation({
4858
functionName,
@@ -55,7 +65,8 @@ export function renderHttpFetchClient({
5565
hasParameters,
5666
method,
5767
servers,
58-
includesStatusCodes
68+
includesStatusCodes,
69+
jsDoc
5970
});
6071

6172
const code = `${contextInterface}
@@ -122,6 +133,7 @@ function generateFunctionImplementation(params: {
122133
method: string;
123134
servers: string[];
124135
includesStatusCodes: boolean;
136+
jsDoc: string;
125137
}): string {
126138
const {
127139
functionName,
@@ -134,7 +146,8 @@ function generateFunctionImplementation(params: {
134146
hasParameters,
135147
method,
136148
servers,
137-
includesStatusCodes
149+
includesStatusCodes,
150+
jsDoc
138151
} = params;
139152

140153
const defaultServer = servers[0] ?? "'localhost:3000'";
@@ -170,7 +183,8 @@ function generateFunctionImplementation(params: {
170183
// Generate default context for optional context parameter
171184
const contextDefault = !hasBody && !hasParameters ? ' = {}' : '';
172185

173-
return `async function ${functionName}(context: ${contextInterfaceName}${contextDefault}): Promise<HttpClientResponse<${replyType}>> {
186+
return `${jsDoc}
187+
export async function ${functionName}(context: ${contextInterfaceName}${contextDefault}): Promise<HttpClientResponse<${replyType}>> {
174188
// Apply defaults
175189
const config = {
176190
path: '${requestTopic}',

0 commit comments

Comments
 (0)