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

Commit e2a8c75

Browse files
authored
feat(project): add serializeSync method (#549)
1 parent f7c9131 commit e2a8c75

File tree

21 files changed

+276
-22
lines changed

21 files changed

+276
-22
lines changed

packages/apib-serializer/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# API Elements: API Blueprint Serializer Changelog
22

3+
## 0.16.2 (2020-08-31)
4+
5+
### Enhancements
6+
7+
- Enable synchronous serialization.
8+
39
## 0.16.1 (2020-08-06)
410

511
Adds compatibility for @apielements/core 0.2.0.

packages/apib-serializer/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,33 @@ $ npm install @apielements/apib-serializer
1313

1414
## Usage
1515

16+
### Async
17+
1618
```js
1719
import fury from 'fury';
1820
import apibSerializer from '@apielements/apib-serializer';
1921

2022
fury.use(apibSerializer);
2123

2224
// Assume `api` is a Minim element instance, e.g. from `fury.parse(...)`
23-
fury.serialize({api}, (err, content) => {
25+
fury.serialize({ api }, (err, content) => {
2426
fs.write('serialized.apib', content, 'utf8');
2527
});
2628
```
29+
30+
### Sync
31+
32+
```js
33+
import fury from 'fury';
34+
import apibSerializer from '@apielements/apib-serializer';
35+
36+
fury.use(apibSerializer);
37+
38+
try {
39+
// Assume `api` is a Minim element instance, e.g. from `fury.parse(...)`
40+
const content = fury.serializeSync({ api });
41+
fs.write('serialized.apib', content, 'utf8');
42+
} catch (error) {
43+
console.log(error);
44+
}
45+
```

packages/apib-serializer/lib/adapter.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,30 @@ const mediaTypes = [
2929
/*
3030
* Serialize an API into API Blueprint.
3131
*/
32+
function filterExtraSpacing(apib) {
33+
const result = apib.trim().replace(/\n\s*\n\s*\n/g, '\n\n');
34+
35+
return `${result}\n`;
36+
}
37+
3238
function serialize({ api }) {
3339
return new Promise((resolve, reject) => {
3440
nunjucks.render('template.nunjucks', { api }, (err, apib) => {
3541
if (err) {
3642
return reject(err);
3743
}
3844

39-
// Attempt to filter out extra spacing
40-
const result = apib.trim().replace(/\n\s*\n\s*\n/g, '\n\n');
41-
return resolve(`${result}\n`);
45+
return resolve(filterExtraSpacing(apib));
4246
});
4347
});
4448
}
4549

46-
module.exports = { name, mediaTypes, serialize };
50+
function serializeSync({ api }) {
51+
const apib = nunjucks.render('template.nunjucks', { api });
52+
53+
return filterExtraSpacing(apib);
54+
}
55+
56+
module.exports = {
57+
name, mediaTypes, serialize, serializeSync,
58+
};

packages/apib-serializer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apielements/apib-serializer",
3-
"version": "0.16.1",
3+
"version": "0.16.2",
44
"description": "API Blueprint serializer for API Elements",
55
"author": "Apiary.io <[email protected]>",
66
"license": "MIT",

packages/apib-serializer/test/adapter-test.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('API Blueprint serializer adapter', () => {
2323
files.forEach((file) => {
2424
const apib = `${file.substr(0, file.length - 4)}apib`;
2525

26-
it(`serializes ${path.basename(file)}`, (done) => {
26+
it(`serializes ${path.basename(file)} asynchronously`, (done) => {
2727
let serializedRefract;
2828
let expectedBlueprint;
2929
let api;
@@ -47,6 +47,17 @@ describe('API Blueprint serializer adapter', () => {
4747
return done();
4848
});
4949
});
50+
51+
it(`serializes ${path.basename(file)} synchronously`, () => {
52+
const serializedRefract = require(file);
53+
const expectedBlueprint = fs.readFileSync(apib, 'utf-8');
54+
55+
const parseResult = fury.load(serializedRefract);
56+
const { api } = parseResult;
57+
58+
const serialized = fury.serializeSync({ api });
59+
expect(serialized).to.deep.equal(expectedBlueprint);
60+
});
5061
});
5162
});
5263

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"dependencies": {
2525
"@apielements/apiaryb-parser": "^0.2.1",
2626
"@apielements/apib-parser": "^0.20.1",
27-
"@apielements/apib-serializer": "^0.16.1",
27+
"@apielements/apib-serializer": "^0.16.2",
2828
"@apielements/core": ">=0.1.0 <0.3.0",
2929
"@apielements/openapi2-parser": "^0.32.3",
3030
"@apielements/openapi3-parser": "^0.15.0",

packages/core/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# API Elements: Core
22

3+
## 0.2.1 (2020-08-27)
4+
5+
### Enhancements
6+
7+
Added `serializeSync` method to Fury.
8+
39
## 0.2.0 (2020-08-05)
410

511
This package updates the version of `api-elements` being used. See

packages/core/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export const mediaTypes = {
137137
```
138138

139139

140-
Adapters are made up of a name, a list of media types, and up to three optional public functions: `detect`, `parse`, and `serialize`. A simple example might look like this:
140+
Adapters are made up of a name, a list of media types, and up to four optional public functions: `detect`, `parse`, `serialize` and `serializeSync`. A simple example might look like this:
141141

142142
```js
143143
export const name = 'my-adapter';
@@ -176,7 +176,14 @@ export async function serialize({api, mediaType, minim}) {
176176
return outputString;
177177
}
178178

179-
export default {name, mediaTypes, detect, parse, serialize};
179+
export function serializeSync({api, mediaType, minim}) {
180+
// Here you convert `api` from javascript element objects to the serialized
181+
// source format.
182+
// ...
183+
return outputString;
184+
}
185+
186+
export default {name, mediaTypes, detect, parse, serialize, serializeSync};
180187
```
181188

182189
Now you can register your adapter with Fury.js:

packages/core/lib/fury.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const minim = new Namespace();
44

55
/*
66
* Find an adapter by a given media type and method name, which should be
7-
* either `parse` or `serialize`. If no adapter is found, then
7+
* either `parse`, `serialize` or `serializeSync`. If no adapter is found, then
88
* undefined is returned.
99
*/
1010
const findAdapter = (adapters, mediaType, method) => {
@@ -80,6 +80,19 @@ const findAdapter = (adapters, mediaType, method) => {
8080
* @memberof FuryAdapter
8181
*/
8282

83+
/**
84+
* @function serializeSync
85+
*
86+
* @param {Object} options
87+
* @param {Category} options.api
88+
* @param {Namespace} options.namespace
89+
*
90+
* @returns {String}
91+
* @throws {Error} error
92+
*
93+
* @memberof FuryAdapter
94+
*/
95+
8396
/**
8497
*/
8598
class Fury {
@@ -244,6 +257,28 @@ class Fury {
244257
return promise;
245258
}
246259

260+
/**
261+
* Synchronously serialize an API Description into the given output format.
262+
*
263+
* @param {Object} options
264+
* @param {Category} options.api
265+
* @param {string} [options.mediaType]
266+
*/
267+
serializeSync({ api, mediaType = 'text/vnd.apiblueprint' }) {
268+
const adapter = findAdapter(this.adapters, mediaType, 'serializeSync');
269+
270+
if (!adapter) {
271+
throw new Error('Media type did not match any registered serializer!');
272+
}
273+
274+
if (!api) {
275+
// eslint-disable-next-line no-param-reassign
276+
api = new this.minim.elements.Category();
277+
}
278+
279+
return adapter.serializeSync({ api, namespace: this.minim, mediaType });
280+
}
281+
247282
/**
248283
* @callback SerializeCallback
249284
*
@@ -252,7 +287,7 @@ class Fury {
252287
*/
253288

254289
/**
255-
* Serialize an API Description into the given output format.
290+
* Asynchronously serialize an API Description into the given output format.
256291
*
257292
* @param {Object} options
258293
* @param {Category} options.api

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apielements/core",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "API Description SDK",
55
"author": "Apiary.io <[email protected]>",
66
"license": "MIT",

packages/core/test/serialize-test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,42 @@ describe('Serialize', () => {
108108
expect(result).to.equal('{"element":"category"}');
109109
});
110110
});
111+
112+
describe('using serializeSync', () => {
113+
it('errors with unknown mediaType', () => {
114+
const fury = new Fury();
115+
const api = new fury.minim.elements.Category();
116+
117+
expect(() => {
118+
fury.serializeSync({ api, mediaType: 'application/unregistered' });
119+
}).to.throw('Media type did not match any registered serializer!');
120+
});
121+
122+
it('can serialize undefined `api` by creating default category', async () => {
123+
const fury = new Fury();
124+
fury.use({
125+
name: 'json',
126+
mediaTypes: ['application/json'],
127+
serializeSync: ({ api, namespace }) => JSON.stringify(namespace.serialiser.serialise(api)),
128+
});
129+
130+
expect(
131+
fury.serializeSync({ api: undefined, mediaType: 'application/json' })
132+
).to.equal('{"element":"category"}');
133+
});
134+
135+
it('can serialize with matching adapter', async () => {
136+
const fury = new Fury();
137+
fury.use({
138+
name: 'json',
139+
mediaTypes: ['application/json'],
140+
serializeSync: ({ api, namespace }) => JSON.stringify(namespace.serialiser.serialise(api)),
141+
});
142+
143+
const api = new fury.minim.elements.Category();
144+
145+
const result = fury.serializeSync({ api, mediaType: 'application/json' });
146+
expect(result).to.equal('{"element":"category"}');
147+
});
148+
});
111149
});

packages/form-serializer/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Form Serializer Changelog
22

3+
## 0.1.3 (2020-08-27)
4+
5+
### Enhancements
6+
7+
- Enable synchronous serialization.
8+
39
## 0.1.2 (2020-08-19)
410

511
### Enhancements

packages/form-serializer/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,44 @@
22

33
## Usage
44

5+
### Async
6+
57
```js
8+
const { Fury } = require('@apielements/core');
69
const formSerializer = require('@apielements/form-serializer');
10+
11+
const fury = new Fury();
712
fury.use(formSerializer);
813

14+
const api = new namespace.elements.DataStructure(
15+
new namespace.elements.String('Hello world')
16+
);
917
const mediaType = 'multipart/form-data';
1018
fury.serialize({ api, mediatype }, (error, body) => {
1119
console.log(body);
20+
// --BOUNDARY\r\nContent-Disposition: form-data; name="undefined"\r\n\r\nHello world\r\n--BOUNDARY--\r\n
1221
});
1322
```
23+
24+
### Sync
25+
26+
```js
27+
const { Fury } = require('@apielements/core');
28+
const formSerializer = require('@apielements/form-serializer');
29+
30+
const fury = new Fury();
31+
fury.use(formSerializer);
32+
33+
const api = new namespace.elements.DataStructure(
34+
new namespace.elements.String('Hello world')
35+
);
36+
const mediaType = 'multipart/form-data';
37+
try {
38+
const body = fury.serializeSync({ api, mediatype });
39+
console.log(body);
40+
// --BOUNDARY\r\nContent-Disposition: form-data; name="undefined"\r\n\r\nHello world\r\n--BOUNDARY--\r\n
41+
} catch (error) {
42+
console.log(error);
43+
// Media type did not match any registered serializer!
44+
}
45+
```

packages/form-serializer/lib/adapter.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,10 @@ function serialize({ api, mediaType }) {
77
return new Promise(resolve => resolve(serializeForm({ api, mediaType })));
88
}
99

10-
module.exports = { name, mediaTypes, serialize };
10+
function serializeSync({ api, mediaType }) {
11+
return serializeForm({ api, mediaType });
12+
}
13+
14+
module.exports = {
15+
name, mediaTypes, serialize, serializeSync,
16+
};

packages/form-serializer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apielements/form-serializer",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"description": "Multipart/form-data serializer for API Elements",
55
"author": "Apiary.io <[email protected]>",
66
"license": "MIT",

0 commit comments

Comments
 (0)