Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/generators/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ All available generators, across languages and inputs:
- [`parameters`](./parameters.md)
- [`custom`](./custom.md)
- [`channels`](./channels.md)
- [`client`](./client.md)

| **Inputs** | [`payloads`](./payloads.md) | [`parameters`](./parameters.md) | [`channels`](./channels.md) | [`custom`](./custom.md) |
| **Inputs** | [`payloads`](./payloads.md) | [`parameters`](./parameters.md) | [`channels`](./channels.md) | [`client`](./client.md) | [`custom`](./custom.md) |
|---|---|---|---|---|
| AsyncAPI | X | X | X | X |
| AsyncAPI | X | X | X | X | X |

| **Languages** | [`payloads`](./payloads.md) | [`parameters`](./parameters.md) | [`channels`](./channels.md) | [`custom`](./custom.md) |
| **Languages** | [`payloads`](./payloads.md) | [`parameters`](./parameters.md) | [`channels`](./channels.md) | [`client`](./client.md) | [`custom`](./custom.md) |
|---|---|---|---|---|
| TypeScript | X | X | X | X |
| TypeScript | X | X | X | X | X |
12 changes: 6 additions & 6 deletions docs/generators/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ sidebar_position: 99
export default {
...,
generators: [
{
preset: 'channels',
outputPath: './src/__gen__/',
language: 'typescript',
protocols: ['nats']
}
{
preset: 'channels',
outputPath: './src/__gen__/',
language: 'typescript',
protocols: ['nats']
}
]
};
```
Expand Down
173 changes: 173 additions & 0 deletions docs/generators/client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
sidebar_position: 99
---

# Client

```js
export default {
...,
generators: [
{
preset: 'client',
outputPath: './src/__gen__/',
language: 'typescript',
protocols: ['nats']
}
]
};
```

`client` preset with `asyncapi` input generates for each protocol a class (`{Protocol}Client`) that makes it easier to interact with the protocol.

It will generate;
- Support function for connecting to the protocol
- Simpler functions then those generated by [`channels`](./channels.md) to interact with the given protocols
- Exporting all generated [`parameters`](./parameters.md)
- Exporting all generated [`payloads`](./payloads.md)

This generator uses `channels` generators, in case you dont have any defined, it will automatically include them with default values and dependencies.

This is supported through the following inputs: [`asyncapi`](#inputs)

It supports the following languages; [`typescript`](#typescript)

It supports the following protocols; [`nats`](../protocols/nats.md)

## TypeScript

### Nats

Dependencies;
- `NATS`: https://github.com/nats-io/nats.js v2

For Nats the `NatsClient` is generated that setups the correct [Nats.js](https://github.com/nats-io/nats.js) clients, marshalling codex, and provide simplier functions to improve DX.

Example;
```ts
//Import and export payload models
import {ComAdeoCasestudyCostingrequestCostingRequestPayload} from './payload/ComAdeoCasestudyCostingrequestCostingRequestPayload';
import {ComAdeoCasestudyCostingresponseCostingResponsePayload} from './payload/ComAdeoCasestudyCostingresponseCostingResponsePayload';
export {ComAdeoCasestudyCostingrequestCostingRequestPayload};
export {ComAdeoCasestudyCostingresponseCostingResponsePayload};

//Import and export parameter models
import {CostingRequestChannelParameters} from './parameters/CostingRequestChannelParameters';
export {CostingRequestChannelParameters};

//Import channel functions
import { Protocols } from './channels/index';
const { nats } = Protocols;

import * as Nats from 'nats';

/**
* @class NatsClient
*/
export class NatsClient {
public nc?: Nats.NatsConnection;
public js?: Nats.JetStreamClient;
public codec?: Nats.Codec<any>;
public options?: Nats.ConnectionOptions;

/**
* Disconnect all clients from the server
*/
async disconnect() {
if (!this.isClosed() && this.nc !== undefined) {
await this.nc.drain();
}
}
/**
* Returns whether or not any of the clients are closed
*/
isClosed() {
if (!this.nc || this.nc!.isClosed()) {
return true;
}
return false;
}
/**
* Try to connect to the NATS server with user credentials
*
* @param userCreds to use
* @param options to connect with
*/
async connectWithUserCreds(userCreds: string, options ? : Nats.ConnectionOptions, codec ? : Nats.Codec < any > ) {
await this.connect({
user: userCreds,
...options
}, codec);
}
/**
* Try to connect to the NATS server with user and password
*
* @param user username to use
* @param pass password to use
* @param options to connect with
*/
async connectWithUserPass(user: string, pass: string, options ? : Nats.ConnectionOptions, codec ? : Nats.Codec < any > ) {
await this.connect({
user: user,
pass: pass,
...options
}, codec);
}
/**
* Try to connect to the NATS server which has no authentication

* @param host to connect to
* @param options to connect with
*/
async connectToHost(host: string, options ? : Nats.ConnectionOptions, codec ? : Nats.Codec < any > ) {
await this.connect({
servers: [host],
...options
}, codec);
}

/**
* Try to connect to the NATS server with the different payloads.
* @param options to use, payload is omitted if sat in the AsyncAPI document.
*/
connect(options: Nats.ConnectionOptions, codec?: Nats.Codec<any>): Promise<void> {
return new Promise(async (resolve: () => void, reject: (error: any) => void) => {
if (!this.isClosed()) {
return reject('Client is still connected, please close it first.');
}
this.options = options;
if (codec) {
this.codec = codec;
} else {
this.codec = Nats.JSONCodec();
}
try {
this.nc = await Nats.connect(this.options);
this.js = this.nc.jetstream();
resolve();
} catch (e: any) {
reject('Could not connect to NATS server');
}
})
}

/**
*
*
* @param message to publish
* @param parameters for topic substitution
* @param options to use while publishing the message
*/
public async jetStreamPublishToCostingRequestChannel(
message: ComAdeoCasestudyCostingrequestCostingRequestPayload, parameters: CostingRequestChannelParameters, options: Partial<Nats.JetStreamPublishOptions> = {}
): Promise<void> {
if (!this.isClosed() && this.nc !== undefined && this.codec !== undefined && this.js !== undefined) {
return nats.jetStreamPublishToCostingRequestChannel(message, parameters, this.js, this.codec, options);
} else {
Promise.reject('Nats client not available yet, please connect or set the client');
}
}

..., jetStreamPullSubscribeTo..., jetStreamPushSubscriptionFrom..., publishTo..., subscribeTo
}
```
2 changes: 1 addition & 1 deletion docs/protocols/nats.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebar_position: 99

[NATS is an open-source, high-performance messaging system designed for cloud-native, distributed systems, and Internet of Things (IoT) applications](https://nats.io/). Developed by Synadia, NATS stands out for its simplicity, lightweight architecture, and low latency, making it ideal for real-time messaging. It supports a variety of messaging patterns including publish-subscribe, request-reply, and queueing.

It is one of the first protocols for The Codegen Project to support, here is what is currently available through the generators ([channels](../generators/channels.md)):
It is one of the first protocols for The Codegen Project to support, here is what is currently available through the generators ([channels](../generators/channels.md) and [client](../generators/client.md)):

| **Languages** | Core publish | Core subscribe | JetStream publish | JetStream pull subscribe | JetStream push subscription
|---|---|---|---|---|---|
Expand Down
40 changes: 38 additions & 2 deletions src/codegen/generators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {
defaultTypeScriptPayloadGenerator,
TypeScriptChannelsGenerator,
generateTypeScriptChannels,
defaultTypeScriptChannelsGenerator
defaultTypeScriptChannelsGenerator,
TypeScriptClientGenerator,
defaultTypeScriptClientGenerator,
generateTypeScriptClient
} from './typescript';
import {defaultCustomGenerator, CustomGenerator} from './generic/custom';
import {TypeScriptPayloadGeneratorInternal} from './typescript/payloads';
Expand All @@ -26,6 +29,7 @@ import {TypeScriptChannelsGeneratorInternal} from './typescript/channels';
import {loadConfigFile} from '../configuration-manager';
import {loadAsyncapi} from '../inputs/asyncapi';
import {runGenerators} from '..';
import { TypeScriptClientGeneratorInternal } from './typescript/client';

export {
TypeScriptChannelsGenerator,
Expand All @@ -37,8 +41,11 @@ export {
TypescriptParametersGenerator,
generateTypescriptParameters,
defaultTypeScriptParametersOptions,
TypeScriptClientGenerator,
defaultTypeScriptClientGenerator,
generateTypeScriptClient,
CustomGenerator,
defaultCustomGenerator
defaultCustomGenerator,
};

export async function renderGenerator(
Expand Down Expand Up @@ -124,6 +131,28 @@ export async function renderGenerator(
}
}

case 'client': {
switch (language) {
case 'typescript': {
return generateTypeScriptClient({
asyncapiDocument,
generator: {
...generator,
outputPath
} as TypeScriptClientGeneratorInternal,
inputType: configuration.inputType,
dependencyOutputs: renderedContext
});
}

default: {
throw new Error(
'Unable to determine language generator for channels preset'
);
}
}
}

case 'custom': {
return generator.renderFunction(
{
Expand Down Expand Up @@ -158,6 +187,13 @@ export function getDefaultConfiguration(
default:
return undefined;
}
case 'client':
switch (language) {
case 'typescript':
return defaultTypeScriptClientGenerator;
default:
return undefined;
}
case 'custom':
return defaultCustomGenerator;
case 'parameters':
Expand Down
Loading