Skip to content

Commit

Permalink
fix: improve payloads generator (#136)
Browse files Browse the repository at this point in the history
- Fix problem where payloads was not generated if AsyncAPI document had no channels
- Remove unusable options for payload generator
- Payload generator now exposes other models generated
- Fix problem where wrong discriminator not found
- Fix sometimes serializer generates unusable code
- Fix payload sometimes gets unusable name
  • Loading branch information
jonaslagoni authored Oct 21, 2024
1 parent d961aa9 commit 82418e1
Show file tree
Hide file tree
Showing 12 changed files with 450 additions and 167 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ tmp
jest.config.js
website
playground/__gen__
test/codegen/generators/*/output
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ oclif.manifest.json
dist
coverage
test/config/src/__gen__/
playground
playground
test/codegen/generators/*/output
107 changes: 60 additions & 47 deletions src/codegen/generators/helpers/payloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import {
OutputModel
} from '@asyncapi/modelina';
import {AsyncAPIDocumentInterface} from '@asyncapi/parser';
import {PayloadRenderType} from '../../types';
import {ChannelPayload, PayloadRenderType} from '../../types';
import {pascalCase} from '../typescript/utils';
import {findNameFromChannel} from '../../utils';
type returnType = Record<
type ChannelReturnType = Record<
string,
{messageModel: OutputModel; messageType: string}
>;
Expand All @@ -17,61 +17,74 @@ export async function generateAsyncAPIPayloads<GeneratorType>(
generator: (input: any) => Promise<OutputModel[]>,
generatorConfig: GeneratorType
): Promise<PayloadRenderType<GeneratorType>> {
const returnType: returnType = {};
for (const channel of asyncapiDocument.allChannels().all()) {
let schemaObj: any = {
type: 'object',
$schema: 'http://json-schema.org/draft-07/schema'
};
const replyMessages = channel.messages().all();
const messages = channel.messages().all();
if (messages.length > 1) {
schemaObj.oneOf = [];
schemaObj['$id'] = pascalCase(`${findNameFromChannel(channel)}_Payload`);
for (const message of messages) {
const channelReturnType: ChannelReturnType = {};
let otherModels: ChannelPayload[] = [];
if (asyncapiDocument.allChannels().all().length > 0) {
for (const channel of asyncapiDocument.allChannels().all()) {
let schemaObj: any = {
type: 'object',
$schema: 'http://json-schema.org/draft-07/schema'
};
const replyMessages = channel.messages().all();
const messages = channel.messages().all();
if (messages.length > 1) {
schemaObj.oneOf = [];
schemaObj['$id'] = pascalCase(`${findNameFromChannel(channel)}_Payload`);
for (const message of messages) {
const schema = AsyncAPIInputProcessor.convertToInternalSchema(
message.payload() as any
);
if (typeof schema === 'boolean') {
schemaObj.oneOf.push(schema);
} else {
schemaObj.oneOf.push({
...schema,
$id: message.id()
});
}
}
} else if (messages.length === 1) {
const messagePayload = messages[0].payload();
const schema = AsyncAPIInputProcessor.convertToInternalSchema(
message.payload() as any
messagePayload as any
);

if (typeof schema === 'boolean') {
schemaObj.oneOf.push(schema);
schemaObj = schema;
} else {
schemaObj.oneOf.push({
...schema,
'x-modelgen-inferred-name': `${message.id()}`
});
schemaObj = {
...schemaObj,
...(schema as any),
$id: messages[0].id()
};
}
}
} else if (messages.length === 1) {
const schema = AsyncAPIInputProcessor.convertToInternalSchema(
messages[0].payload() as any
);

if (typeof schema === 'boolean') {
schemaObj = schema;
} else {
schemaObj = {
...schemaObj,
...(schema as any),
$id: `${messages[0].payload()?.id()}`
};
continue;
}
} else {
continue;
}
const models = await generator(schemaObj);
const messageModel = models[0].model;
let messageType = messageModel.type;
// Workaround from Modelina as rendering root payload model can create simple types and `.type` is no longer valid for what we use it for
if (!(messageModel instanceof ConstrainedObjectModel)) {
messageType = messageModel.name;
const models = await generator(schemaObj);
const messageModel = models[0].model;
let messageType = messageModel.type;
// Workaround from Modelina as rendering root payload model can create simple types and `.type` is no longer valid for what we use it for
if (!(messageModel instanceof ConstrainedObjectModel)) {
messageType = messageModel.name;
}
channelReturnType[channel.id()] = {
messageModel: models[0],
messageType
};
}
returnType[channel.id()] = {
messageModel: models[0],
messageType
};
} else {
const generatedModels = await generator(asyncapiDocument);
otherModels = generatedModels.map((model) => {
return {
messageModel: model,
messageType: model.model.type
};
});
}
return {
channelModels: returnType,
channelModels: channelReturnType,
otherModels,
generator: generatorConfig
};
}
Loading

0 comments on commit 82418e1

Please sign in to comment.