Azure Function Lightweight frameworks with DI, providing type safe function triggers and bindings
Nammatham (นามธรรม in Thai, pronounced /naam ma tham/
, means abstract in Thai) is Azure Function Nodejs Lightweight framework with Dependency Injection. Provide type safety wrapping function.json
- Azure Function NodeJs : v3.x (
@azure/functions
) - Runtime Version: 4 (Source Code)
- Node.js Versions: 16, 18
Nammatham is a framework that allows you to use Azure Functions with TypeScript and decorators. It provides pre-defined JSON binding objects and utility functions, such as httpTrigger
, to make it easier to create Azure Functions.
Example:
import { AuthorizationLevel, BaseFunction, functionName, httpTrigger } from "nammatham";
import { HttpRequest } from "@azure/functions";
@functionName("GetUsers", httpTrigger(AuthorizationLevel.Anonymous, ["get"]))
export class UserFunction extends BaseFunction {
public override execute(req: HttpRequest): void {
const name = req.query.name;
this.res.send(`hello get user with ${name}`);
}
}
- Simple Framework, support all functionality with Azure Functions features
- Provide type utiltiy wrapping around
function.json
- Better project orgnization
- Bindings & Triggers Built-in type support
- Http
- Timer
- Cosmos DB, support both v2 and v4.
- Blob
- Service Bus
- If your binding type isn't in the list, please use custom type
- You can see All available type support or create a PR ;).
- Support TypeScript and InversifyJS as the Most Popular Inversion of Control Container and Dependency Injection Approach
- Build Tool Agnostic, this framework just provide the library. It can work with all TypeScript build tool e.g. tsc, esbuild, etc.
You can install nammatham using npm:
npm install nammatham inversify reflect-metadata --save
For the InversifyJS, please refer the documentation for usage.
Full examples please, go to examples directory
This is basic to use partially type support, you can follow steps below:
-
define
startup.ts
(or any name)// File: src/startup.ts import 'reflect-metadata'; import { NammathamApp } from 'nammatham'; import { SampleHttpFunction } from './functions/sample-http.function'; const builder = NammathamApp.createBuilder(__filename); builder.addFunctions(SampleHttpFunction); builder.build(); export default builder.getApp();
-
Write a function handler, extend with
BaseFunction
we will auto inject Azure Function's Context// src/functions/sample-http.function.ts import { AuthorizationLevel, BaseFunction, functionName, httpTrigger } from 'nammatham'; import { HttpRequest } from '@azure/functions'; @functionName('SampleHttp', httpTrigger(AuthorizationLevel.Anonymous, ['get'])) export class SampleHttpFunction extends BaseFunction { public override execute(req: HttpRequest): void { const name = req.query.name; const message = `hello get user with ${name}`; this.context.log(message); this.res.send(message); } }
-
Add Azure Functions files at root
host.json
local.settings.json
-
Run
ts-node
to generate all Azure Functionsexport nammatham_env=build; ts-node src/startup.ts && tsc
-
Start Azure Functions
func start
This method will support full support type when bindings config is set, for example below:
you can define your own function.json
in Typescript object (as you can see the variable bindings
), this will binding type into this.context.bindings
.
import { BaseFunction, binding, functionName } from 'nammatham';
const bindings = [
binding.httpTrigger({ name: 'req' as const }), // make string to literal type
binding.http({ name: 'res' as const }), // make string to literal type
] as const;
@functionName('GetUser', ...bindings)
export class UserFunction extends BaseFunction<typeof bindings> {
public override execute() {
const { req } = this.context.bindings;
// ^---- `req` will be type HttpRequest
const name = req.query.name;
this.context.res = {
body: `hello get user with ${name}}`,
};
}
}
// src/startup.ts
import 'reflect-metadata';
import { NammathamApp } from 'nammatham';
import { UserService } from './services/user.services';
import { UserFunction } from './functions/user.function';
const builder = NammathamApp.createBuilder(__filename);
builder.addFunctions(UserFunction);
builder.configureServices(services => {
services.addSingleton(Service);
// services.addScoped(Service);
// services.addTransient(Service);
});
builder.build();
export default builder.getApp();
define a function handler
import { AuthorizationLevel, BaseFunction, functionName, httpTrigger } from 'nammatham';
import { HttpRequest } from '@azure/functions';
import { UserService } from '../services/user.service';
import { inject } from 'inversify';
@functionName('GetUsers', httpTrigger(AuthorizationLevel.Anonymous, ['get']))
export class UserFunction extends BaseFunction {
constructor(@inject(UserService) private userService: UserService){
super();
}
public getUsers(): void {
const { req } = this.context.bindings;
const name = req.query.name;
const message = `hello get user with ${name}, service data: ${this.userService.getData()}`;
this.context.log(message);
this.res.send(message);
}
}
service:
import { injectable } from 'inversify';
@injectable()
export class UserService {
constructor() {}
public getData() {
return `Hey I'm service`;
}
}
In some cases, if you want to binding services with Inversify Container by yourself.
In the startup file, you can simply get the Container from builder.container
as shown in the example below:
// src/startup.ts
import 'reflect-metadata';
import { NammathamApp } from 'nammatham';
import { UserService } from './services/user.services';
import { UserFunction } from './functions/user.function';
const builder = NammathamApp.createBuilder(__filename);
builder.addFunctions(UserFunction);
// Using Inversify Container API
builder.container.bind(Service).toSelf();
builder.build();
export default builder.getApp();
Please read the full documentation in the repo
- Azure Functions .NET
- inversify-express-utils - We use inversify as a Dependency Injection Tool.
- Nestjs
- typestack/routing-controllers
- azure-middleware - Azure Functions Middleware Libray
- Thada Wangthammang, Software Engineer, Thailand