Skip to content
This repository was archived by the owner on Feb 2, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"tslint:fix": "npm run lint -- --fix",
"prepublish": "npm run build",
"pretest": "npm run clean && npm run build",
"test": "mocha",
"test": "/bin/bash -c '[[ $(node -v) =~ [[:digit:]]+ ]] && [[ ${BASH_REMATCH[0]} -gt 6 ]]' && mocha dist/test || mocha dist6/test",
"posttest": "npm run lint",
"test:dev": "mocha && npm run lint"
},
Expand Down
28 changes: 28 additions & 0 deletions src/decorators/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 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**
```
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)
14 changes: 14 additions & 0 deletions src/decorators/txIdFromHeader.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-next-extension-starter
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {param} from '@loopback/rest';

/**
* Decorator to inject the current transaction-id from a request's
* 'X-Transaction-Id' header into the decorated function.
*/
export function txIdFromHeader() {
return param.header.string('X-Transaction-Id');
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
// Node module: loopback-next-extension-starter
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

export * from './decorators/txIdFromHeader.decorator';
57 changes: 57 additions & 0 deletions test/acceptance/decorators/txIdFromHeader.acceptance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-next-hello-extension
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Application} from '@loopback/core';
import {get, RestComponent, RestServer} from '@loopback/rest';
import {txIdFromHeader} from '../../..';
import {Client, createClientForHandler} from '@loopback/testlab';

describe('@txIdFromHeader() (acceptance)', () => {
let app: Application;
let server: RestServer;

beforeEach(createApp);
beforeEach(createController);
beforeEach(getServerFromApp);

it('works with header set', async () => {
const client: Client = createClientForHandler(server.handleHttp);

await client
.get('/')
.set('X-Transaction-Id', 'testid123')
.expect(200, 'Your id is testid123');
});

it('works without header', async () => {
const client: Client = createClientForHandler(server.handleHttp);

await client.get('/').expect(200, 'Your id is undefined');
});

async function createApp() {
app = new Application({
components: [RestComponent],
rest: {
port: 3000,
},
});
}

function createController() {
class MyController {
@get('/')
test(@txIdFromHeader() txId: string) {
return `Your id is ${txId}`;
}
}

app.controller(MyController);
}

async function getServerFromApp() {
server = await app.getServer(RestServer);
}
});
1 change: 0 additions & 1 deletion test/mocha.opts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
--recursive
--reporter dot
dist/test
12 changes: 0 additions & 12 deletions test/smoke.test.ts

This file was deleted.

27 changes: 27 additions & 0 deletions test/unit/decorators/txIdFromHeader.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright IBM Corp. 2017. All Rights Reserved.
// Node module: loopback-next-hello-extension
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {expect} from '@loopback/testlab';
import {get, getControllerSpec} from '@loopback/rest';
import {txIdFromHeader} from '../../..';

describe('@txHeaderFromId() (unit)', () => {
it('defines a parameter for X-Transaction-Id', () => {
class MyController {
@get('/')
hello(@txIdFromHeader() txId: string) {}
}

const actualSpec = getControllerSpec(MyController);

expect(actualSpec.paths['/']['get'].parameters).to.eql([
{
name: 'X-Transaction-Id',
type: 'string',
in: 'header',
},
]);
});
});