Skip to content

Commit

Permalink
feat(server): support stream and buffers
Browse files Browse the repository at this point in the history
Supports stream and buffer as single parameter of exposed API.
  • Loading branch information
feugy committed Apr 22, 2018
1 parent 297ecdd commit 3ff25e0
Show file tree
Hide file tree
Showing 12 changed files with 5,413 additions and 43 deletions.
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ test/
.editorconfig
.jsdoc.json
proxy-benchmark.js
TODO.md
TODO.md
yarn.lock
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ language: node_js
node_js:
- node
after_script:
- npm run submit-coverage
- yarn submit-coverage
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
# Changelog

## Unreleased
#### Added
- Support for Buffer and Stream parameters and results
- Validates exposed API metadata such as `validate`, `validateResponse` or `responseSchema`
- Usage of Yarn

#### Changed
- Reformat CHANGELOG to follow [Keep a Changelog](https://keepachangelog.com) recommandations
- New documentation with latest docma v2.0.0
Expand Down
55 changes: 55 additions & 0 deletions FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- [What are deployment modes?](#what-are-deployment-modes-)
- [Can exposed API be asynchronous?](#can-exposed-api-be-asynchronous-)
- [Are there limitations on exposed API signatures?](#are-there-limitations-on-exposed-api-signatures-)
- [Where to put asynchronous initialization?](#where-to-put-asynchronous-initialization-)
- [Can initialization code be configured?](#can-initialization-code-be-configured-)
- [How can service definition be more modular?](#how-can-service-definition-be-more-modular-)
Expand Down Expand Up @@ -83,6 +84,60 @@ startService({
```


## Are there limitations on exposed API signatures?

Despite all our efforts, yes. Hopefully main cases are covered.

Because parameters will be stringified when sent to server:
- they could be `null` or `undefined`
- they could be booleans, numbers, strings, arrays, and plain object (contains only properties of the previous types)
- they could be of other types (Date, Error, RegExp, custom classes...) but will boils down to the output of their `toString()` method
- they could be `Buffer` or `Stream` (see bellow). All paremeter but the first will be ignored

In particular, don't use functions as parameters.

Same limitations applies to API returned object.

You can use destructuring, rest parameters and even default values:
```js
async withExoticParameters ([a, b], {c: {d}} = {}, ...other) {
return [a, b, d, ...other]
}
```

To use `Buffer` input parameter:
- decorate API with `hasBufferInput`
- use only one parameter (others will be set to `undefined`)
```js
const api = {
async bufferHandling (buffer) {
assert(Buffer.isBuffer(buffer))
return Buffer.concat([buffer, new Uint8Array([3, 4])])
}
}
// decorate
apis.bufferHandling.hasBufferInput = true
```

To use `Stream` input parameter:
- decorate API with `hasStreamInput`
- use only one parameter (others will be set to `undefined`)
```js
const api = {
async streamHandling (stream) {
assert(stream instanceof Readable)
const prefix = new BufferList()
prefix.append('here is a prefix -- ', 'utf8')
return multistream([prefix, stream])
}
}
// decorate
apis.streamHandling.hasStreamInput = true
```

You can return `Stream` and `Buffer` without any decoration, but don't nest them in objects (they will be stringified).


## Where to put asynchronous initialization?

To serve this purpose, the `init()` function can be either synchronous or return a Promise.
Expand Down
6 changes: 6 additions & 0 deletions docs/content/changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
<hr />
<h2 id="unreleased">Unreleased</h2>
<hr />
<h4 id="added">Added</h4>
<ul>
<li>Support for Buffer and Stream parameters and results</li>
<li>Validates exposed API metadata such as <code>validate</code>, <code>validateResponse</code> or <code>responseSchema</code></li>
<li>Usage of Yarn </li>
</ul>
<h4 id="changed">Changed</h4>
<ul>
<li>Reformat CHANGELOG to follow <a href="https://keepachangelog.com">Keep a Changelog</a> recommandations</li>
Expand Down
49 changes: 49 additions & 0 deletions docs/content/faq.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ul>
<li><a href="#what-are-deployment-modes-">What are deployment modes?</a></li>
<li><a href="#can-exposed-api-be-asynchronous-">Can exposed API be asynchronous?</a></li>
<li><a href="#are-there-limitations-on-exposed-api-signatures-">Are there limitations on exposed API signatures?</a></li>
<li><a href="#where-to-put-asynchronous-initialization-">Where to put asynchronous initialization?</a></li>
<li><a href="#can-initialization-code-be-configured-">Can initialization code be configured?</a></li>
<li><a href="#how-can-service-definition-be-more-modular-">How can service definition be more modular?</a></li>
Expand Down Expand Up @@ -77,6 +78,54 @@ <h2 id="can-exposed-api-be-asynchronous-">Can exposed API be asynchronous?</h2>
})
})
</code></pre>
<h2 id="are-there-limitations-on-exposed-api-signatures-">Are there limitations on exposed API signatures?</h2>
<hr />
<p>Despite all our efforts, yes. Hopefully main cases are covered.</p>
<p>Because parameters will be stringified when sent to server:</p>
<ul>
<li>they could be <code>null</code> or <code>undefined</code></li>
<li>they could be booleans, numbers, strings, arrays, and plain object (contains only properties of the previous types)</li>
<li>they could be of other types (Date, Error, RegExp, custom classes...) but will boils down to the output of their <code>toString()</code> method</li>
<li>they could be <code>Buffer</code> or <code>Stream</code> (see bellow). All paremeter but the first will be ignored</li>
</ul>
<p>In particular, don't use functions as parameters.</p>
<p>Same limitations applies to API returned object.</p>
<p>You can use destructuring, rest parameters and even default values:</p>
<pre><code class="lang-js">async withExoticParameters ([a, b], {c: {d}} = {}, ...other) {
return [a, b, d, ...other]
}
</code></pre>
<p>To use <code>Buffer</code> input parameter:</p>
<ul>
<li>decorate API with <code>hasBufferInput</code></li>
<li>use only one parameter (others will be set to <code>undefined</code>)<pre><code class="lang-js"> const api = {
async bufferHandling (buffer) {
assert(Buffer.isBuffer(buffer))
return Buffer.concat([buffer, new Uint8Array([3, 4])])
}
}
// decorate
apis.bufferHandling.hasBufferInput = true
</code></pre>
</li>
</ul>
<p>To use <code>Stream</code> input parameter:</p>
<ul>
<li>decorate API with <code>hasStreamInput</code></li>
<li>use only one parameter (others will be set to <code>undefined</code>)<pre><code class="lang-js"> const api = {
async streamHandling (stream) {
assert(stream instanceof Readable)
const prefix = new BufferList()
prefix.append('here is a prefix -- ', 'utf8')
return multistream([prefix, stream])
}
}
// decorate
apis.streamHandling.hasStreamInput = true
</code></pre>
</li>
</ul>
<p>You can return <code>Stream</code> and <code>Buffer</code> without any decoration, but don't nest them in objects (they will be stringified).</p>
<h2 id="where-to-put-asynchronous-initialization-">Where to put asynchronous initialization?</h2>
<hr />
<p>To serve this purpose, the <code>init()</code> function can be either synchronous or return a Promise.</p>
Expand Down
Loading

0 comments on commit 3ff25e0

Please sign in to comment.