sls-api-decorator is a PoC on using typescript decorators to decorate classes that rapresents a service (in serverless idiom) and their methods that will map to endpoints. It supports only aws lambdas.
It basically allow the developer to define a set of aws lambda functions as methods of the same class.
Loading the sls-api-decorators plugin will automatically generate the lambda definitions in serverless.yaml
@Endpoint()
export class MyService {
@Lambda()
public sayHello(event) {
return { message : 'Hello there'}
}
}
sayHello
function is wrapped in a promise and will automatically handle thrown errors.
sls create -t aws-nodejs
- specify your service name and comment out
functions
section
####Install serverless-webpack plugin
npm i -S serverless-webpack
set up to run with typescript
npm i -S typescript ts-node
plugins:
- serverless-webpack
create webpack.config.js
// webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './api/index.ts',
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: 'index.js'
},
target: 'node',
module: {
loaders: [
{ test: /\.ts(x?)$/, loader: 'ts-loader' }
]
},
resolve: {
extensions: ['.ts', '.js', '.tsx', '.jsx', '']
},
};
create tsconfig.json
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"sourceMap": true,
"declaration": true
},
"exclude": [
"node_modules"
]
}
add npm scripts
"scripts": {
"start": "npm run webpack",
"webpack": "sls webpack serve'"
}
npm i -S sls-api-decorators
Edit you plugins section and add typescript output folder.
plugins:
- serverless-webpack
# this will dynamically set the functions in serverless.yaml
- sls-api-decorators
custom:
# this will be the same output folder set up in webpack.config.js
artifactsFolder: .webpack
create api/user/user.service.ts
The following will define a service with base path users that will expose two endpoints:
- users/
- users/error
The latter being to demostrate error throwing.
// user.service.ts
import * as Debug from "debug";
import {Service, Endpoint} from "sls-api-decorators";
const debug = Debug('bazooka');
@Endpoint({
// name of the service (not in the serverless meaning of service)
// will be used in the future for di purpose
name: 'userService',
// this will rapresent the base path for this service
// i.e.: http://localhost:8000/users
path: 'users',
// Allow xOrigin request [TBD]
xOrigin: true
})
class UserService {
constructor() { }
@Lambda({
// name to reference this method in the serverless ecosystem
// i.e.: to be used with invoke command
name: 'hello',
// sub-path for this endpoint
// i.e.: http://localhost:8000/users/
path: '/',
// method to which this function should listen
// i.e.: 'get' or ['get', 'post'] [TBD]
method: 'get',
// this is just required from serverless-webpack plugin
integration: 'lambda'
})
public welcome(event) {
debug('Running welcome');
return { message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!', event };
}
// demostrate use of path params and arguments injection
// arguments being injected from event.path
@Lambda({
name: 'getById',
path: '/{id}',
method: 'get',
integration: 'lambda'
})
public getById(id) {
debug('Running get by id:', id);
return {
id: 'abc',
name: 'dcavaliere',
email: 'cavaliere.davide@gmail.com'
};
}
@Lambda({
name: 'error',
path: 'error',
method: 'get',
integration: 'lambda'
})
public error(event) {
debug('throwing an error');
// throwing an error will reject the lambda cb
throw new Error('something weird just happened');
}
}
export { UserService };
create api/index.ts
The following will expose the service to be used by serverless
this should be replaced in future versions by a DI system
// api/index.ts
import { Api } from 'sls-api-decorators/lib/application';
import { UserService } from './user/user.service';
import { User } from './user/user.model';
@Api({
// used for DI purposes
name : 'app'
// need to define factories and servises
factories: [User],
services: [UserService]
})
class App { }
const app = new App();
export { app };
run npm start
sit back and start coding :)