Skip to content

Commit

Permalink
feat: add initial v3 converter support (#180)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Gornicki <[email protected]>%0ACo-authored-by: Maciej Urbańczyk <[email protected]>%0ACo-authored-by: Matatjahu <[email protected]>
  • Loading branch information
jonaslagoni and magicmatatjahu authored Jul 24, 2023
1 parent 64f27e0 commit 211fc48
Show file tree
Hide file tree
Showing 11 changed files with 1,388 additions and 4 deletions.
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Convert [AsyncAPI](https://asyncapi.com) documents older to newer versions.
* [From CLI](#from-cli)
* [In JS](#in-js)
* [In TS](#in-ts)
- [Conversion 2.x.x to 3.x.x](#conversion-2xx-to-3xx)
- [Known missing features](#known-missing-features)
- [Development](#development)
- [Contribution](#contribution)
Expand Down Expand Up @@ -91,6 +92,75 @@ try {
}
```

## Conversion 2.x.x to 3.x.x

> **NOTE**: This feature is still WIP, and is until the final release of `3.0.0`.
Conversion to version `3.x.x` from `2.x.x` has several assumptions that should be know before converting:

- The input must be valid AsyncAPI document.
- External references are not resolved and converted, they remain untouched, even if they are incorrect.
- In version `3.0.0`, the channel identifier is no longer its address, but due to the difficulty of defining a unique identifier, we still treat the address as an identifier. If there is a need to assign an identifier other than an address, an `x-channelId` extension should be defined at the level of the given channel.

```yaml
# 2.x.x
channels:
users/signup:
x-channelId: 'userSignUp'
...
users/logout:
...

# 3.0.0
channels:
userSignUp:
...
users/logout:
...
```
- The `publish` operation is treated as a `receive` action, and `subscribe` is treated as a `send` action. Conversion by default is embraced from the application perspective. If you want to change this logic, you need to specify `v2tov3.pointOfView` configuration as `client`.
- If the operation does not have an `operationId` field defined, the unique identifier of the operation will be defined as a combination of the identifier of the channel on which the operation was defined + the type of operation, `publish` or `subscribe`. Identical situation is with messages. However, here the priority is the `messageId` field and then the concatenation `{publish|subscribe}.messages.{optional index of oneOf messages}`.

```yaml
# 2.x.x
channels:
users/signup:
publish:
message:
...
subscribe:
operationId: 'userSignUpEvent'
message:
oneOf:
- messageId: 'userSignUpEventMessage'
...
- ...
# 3.0.0
channels:
users/signup:
messages:
publish.message:
...
userSignUpEventMessage:
...
userSignUpEvent.message.1:
...
operations:
users/signup.publish:
action: receive
...
userSignUpEvent:
action: send
...
```

- Security requirements that use scopes are defined in the appropriate places inline, the rest as a reference to the `components.securitySchemes` objects.
- If servers are defined at the channel level, they are converted as references to the corresponding objects defined in the `servers` field.
- Channels and servers defined in components are also converted (unless configured otherwise).

## Known missing features

* When converting from 1.x to 2.x, Streaming APIs (those using `stream` instead of `topics` or `events`) are converted correctly but information about framing type and delimiter is missing until a [protocolInfo](https://github.com/asyncapi/extensions-catalog/issues/1) for that purpose is created.
Expand Down
4 changes: 3 additions & 1 deletion src/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { dump } from 'js-yaml';

import { converters as firstConverters } from "./first-version";
import { converters as secondConverters } from "./second-version";
import { converters as thirdConverters } from "./third-version";

import { serializeInput } from "./utils";

Expand All @@ -12,7 +13,8 @@ import type { AsyncAPIDocument, ConvertVersion, ConvertOptions, ConvertFunction
*/
const converters: Record<string, ConvertFunction> = {
...firstConverters,
...secondConverters
...secondConverters,
...thirdConverters,
};
const conversionVersions = Object.keys(converters);

Expand Down
14 changes: 12 additions & 2 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@
* PUBLIC TYPES
*/
export type AsyncAPIDocument = { asyncapi: string } & Record<string, any>;
export type ConvertVersion = '1.1.0' | '1.2.0' | '2.0.0-rc1' | '2.0.0-rc2' | '2.0.0' | '2.1.0' | '2.2.0' | '2.3.0' | '2.4.0' | '2.5.0' | '2.6.0';
export type ConvertOptions = { }
export type ConvertVersion = '1.1.0' | '1.2.0' | '2.0.0-rc1' | '2.0.0-rc2' | '2.0.0' | '2.1.0' | '2.2.0' | '2.3.0' | '2.4.0' | '2.5.0' | '2.6.0' | '3.0.0';
export type ConvertV2ToV3Options = {
idGenerator?: (data: { asyncapi: AsyncAPIDocument, kind: 'channel' | 'operation' | 'message', key: string | number | undefined, path: Array<string | number>, object: any, parentId?: string }) => string,
pointOfView?: 'application' | 'client',
useChannelIdExtension?: boolean;
convertServerComponents?: boolean;
convertChannelComponents?: boolean;
}
export type ConvertOptions = {
v2tov3?: ConvertV2ToV3Options;
}

/**
* PRIVATE TYPES
*/
export type ConvertFunction = (asyncapi: AsyncAPIDocument, options: ConvertOptions) => AsyncAPIDocument;

Loading

0 comments on commit 211fc48

Please sign in to comment.