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(reference): support native fragment deref/resolve - AsyncAPI 2.x #2945

Merged
merged 1 commit into from
Jul 13, 2023
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,8 @@ const AsyncApi2DereferenceVisitor = stampit({
return undefined;
}

// @ts-ignore
const reference = await this.toReference(referencingElement.$ref?.toValue());
const retrievalURI = reference.uri;
const { uri: retrievalURI } = reference;
const $refBaseURI = url.resolve(retrievalURI, referencingElement.$ref?.toValue());

this.indirections.push(referencingElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ const AsyncApi2ResolveVisitor = stampit({
},

async crawlChannelItemElement(channelItemElement: ChannelItemElement) {
// @ts-ignore
const reference = await this.toReference(channelItemElement.$ref?.toValue());

this.indirections.push(channelItemElement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,145 +14,245 @@ describe('dereference', function () {
context('strategies', function () {
context('asyncapi-2', function () {
context('Reference Object', function () {
context('given single ReferenceElement passed to dereferenceApiDOM', function () {
context('given dereferencing using local file system', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'external-only', 'root.json');
context(
'given single ReferenceElement passed to dereferenceApiDOM with internal references',
function () {
context('given dereferencing using local file system', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'internal-only', 'root.json');

specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: fixturePath },
specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/userId',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: {
baseURI: `${fixturePath}#/components/parameters/userId`,
},
});

assert.isTrue(isParameterElement(dereferenced));
});

assert.isTrue(isParameterElement(dereferenced));
specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/userId',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `${fixturePath}#/components/parameters/userId` },
});

assert.match(
dereferenced.meta.get('ref-origin').toValue(),
/internal-only\/root\.json$/,
);
});
});

specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
context('given dereferencing using HTTP protocol', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'internal-only', 'root.json');
const httpPort = 8123;
let httpServer: ServerTerminable;

beforeEach(function () {
const cwd = path.join(__dirname, 'fixtures', 'internal-only');
httpServer = createHTTPServer({ port: httpPort, cwd });
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: fixturePath },

afterEach(async function () {
await httpServer.terminate();
});

assert.match(
dereferenced.meta.get('ref-origin').toValue(),
/external-only\/ex\.json$/,
);
});
});
specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/userId',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: {
baseURI: `http://localhost:${httpPort}/root.json#/components/parameters/userId`,
},
});

context('given dereferencing using HTTP protocol', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'external-only', 'root.json');
const httpPort = 8123;
let httpServer: ServerTerminable;
assert.isTrue(isParameterElement(dereferenced));
});

beforeEach(function () {
const cwd = path.join(__dirname, 'fixtures', 'external-only');
httpServer = createHTTPServer({ port: httpPort, cwd });
});
specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/userId',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: {
baseURI: `http://localhost:${httpPort}/root.json#/components/parameters/userId`,
},
});

afterEach(async function () {
await httpServer.terminate();
assert.match(dereferenced.meta.get('ref-origin').toValue(), /\/root\.json$/);
});
});
},
);

specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
context(
'given single ReferenceElement passed to dereferenceApiDOM with external references',
function () {
context('given dereferencing using local file system', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'external-only', 'root.json');

specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: fixturePath },
});

assert.isTrue(isParameterElement(dereferenced));
});

assert.isTrue(isParameterElement(dereferenced));
specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: fixturePath },
});

assert.match(
dereferenced.meta.get('ref-origin').toValue(),
/external-only\/ex\.json$/,
);
});
});

specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
context('given dereferencing using HTTP protocol', function () {
const fixturePath = path.join(__dirname, 'fixtures', 'external-only', 'root.json');
const httpPort = 8123;
let httpServer: ServerTerminable;

beforeEach(function () {
const cwd = path.join(__dirname, 'fixtures', 'external-only');
httpServer = createHTTPServer({ port: httpPort, cwd });
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },

afterEach(async function () {
await httpServer.terminate();
});

assert.match(dereferenced.meta.get('ref-origin').toValue(), /\/ex\.json$/);
});
});

context('given dereferencing using HTTP protocol and absolute URLs', function () {
const fixturePath = path.join(
__dirname,
'fixtures',
'external-only-absolute-url',
'root.json',
);
const httpPort = 8123;
let httpServer: ServerTerminable;

beforeEach(function () {
const cwd = path.join(__dirname, 'fixtures', 'external-only-absolute-url');
httpServer = createHTTPServer({ port: httpPort, cwd });
});
specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
});

afterEach(async function () {
await httpServer.terminate();
});
assert.isTrue(isParameterElement(dereferenced));
});

specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
});

assert.match(dereferenced.meta.get('ref-origin').toValue(), /\/ex\.json$/);
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
});

context('given dereferencing using HTTP protocol and absolute URLs', function () {
const fixturePath = path.join(
__dirname,
'fixtures',
'external-only-absolute-url',
'root.json',
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
});
const httpPort = 8123;
let httpServer: ServerTerminable;

assert.isTrue(isParameterElement(dereferenced));
});
beforeEach(function () {
const cwd = path.join(__dirname, 'fixtures', 'external-only-absolute-url');
httpServer = createHTTPServer({ port: httpPort, cwd });
});

specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
afterEach(async function () {
await httpServer.terminate();
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },

specify('should dereference', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
});

assert.isTrue(isParameterElement(dereferenced));
});

assert.match(dereferenced.meta.get('ref-origin').toValue(), /\/ex\.json$/);
specify('should dereference and contain metadata about origin', async function () {
const parseResult = await parse(fixturePath, {
parse: { mediaType: mediaTypes.latest('json') },
});
const referenceElement = evaluate(
'/components/parameters/externalRef',
parseResult.api as AsyncApi2Element,
);
const dereferenced = await dereferenceApiDOM(referenceElement, {
parse: { mediaType: mediaTypes.latest('json') },
resolve: { baseURI: `http://localhost:${httpPort}/root.json` },
});

assert.match(dereferenced.meta.get('ref-origin').toValue(), /\/ex\.json$/);
});
});
});
});
},
);
});
});
});
Expand Down