nammatham
TypeScript icon, indicating that this package has built-in type declarations

1.3.0 • Public • Published

Nammatham Logo

Azure Function Lightweight frameworks with DI, providing type safe function triggers and bindings

Build & Test codecov npm version npm download

Description

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

Compatibility with Azure Functions

Introduction

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}`);
  }
}

Features

Installation

You can install nammatham using npm:

npm install nammatham inversify reflect-metadata --save

For the InversifyJS, please refer the documentation for usage.

Starter Project

Getting Started

Full examples please, go to examples directory

1. Basic

This is basic to use partially type support, you can follow steps below:

  1. 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();
  2. 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);
      }
    }
  3. Add Azure Functions files at root

    • host.json
    • local.settings.json
  4. Run ts-node to generate all Azure Functions

    export nammatham_env=build; ts-node src/startup.ts && tsc
  5. Start Azure Functions

    func start
    

2. Handle function.json config by yourself

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}}`,
    };
  }
}

3. Add Services

// 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`;
  }
}

Using Inversify API for Binding Services

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();

Documentation

Please read the full documentation in the repo

Inspiration

Author

  • Thada Wangthammang, Software Engineer, Thailand

Package Sidebar

Install

npm i nammatham

Weekly Downloads

6

Version

1.3.0

License

MIT

Unpacked Size

252 kB

Total Files

93

Last publish

Collaborators

  • mildronize