Skip to content

Commit

Permalink
Merge 7314da8 into bb5d0ad
Browse files Browse the repository at this point in the history
  • Loading branch information
dougal83 committed Jan 26, 2020
2 parents bb5d0ad + 7314da8 commit 8ce24a5
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 1 deletion.
Expand Up @@ -5,7 +5,11 @@

import {expect} from '@loopback/testlab';
import {ParameterObject} from 'openapi3-ts';
import {anOpenApiSpec, anOperationSpec} from '../../openapi-spec-builder';
import {
aComponentsSpec,
anOpenApiSpec,
anOperationSpec,
} from '../../openapi-spec-builder';

describe('OpenAPI Spec Builder', () => {
describe('anOpenApiSpec', () => {
Expand Down Expand Up @@ -40,6 +44,14 @@ describe('OpenAPI Spec Builder', () => {
},
});
});

it('adds components', () => {
const comSpec = aComponentsSpec().build();
const spec = anOpenApiSpec()
.withComponents(comSpec)
.build();
expect(spec.components).to.containEql(comSpec);
});
});

describe('anOperationSpec', () => {
Expand Down Expand Up @@ -148,4 +160,94 @@ describe('OpenAPI Spec Builder', () => {
expect(spec.parameters).to.eql([apiKey, limit]);
});
});

describe('aComponentsSpec', () => {
it('adds a spec to schemas', () => {
const spec = aComponentsSpec()
.withSchema('TestSchema', {type: 'object'})
.build();
expect(spec).to.eql({
schemas: {TestSchema: {type: 'object'}},
});
});

it('adds a spec to responses', () => {
const spec = aComponentsSpec()
.withResponse('TestResponse', {description: 'test'})
.build();
expect(spec).to.eql({
responses: {TestResponse: {description: 'test'}},
});
});

it('adds a spec to parameters', () => {
const spec = aComponentsSpec()
.withParameter('TestParameter', {name: 'test', in: 'path'})
.build();
expect(spec).to.eql({
parameters: {TestParameter: {name: 'test', in: 'path'}},
});
});

it('adds a spec to examples', () => {
const spec = aComponentsSpec()
.withExample('TestExample', {description: 'test', anyProp: {}})
.build();
expect(spec).to.eql({
examples: {TestExample: {description: 'test', anyProp: {}}},
});
});

it('adds a spec to requestBodies', () => {
const spec = aComponentsSpec()
.withRequestBody('TestRequestBody', {content: {'application/json': {}}})
.build();
expect(spec).to.eql({
requestBodies: {TestRequestBody: {content: {'application/json': {}}}},
});
});

it('adds a spec to headers', () => {
const spec = aComponentsSpec()
.withHeader('TestHeader', {description: 'test'})
.build();
expect(spec).to.eql({
headers: {TestHeader: {description: 'test'}},
});
});

it('adds a spec to securitySchemes', () => {
const spec = aComponentsSpec()
.withSecurityScheme('TestSecurityScheme', {type: 'http'})
.build();
expect(spec).to.eql({
securitySchemes: {TestSecurityScheme: {type: 'http'}},
});
});

it('adds a spec to links', () => {
const spec = aComponentsSpec()
.withLink('TestLink', {description: 'test', anyProp: {}})
.build();
expect(spec).to.eql({
links: {TestLink: {description: 'test', anyProp: {}}},
});
});

it('adds a spec to callbacks', () => {
const spec = aComponentsSpec()
.withCallback('TestCallback', {anyProp: {}})
.build();
expect(spec).to.eql({
callbacks: {TestCallback: {anyProp: {}}},
});
});

it('adds an extension', () => {
const spec = aComponentsSpec()
.withExtension('x-loopback-test', 'test')
.build();
expect(spec).to.containEql({'x-loopback-test': 'test'});
});
});
});
161 changes: 161 additions & 0 deletions packages/openapi-spec-builder/src/openapi-spec-builder.ts
Expand Up @@ -5,12 +5,20 @@

import assert from 'assert';
import {
CallbackObject,
ComponentsObject,
ExampleObject,
HeaderObject,
ISpecificationExtension,
LinkObject,
OpenAPIObject,
OperationObject,
ParameterObject,
ReferenceObject,
RequestBodyObject,
ResponseObject,
SchemaObject,
SecuritySchemeObject,
} from 'openapi3-ts';

/**
Expand All @@ -29,6 +37,13 @@ export function anOperationSpec() {
return new OperationSpecBuilder();
}

/**
* Create a new instance of ComponentsSpecBuilder.
*/
export function aComponentsSpec() {
return new ComponentsSpecBuilder();
}

export class BuilderBase<T extends ISpecificationExtension> {
protected _spec: T;

Expand Down Expand Up @@ -122,6 +137,17 @@ export class OpenApiSpecBuilder extends BuilderBase<OpenAPIObject> {

return this.withOperation(verb, path, spec);
}

/**
* Define a new ComponentsObject.
*
* @param spec - Specification of the components.
*/
withComponents(spec: ComponentsObject | ComponentsSpecBuilder): this {
if (spec instanceof ComponentsSpecBuilder) spec = spec.build();
if (!this._spec.components) this._spec.components = spec;
return this;
}
}

/**
Expand Down Expand Up @@ -231,3 +257,138 @@ export class OperationSpecBuilder extends BuilderBase<OperationObject> {
return this;
}
}

/**
* A builder for creating ComponentsObject specifications.
*/
export class ComponentsSpecBuilder extends BuilderBase<ComponentsObject> {
constructor() {
super({});
}

/**
* Define a component schema.
*
* @param name - The name of the schema
* @param schema - Specification of the schema
*
*/
withSchema(name: string, schema: SchemaObject | ReferenceObject): this {
if (!this._spec.schemas) this._spec.schemas = {};
this._spec.schemas[name] = schema;
return this;
}

/**
* Define a component response.
*
* @param name - The name of the response
* @param response - Specification of the response
*
*/
withResponse(name: string, response: ResponseObject | ReferenceObject): this {
if (!this._spec.responses) this._spec.responses = {};
this._spec.responses[name] = response;
return this;
}

/**
* Define a component parameter.
*
* @param name - The name of the parameter
* @param parameter - Specification of the parameter
*
*/
withParameter(
name: string,
parameter: ParameterObject | ReferenceObject,
): this {
if (!this._spec.parameters) this._spec.parameters = {};
this._spec.parameters[name] = parameter;
return this;
}

/**
* Define a component example.
*
* @param name - The name of the example
* @param example - Specification of the example
*
*/
withExample(name: string, example: ExampleObject | ReferenceObject): this {
if (!this._spec.examples) this._spec.examples = {};
this._spec.examples[name] = example;
return this;
}

/**
* Define a component request body.
*
* @param name - The name of the request body
* @param requestBody - Specification of the request body
*
*/
withRequestBody(
name: string,
requestBody: RequestBodyObject | ReferenceObject,
): this {
if (!this._spec.requestBodies) this._spec.requestBodies = {};
this._spec.requestBodies[name] = requestBody;
return this;
}

/**
* Define a component header.
*
* @param name - The name of the header
* @param header - Specification of the header
*
*/
withHeader(name: string, header: HeaderObject | ReferenceObject): this {
if (!this._spec.headers) this._spec.headers = {};
this._spec.headers[name] = header;
return this;
}

/**
* Define a component security scheme.
*
* @param name - The name of the security scheme
* @param securityScheme - Specification of the security scheme
*
*/
withSecurityScheme(
name: string,
securityScheme: SecuritySchemeObject | ReferenceObject,
): this {
if (!this._spec.securitySchemes) this._spec.securitySchemes = {};
this._spec.securitySchemes[name] = securityScheme;
return this;
}

/**
* Define a component link.
*
* @param name - The name of the link
* @param link - Specification of the link
*
*/
withLink(name: string, link: LinkObject | ReferenceObject): this {
if (!this._spec.links) this._spec.links = {};
this._spec.links[name] = link;
return this;
}

/**
* Define a component callback.
*
* @param name - The name of the callback
* @param callback - Specification of the callback
*
*/
withCallback(name: string, callback: CallbackObject | ReferenceObject): this {
if (!this._spec.callbacks) this._spec.callbacks = {};
this._spec.callbacks[name] = callback;
return this;
}
}

0 comments on commit 8ce24a5

Please sign in to comment.