Skip to content

Commit

Permalink
Merge branch 'master' into update_browser_export
Browse files Browse the repository at this point in the history
  • Loading branch information
smoya authored Mar 12, 2024
2 parents 7684893 + 8fdf233 commit 592e691
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 79 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/bump.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ jobs:
run: test -e ./package.json && echo "exists=true" >> $GITHUB_OUTPUT || echo "exists=false" >> $GITHUB_OUTPUT
- if: steps.packagejson.outputs.exists == 'true'
name: Bumping latest version of this package in other repositories
uses: derberg/npm-dependency-manager-for-your-github-org@26a4f13d740254719971325046822a169aaa7441 # using v5.-.- https://github.com/derberg/npm-dependency-manager-for-your-github-org/releases/tag/v5.0.0
uses: derberg/npm-dependency-manager-for-your-github-org@3df56be95bcaa5c76a9c9a4af863ab151545b649 # using v6.-.- https://github.com/derberg/npm-dependency-manager-for-your-github-org/releases/tag/v6
with:
github_token: ${{ secrets.GH_TOKEN }}
committer_username: asyncapi-bot
committer_email: [email protected]
repos_to_ignore: spec,bindings
repos_to_ignore: spec,bindings,saunter
52 changes: 26 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@asyncapi/parser",
"version": "3.0.2",
"version": "3.0.7",
"description": "JavaScript AsyncAPI parser.",
"bugs": {
"url": "https://github.com/asyncapi/parser-js/issues"
Expand Down Expand Up @@ -44,7 +44,7 @@
"prepublishOnly": "npm run generate:assets"
},
"dependencies": {
"@asyncapi/specs": "^6.2.0",
"@asyncapi/specs": "^6.5.0",
"@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0",
"@stoplight/json": "^3.20.2",
"@stoplight/json-ref-readers": "^1.2.2",
Expand All @@ -65,7 +65,7 @@
"node-fetch": "2.6.7"
},
"devDependencies": {
"@asyncapi/avro-schema-parser": "^3.0.9",
"@asyncapi/avro-schema-parser": "^3.0.15",
"@jest/types": "^29.0.2",
"@swc/core": "^1.2.248",
"@swc/jest": "^0.2.22",
Expand Down
35 changes: 24 additions & 11 deletions src/custom-operations/apply-unique-ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,36 @@ import { xParserObjectUniqueId } from '../constants';
/**
* This function applies unique ids for objects whose key's function as ids, ensuring that the key is part of the value.
*
* For v3; Apply unique ids to channel's, and message's
* For v3; Apply unique ids to all channel's, operations, and message's.
*/
export function applyUniqueIds(structure: any) {
const asyncapiVersion = structure.asyncapi.charAt(0);
switch (asyncapiVersion) {
case '3':
if (structure.channels) {
for (const [channelId, channel] of Object.entries(structure.channels as Record<string, any>)) {
channel[xParserObjectUniqueId] = channelId;
if (channel.messages) {
for (const [messageId, message] of Object.entries(channel.messages as Record<string, any>)) {
message[xParserObjectUniqueId] = messageId;
}
}
}
applyUniqueIdToChannels(structure.channels);
applyUniqueIdToObjects(structure.operations);
if (structure.components) {
applyUniqueIdToObjects(structure.components.messages);
applyUniqueIdToObjects(structure.components.operations);
applyUniqueIdToChannels(structure.components.channels);
}
break;
}
}


function applyUniqueIdToChannels(channels: any) {
for (const [channelId, channel] of Object.entries((channels ?? {}) as Record<string, any>)) {
if (!channel[xParserObjectUniqueId]) {
channel[xParserObjectUniqueId] = channelId;
}
applyUniqueIdToObjects(channel.messages);
}
}

function applyUniqueIdToObjects(objects: any) {
for (const [objectKey, object] of Object.entries((objects ?? {}) as Record<string, any>)) {
if (!object[xParserObjectUniqueId]) {
object[xParserObjectUniqueId] = objectKey;
}
}
}
5 changes: 3 additions & 2 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ export async function parse(parser: Parser, spectral: Spectral, asyncapi: Input,
} else {
loadedObj = asyncapi;
}
// Apply unique ids before resolving references
applyUniqueIds(loadedObj);
const { validated, diagnostics, extras } = await validate(parser, spectral, loadedObj, { ...options.validateOptions, source: options.source, __unstable: options.__unstable });
if (validated === undefined) {
return {
Expand All @@ -71,6 +69,9 @@ export async function parse(parser: Parser, spectral: Spectral, asyncapi: Input,

// unfreeze the object - Spectral makes resolved document "freezed"
const validatedDoc = copy(validated as Record<string, any>);

// Apply unique ids which are used as part of iterating between channels <-> operations <-> messages
applyUniqueIds(validatedDoc);
const detailed = createDetailedAsyncAPI(validatedDoc, loadedObj as DetailedAsyncAPI['input'], options.source);
const document = createAsyncAPIDocument(detailed);
setExtension(xParserSpecParsed, true, document);
Expand Down
102 changes: 67 additions & 35 deletions test/custom-operations/apply-traits-v3.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ describe('custom operations - apply traits v3', function() {
const v3Document = document as AsyncAPIDocumentV3;
expect(v3Document).toBeInstanceOf(AsyncAPIDocumentV3);

const someOperation1 = v3Document?.json()?.operations?.someOperation1;
const someOperation1 = v3Document?.json()?.operations?.someOperation1 as v3.OperationObject;
delete someOperation1?.traits;
expect(someOperation1).toEqual({ action: 'send', channel: { 'x-parser-unique-object-id': 'channel1' }, description: 'another description' });
expect(someOperation1).toEqual({ action: 'send', channel: { 'x-parser-unique-object-id': 'channel1' }, description: 'another description', 'x-parser-unique-object-id': 'someOperation1' });

const someOperation2 = v3Document?.json()?.operations?.someOperation2;
const someOperation2 = v3Document?.json()?.operations?.someOperation2 as v3.OperationObject;
delete someOperation2?.traits;
expect(someOperation2).toEqual({ action: 'send', channel: { 'x-parser-unique-object-id': 'channel1' }, description: 'root description' });
expect(someOperation2).toEqual({ action: 'send', channel: { 'x-parser-unique-object-id': 'channel1' }, description: 'root description', 'x-parser-unique-object-id': 'someOperation2' });
});

it('should apply traits to messages (channels)', async function() {
Expand Down Expand Up @@ -111,11 +111,11 @@ describe('custom operations - apply traits v3', function() {
const v3Document = document as AsyncAPIDocumentV3;
expect(v3Document).toBeInstanceOf(AsyncAPIDocumentV3);

const message1 = v3Document?.json()?.channels?.someChannel1?.messages?.someMessage;
const message1 = (v3Document?.json()?.channels?.someChannel1 as v3.ChannelObject).messages?.someMessage;
delete (message1 as v3.MessageObject)?.traits;
expect(message1).toEqual({ summary: 'some summary', description: 'another description', 'x-parser-message-name': 'someMessage', 'x-parser-unique-object-id': 'someMessage' });

const message2 = v3Document?.json()?.channels?.someChannel2?.messages?.someMessage;
const message2 = (v3Document?.json()?.channels?.someChannel2 as v3.ChannelObject).messages?.someMessage;
delete (message2 as v3.MessageObject)?.traits;
expect(message2).toEqual({ summary: 'root summary', description: 'root description', 'x-parser-message-name': 'someMessage', 'x-parser-unique-object-id': 'someMessage' });
});
Expand Down Expand Up @@ -163,14 +163,14 @@ describe('custom operations - apply traits v3', function() {

const message1 = v3Document?.json()?.components?.messages?.someMessage1;
delete (message1 as v3.MessageObject)?.traits;
expect(message1).toEqual({ summary: 'some summary', description: 'another description', 'x-parser-message-name': 'someMessage1' });
expect(message1).toEqual({ summary: 'some summary', description: 'another description', 'x-parser-message-name': 'someMessage1', 'x-parser-unique-object-id': 'someMessage1' });

const message2 = v3Document?.json()?.components?.messages?.someMessage2;
delete (message2 as v3.MessageObject)?.traits;
expect(message2).toEqual({ summary: 'root summary', description: 'root description', 'x-parser-message-name': 'someMessage2' });
expect(message2).toEqual({ summary: 'root summary', description: 'root description', 'x-parser-message-name': 'someMessage2', 'x-parser-unique-object-id': 'someMessage2' });
});

it('iterative functions should still work after traits have been applied', async function() {
describe('iterative functions should still work after traits have been applied', function() {
const documentRaw = {
asyncapi: '3.0.0',
info: {
Expand All @@ -187,7 +187,7 @@ describe('custom operations - apply traits v3', function() {
'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured': {
address: 'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured',
messages: {
'receiveLightMeasurement.message': {
lightMeasured: {
$ref: '#/components/messages/lightMeasured'
}
},
Expand All @@ -213,7 +213,7 @@ describe('custom operations - apply traits v3', function() {
],
messages: [
{
$ref: '#/components/messages/lightMeasured'
$ref: '#/channels/smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured/messages/lightMeasured'
}
]
}
Expand Down Expand Up @@ -290,32 +290,64 @@ describe('custom operations - apply traits v3', function() {
}
}
};
const { document } = await parser.parse(documentRaw);

const v3Document = document as AsyncAPIDocumentV3;
expect(v3Document).toBeInstanceOf(AsyncAPIDocumentV3);
let v3Document: AsyncAPIDocumentV3;
const expectedOperationId = 'receiveLightMeasurement';
const expectedChannelId = 'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured';
const operations = v3Document.operations();
expect(operations.length).toEqual(1);
const operation = operations[0];
expect(operation.id()).toEqual(expectedOperationId);
const operationChannels = operation.channels().all();
expect(operationChannels.length).toEqual(1);
const lightMeasuredChannel = operationChannels[0];
expect(lightMeasuredChannel.json()[xParserObjectUniqueId]).toEqual(expectedChannelId);
const channelOperations = lightMeasuredChannel.operations().all();
expect(channelOperations.length).toEqual(1);
const circularOperation = channelOperations[0];
expect(circularOperation.id()).toEqual(expectedOperationId);
const expectedMessageId = 'lightMeasured';

beforeAll(async () => {
const { document, diagnostics } = await parser.parse(documentRaw);
expect(diagnostics.length).toEqual(0);
v3Document = document as AsyncAPIDocumentV3;
});

it('should be able to go from operation -> channel', () => {
const operations = v3Document.operations().all();
expect(operations.length).toEqual(1);
const operation = operations[0];
expect(operation.id()).toEqual(expectedOperationId);
const operationChannels = operation.channels().all();
expect(operationChannels.length).toEqual(1);
const lightMeasuredChannel = operationChannels[0];
expect(lightMeasuredChannel.json()[xParserObjectUniqueId]).toEqual(expectedChannelId);
const messages = lightMeasuredChannel.messages().all();
expect(messages.length).toEqual(1);
const message = messages[0];
expect(message.id()).toEqual(expectedMessageId);
});

it('should be able to go from channel -> operation', () => {
const channels = v3Document.channels().all();
expect(channels.length).toEqual(1);
const channel = channels[0];
expect(channel.json()[xParserObjectUniqueId]).toEqual(expectedChannelId);
const channelOperations = channel.operations().all();
expect(channelOperations.length).toEqual(1);
const operation = channelOperations[0];
expect(operation.id()).toEqual(expectedOperationId);
const messages = operation.messages().all();
expect(messages.length).toEqual(1);
const message = messages[0];
expect(message.id()).toEqual(expectedMessageId);
});

const channels = v3Document.channels();
expect(channels.length).toEqual(1);
const channel = channels[0];
expect(channel.json()[xParserObjectUniqueId]).toEqual(expectedChannelId);
const channelOperations2 = channel.operations().all();
expect(channelOperations2.length).toEqual(1);
const operation2 = channelOperations2[0];
expect(operation2.id()).toEqual(expectedOperationId);
it('should be able to go in full circle operation -> channel -> operation', () => {
const operations = v3Document.operations().all();
expect(operations.length).toEqual(1);
const operation = operations[0];
expect(operation.id()).toEqual(expectedOperationId);
const operationChannels = operation.channels().all();
expect(operationChannels.length).toEqual(1);
const lightMeasuredChannel = operationChannels[0];
expect(lightMeasuredChannel.json()[xParserObjectUniqueId]).toEqual(expectedChannelId);
const channelOperations = lightMeasuredChannel.operations().all();
expect(channelOperations.length).toEqual(1);
const circularOperation = channelOperations[0];
expect(circularOperation.id()).toEqual(expectedOperationId);
const messages = circularOperation.messages().all();
expect(messages.length).toEqual(1);
const message = messages[0];
expect(message.id()).toEqual(expectedMessageId);
});
});
});
Loading

0 comments on commit 592e691

Please sign in to comment.