Skip to content

Commit 76486ce

Browse files
committed
feat: adding API serialization
Signed-off-by: Pawel Psztyc <[email protected]>
1 parent 36ef40e commit 76486ce

File tree

11 files changed

+469
-38
lines changed

11 files changed

+469
-38
lines changed

apis/arc-demo-api/arc-demo-api.raml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ documentation:
115115
- title: Test doc
116116
content: Test content
117117

118+
securedBy: [basic]
118119

119120
/test-parameters/{feature}:
120121
(deprecated): This endpoint is deprecated and will be removed.

apis/petstore/petstore.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ info:
1616
termsOfService: 'http://swagger.io/terms/'
1717
contact:
1818
19+
name: Swagger IO
20+
url: swagger.io
1921
license:
2022
name: Apache 2.0
2123
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@api-components/amf-helper-mixin",
33
"description": "A mixin with common functions user by most AMF components to compute AMF values",
4-
"version": "4.5.12",
4+
"version": "4.5.13",
55
"license": "Apache-2.0",
66
"main": "index.js",
77
"module": "index.js",

src/AmfHelperMixin.d.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { AmfDocument, AsyncApi, DomainElement, Endpoint, Operation, Parameter, Payload, Request, Response, SecurityRequirement, SecurityScheme, Server, Shape, WebApi } from './amf';
1+
import {
2+
AmfDocument, AsyncApi, DomainElement, EndPoint, Operation, Parameter, Payload, Request, Response,
3+
SecurityRequirement, SecurityScheme, Server, Shape, WebApi, Api
4+
} from './amf';
25
import { Namespace } from './Namespace';
36
import { ComputeUriOptions, ServerQueryOptions, ServersQueryOptions } from './types';
47

@@ -281,7 +284,7 @@ interface AmfHelperMixin {
281284
* @param model AMF data model
282285
* @returns List of encodes
283286
*/
284-
_computeEncodes(model: AmfDocument): DomainElement[]|undefined;
287+
_computeEncodes(model: AmfDocument): Api|undefined;
285288

286289
/**
287290
* Computes list of declarations in the AMF api model.
@@ -376,20 +379,20 @@ interface AmfHelperMixin {
376379
* @returns Endpoint's URI
377380
* @deprecated Use `_computeUri()` instead
378381
*/
379-
_computeEndpointUri(server: Server, endpoint: Endpoint, baseUri?: string, version?: string): string|undefined;
382+
_computeEndpointUri(server: Server, endpoint: EndPoint, baseUri?: string, version?: string): string|undefined;
380383

381384
/**
382385
* Computes endpoint's URI based on `endpoint` model.
383386
*
384387
* @param endpoint Model for the endpoint
385388
* @param opts Configuration options
386389
*/
387-
_computeUri(endpoint: Endpoint, opts?: ComputeUriOptions): string;
390+
_computeUri(endpoint: EndPoint, opts?: ComputeUriOptions): string;
388391

389392
/**
390393
* Appends endpoint's path to the url
391394
*/
392-
_appendPath(url: string, endpoint: Endpoint): string;
395+
_appendPath(url: string, endpoint: EndPoint): string;
393396

394397
/**
395398
* Computes base URI value from either `baseUri`, `iron-meta` with
@@ -453,7 +456,7 @@ interface AmfHelperMixin {
453456
*
454457
* @returns Always returns an array of endpoints.
455458
*/
456-
_computeEndpoints(webApi: WebApi): Endpoint[]|undefined;
459+
_computeEndpoints(webApi: WebApi): EndPoint[]|undefined;
457460

458461
/**
459462
* Computes model for an endpoint documentation.
@@ -462,7 +465,7 @@ interface AmfHelperMixin {
462465
* @param id Selected shape ID
463466
* @returns An endpoint definition
464467
*/
465-
_computeEndpointModel(webApi: WebApi, id: string): Endpoint|undefined;
468+
_computeEndpointModel(webApi: WebApi, id: string): EndPoint|undefined;
466469

467470
/**
468471
* Computes model for an endpoint documentation using it's path.
@@ -471,7 +474,7 @@ interface AmfHelperMixin {
471474
* @param path Endpoint path
472475
* @returns An endpoint definition
473476
*/
474-
_computeEndpointByPath(webApi: WebApi, path: string): Endpoint|undefined;
477+
_computeEndpointByPath(webApi: WebApi, path: string): EndPoint|undefined;
475478

476479
/**
477480
* Computes method for the method documentation.
@@ -498,7 +501,7 @@ interface AmfHelperMixin {
498501
* @param methodId Method id
499502
* @returns An endpoint model of undefined.
500503
*/
501-
_computeMethodEndpoint(webApi: WebApi, methodId: string): Endpoint|undefined;
504+
_computeMethodEndpoint(webApi: WebApi, methodId: string): EndPoint|undefined;
502505

503506
/**
504507
* Computes a list of methods for an endpoint that contains a method with

src/AmfSerializer.d.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1-
/* eslint-disable class-methods-use-this */
2-
import { AnyShape, ApiKeySettings, ArrayNode, ArrayShape, Callback, CreativeWork, DataArrangeShape, DataNode, DocumentSourceMaps, DomainElement, EndPoint, Example, FileShape, HttpSettings, IriTemplateMapping, NodeShape, OAuth1Settings, OAuth2Flow, OAuth2Settings, ObjectNode, OpenIdConnectSettings, Operation, Parameter, ParametrizedSecurityScheme, Payload, PropertyShape, RecursiveShape, Request, Response, ScalarNode, ScalarShape, SchemaShape, Scope, SecurityRequirement, SecurityScheme, Server, Settings, Shape, SynthesizedField, Tag, TemplatedLink, TupleShape, UnionShape } from "./amf.js";
3-
import { AmfHelperMixin, expandKey, findAmfType, getArrayItems } from "./AmfHelperMixin.js";
4-
import { ApiAnyShape, ApiArrayNode, ApiArrayShape, ApiCallback, ApiCustomDomainProperty, ApiDataArrangeShape, ApiDataNode, ApiDataNodeUnion, ApiDocumentation, ApiDocumentSourceMaps, ApiEndPoint, ApiExample, ApiFileShape, ApiIriTemplateMapping, ApiNodeShape, ApiObjectNode, ApiOperation, ApiParameter, ApiParametrizedSecurityScheme, ApiPayload, ApiPropertyShape, ApiRecursiveShape, ApiRequest, ApiResponse, ApiScalarNode, ApiScalarShape, ApiSchemaShape, ApiSecurityApiKeySettings, ApiSecurityHttpSettings, ApiSecurityOAuth1Settings, ApiSecurityOAuth2Flow, ApiSecurityOAuth2Settings, ApiSecurityOpenIdConnectSettings, ApiSecurityRequirement, ApiSecurityScheme, ApiSecurityScope, ApiSecuritySettings, ApiSecuritySettingsUnion, ApiServer, ApiShape, ApiShapeUnion, ApiSynthesizedField, ApiTag, ApiTupleShape, ApiUnionShape, ApiXMLSerializer } from "./types.js";
1+
import { AmfHelperMixin } from "./AmfHelperMixin.js";
2+
import {
3+
AnyShape, ApiKeySettings, ArrayNode, ArrayShape, Callback, CreativeWork, DataArrangeShape,
4+
DataNode, DocumentSourceMaps, DomainElement, EndPoint, Example, FileShape, HttpSettings,
5+
IriTemplateMapping, NodeShape, OAuth1Settings, OAuth2Flow, OAuth2Settings, ObjectNode,
6+
OpenIdConnectSettings, Operation, Parameter, ParametrizedSecurityScheme, Payload,
7+
PropertyShape, RecursiveShape, Request, Response, ScalarNode, ScalarShape, SchemaShape,
8+
Scope, SecurityRequirement, SecurityScheme, Server, Settings, Shape, SynthesizedField,
9+
Tag, TemplatedLink, TupleShape, UnionShape, Api, WebApi, AsyncApi, Organization, License,
10+
} from "./amf.js";
11+
import {
12+
ApiAnyShape, ApiArrayNode, ApiArrayShape, ApiCallback, ApiCustomDomainProperty, ApiDataArrangeShape,
13+
ApiDataNode, ApiDataNodeUnion, ApiDocumentation, ApiDocumentSourceMaps, ApiEndPoint, ApiExample,
14+
ApiFileShape, ApiIriTemplateMapping, ApiNodeShape, ApiObjectNode, ApiOperation, ApiParameter,
15+
ApiParametrizedSecurityScheme, ApiPayload, ApiPropertyShape, ApiRecursiveShape, ApiRequest, ApiResponse,
16+
ApiScalarNode, ApiScalarShape, ApiSchemaShape, ApiSecurityApiKeySettings, ApiSecurityHttpSettings,
17+
ApiSecurityOAuth1Settings, ApiSecurityOAuth2Flow, ApiSecurityOAuth2Settings,
18+
ApiSecurityOpenIdConnectSettings, ApiSecurityRequirement, ApiSecurityScheme, ApiSecurityScope,
19+
ApiSecuritySettings, ApiSecuritySettingsUnion, ApiServer, ApiShape, ApiShapeUnion, ApiSynthesizedField,
20+
ApiTag, ApiTupleShape, ApiUnionShape, ApiXMLSerializer, ApiOrganization, ApiSummary, ApiBase,
21+
ApiWeb, ApiAsync, ApiLicense,
22+
} from "./types.js";
523

624
/**
725
* A class that takes AMF's ld+json model and outputs JavaScript interface of it.
@@ -11,6 +29,17 @@ export declare class AmfSerializer extends AmfHelperMixin(Object) {
1129
* @param graph Optional AMF generated graph model.
1230
*/
1331
constructor(graph?: DomainElement);
32+
/**
33+
* @param object The API to serialize.
34+
* @returns API summary, without complex objects.
35+
*/
36+
apiSummary(object: Api): ApiSummary;
37+
api(object: Api): ApiBase;
38+
webApi(object: WebApi): ApiWeb;
39+
asyncApi(object: AsyncApi): ApiAsync;
40+
provider(object: Organization): ApiOrganization;
41+
license(object: License): ApiLicense;
42+
1443
/**
1544
* @param object The AMF Server to serialize.
1645
* @returns Serialized Server
@@ -143,6 +172,6 @@ export declare class AmfSerializer extends AmfHelperMixin(Object) {
143172
/**
144173
* Serializes source maps, when available.
145174
*/
146-
sourceMap(object: DocumentSourceMaps): ApiDocumentSourceMaps|undefined;
175+
sourceMap(object: DocumentSourceMaps): ApiDocumentSourceMaps | undefined;
147176
synthesizedField(object: SynthesizedField): ApiSynthesizedField;
148177
}

src/AmfSerializer.js

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { AmfHelperMixin, expandKey, findAmfType, getArrayItems } from "./AmfHelp
1414
/** @typedef {import('./types').ApiEndPoint} ApiEndPoint */
1515
/** @typedef {import('./types').ApiServer} ApiServer */
1616
/** @typedef {import('./types').ApiDocumentation} ApiDocumentation */
17-
/** @typedef {import('./types').SerializedApi} SerializedApi */
1817
/** @typedef {import('./types').ApiShape} ApiShape */
1918
/** @typedef {import('./types').ApiPropertyShape} ApiPropertyShape */
2019
/** @typedef {import('./types').ApiAnyShape} ApiAnyShape */
@@ -54,6 +53,15 @@ import { AmfHelperMixin, expandKey, findAmfType, getArrayItems } from "./AmfHelp
5453
/** @typedef {import('./types').ApiVariableValue} ApiVariableValue */
5554
/** @typedef {import('./types').ApiAbstractDeclaration} ApiAbstractDeclaration */
5655
/** @typedef {import('./types').ShapeProcessingOptions} ShapeProcessingOptions */
56+
/** @typedef {import('./types').ApiSummary} ApiSummary */
57+
/** @typedef {import('./types').ApiOrganization} ApiOrganization */
58+
/** @typedef {import('./types').ApiLicense} ApiLicense */
59+
/** @typedef {import('./types').ApiBase} ApiBase */
60+
/** @typedef {import('./types').ApiWeb} ApiWeb */
61+
/** @typedef {import('./types').ApiAsync} ApiAsync */
62+
/** @typedef {import('./amf').Api} Api */
63+
/** @typedef {import('./amf').WebApi} WebApi */
64+
/** @typedef {import('./amf').AsyncApi} AsyncApi */
5765
/** @typedef {import('./amf').Server} Server */
5866
/** @typedef {import('./amf').Parameter} Parameter */
5967
/** @typedef {import('./amf').Shape} Shape */
@@ -101,6 +109,8 @@ import { AmfHelperMixin, expandKey, findAmfType, getArrayItems } from "./AmfHelp
101109
/** @typedef {import('./amf').ParametrizedTrait} ParametrizedTrait */
102110
/** @typedef {import('./amf').VariableValue} VariableValue */
103111
/** @typedef {import('./amf').AbstractDeclaration} AbstractDeclaration */
112+
/** @typedef {import('./amf').Organization} Organization */
113+
/** @typedef {import('./amf').License} License */
104114

105115
/**
106116
* A class that takes AMF's ld+json model and outputs JavaScript interface of it.
@@ -116,6 +126,167 @@ export class AmfSerializer extends AmfHelperMixin(Object) {
116126
}
117127
}
118128

129+
/**
130+
* @param {Api} object The API to serialize.
131+
* @returns {ApiSummary} API summary, without complex objects.
132+
*/
133+
apiSummary(object) {
134+
const result = /** @type ApiSummary */ ({
135+
id: object['@id'],
136+
types: object['@type'].map(this[expandKey].bind(this)),
137+
customDomainProperties: this.customDomainProperties(object),
138+
sourceMaps: this.sourceMap(object),
139+
schemes: [],
140+
accepts: [],
141+
contentType: [],
142+
documentations: [],
143+
tags: [],
144+
});
145+
const { ns } = this;
146+
const name = this._getValue(object, ns.aml.vocabularies.core.name);
147+
if (name && typeof name === 'string') {
148+
result.name = name;
149+
}
150+
const description = this._getValue(object, ns.aml.vocabularies.core.description);
151+
if (description && typeof description === 'string') {
152+
result.description = description;
153+
}
154+
const version = this._getValue(object, ns.aml.vocabularies.core.version);
155+
if (version && typeof version === 'string') {
156+
result.version = version;
157+
}
158+
const termsOfService = this._getValue(object, ns.aml.vocabularies.core.termsOfService);
159+
if (termsOfService && typeof termsOfService === 'string') {
160+
result.termsOfService = termsOfService;
161+
}
162+
const accepts = object[this._getAmfKey(ns.aml.vocabularies.apiContract.accepts)];
163+
if (Array.isArray(accepts) && accepts.length) {
164+
result.accepts = /** @type string[] */ (this._getValueArray(object, ns.aml.vocabularies.apiContract.accepts));
165+
}
166+
const contentType = object[this._getAmfKey(ns.aml.vocabularies.apiContract.contentType)];
167+
if (Array.isArray(contentType) && contentType.length) {
168+
result.contentType = /** @type string[] */ (this._getValueArray(object, ns.aml.vocabularies.apiContract.contentType));
169+
}
170+
const schemes = object[this._getAmfKey(ns.aml.vocabularies.apiContract.scheme)];
171+
if (Array.isArray(schemes) && schemes.length) {
172+
result.schemes = /** @type string[] */ (this._getValueArray(object, ns.aml.vocabularies.apiContract.scheme));
173+
}
174+
let provider = object[this._getAmfKey(ns.aml.vocabularies.core.provider)];
175+
if (Array.isArray(provider)) {
176+
[provider] = provider;
177+
}
178+
if (provider) {
179+
result.provider = this.provider(provider);
180+
}
181+
let license = object[this._getAmfKey(ns.aml.vocabularies.core.license)];
182+
if (Array.isArray(license)) {
183+
[license] = license;
184+
}
185+
if (license) {
186+
result.license = this.license(license);
187+
}
188+
const tags = object[this._getAmfKey(ns.aml.vocabularies.apiContract.tag)];
189+
if (Array.isArray(tags) && tags.length) {
190+
result.tags = tags.map(t => this.tag(t));
191+
}
192+
const docs = object[this._getAmfKey(ns.aml.vocabularies.core.documentation)];
193+
if (Array.isArray(docs) && docs.length) {
194+
result.documentations = docs.map(d => this.documentation(d));
195+
}
196+
return result;
197+
}
198+
199+
/**
200+
* @param {Api} object
201+
* @returns {ApiBase}
202+
*/
203+
api(object) {
204+
const result = /** @type ApiBase */ (this.apiSummary(object));
205+
result.endPoints = [];
206+
result.servers = [];
207+
result.security = [];
208+
const { ns } = this;
209+
const endPoints = object[this._getAmfKey(ns.aml.vocabularies.apiContract.endpoint)];
210+
if (Array.isArray(endPoints) && endPoints.length) {
211+
result.endPoints = endPoints.map(e => this.endPoint(e));
212+
}
213+
const servers = object[this._getAmfKey(ns.aml.vocabularies.apiContract.server)];
214+
if (Array.isArray(servers) && servers.length) {
215+
result.servers = servers.map(s => this.server(s));
216+
}
217+
const security = object[this._getAmfKey(ns.aml.vocabularies.security.security)];
218+
if (Array.isArray(security) && security.length) {
219+
result.security = security.map(s => this.securityRequirement(s));
220+
}
221+
return result;
222+
}
223+
224+
/**
225+
* @param {WebApi} object
226+
* @returns {ApiWeb}
227+
*/
228+
webApi(object) {
229+
return this.api(object);
230+
}
231+
232+
/**
233+
* @param {AsyncApi} object
234+
* @returns {ApiAsync}
235+
*/
236+
asyncApi(object) {
237+
return this.api(object);
238+
}
239+
240+
/**
241+
* @param {Organization} object
242+
* @returns {ApiOrganization}
243+
*/
244+
provider(object) {
245+
const result = /** @type ApiOrganization */ ({
246+
id: object['@id'],
247+
types: object['@type'].map(this[expandKey].bind(this)),
248+
customDomainProperties: this.customDomainProperties(object),
249+
sourceMaps: this.sourceMap(object),
250+
});
251+
const { ns } = this;
252+
const name = this._getValue(object, ns.aml.vocabularies.core.name);
253+
if (name && typeof name === 'string') {
254+
result.name = name;
255+
}
256+
const url = this._getLinkValue(object, ns.aml.vocabularies.core.url);
257+
if (url && typeof url === 'string') {
258+
result.url = url;
259+
}
260+
const email = this._getValue(object, ns.aml.vocabularies.core.email);
261+
if (email && typeof email === 'string') {
262+
result.email = email;
263+
}
264+
return result;
265+
}
266+
267+
/**
268+
* @param {License} object
269+
* @returns {ApiLicense}
270+
*/
271+
license(object) {
272+
const result = /** @type ApiLicense */ ({
273+
id: object['@id'],
274+
types: object['@type'].map(this[expandKey].bind(this)),
275+
customDomainProperties: this.customDomainProperties(object),
276+
sourceMaps: this.sourceMap(object),
277+
});
278+
const { ns } = this;
279+
const name = this._getValue(object, ns.aml.vocabularies.core.name);
280+
if (name && typeof name === 'string') {
281+
result.name = name;
282+
}
283+
const url = this._getLinkValue(object, ns.aml.vocabularies.core.url);
284+
if (url && typeof url === 'string') {
285+
result.url = url;
286+
}
287+
return result;
288+
}
289+
119290
/**
120291
* @param {Server} object The AMF Server to serialize.
121292
* @returns {ApiServer} Serialized Server

0 commit comments

Comments
 (0)