Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 8e8caf5

Browse files
klokanekylef
authored andcommitted
feat(remote): implement remote adapter
1 parent e3fe71b commit 8e8caf5

File tree

6 files changed

+625
-10
lines changed

6 files changed

+625
-10
lines changed

commitlint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module.exports = {
99
'oas2',
1010
'apib',
1111
'apiaryb',
12+
'remote',
1213
]],
1314
'scope-empty': [2, 'never'],
1415
},
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Fury Remote Adapter
2+
3+
[![NPM version](https://img.shields.io/npm/v/fury-adapter-remote.svg)](https://www.npmjs.org/package/fury-adapter-remote)
4+
[![License](https://img.shields.io/npm/l/fury-adapter-remote.svg)](https://www.npmjs.org/package/fury-adapter-remote)
5+
6+
This adapter provides support for parsing, validation and serialization via the [API Elements Web Service](https://api.apielements.org/) in [Fury](https://github.com/apiaryio/api-elements.js/tree/master/packages/fury).
7+
8+
The remote adapter can be configured to work with any API service compatible with [API Blueprint API](https://apiblueprintapi.docs.apiary.io).
9+
By default the [API Elements Web Service](http://api.apielements.org/) is used.
10+
11+
```js
12+
const defaultOptions = {
13+
url: 'https://api.apielements.org',
14+
15+
parseEndpoint: '/parser',
16+
validateEndpoint: '/validate',
17+
serializeEndpoint: '/composer',
18+
19+
// the collection of "parse", media types we want this
20+
// instance of the adapter to handle.
21+
// NOTE, this allows you to use the API for one media type but
22+
// another local adapter for another.
23+
parseMediaTypes: [
24+
'text/vnd.apiblueprint',
25+
'application/swagger+json',
26+
'application/swagger+yaml',
27+
'application/vnd.oai.openapi',
28+
'application/vnd.oai.openapi+json',
29+
],
30+
31+
// the collection of "serialize", media types we want this
32+
// instance of the adapter to handle.
33+
serializeMediaTypes: [
34+
'application/vnd.refract+json',
35+
'application/vnd.refract.parse-result+json',
36+
],
37+
38+
// fallback to try send input, if not indentified by deckardcain
39+
defaultParseMediaType: 'text/vnd.apiblueprint',
40+
defaultSerializeMediaType: 'application/vnd.refract+json',
41+
};
42+
```
43+
44+
## Install
45+
46+
```sh
47+
$ npm install fury-adapter-remote
48+
```
49+
50+
## Usage
51+
52+
```js
53+
const { Fury } = require('fury');
54+
const FuryRemoteAdapter = require('fury-adapter-remote');
55+
56+
const fury = new Fury();
57+
fury.use(new FuryRemoteAdapter(options);
58+
59+
fury.validate(...);
60+
fury.parse(...);
61+
fury.serialise(...);
62+
```
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
const deckardcain = require('deckardcain');
2+
const axios = require('axios');
3+
4+
const name = 'remote';
5+
6+
const outputMediaType = 'application/vnd.refract.parse-result+json; version=1.0';
7+
8+
const defaultOptions = {
9+
// the default value, but consumers should be able to override to use their own deployment
10+
url: 'https://api.apielements.org',
11+
12+
parseEndpoint: '/parser',
13+
validateEndpoint: '/validate',
14+
serializeEndpoint: '/composer',
15+
16+
// the collection of "parse", media types we want this
17+
// instance of the adapter to handle.
18+
// NOTE, this allows you to use the API for one media type but
19+
// another local adapter for another.
20+
parseMediaTypes: [
21+
'text/vnd.apiblueprint',
22+
'application/swagger+json',
23+
'application/swagger+yaml',
24+
'application/vnd.oai.openapi',
25+
'application/vnd.oai.openapi+json',
26+
],
27+
28+
// the collection of "serialize", media types we want this
29+
// instance of the adapter to handle.
30+
serializeMediaTypes: [
31+
'application/vnd.refract+json',
32+
'application/vnd.refract.parse-result+json',
33+
],
34+
35+
// fallback to try send input, if not indentified by deckardcain
36+
defaultParseMediaType: 'text/vnd.apiblueprint',
37+
defaultSerializeMediaType: 'application/vnd.refract+json',
38+
};
39+
40+
const detectMediaType = (source, defaultMediaType) => {
41+
const mediaType = deckardcain.identify(source);
42+
return mediaType || defaultMediaType;
43+
};
44+
45+
class FuryRemoteAdapter {
46+
constructor(options) {
47+
this.name = name;
48+
this.options = options || defaultOptions;
49+
const parseMediaTypes = this.options.parseMediaTypes || [];
50+
const serializeMediaTypes = this.options.serializeMediaTypes || [];
51+
52+
this.mediaTypes = parseMediaTypes.concat(serializeMediaTypes);
53+
}
54+
55+
detect(source) {
56+
return this.mediaTypes.includes(deckardcain.identify(source));
57+
}
58+
59+
parse({ source, minim }, cb) {
60+
const inputMediaType = detectMediaType(source, this.options.defaultInputMediaType);
61+
62+
axios({
63+
method: 'post',
64+
url: this.options.parseEndpoint,
65+
baseURL: this.options.url,
66+
data: source,
67+
headers: {
68+
'Content-Type': inputMediaType,
69+
Accept: outputMediaType,
70+
},
71+
// allow code 422 to be identified as valid response
72+
validateStatus: status => ((status >= 200 && status < 300) || status === 422),
73+
})
74+
.then((response) => {
75+
cb(null, minim.serialiser.deserialise(response.data));
76+
}, (err) => {
77+
cb(err, undefined);
78+
});
79+
}
80+
81+
validate({ source, minim }, cb) {
82+
const inputMediaType = detectMediaType(source, this.options.defaultInputMediaType);
83+
84+
axios({
85+
method: 'post',
86+
url: this.options.validateEndpoint,
87+
baseURL: this.options.url,
88+
data: {
89+
input_document: source,
90+
input_type: inputMediaType,
91+
output_type: outputMediaType,
92+
},
93+
headers: {
94+
'Content-Type': 'application/json',
95+
Accept: outputMediaType,
96+
},
97+
})
98+
.then((response) => {
99+
cb(null, minim.serialiser.deserialise(response.data));
100+
}, (err) => {
101+
cb(err, undefined);
102+
});
103+
}
104+
105+
serialize({ api, minim }, cb) {
106+
let inputMediaType = this.options.defaultSerializeMediaType;
107+
const content = minim.serialiser.serialise(api);
108+
109+
if (content.element && content.element === 'parseResult') {
110+
inputMediaType = 'application/vnd.refract.parse-result+json';
111+
}
112+
113+
axios({
114+
method: 'post',
115+
url: this.options.serializeEndpoint,
116+
baseURL: this.options.url,
117+
data: content,
118+
headers: {
119+
'Content-Type': inputMediaType,
120+
Accept: 'text/vnd.apiblueprint',
121+
},
122+
})
123+
.then((response) => {
124+
cb(null, response.data);
125+
}, (err) => {
126+
cb(err, undefined);
127+
});
128+
}
129+
}
130+
131+
module.exports = {
132+
FuryRemoteAdapter,
133+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "fury-adapter-remote",
3+
"version": "0.0.1",
4+
"description": "Provide adapter for Element API based on callin remote API site",
5+
"author": "Apiary.io <[email protected]>",
6+
"license": "MIT",
7+
"main": "./lib/adapter.js",
8+
"homepage": "https://github.com/apiaryio/api-elements.js/tree/master/packages/fury-adapter-remote",
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/apiaryio/api-elements.js.git"
12+
},
13+
"scripts": {
14+
"lint": "eslint .",
15+
"lint:fix": "eslint . --fix",
16+
"test": "mocha test"
17+
},
18+
"engines": {
19+
"node": ">=6"
20+
},
21+
"dependencies": {
22+
"axios": "^0.18.0",
23+
"deckardcain": "^0.4.1"
24+
},
25+
"peerDependencies": {
26+
"fury": "3.0.0-beta.9"
27+
},
28+
"devDependencies": {
29+
"chai": "^4.2.0",
30+
"eslint": "^5.15.1",
31+
"fury": "3.0.0-beta.9",
32+
"mocha": "^5.2.0"
33+
}
34+
}

0 commit comments

Comments
 (0)