Skip to content

Commit

Permalink
Release to main move to alpha version (internal testing) (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
mildronize authored Dec 30, 2023
2 parents 5ae2942 + 15280f0 commit c87dff7
Show file tree
Hide file tree
Showing 181 changed files with 4,229 additions and 7,456 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.eslintrc.js
24 changes: 24 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
// https://stackoverflow.com/questions/58510287/parseroptions-project-has-been-set-for-typescript-eslint-parser
overrides: [
{
files: ['*.ts', '*.tsx'], // Your TypeScript files extension

// As mentioned in the comments, you should extend TypeScript plugins here,
// instead of extending them outside the `overrides`.
// If you don't want to extend any rules, you don't need an `extends` attribute.
extends: [
'plugin:@typescript-eslint/recommended',
// 'plugin:@typescript-eslint/recommended-requiring-type-checking',
// 'plugin:@typescript-eslint/strict',
],

parserOptions: {
project: ['./tsconfig.json'], // Specify it only for TypeScript files
},
},
],
root: true,
};
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,7 @@ dist
inversify-express-utils

.idea
.DS_Store
.DS_Store

.azurite
tmp
262 changes: 58 additions & 204 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@
</p>

<p align="center">
Azure Function Lightweight frameworks with DI, providing type safe function triggers and bindings
Type-safe Azure Function Library
</p>

<p align="center"><a href="https://github.com/mildronize/nammatham/actions/workflows/test.yml"><img src="https://github.com/mildronize/nammatham/actions/workflows/test.yml/badge.svg" alt="Build &amp; Test"></a> <a href="https://codecov.io/gh/mildronize/nammatham"><img src="https://codecov.io/gh/mildronize/nammatham/branch/main/graph/badge.svg?token=Y7ZMDKFPAN" alt="codecov"></a> <a href="https://www.npmjs.com/package/nammatham"><img src="https://img.shields.io/npm/v/nammatham" alt="npm version"></a> <a href="https://www.npmjs.com/package/nammatham"><img src="https://img.shields.io/npm/dt/nammatham" alt="npm download"></a></p>
<p align="center"><a href="https://www.npmjs.com/package/nammatham"><img src="https://img.shields.io/npm/v/nammatham" alt="npm version"></a> <a href="https://www.npmjs.com/package/nammatham"><img src="https://img.shields.io/npm/dt/nammatham" alt="npm download"></a></p>


> **Nammatham** v1 is stable now (I've currently used in production), due to Nammatham v1 is based on Azure Functions Node.js v3.5.x. Azure will release Azure Functions Node.js v4 in GA (General availability) soon, [See in Roadmap 2023](https://github.com/Azure/azure-functions-nodejs-library/wiki/Roadmap)
>
> **Nammatham** v2 is [currently in development](https://github.com/thaitype/nammatham/issues/77), it will based on Azure Functions Node.js v4. [Tracking issue Nammatham supported with v4](https://github.com/thaitype/nammatham/issues?q=is%3Aissue+is%3Aopen+label%3Afunc-v4)
> Due to Azure Functions Node.js v4 Release GA General availability, **Nammatham** v1 is now maintainance mode.
| Version | Status | Azure Functions Node.js | Branch | Build Status |
| ------- | -------------- | ----------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| v1.x | Maintenance | v3.x | [v1.x][v1.x] | [![Build & Test](https://github.com/thaitype/nammatham/actions/workflows/test.yml/badge.svg)](https://github.com/thaitype/nammatham/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/mildronize/nammatham/branch/main/graph/badge.svg?token=Y7ZMDKFPAN)](https://codecov.io/gh/mildronize/nammatham) |
| v2.x | In Development | v4.x | [next][next] | [Tracking v2 Roadmap](https://github.com/thaitype/nammatham/issues?q=is%3Aissue+is%3Aopen+label%3Afunc-v4) |

[v1.x]: https://github.com/thaitype/nammatham/tree/v1.x
[next]: https://github.com/thaitype/nammatham/tree/next


## 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`
Expand All @@ -22,225 +29,72 @@ Empowering TypeScript on Azure Functions with Nammatham, Azure Open Source Day @
[![](docs/imgs/azure-open-source-day-2023.png)](https://www.youtube.com/watch?v=n6B4-5Lt2h0) (Thai speech, subtitle will added later)
- Slides: https://docs.google.com/presentation/d/1WUIXaUxXaiixZ2bgGCfx-f4Gdrmjl4RfbwKaEfAC6t4/edit?usp=sharing

## Compatibility with Azure Functions
- [Azure Function NodeJs](https://github.com/Azure/azure-functions-nodejs-worker/) : v3.x (`@azure/functions`)
- [Runtime Version](https://docs.microsoft.com/azure/azure-functions/functions-versions): 4 ([Source Code](https://github.dev/Azure/azure-functions-host/tree/release/4.x))
- Node.js Versions: 16, 18


## 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:

```ts
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}`);
}
## Minimal Get Started

For dev server, using express.js

```typescript
import { AzureFunctionsAdapter } from "@nammatham/azure-functions";
import { initNammatham } from "@nammatham/core";
import { expressServer } from "@nammatham/express";

const n = initNammatham.create(new AzureFunctionsAdapter());
const func = n.func;
const app = n.app;

const helloFunction = func
.httpGet('hello', {
route: 'hello-world',
})
.handler(async (request, ctx) => {
ctx.context.log('HTTP trigger function processed a request.');
ctx.context.debug(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || (await request.text()) || 'world';
return { body: `Hello, ${name}!` };
});

app.addFunctions(helloFunction);
if (process.env.NODE_ENV === 'development') {
app.use(expressServer());
}
app.start();
```

## Features
- 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](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-cosmosdb-v2-trigger?tabs=in-process%2Cfunctionsv2&pivots=programming-language-javascript#configuration) and [v4](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-cosmosdb-v2-trigger?tabs=in-process%2Cextensionv4&pivots=programming-language-javascript#configuration).
- Blob
- Service Bus
- If your binding type isn't in the list, please use [custom type](docs/define-azure-function.md#custom-binding)
- You can see [All available type support](docs/binding-type.md) or create a PR ;).
- Support TypeScript and [InversifyJS](https://github.com/inversify/Inversify) as the [Most Popular Inversion of Control Container and Dependency Injection Approach](https://npmtrends.com/awilix-vs-bottlejs-vs-inversify-vs-node-dependency-injection-vs-tsyringe-vs-typedi-vs-typescript-ioc)
- Build Tool Agnostic, this framework just provide the library. It can work with all TypeScript build tool e.g. tsc, esbuild, etc.

## Installation
You can install nammatham using npm:

```
npm install nammatham inversify reflect-metadata --save
```
Then edit `package.json` like this;

For the [InversifyJS](https://github.com/inversify/InversifyJS#-installation), please refer the documentation for usage.

## Starter Project

- [Basic Nammtham Starter Template](https://github.com/mildronize/nammatham-starter)

## Getting Started

Full examples please, go to [examples](examples) directory

### 1. Basic

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

1. define `startup.ts` (or any name)
```ts
// 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
```ts
// 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
```ts
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`.

```ts
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}}`,
};
```json
{
"main": "dist/src/main.js",
"scripts": {
"dev": "cross-env NODE_ENV=development tsx watch src/main.ts"
}
}
```

### 3. Add Services


```ts
// src/startup.ts
import 'reflect-metadata';
import { NammathamApp } from 'nammatham';
import { UserService } from './services/user.services';
import { UserFunction } from './functions/user.function';
Run

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

```ts
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);
}
}
npm run dev
```

service:
The result commandline will show (Dev Server):

```ts
import { injectable } from 'inversify';
@injectable()
export class UserService {
constructor() {}
public getData() {
return `Hey I'm service`;
}
}
```
## Using Inversify API for Binding Services
Start Nammatham, Type-safe Serverless Framework
In some cases, if you want to binding services with [Inversify Container](https://github.com/inversify/InversifyJS/blob/master/wiki/container_api.md) by yourself.
In the startup file, you can simply get the Container from `builder.container` as shown in the example below:
[12:44:14.784] INFO (44575): Using adapter: AzureFunctionsAdapter
[12:44:14.786] INFO (44575): Function "hello" added
[12:44:14.786] INFO (44575): Using middleware: expressServer
[12:44:14.793] INFO (44575): All functions registered
[12:44:14.794] INFO (44575): Dev Server started at http://localhost:3000
```ts
// src/startup.ts
import 'reflect-metadata';
import { NammathamApp } from 'nammatham';
import { UserService } from './services/user.services';
import { UserFunction } from './functions/user.function';
Functions:
const builder = NammathamApp.createBuilder(__filename);
builder.addFunctions(UserFunction);
// Using Inversify Container API
builder.container.bind(Service).toSelf();

builder.build();

export default builder.getApp();
hello: [GET] http://localhost:3000/api/hello-world
```

## Documentation

Please read the [full documentation in the repo](docs)
<!-- ## What's different with Azure Functions v4 (Official Library) -->

## Inspiration
- [Azure Functions .NET](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-csharp?tabs=azure-cli%2Cin-process)
Expand Down
13 changes: 0 additions & 13 deletions docs/README.md

This file was deleted.

31 changes: 0 additions & 31 deletions docs/azure-functions/README.md

This file was deleted.

Loading

0 comments on commit c87dff7

Please sign in to comment.