Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow servers and channels to be fetched from components #430

Merged
46 changes: 46 additions & 0 deletions lib/models/components.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const { createMapOfType, getMapValueOfType, mix } = require('./utils');

const Base = require('./base');
const Channel = require('./channel');
const Message = require('./message');
const Schema = require('./schema');
const SecurityScheme = require('./security-scheme');
const Server = require('./server');
const ChannelParameter = require('./channel-parameter');
const CorrelationId = require('./correlation-id');
const OperationTrait = require('./operation-trait');
Expand All @@ -20,6 +22,28 @@ const MixinSpecificationExtensions = require('../mixins/specification-extensions
* @returns {Components}
*/
class Components extends Base {
/**
* @returns {Object<string, Channel>}
*/
channels() {
return createMapOfType(this._json.channels, Channel);
}

/**
* @returns {boolean}
*/
hasChannels() {
return !!this._json.channels;
}

/**
* @param {string} name - Name of the channel.
* @returns {Channel}
*/
channel(name) {
return getMapValueOfType(this._json.channels, name, Channel);
}

/**
* @returns {Object<string, Message>}
*/
Expand Down Expand Up @@ -85,6 +109,28 @@ class Components extends Base {
securityScheme(name) {
return getMapValueOfType(this._json.securitySchemes, name, SecurityScheme);
}

/**
* @returns {Object<string, Server>}
*/
servers() {
return createMapOfType(this._json.servers, Server);
}

/**
* @returns {boolean}
*/
hasServers() {
return !!this._json.servers;
}

/**
* @param {string} name - Name of the server.
* @returns {Server}
*/
server(name) {
return getMapValueOfType(this._json.servers, name, Server);
}

/**
* @returns {Object<string, ChannelParameter>}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
},
"dependencies": {
"@apidevtools/json-schema-ref-parser": "^9.0.6",
"@asyncapi/specs": "^2.11.0",
"@asyncapi/specs": "asyncapi/spec-json-schemas#2022-01-release",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmvilas are you sure we should grab sources from github?
imho we should either pull a specific version from npm 2.13.0-2022-01-release.1 or just fix to the release candidate tag, so 2022-01-release

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: If we use 2022-01-release as version, it will point to the same code as latest commit in that branch? So it is the same as I added but pointing to the npm package tag instead of github branch, right? If so, I can change to it as IMHO it also makes sense as you said.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically if you point to 2022-01-release and you do npm install then @asyncapi/specs version 2.13.0-2022-01-release.1 will be installed, if 2 release candidate is available, then 2.13.0-2022-01-release.2 will be installed.

so yeah, might be that the best solution is to point to the 2022-01-release npm tag instead of a specific version each time

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done!

"@fmvilas/pseudo-yaml-ast": "^0.3.1",
"ajv": "^6.10.1",
"js-yaml": "^3.13.1",
Expand Down
102 changes: 102 additions & 0 deletions test/models/components_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,57 @@ const Components = require('../../lib/models/components');
const { assertMixinSpecificationExtensionsInheritance } = require('../mixins/specification-extensions_test');

describe('Components', function() {
describe('#channels()', function() {
it('should return a map of Channel objects', function() {
const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } };
const d = new Components(doc);
expect(typeof d.channels()).to.be.equal('object');
expect(d.channels().test1.constructor.name).to.equal('Channel');
expect(d.channels().test1.json()).to.equal(doc.channels.test1);
expect(d.channels().test2.constructor.name).to.equal('Channel');
expect(d.channels().test2.json()).to.equal(doc.channels.test2);
});

it('should return an empty object if the components field has no defined channels', function() {
const doc = {};
const d = new Components(doc);
expect(typeof d.channels()).to.be.equal('object');
expect(d.channels()).to.deep.equal({});
});
});

describe('#hasChannels()', function() {
it('should return a boolean indicating if the components field has channels', function() {
const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } };
const docNoChannels = { schemas: {} };
const d = new Components(doc);
const d2 = new Components(docNoChannels);
expect(d.hasChannels()).to.equal(true);
expect(d2.hasChannels()).to.equal(false);
});
});

describe('#channel()', function() {
it('should return a specific Channel object', function() {
const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } };
const d = new Components(doc);
expect(d.channel('test1').constructor.name).to.equal('Channel');
expect(d.channel('test1').json()).to.equal(doc.channels.test1);
});

it('should return null if a channel name is not provided', function() {
const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } };
const d = new Components(doc);
expect(d.channel()).to.equal(null);
});

it('should return null if a channel name is not found', function() {
const doc = { channels: { test1: { description: 'test1' }, test2: { description: 'test2' } } };
const d = new Components(doc);
expect(d.channel('not found')).to.equal(null);
});
});

describe('#messages()', function() {
it('should return a map of Message objects', function() {
const doc = { messages: { test1: { test: 'test1' }, test2: { test: 'test2' } } };
Expand Down Expand Up @@ -157,6 +208,57 @@ describe('Components', function() {
expect(d.securityScheme('not found')).to.equal(null);
});
});

describe('#servers()', function() {
it('should return a map of Server objects', function() {
const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } };
const d = new Components(doc);
expect(typeof d.servers()).to.be.equal('object');
expect(d.servers().test1.constructor.name).to.equal('Server');
expect(d.servers().test1.json()).to.equal(doc.servers.test1);
expect(d.servers().test2.constructor.name).to.equal('Server');
expect(d.servers().test2.json()).to.equal(doc.servers.test2);
});

it('should return an empty object if the components field has no defined servers', function() {
const doc = {};
const d = new Components(doc);
expect(typeof d.servers()).to.be.equal('object');
expect(d.servers()).to.deep.equal({});
});
});

describe('#hasServers()', function() {
it('should return a boolean indicating if the components field has servers', function() {
const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } };
const docNoServers = { schemas: {} };
const d = new Components(doc);
const d2 = new Components(docNoServers);
expect(d.hasServers()).to.equal(true);
expect(d2.hasServers()).to.equal(false);
});
});

describe('#server()', function() {
it('should return a specific Server object', function() {
const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } };
const d = new Components(doc);
expect(d.server('test1').constructor.name).to.equal('Server');
expect(d.server('test1').json()).to.equal(doc.servers.test1);
});

it('should return null if a message name is not provided', function() {
const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } };
const d = new Components(doc);
expect(d.server()).to.equal(null);
});

it('should return null if a message name is not found', function() {
const doc = { servers: { test1: { url: 'test1' }, test2: { url: 'test2' } } };
const d = new Components(doc);
expect(d.server('not found')).to.equal(null);
});
});

describe('#parameters()', function() {
it('should return a map of ChannelParameter objects', function() {
Expand Down