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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

# Core Features
- 📃 From your [AsyncAPI v2 and v3](https://the-codegen-project.org/docs/inputs/asyncapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [protocol helpers](https://the-codegen-project.org/docs/generators/channels), [full clients](https://the-codegen-project.org/docs/generators/client), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above.
- 📃 From your [Swagger 2.0, or OpenAPI 3.0, and 3.1](https://the-codegen-project.org/docs/inputs/openapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above.
- 📃 From your [Swagger 2.0, or OpenAPI 3.0, and 3.1](https://the-codegen-project.org/docs/inputs/openapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [protocol helpers](https://the-codegen-project.org/docs/generators/channels), [full clients](https://the-codegen-project.org/docs/generators/client), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above.
- 📃 From your [JSON Schema Draft-4, Draft-6 and Draft-7](https://the-codegen-project.org/docs/inputs/jsonschema) schemas, generate [models](https://the-codegen-project.org/docs/generators/models) or [completely customize it](https://the-codegen-project.org/docs/generators/custom).
- 📊 Every generator fully customizable to fit your hearts desire
- 👀 Integrate it into any project (Demos in [Next.JS](./examples/typescript-nextjs), [TypeScript Libraries](./examples/typescript-library))
Expand Down
5 changes: 3 additions & 2 deletions docs/generators/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export default {
};
```

`channels` preset with `asyncapi` input generates support functions for each operation based on the selected protocol.
`channels` preset generates support functions for each operation based on the selected protocol.

This generator uses [`payloads`](./payloads.md), [`headers`](./headers.md) and [`parameters`](./parameters.md) generators, in case you dont have any defined, it will automatically include them with default values.

This is supported through the following inputs: [`asyncapi`](../inputs/asyncapi.md)
This is supported through the following inputs: [`asyncapi`](../inputs/asyncapi.md), [`openapi`](../inputs/openapi.md)

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

Expand All @@ -43,6 +43,7 @@ These are the available options for the `channels` generator;
## TypeScript
Regardless of protocol, these are the dependencies:
- If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1
- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1

Depending on which protocol, these are the dependencies:
- `NATS`: https://github.com/nats-io/nats.js v2
Expand Down
24 changes: 15 additions & 9 deletions docs/generators/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ export {Payload};
import {Parameters} from './parameters/Parameters';

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

import * as Nats from 'nats';

Expand Down Expand Up @@ -96,15 +95,22 @@ export class NatsClient {
/**
* Try to connect to the NATS server with the different payloads.
*/
connect(options: Nats.ConnectionOptions, codec?: Nats.Codec<any><any>): Promise<void> {
connect(
options: Nats.ConnectionOptions,
codec?: Nats.Codec<any>
): Promise<{nc: Nats.NatsConnection, js: Nats.JetStreamClient}> {
...
}

public async jetStreamPublishToChannel(
message: Payload,
parameters: Parameters,
options: Partial<Nats.JetStreamPublishOptions> = {}
): Promise<void> {

public async jetStreamPublishToChannel({
message,
parameters,
options = {}
}: {
message: PayloadInterface | Payload,
parameters: Parameters,
options?: Partial<Nats.JetStreamPublishOptions>
}): Promise<void> {
...
}
jetStreamPullSubscribeToChannel
Expand Down
4 changes: 2 additions & 2 deletions docs/generators/custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ export default {
{
preset: 'custom',
...
renderFunction: ({generator, inputType, asyncapiDocument, openapiDocument, dependencyOutputs})
{
renderFunction: ({generator, inputType, asyncapiDocument, openapiDocument, jsonSchemaDocument, dependencyOutputs}) => {
const modelinaGenerator = new JavaFileGenerator({});
modelinaGenerator.generateCompleteModels(...)
}
Expand Down Expand Up @@ -71,4 +70,5 @@ In the `renderFunction` you have access to a bunch of arguments to help you crea
- `inputType` - is the root `inputType` for the input document
- `asyncapiDocument` - is the parsed AsyncAPI document input (according to the [AsyncAPI parser](https://github.com/asyncapi/parser-js/)), undefined if the `inputType` is not `asyncapi`
- `openapiDocument` - is the parsed OpenAPI document input (according to the [readme/openapi-parser](https://github.com/readmeio/oas)), undefined if the `inputType` is not `openapi`
- `jsonSchemaDocument` - is the parsed JSON Schema document input, undefined if the `inputType` is not `jsonschema`
- `dependencyOutputs` - if you have defined any `dependencies`, this is where you can access the output. Checkout the [dependency documentation](#dependencies) for more information.
12 changes: 12 additions & 0 deletions docs/generators/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,21 @@ The `headers` preset with `openapi` input generates all the headers for each pat

The return type is a map of paths and the model that represent the headers.

## Options
These are the available options for the `headers` generator;

| **Option** | Default | Type | Description |
|---|---|---|---|
| id | `'headers-typescript'` | String | Unique identifier for this generator instance. The `channels`/`client` generators reference it as their `headerGeneratorId`. |
| dependencies | `[]` | String[] | IDs of other generators that must run before this one. |
| outputPath | `'src/__gen__/headers'` | String | Directory the generated header models are written to. |
| serializationType | `'json'` | `'json'` | Serialization format used by the generated models. Only `json` is supported. |
| includeValidation | `true` | Boolean | Include the built-in JSON Schema `validate`/`createValidator` methods. Requires `ajv` and `ajv-formats` (see [Dependencies](#typescript)). |

## Typescript
Dependencies:
- If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1
- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1

### Validation
Each generated class includes built-in JSON Schema validation capabilities through two static methods:
Expand Down
3 changes: 2 additions & 1 deletion docs/generators/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,11 @@ The TypeScript implementation provides full access to Modelina's TypeScript gene
|--------|------|---------|-------------|
| `modelType` | `'class' \| 'interface'` | `'class'` | Type of models to generate |
| `enumType` | `'enum' \| 'union'` | `'enum'` | How to render enum types |
| `mapType` | `'indexedObject' \| 'record'` | `'record'` | How to render map/dictionary types |
| `mapType` | `'indexedObject' \| 'map' \| 'record'` | `'map'` | How to render map/dictionary types |
| `moduleSystem` | `'CJS' \| 'ESM'` | `'ESM'` | Module system to use |
| `rawPropertyNames` | `boolean` | `false` | Use raw property names without transformation |
| `useJavascriptReservedKeywords` | `boolean` | `true` | Allow JavaScript reserved keywords |
| `isolatedModules` | `boolean` | `false` | Emit `export type` / `import type` for type-only models. Required for projects using TypeScript's `isolatedModules` (Next.js, SWC, esbuild) |

**Common Presets**:

Expand Down
23 changes: 23 additions & 0 deletions docs/generators/payloads.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ free-function marshalling — they have no companion interface and are exported
a single symbol. See the [protocols documentation](../protocols) for how each
channel accepts payloads.

## Options
These are the available options for the `payloads` generator;

| **Option** | Default | Type | Description |
|---|---|---|---|
| id | `'payloads-typescript'` | String | Unique identifier for this generator instance. Other generators reference it as a dependency, and the `channels`/`client` generators use it as their `payloadGeneratorId`. |
| dependencies | `[]` | String[] | IDs of other generators that must run before this one. |
| outputPath | `'src/__gen__/payloads'` | String | Directory the generated payload models are written to. |
| serializationType | `'json'` | `'json'` | Serialization format used by the generated models. Only `json` is supported. |
| enum | `'enum'` | `'enum' \| 'union'` | Render enums as TypeScript `enum`s, or as string/number union types. |
| map | `'record'` | `'indexedObject' \| 'map' \| 'record'` | Render dictionary/map types as `Record<K, V>`, the `Map` class, or an index signature. |
| useForJavaScript | `true` | Boolean | Apply JavaScript restrictions so the models stay valid when transpiled to JavaScript (for example avoiding reserved keywords as identifiers). |
| includeValidation | `true` | Boolean | Include the built-in JSON Schema `validate`/`createValidator` methods. Requires `ajv` and `ajv-formats` (see [Dependencies](#typescript)). |
| rawPropertyNames | `false` | Boolean | Keep the raw property names from the input schema. Consumers then access them with `obj["propertyName"]` instead of `obj.propertyName`. |

The global [`importExtension`](../configurations.md#import-extensions-node16nodenextverbatimmodulesyntax) option also applies to the imports between generated payload models.

## Languages
Each language has a set of constraints which means that some typed model types are either supported or not, or it might just be the code generation library that does not yet support it.

Expand All @@ -67,6 +84,12 @@ Each language has a set of constraints which means that some typed model types a

Dependencies:
- If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1
- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1

> `ajv-formats` v3 follows RFC 3339 more strictly than v2 did. Most notably,
> `format: time` now requires a time offset, so `"10:30:00"` is rejected while
> `"10:30:00Z"` and `"10:30:00+02:00"` are accepted. Pin `ajv-formats@^2` if you
> need the previous, more lenient behaviour.

#### Validation
Each generated class includes built-in JSON Schema validation capabilities through two static methods:
Expand Down
35 changes: 20 additions & 15 deletions docs/getting-started/generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ Generators take your specifications (AsyncAPI, OpenAPI, or JSON Schema) and extr
```js
export default {
inputType: 'asyncapi',
inputPath: './my-api.yaml'
inputPath: './my-api.yaml',
generators: [
{ preset: 'payloads', outputPath: './src/__gen__/payloads' }
]
};
```

Expand Down Expand Up @@ -65,27 +68,29 @@ Each generator produces different code, so have a look at each generator to get

**Payload Generator** produces:
```typescript
// A companion interface is exported alongside the class, so you can construct
// a payload from a plain object.
export interface UserSignupInterface { /* ... */ }
export class UserSignup {
constructor(data: UserSignupData) { /* ... */ }
constructor(input: UserSignupInterface) { /* ... */ }
marshal(): string { /* ... */ }
static unmarshal(json: string): UserSignup { /* ... */ }
static unmarshal(json: string | object): UserSignup { /* ... */ }
}
```

**Channels Generator** produces:
```typescript
export const Protocols = {
nats: {
publishToUserSignup: ...,
subscribeToUserSignup: ...,
jetStreamPublishToUserSignup: ...
},
kafka: {
publishToUserSignup: ...,
subscribeToUserSignup: ...
},
// ... other protocols
};
// One module per protocol, re-exported from the generated barrel file
import * as nats from './nats';
import * as kafka from './kafka';

export { nats, kafka };

// nats.publishToUserSignup({ message, nc })
// nats.subscribeToUserSignup({ onDataCallback, nc })
// nats.jetStreamPublishToUserSignup({ message, js })
// kafka.produceToUserSignup({ message, kafka })
// kafka.consumeFromUserSignup({ onDataCallback, kafka, options })
```

## Input Type Support
Expand Down
27 changes: 18 additions & 9 deletions docs/getting-started/protocols.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,29 @@ export default {

The `channels` generator creates protocol-specific functions for each channel in your AsyncAPI specification:

```typescript
import { Protocols } from './src/__gen__/index';
Each protocol is exported as its own namespace from the generated barrel file,
and every generated function takes a single object argument:

const { nats, kafka } = Protocols;
```typescript
import { nats, kafka } from './src/__gen__/channels';

// NATS functions
await nats.publishToUserSignup(connection, message);
await nats.subscribeToUserSignup(connection, callback);

// Kafka functions
await kafka.publishToUserSignup(producer, message);
await kafka.subscribeToUserSignup(consumer, callback);
await nats.publishToUserSignup({ message, nc: connection });
await nats.subscribeToUserSignup({ onDataCallback: callback, nc: connection });

// Kafka functions — note Kafka uses produceTo/consumeFrom
await kafka.produceToUserSignup({ message, kafka: kafkaClient });
await kafka.consumeFromUserSignup({
onDataCallback: callback,
kafka: kafkaClient,
options: { fromBeginning: true, groupId: 'my-group' }
});
```

The exact parameters depend on the channel — channels with parameters also take
`parameters`, and channels with headers accept `headers`. See each protocol's
page for the full generated signatures.

Each protocol has unique features that are reflected in the generated code:

**NATS** supports:
Expand Down
4 changes: 2 additions & 2 deletions docs/inputs/asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ Generate AMQP producers and consumers for message queuing.
}
},
"x-the-codegen-project": {
"functionTypeMapping": ["amqp_publish"]
"functionTypeMapping": ["amqp_queue_publish"]
}
},
"consumeOrders": {
Expand All @@ -756,7 +756,7 @@ Generate AMQP producers and consumers for message queuing.
}
},
"x-the-codegen-project": {
"functionTypeMapping": ["amqp_consume"]
"functionTypeMapping": ["amqp_queue_subscribe"]
}
}
},
Expand Down
3 changes: 2 additions & 1 deletion docs/migrations/v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ await jetStreamPublishToSendUserSignedup({
await publishToSendUserSignedup({
message,
parameters,
connection
nc
});

// Subscribing
Expand Down Expand Up @@ -248,5 +248,6 @@ import * as NodeFetch from 'node-fetch';






20 changes: 13 additions & 7 deletions docs/protocols/amqp.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ import * as Amqp from 'amqplib';
// Location depends on the payload generator configurations
import { UserSignedup } from './__gen__/payloads/UserSignedup';
// Location depends on the channel generator configurations
import { Protocols } from './__gen__/channels';
const { amqp } = Protocols;
import { amqp } from './__gen__/channels';
const { publishToPublishUserSignupsExchange, publishToPublishUserSignupsQueue, subscribeToConsumeUserSignupsQueue } = amqp;

/**
Expand All @@ -81,13 +80,20 @@ const client = await Amqp.connect('amqp://localhost');
const myPayload = new UserSignedup({displayName: 'test', email: 'test@test.dk'});

// Use exchange
await publishToPublishUserSignupsExchange(myPayload, client);
await publishToPublishUserSignupsExchange({ message: myPayload, amqp: client });

// Use queue
await publishToPublishUserSignupsQueue(myPayload, client);
await subscribeToConsumeUserSignupsQueue((message) => {
console.log(`Received message: ${message.displayName}, ${message.email}`);
}, client);
await publishToPublishUserSignupsQueue({ message: myPayload, amqp: client });
await subscribeToConsumeUserSignupsQueue({
onDataCallback: ({ err, msg, headers, amqpMsg }) => {
if (err) {
console.error('Error receiving message:', err);
return;
}
console.log(`Received message: ${msg?.displayName}, ${msg?.email}`);
},
amqp: client
});
```
</td>
</tr>
Expand Down
37 changes: 20 additions & 17 deletions docs/protocols/eventsource.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,28 +75,31 @@ import express, { Router } from 'express'
// Location depends on the payload generator configurations
import { UserSignedup } from './__gen__/payloads/UserSignedup';
// Location depends on the channel generator configurations
import { Protocols } from './__gen__/channels';
const { event_source_client } = Protocols;
const { listenForUserSignedup } = event_source_client;
const listenCallback = async (
messageEvent: UserSignedUp | null,
parameters: UserSignedUpParameters | null,
error?: string
) => {
// Do stuff once you receive the event from the server
};
listenForUserSignedup(listenCallback, {baseUrl: 'http://localhost:3000'})
import { event_source } from './__gen__/channels';
const { listenForUserSignedup, registerSendUserSignedup } = event_source;

// Use express to listen for clients registering for events
// The client-side listener takes an object callback
listenForUserSignedup({
callback: ({ error, messageEvent }) => {
// Do stuff once you receive the event from the server
},
options: { baseUrl: 'http://localhost:3000' }
})

// Use express to listen for clients registering for events. The Express
// handler keeps Express' own positional (req, res, next) convention.
const router = Router()
const app = express()
app.use(express.json({ limit: '3000kb' }))
app.use(express.urlencoded({ extended: true }))
registerSendUserSignedup(router, (req, res, next, parameters, sendEvent) => {
//Do stuff when client starts listening to the event.
//For example send a message to the client
const testMessage = new UserSignedup({displayName: 'test', email: 'test@test.dk'});
sendEvent(testMessage);
registerSendUserSignedup({
router,
callback: (req, res, next, parameters, sendEvent) => {
//Do stuff when client starts listening to the event.
//For example send a message to the client
const testMessage = new UserSignedup({displayName: 'test', email: 'test@test.dk'});
sendEvent(testMessage);
}
})
app.use(router)
app.listen(3000)
Expand Down
Loading
Loading