Skip to content

Commit

Permalink
fix: add v2-specific root properties to sorting alg (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
aeworxet committed Aug 18, 2024
1 parent a9b0788 commit 5b7fec4
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 3 deletions.
18 changes: 17 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,16 @@ export async function mergeIntoBaseFile(
}

// Purely decorative stuff, just to bring the order of the AsyncAPI Document's
// properties into a familiar form.
// root properties into a familiar form.
export function orderPropsAccToAsyncAPISpec(
inputAsyncAPIObject: any
): AsyncAPIObject {
const orderOfPropsAccToAsyncAPISpec = [
'asyncapi',
'id',
'info',
'tags', // v2-specific root property
'externalDocs', // v2-specific root property
'defaultContentType',
'servers',
'channels',
Expand All @@ -156,7 +158,21 @@ export function orderPropsAccToAsyncAPISpec(
];

const outputAsyncAPIObject: any = {};
let i = 0;

// Making the best guess where root properties that are not specified in the
// AsyncAPI Specification were located in the original AsyncAPI Document
// (inserting them between known root properties.)
// DISCLAIMER: The original order is not guaranteed, it is only an
// extrapolating guess.
for (const key of Object.keys(inputAsyncAPIObject)) {
if (!orderOfPropsAccToAsyncAPISpec.includes(key)) {
orderOfPropsAccToAsyncAPISpec.splice(i, 0, key);
}
i++;
}

// Merging of known AsyncAPI Object root properties in a familiar order.
for (const prop of orderOfPropsAccToAsyncAPISpec) {
if (inputAsyncAPIObject[`${prop}`]) {
outputAsyncAPIObject[`${prop}`] = structuredClone(
Expand Down
48 changes: 48 additions & 0 deletions tests/gh-185.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
asyncapi: '2.0.0'
x-company-attr-1: attr-value-1
x-company-attr-2: attr-value-2
id: 'urn:rpc:example:server'
defaultContentType: application/json

info:
title: RPC Server Example
description: This example demonstrates how to define an RPC server.
version: '1.0.0'
x-company-version: 1.2.3

tags:
- name: my-tag
description: tag description

channels:
'{queue}':
parameters:
queue:
schema:
type: string
pattern: '^amq\\.gen\\-.+$'
bindings:
amqp:
is: queue
queue:
exclusive: true
subscribe:
operationId: sendSumResult
bindings:
amqp:
ack: true
message:
correlationId:
location: $message.header#/correlation_id
payload:
type: object
properties:
result:
type: number
examples:
- 7

servers:
production:
url: rabbitmq.example.org
protocol: amqp
82 changes: 80 additions & 2 deletions tests/lib/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ describe('[integration testing] bundler should ', () => {
});

test('should be able to bundle specification files in subdirectories and merge them into the base file', async () => {
const object = {
const resultingObject = {
asyncapi: '3.0.0',
info: {
title: 'Streetlights MQTT API',
Expand Down Expand Up @@ -306,7 +306,85 @@ describe('[integration testing] bundler should ', () => {
noValidation: true,
});

expect(document.json()).toMatchObject(object);
expect(document.json()).toMatchObject(resultingObject);
});

test('should be able to bundle v2 YAML, leaving `x-` properties intact and sorting root props according to AsyncAPI Spec', async () => {
const resultingObject = {
asyncapi: '2.0.0',
'x-company-attr-1': 'attr-value-1',
'x-company-attr-2': 'attr-value-2',
id: 'urn:rpc:example:server',
defaultContentType: 'application/json',
info: {
title: 'RPC Server Example',
description: 'This example demonstrates how to define an RPC server.',
version: '1.0.0',
'x-company-version': '1.2.3',
},
tags: [
{
name: 'my-tag',
description: 'tag description',
},
],
servers: {
production: {
url: 'rabbitmq.example.org',
protocol: 'amqp',
},
},
channels: {
'{queue}': {
parameters: {
queue: {
schema: {
type: 'string',
pattern: '^amq\\\\.gen\\\\-.+$',
},
},
},
bindings: {
amqp: {
is: 'queue',
queue: {
exclusive: true,
},
},
},
subscribe: {
operationId: 'sendSumResult',
bindings: {
amqp: {
ack: true,
},
},
message: {
correlationId: {
location: '$message.header#/correlation_id',
},
payload: {
type: 'object',
properties: {
result: {
type: 'number',
examples: [7],
},
},
},
},
},
},
},
};

const files = 'tests/gh-185.yaml';

const document = await bundle(files, {
noValidation: true,
});

expect(document.json()).toMatchObject(resultingObject);
});
});

Expand Down

0 comments on commit 5b7fec4

Please sign in to comment.