@microgamma/apigator
Annotate a class with @Endpoint
its methods with @Lambda
with metadata that can be retrieved at runtime to bind them to providers such as AWS Lambda, Express.js, Google Functions, Azure Function and potentially any.
Right now the only providers available are: AWS with their Lambda service and Express.js see use with express.js
A serverless plugin is provided. It uses the metadata within the classes to create at runtime the serverless configuration. In other words the developer won't need to worry about adding/editing serverless.yml
functions section. See serverless-apigator
How to use it
Install
yarn add @microgamma/apigator
Create the app container
Create a service file.
import { Endpoint, Lambda } from '@microgamma/apigator';
@Endpoint({
cors: true,
name: 'my-first-service',
private: false
})
export class MyFirstService {
@Lambda({
method: 'GET',
path: '/'
})
public index() {
return `Hello world! Today is ${new Date().toISOString()}`;
}
}
Now you can retrieve the metadata at run time:
import { getEndpointMetadataFromClass, getLambdaMetadataFromClass } from '@microgamma/apigator';
import { MyFirstService } from './my-first.service';
const endpointMetadata = getEndpointMetadataFromClass(MyFirstService);
console.log({endpointMetadata});
const lambdas = getLambdaMetadataFromClass(MyFirstService);
lambdas.forEach((lambda) => console.log({lambda}));
Usually you won't need to do the above though.
@Lambda
The @Lambda
decorator stores the provided metadata and wraps the annotated method inside an asynchronous function. At runtime the function's real arguments may vary: i.e.: if it's called as an Aws Lambda its arguments will be event, context
whether if called within express they will be request, response
. To handle the differences between environments we use a service called LambdaDefaultHandler
. By default, the AwsEventHandler
is used. To use a different handler it must be specified in the @Endpoint
decorator (see below).
Valid values are:
interface LambdaOptions {
name?: string;
path: string;
method: string;
integration?: string;
private?: boolean;
cors?: boolean;
authorizer?: string | {};
description?: string;
}
@Endpoint
The endpoint decorator stores the provided metadata and sets the implementation of the LambdaDefaultHandler
to use.
Valid values are:
interface EndpointOptions {
readonly name: string;
readonly basePath?: string;
readonly private?: boolean;
readonly cors?: boolean;
}
I.e. when using it with express.js ExpressEventHandler
needs to be used.
@Endpoint({
cors: true,
name: 'my-first-service',
private: false,
providers: [{
provide: LambdaDefaultHandler,
implementation: ExpressEventHandler
}]
})
@Path
Retrieves a value from the path and assign it to the annotated argument
@Lambda({
method: 'GET',
path: '/me/{name}'
})
public me(@Path('name') user) {
return `Hello ${user}`;
}
@Body
Retrieves the body and assign it to the annotated argument
@Lambda({
method: 'POST',
path: '/me'
})
public me(@Body() user) {
return `Hello ${user}`;
}
Retrieves a value from the http headers and assign it to the annotated argument
@Lambda({
method: 'GET',
path: '/me'
})
public me(@Header('name') user) {
return `Hello ${user}`;
}
Use with express.js
Install express.js
yarn add express @types/express
Set ExpressEventHanlder
as described above.
Be aware that express uses the :param
notation for path parameters so the lambda path need to be such as
@Lambda({
method: 'GET',
path: '/me/:name'
})
public me(@Path('name') user) {
return `Hello ${user}`;
}
Create server.ts
file:
import { bootstrap, getEndpointMetadataFromClass, getLambdaMetadataFromClass, LambdaOptions } from '@microgamma/apigator';
import express, { Application } from 'express';
import { MyFirstService } from './my-first.service';
const app: Application = express();
const port = 3000;
const service = bootstrap(MyFirstService);
function createExpressHandler(lambda: LambdaOptions, app: Express.Application) {
app[lambda.method.toLowerCase()](lambda.path, service[lambda.name]);
}
lambdas.forEach((lambda) => createExpressHandler(lambda, app));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Run after transpile or with ts-node
yarn ts-node server.ts
You can hit your lambda at localhost:3000
Use with Serverless Framework
See serverless-apigator for more information.