@danieleisenhardt/brazier
TypeScript icon, indicating that this package has built-in type declarations

0.7.2 • Public • Published

Brazier

a TypeScript framework for Firebase

Installation

In order to use Brazier you will need a Google Firebase project. If you do not have this already you can start by creating one here:

https://console.firebase.google.com/u/0/

The next thing you will need is Firebase CLI, installation and info can be found here:

https://firebase.google.com/docs/cli

Then make a directory for your project and go there:

mkdir myproject
cd myproject

Here you can run the firebase installation:

firebase init

Select at least Firestore, Functions and Emulators.

Choose Typescript when asked which language you want to use.

Add the following to the compilerOptions in functions/tsconfig.json:

"experimentalDecorators": true

After this is done go to the functions dir created by Firebase CLI and install brazier:

cd functions
npm i @danieleisenhardt/brazier
node_modules/@danieleisenhardt/brazier/script/init.js

Autoloading

In config/app.ts is an array of folders that will be autoloaded recursively by Brazier. Classes from these folders can be used for dependency injection and in the routes defined in config/route.ts

Routing

Routes are defined in config/route.ts which exports an array of Route and RouteGroup objects. The latter can contain an array of Routes and RouteGroups enabling nested groups.

Routes take a method, path, controllerName, and methodName parameter as well as an optional config parameter with can contain the name of a Request object and an array names of Middleware.

Dependency injection

Services can be injected in other classes such as controllers and requests. Here is a controller loading a class named ExampleService:

export default class ExampleController {
    constructor(
        private exampleService: ExampleService,
    ) {
    }
    
    ...
}

It is important to name the private variable the same as the Service name, but starting with a lowercase character or Awilix autoloading will be unable to find it.

Controllers

Controllers are placed in the controller folder for the router to use.

Requests

Requests are placed in the request folder. The router will handle the request before the controller function. This way validation and data tranformation can be executed before business logic.

Brazier comes with built-in request validation by validator-js. Meaning validation can either be done through the handle() function, or the rules property:

import {ApiRequest, ValidationRule, Request, Response} from 'brazier';

export default class ExampleRequest extends ApiRequest {

    protected rules: {[key: string]: ValidationRule[]} = {
        name: [['isLength', {max: 4}]]
    };

    async handle(request: Request, response: Response, next: () => void) {
        if (request.body['name'] !== 'foo' && request.body['name'] !== 'bar') {
            return this.respondWithError(response, 'name has to be either foo or bar');
        }

        next();
    }
}

The validations from the rules property are checked first, which saves on performance if the handle() function makes calls to a database or other external resource.

Middleware

Middleware is placed in the middleware folder. In addition to a Request, routes can also have a variable amount of Middleware applied to them. These have a handle() function similar to requests and can be used to execute any code before the business logic in the controller.

Entities

Entities are placed in the entity folder. They can be transformed by transformers and their child class FirestoreEntity is used by repositories.

Repositories

Repositories are provided by wovalle/fireorm as a way to comminicate with firestore. They are placed in the repositories folder, but have a slightly different syntax from the rest of the framework:

import {CustomRepository, getRepository} from 'fireorm';
import {FirestoreRepository} from 'brazier';
import Example from '../entity/Example';

@CustomRepository(Example)
class ExampleRepository extends FirestoreRepository<Example> {
}

export const exampleRepository = getRepository(Example) as ExampleRepository;

The exampleRepository can be only loaded without dependency injection:

import {exampleRepository} from '../repository/ExampleRepository';

This does mean Awilix autoloading will not contain repositories per request.

For this reason you should never put data properties within a repository (i.e. for caching) because these could end up being used by another request from a different end user.

Transformers

Transformers are placed in the transformer folder. They are used by Controllers to generate output for API responses. This way data can be transformed and/or obfuscated to send only what is useful and secure to API consumers.

Readme

Keywords

none

Package Sidebar

Install

npm i @danieleisenhardt/brazier

Weekly Downloads

1

Version

0.7.2

License

MIT

Unpacked Size

96.2 kB

Total Files

61

Last publish

Collaborators

  • danieleisenhardt