Skip to content

Commit

Permalink
feat: moves msgpack bodyparser to standalone package
Browse files Browse the repository at this point in the history
Signed-off-by: Rifa Achrinza <[email protected]>
  • Loading branch information
achrinza committed Aug 21, 2020
1 parent ed552f6 commit 5c47ac8
Show file tree
Hide file tree
Showing 28 changed files with 764 additions and 130 deletions.
2 changes: 2 additions & 0 deletions extensions/bodyparser-msgpack/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
package-lock=true
scripts-prepend-node-path=true
3 changes: 3 additions & 0 deletions extensions/bodyparser-msgpack/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @loopback/bodyparser-msgpack

[![LoopBack](https://github.com/strongloop/loopback-next/raw/master/docs/site/imgs/branding/Powered-by-LoopBack-Badge-(blue)[email protected])](http://loopback.io/)
101 changes: 101 additions & 0 deletions extensions/bodyparser-msgpack/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions extensions/bodyparser-msgpack/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "@loopback/bodyparser-msgpack",
"version": "0.0.1",
"description": "@loopback/bodyparser-msgpack",
"keywords": [
"loopback-extension",
"loopback"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"engines": {
"node": ">=10.16"
},
"scripts": {
"build": "lb-tsc",
"build:watch": "lb-tsc --watch",
"pretest": "npm run clean && npm run build",
"test": "lb-mocha \"dist/__tests__/**/*.js\"",
"clean": "lb-clean dist *.tsbuildinfo .eslintcache"
},
"repository": {
"type": "git",
"url": "https://github.com/strongloop/loopback-next.git",
"directory": "extensions/bodyparser-msgpack"
},
"author": "IBM Corp.",
"license": "MIT",
"files": [
"README.md",
"dist",
"src",
"!*/__tests__"
],
"dependencies": {
"@loopback/core": "^2.9.4",
"@loopback/rest": "^6.1.0",
"msgpack-lite": "^0.1.26",
"tslib": "^2.0.0",
"type-is": "^1.6.18"
},
"devDependencies": {
"@loopback/build": "^6.2.1",
"@loopback/testlab": "^3.2.3",
"@types/msgpack-lite": "^0.1.7",
"@types/node": "^10.17.28",
"@types/type-is": "^1.6.3",
"typescript": "~3.9.7"
},
"copyright.owner": "IBM Corp.",
"publishConfig": {
"access": "public"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Acceptance tests
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Integration tests
1 change: 1 addition & 0 deletions extensions/bodyparser-msgpack/src/__tests__/unit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Unit tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {Context} from '@loopback/core';
import {
createResolvedRoute,
OperationObject,
parseOperationArgs,
PathParameterValues,
Request,
RequestBodyObject,
RequestBodyParser,
Route,
} from '@loopback/rest';
import {
expect,
ShotRequestOptions,
stubExpressContext,
} from '@loopback/testlab';
import {encode} from 'msgpack-lite';
import {MsgPackBodyParser} from '../..';

describe('MessagePack body parser', () => {
let requestBodyParser: RequestBodyParser;
beforeEach(givenRequestBodyParser);

it('parses body parameter for MessagePack data', async () => {
const contentTypes = [
'application/msgpack',
'application/x-msgpack',
'application/subtype+msgpack',
];

for (const contentType of contentTypes) {
const spec = givenOperationWithRequestBody({
description: 'data',
content: {
[contentType]: {
schema: {
type: 'object',
properties: {
data: {
type: 'string',
},
},
},
},
},
});

const req = givenRequest({
url: '/',
headers: {
'Content-Type': contentType,
},
payload: encode({
data: 'hello world',
}),
});

const route = givenResolvedRoute(spec);

const args = await parseOperationArgs(req, route, requestBodyParser);

expect(args).to.eql([{data: 'hello world'}]);
}
});

function givenOperationWithRequestBody(requestBody?: RequestBodyObject) {
return <OperationObject>{
'x-operation-name': 'testOp',
requestBody: requestBody,
responses: {},
};
}

function givenRequest(options?: ShotRequestOptions): Request {
return stubExpressContext(options).request;
}

function givenResolvedRoute(
spec: OperationObject,
pathParams: PathParameterValues = {},
) {
const route = new Route('get', '/', spec, () => {});
return createResolvedRoute(route, pathParams);
}

function givenRequestBodyParser() {
const options = {};
const parsers = [new MsgPackBodyParser(options)];
requestBodyParser = new RequestBodyParser(parsers, new Context());
}
});
39 changes: 39 additions & 0 deletions extensions/bodyparser-msgpack/src/bodyparser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {inject} from '@loopback/core';
import {
RawBodyParser,
Request,
RequestBody,
RequestBodyParserOptions,
RestBindings,
} from '@loopback/rest';
import {decode} from 'msgpack-lite';
import {is} from 'type-is';

export class MsgPackBodyParser extends RawBodyParser {
name = Symbol('msgpack');

constructor(
@inject(RestBindings.REQUEST_BODY_PARSER_OPTIONS, {optional: true})
options: RequestBodyParserOptions = {},
) {
super(options);
}

supports(mediaType: string) {
return !!is(
mediaType,
'application/msgpack',
'application/x-msgpack',
'application/*+msgpack',
);
}

async parse(request: Request): Promise<RequestBody> {
const result = await super.parse(request);
const body = decode(result.value);

return {
value: body,
};
}
}
19 changes: 19 additions & 0 deletions extensions/bodyparser-msgpack/src/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/bodyparser-msgpack
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Component} from '@loopback/core';
import {createBodyParserBinding} from '@loopback/rest';
import {BODY_PARSER_MSGPACK_BINDINGS, MsgPackBodyParser} from '.';

export class LoopbackBodyparserMsgpackComponent implements Component {
constructor() {}

bindings = [
createBodyParserBinding(
MsgPackBodyParser,
BODY_PARSER_MSGPACK_BINDINGS.BODY_PARSER,
),
];
}
6 changes: 6 additions & 0 deletions extensions/bodyparser-msgpack/src/controllers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Controllers

This directory contains source files for the controllers exported by this
extension.

For more information, see <http://loopback.io/doc/en/lb4/Controllers.html>.
34 changes: 34 additions & 0 deletions extensions/bodyparser-msgpack/src/decorators/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Decorators

## Overview

Decorators provide annotations for class methods and arguments. Decorators use
the form `@decorator` where `decorator` is the name of the function that will be
called at runtime.

## Basic Usage

### txIdFromHeader

This simple decorator allows you to annotate a `Controller` method argument. The
decorator will annotate the method argument with the value of the header
`X-Transaction-Id` from the request.

**Example**

```ts
class MyController {
@get('/')
getHandler(@txIdFromHeader() txId: string) {
return `Your transaction id is: ${txId}`;
}
}
```

## Related Resources

You can check out the following resource to learn more about decorators and how
they are used in LoopBack Next.

- [TypeScript Handbook: Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html)
- [Decorators in LoopBack](http://loopback.io/doc/en/lb4/Decorators.html)
8 changes: 8 additions & 0 deletions extensions/bodyparser-msgpack/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/bodyparser-msgpack
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

export * from './bodyparser';
export * from './component';
export * from './keys';
8 changes: 8 additions & 0 deletions extensions/bodyparser-msgpack/src/keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {BindingKey} from '@loopback/core';
import {BodyParser, RestBindings} from '@loopback/rest';

export namespace BODY_PARSER_MSGPACK_BINDINGS {
export const BODY_PARSER = BindingKey.create<BodyParser>(
`${RestBindings.REQUEST_BODY_PARSER}.msgpack`,
);
}
Loading

0 comments on commit 5c47ac8

Please sign in to comment.