Skip to content
Open
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
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Each input has its own limitations, corner cases, and features; thus, each has s
- [AsyncAPI](./inputs/asyncapi.md)
- [OpenAPI](./inputs/openapi.md)
- [JSON Schema](./inputs/jsonschema.md)
- [EventCatalog](./inputs/eventcatalog.md)

### Protocols
Each protocol has its own limitations, corner cases, and features; thus, each has separate documentation.
Expand Down
9 changes: 9 additions & 0 deletions docs/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ If no explicit configuration file is sat, it will be looked for in the following
- codegen.mjs
- codegen.cjs

## Input Types

The `inputType` field selects which input pipeline drives generation. Supported values:

- `'asyncapi'` — AsyncAPI 2.x / 3.x documents. See [AsyncAPI input](./inputs/asyncapi.md).
- `'openapi'` — Swagger 2.0 / OpenAPI 3.0 / 3.1 documents. See [OpenAPI input](./inputs/openapi.md).
- `'jsonschema'` — Standalone JSON Schema documents. See [JSON Schema input](./inputs/jsonschema.md).
- `'eventcatalog'` — An [EventCatalog](https://eventcatalog.dev) directory; the loader picks one service via the required `service` field and forwards generation through the AsyncAPI or OpenAPI pipeline. See [EventCatalog input](./inputs/eventcatalog.md).

## TypeScript Configuration

When generating TypeScript code, you can configure global options that apply to all generators. These options can be overridden per-generator if needed.
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,6 @@ Discover how The Codegen Project supports various messaging protocols like NATS,
### Explore Further
- **[Generator Documentation](../generators/README.md)** - Detailed documentation for each generator type
- **[Protocol Documentation](../protocols/)** - Complete protocol reference and implementation details
- **[Input Types](../inputs/)** - Learn about AsyncAPI, OpenAPI, and JSON Schema support
- **[Input Types](../inputs/)** - Learn about AsyncAPI, OpenAPI, JSON Schema, and EventCatalog support
- **[Examples](../../examples/)** - Real-world examples and integration patterns

146 changes: 146 additions & 0 deletions docs/inputs/eventcatalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
sidebar_position: 99
---

# EventCatalog

[EventCatalog](https://eventcatalog.dev) is a documentation tool that organizes events, services, and domains in a single browsable catalog. The Codegen Project can read an EventCatalog directory directly and generate code for a chosen service — no need to maintain a separate AsyncAPI/OpenAPI file alongside the catalog.

The loader is a translation layer: it picks the requested service, follows its `specifications` block (or its `sends`/`receives` events for native mode), and routes the run through the existing AsyncAPI or OpenAPI pipeline. As a result, every preset that works for those input types works here too.

## Supported Generators

| **Presets** | EventCatalog |
|---|---|
| [`payloads`](../generators/payloads.md) | ✅ |
| [`parameters`](../generators/parameters.md) | ✅ |
| [`headers`](../generators/headers.md) | ✅ |
| [`types`](../generators/types.md) | ✅ |
| [`channels`](../generators/channels.md) | ✅ |
| [`client`](../generators/client.md) | ✅ * |
| [`custom`](../generators/custom.md) | ✅ |
| [`models`](../generators/models.md) | ✅ |

\* The `client` preset is currently only generated when the resolved spec is AsyncAPI; OpenAPI services do not produce a client wrapper.

## Configuration

| Field | Required | Description |
|---|---|---|
| `inputType` | yes | Must be `'eventcatalog'`. |
| `inputPath` | yes | Path (or remote URL) to the EventCatalog root — the directory that contains `services/`. |
| `service` | yes | The `id` of the service inside `services/<id>/index.md` to generate from. |
| `specType` | no | Set to `'asyncapi'` or `'openapi'` to disambiguate when a service declares both `asyncapiPath` and `openapiPath`. |
| `auth` | no | Bearer / apiKey / custom auth used when the service's spec path is a remote URL. See [configurations guide](../configurations.md#remote-url-inputs). |

```js
export default {
inputType: 'eventcatalog',
inputPath: './eventcatalog',
service: 'user-service',
language: 'typescript',
generators: [
{ preset: 'payloads', outputPath: './src/payloads' },
{ preset: 'channels', outputPath: './src/channels', protocols: ['nats'] },
{ preset: 'client', outputPath: './src/client', protocols: ['nats'] }
]
};
```

## The three modes

The loader picks one of three modes based on the selected service's `index.md` frontmatter.

### 1. AsyncAPI service

The service declares an `asyncapiPath` under `specifications`. The loader reads that file and runs the AsyncAPI pipeline.

```yaml
---
id: user-service
name: User Service
specifications:
asyncapiPath: asyncapi.yaml
---
```

### 2. OpenAPI service

The service declares an `openapiPath` under `specifications`. The loader reads that file and runs the OpenAPI pipeline.

```yaml
---
id: petstore-api
name: Petstore API
specifications:
openapiPath: openapi.json
---
```

### 3. Native service (no `specifications`)

The service has no spec file but does list `sends` / `receives` events. The loader walks each referenced event under `events/<event-id>/`, reads its `schema.json` (or whatever `schemaPath` is set in the event's frontmatter), and **synthesizes an AsyncAPI 3.0 document** from the result. That synthesized document then drives every downstream generator, so presets like `channels` and `client` work seamlessly without you authoring an AsyncAPI file.

```yaml
---
id: order-service
name: Order Service
sends:
- id: OrderCreated
version: 1.0.0
receives:
- id: OrderShipped
version: 1.0.0
---
```

#### Native-mode synthesis rules

For each `sends[i]` event the synthesized document contains:
- a channel keyed by the event id, with a single message whose payload is the event's schema content
- an operation `send<EventId>` with `action: 'send'` referring to that channel

Each `receives[i]` event produces the same channel/message pair but with `action: 'receive'`. The synthesized `info` block uses:
- `info.title` = `service.name` (falls back to `service.id`)
- `info.version` = `service.version` (falls back to `'1.0.0'`)
- `info.description` = `service.summary` when present

If you need richer mappings — multi-message channels, parameters, status-code variants, etc. — author a real AsyncAPI document and reference it via `specifications.asyncapiPath` instead.

## Both-specs services

If a service declares **both** `asyncapiPath` and `openapiPath`, the loader needs to know which one to follow. Set `specType` on the configuration:

```js
export default {
inputType: 'eventcatalog',
inputPath: './eventcatalog',
service: 'order-service',
specType: 'openapi',
language: 'typescript',
generators: [/* … */]
};
```

If `specType` is missing the loader throws a descriptive error so the run fails early with a clear next step. Generating from both specs in a single run is **not supported** in this version (see the limitations section). The recommended workaround is to keep two separate config files — one with `specType: 'asyncapi'`, one with `specType: 'openapi'` — and run them independently.

## Remote URLs in `asyncapiPath` / `openapiPath`

If your service frontmatter points to a remote URL instead of a local file, the loader fetches it the same way the underlying input pipeline does. The `auth` field on your codegen configuration is passed through unchanged. See the [remote URL inputs section](../configurations.md#remote-url-inputs) of the configurations guide for the full set of auth options and security considerations.

## Examples

The repository ships three end-to-end examples under `examples/`:

- `examples/eventcatalog-asyncapi/` — a service backed by a real AsyncAPI 3.0 document
- `examples/eventcatalog-openapi/` — a service backed by an OpenAPI 3.0 document
- `examples/eventcatalog-native/` — a service with no spec file, demonstrating the native-mode synthesis

Each example contains an `eventcatalog/` directory plus a `codegen.config.mjs` that mirrors the snippets above. Running `npx codegen generate` inside any of the three produces the generated TypeScript directly.

## Limitations

- **Dual-spec generation in one run is not supported.** Use two configs and run them sequentially.
- **`domains/` and `flows/` are ignored.** Only the selected service plus the events it directly references are read.
- **Cross-service event references aren't resolved.** Events referenced via `receives` are loaded from the catalog's `events/<id>/` directory, not from the producing service.
- **Browser mode is not supported.** EventCatalog is filesystem-bound; the browser bundle returns a clear error when invoked with `specFormat: 'eventcatalog'`. Use AsyncAPI / OpenAPI / JSON Schema directly in the browser.
2 changes: 1 addition & 1 deletion docs/telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ Example configuration:
{
event: 'generator_used',
generator_type: 'payloads',
input_type: 'asyncapi', // Can be: asyncapi, openapi, jsonschema
input_type: 'asyncapi', // Can be: asyncapi, openapi, jsonschema, eventcatalog
input_source: 'remote_url', // Not the actual URL!
language: 'typescript',
options: '{"includeValidation":true,"serializationType":"json"}',
Expand Down
11 changes: 7 additions & 4 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ Initialize The Codegen Project in your project
```
USAGE
$ codegen init [--json] [--no-color] [--debug | | [--silent | -v | -q]] [--help] [--input-file <value>]
[--config-name <value>] [--input-type asyncapi|openapi] [--output-directory <value>] [--config-type
esm|json|yaml|ts] [--languages typescript] [--no-tty] [--include-payloads] [--include-headers] [--include-client]
[--include-parameters] [--include-channels] [--gitignore-generated]
[--config-name <value>] [--input-type asyncapi|openapi|jsonschema|eventcatalog] [--service <value>]
[--output-directory <value>] [--config-type esm|json|yaml|ts] [--languages typescript] [--no-tty]
[--include-payloads] [--include-headers] [--include-client] [--include-parameters] [--include-channels]
[--gitignore-generated]

FLAGS
-q, --quiet Only show errors and warnings
Expand All @@ -163,7 +164,7 @@ FLAGS
--include-payloads Include payloads generation, available for TypeScript
--input-file=<value> File path for the code generation input such as AsyncAPI document
--input-type=<option> Input file type
<options: asyncapi|openapi>
<options: asyncapi|openapi|jsonschema|eventcatalog>
--json Output results as JSON for scripting
--languages=<option> Which languages do you wish to generate code for?
<options: typescript>
Expand All @@ -172,6 +173,8 @@ FLAGS
--output-directory=<value> [default: ./] Output configuration location, path to where the configuration file
should be located. If relative path, the current working directory of the terminal
will be used
--service=<value> Service ID inside the EventCatalog directory (only used with
--input-type=eventcatalog)
--silent Suppress all output except fatal errors

DESCRIPTION
Expand Down
9 changes: 9 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ An example demonstrating how to generate complete, type-safe client SDKs for NAT
### [E-commerce AsyncAPI Types](./ecommerce-asyncapi-types/)
A comprehensive example showing how to generate TypeScript types from AsyncAPI specifications for an e-commerce messaging system.

### [EventCatalog + AsyncAPI](./eventcatalog-asyncapi/)
An example demonstrating how to generate TypeScript code from AsyncAPI specifications stored in an [EventCatalog](https://eventcatalog.dev/). Shows how to use The Codegen Project with EventCatalog's service documentation structure.

### [EventCatalog + OpenAPI](./eventcatalog-openapi/)
An example demonstrating how to generate a TypeScript HTTP client from OpenAPI specifications stored in an [EventCatalog](https://eventcatalog.dev/). Shows how to use The Codegen Project with EventCatalog's API documentation structure.

### [EventCatalog Native](./eventcatalog-native/)
An example showing the native EventCatalog structure with markdown documentation and JSON Schema files, without AsyncAPI or OpenAPI specifications. Demonstrates generating models directly from EventCatalog event schemas.

## Getting Started

1. Choose an example that matches your use case
Expand Down
9 changes: 9 additions & 0 deletions examples/eventcatalog-asyncapi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Generated code
src/

# Dependencies
node_modules/
eventcatalog/node_modules/

# Build artifacts
.eventcatalog/
72 changes: 72 additions & 0 deletions examples/eventcatalog-asyncapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# EventCatalog + AsyncAPI Example

This example demonstrates the **proposed** EventCatalog integration where a service has an AsyncAPI specification attached.

> **Note**: This is a showcase of the proposed `inputType: 'eventcatalog'` configuration. This feature does not exist yet.

## Configuration

```javascript
// codegen.config.mjs
export default {
inputType: 'eventcatalog',
inputPath: './eventcatalog',
service: 'user-service', // Service with asyncapiPath
language: 'typescript',
generators: [
{ preset: 'payloads', outputPath: './src/payloads' },
{ preset: 'channels', outputPath: './src/channels', protocols: ['nats'] },
{ preset: 'client', outputPath: './src/client', protocols: ['nats'] },
],
};
```

## How It Works

1. Read EventCatalog at `./eventcatalog`
2. Find `user-service` in `services/`
3. Detect `asyncapiPath: asyncapi.yaml` in service metadata
4. Load and parse the AsyncAPI spec
5. Generate code using AsyncAPI processing

## Service Metadata

The service's `index.md` declares its AsyncAPI spec:

```yaml
---
id: user-service
name: User Service
version: 1.0.0
specifications:
asyncapiPath: asyncapi.yaml # <-- Auto-detected
---
```

## Project Structure

```
eventcatalog-asyncapi/
├── codegen.config.mjs
├── eventcatalog/
│ ├── eventcatalog.config.js
│ ├── domains/user-domain/index.md
│ ├── services/user-service/
│ │ ├── index.md # Has asyncapiPath in metadata
│ │ └── asyncapi.yaml # AsyncAPI 3.0 spec
│ └── events/UserSignedUp/index.md
└── src/ # Generated code
```

## Auto-Detection Logic

| Service Metadata | Processing |
|------------------|------------|
| `asyncapiPath: ...` | AsyncAPI processing |
| `openapiPath: ...` | OpenAPI processing |
| Neither (just `sends`/`receives`) | Native JSON Schema |

## Related Examples

- [eventcatalog-openapi](../eventcatalog-openapi/) - Service with OpenAPI spec
- [eventcatalog-native](../eventcatalog-native/) - Service with native JSON Schema events
47 changes: 47 additions & 0 deletions examples/eventcatalog-asyncapi/codegen.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Codegen configuration for EventCatalog with an AsyncAPI service.
*
* The loader reads the selected service's frontmatter, sees that
* user-service declares `specifications.asyncapiPath: asyncapi.yaml`,
* and routes generation through the AsyncAPI pipeline.
*
* @type {import("@the-codegen-project/cli").TheCodegenConfiguration}
*/
export default {
inputType: 'eventcatalog',
inputPath: './eventcatalog',
language: 'typescript',

// Select which service to generate code for
service: 'user-service',

generators: [
{
preset: 'payloads',
outputPath: './src/payloads',
serializationType: 'json',
},
{
preset: 'parameters',
outputPath: './src/parameters',
},
{
preset: 'headers',
outputPath: './src/headers',
},
{
preset: 'types',
outputPath: './src',
},
{
preset: 'channels',
outputPath: './src/channels',
protocols: ['nats'],
},
{
preset: 'client',
outputPath: './src/client',
protocols: ['nats'],
},
],
};
Loading
Loading