diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..bb2b05d --- /dev/null +++ b/index.ts @@ -0,0 +1,6 @@ +// Copyright IBM Corp. 2013,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 + +export * from './src'; diff --git a/package.json b/package.json index 818726a..c6873ac 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "lint": "tslint -c tslint.full.json --project tsconfig.json --type-check", "lint:fix": "npm run lint -- --fix", "prepublish": "npm run build", - "pretest": "npm run build", + "clean": "rm -rf dist dist6", + "pretest": "npm run clean && npm run build", "test": "mocha", "posttest": "npm run lint", "vscode-test": "mocha && npm run lint" diff --git a/src/decorators/README.md b/src/decorators/README.md new file mode 100644 index 0000000..8d5fe48 --- /dev/null +++ b/src/decorators/README.md @@ -0,0 +1,46 @@ +# Decorators + +## Overview + +Decorators provide annotations for class methods and properties. 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 operation. The decorator will annotate the operation with the value of the header `X-Transaction-Id` from the request. + +**Example** +``` +class MyController { + @get('/') + @txIdFromHeader() + getHandler(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) + +## Contributions + +- [Guidelines](http://loopback.io/doc/en/contrib/index.html) +- [Join the team](https://github.com/strongloop/loopback-next/issues/110) + +## Tests + +Run `npm test` from the root folder. + +## Contributors + +See [all contributors](https://github.com/strongloop/loopback-next-extension-starter/graphs/contributors). + +## License + +MIT diff --git a/src/decorators/txIdFromHeader.ts b/src/decorators/txIdFromHeader.ts new file mode 100644 index 0000000..3c85372 --- /dev/null +++ b/src/decorators/txIdFromHeader.ts @@ -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/core'; + +/** + * 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'); +} diff --git a/src/index.ts b/src/index.ts index 0c8fd35..e23ff5e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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'; diff --git a/test/acceptance/txIdFromHeader.test.ts b/test/acceptance/txIdFromHeader.test.ts new file mode 100644 index 0000000..88fd7c2 --- /dev/null +++ b/test/acceptance/txIdFromHeader.test.ts @@ -0,0 +1,46 @@ +// Copyright IBM Corp. 2017. All Rights Reserved. +// Node module: @loopback/core +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {Application, get} from '@loopback/core'; +import {txIdFromHeader} from '../..'; +import {Client, createClientForApp} from '@loopback/testlab'; + +describe('@txIdFromHeader() tests', () => { + let app: Application; + + beforeEach(createApp); + beforeEach(createController); + + it('works with header set', async () => { + const client: Client = createClientForApp(app); + + await client + .get('/') + .set('X-Transaction-Id', 'testid123') + .expect(200, 'Your id is testid123'); + }); + + it('works without header', async () => { + const client: Client = createClientForApp(app); + + await client.get('/').expect(200, 'Your id is undefined'); + }); + + function createApp() { + app = new Application(); + } + + function createController() { + class MyController { + @get('/') + @txIdFromHeader() + test(txId: string) { + return `Your id is ${txId}`; + } + } + + app.controller(MyController); + } +}); diff --git a/test/unit/txIdFromHeader.test.ts b/test/unit/txIdFromHeader.test.ts new file mode 100644 index 0000000..dd31d4f --- /dev/null +++ b/test/unit/txIdFromHeader.test.ts @@ -0,0 +1,28 @@ +// Copyright IBM Corp. 2017. All Rights Reserved. +// Node module: @loopback/core +// 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/core'; +import {txIdFromHeader} from '../..'; + +describe('@txHeaderFromId', () => { + it('defines a parameter for X-Transaction-Id', () => { + class MyController { + @get('/') + @txIdFromHeader() + hello(txId: string) {} + } + + const actualSpec = getControllerSpec(MyController); + + expect(actualSpec.paths['/']['get'].parameters).to.eql([ + { + name: 'X-Transaction-Id', + type: 'string', + in: 'header', + }, + ]); + }); +});