Skip to content

FuseDB - blazing fast ORM with simplicity in mind with love from FuseBox

Notifications You must be signed in to change notification settings

fuse-box/fusedb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

FuseDB

FuseDB is an ORM with traditional ActiveRecord approach, that provides a simple yet powerful API. FuseDB stores data in the filesystem (nedb) or MongoDB. You write your own adapter and implement a different database suppport.

It's perfectly suitable for medium scale databases or Electron apps and takes 5 minutes to dive in.

Checkout this example

Setting up a connection

Everything works by default, and the files will be stored in your home folder e.g /home/user/.fusedb on linux or /Users/user/.fusedb on mac. In order to customise it, do the following

File database

import { FuseDB, FileAdapter } from "fusedb"
FuseDB.setup({ adapter : 
    FileAdapter({ path: "/path/to/folder/", database: "test" }) });

MongoDB database

Install mongo module first

npm install mongodb --save
import { FuseDB, MongoAdapter } from "fusedb";
FuseDB.setup({
    adapter: MongoAdapter({
        url : "mongodb://localhost:27017/fusedb",
        dbName : "myProject"
    })
});

Models

Models contain essential methods to talk to the database, methods like save, find, remove are reserved. Therefore we don't need any "repositories" and connection pools as everything is handled internally

import { Field, Model } from "fusedb";

class Author extends Model<Author> {
    @Field()
    public name: string;

    @Field()
    public books: Book[];
}


class Book extends Model<Book> {
    @Field()
    public name: string;

    @Field()
    public author: Author;
}

Field decorator tells fusedb to serialize the field. There are a few reserved methods:

Creating records

const john = new Author({ name: "John" });
await john.save();

const book1 = new Book({ name: "book1", author: john });
const book2 = new Book({ name: "book2", author: john });

await book1.save();
await book2.save();


john.books = [book1, book2];
await john.save();

FuseDB will save references as ids and it won't store the entire model

Field decorator

Field decorator has a few properties you might find useful

hidden

Hiding your field when sending to view

@Field({ hidden : true })
public password: string;

toJSON

Define custom serialiser when sending to view

@Field({ 
    toJSON : value => moment(value).format("LLLL") 
})
public date: Date;

Finding

First record:

const author = await Author.find<Author>({ name: "john" }).first();

All records:

const authors = await Author.find<Author>({
        name : {$in : ["a", "b"]}
        }).all();

Count:

const num = await Author.find<Author>().count();

Query normalization

ObjectID

You don't need to convert strings to ObjectID When you using MongoAdapter. FuseDB does it for you.

for example:

 const record = await Foo.findById<Foo>("5b290c188e9f69ab51c3bd41");

It will be applied for find method recursively for example

 await Foo.find<Foo>({
     _id : $in : ["5b290c188e9f69ab51c3bd41", "5b290c188e9f69ab51c3bd42"]
  }).first()

Passing real objects to query

Instead of extracting IDs you can pass a real FuseDB Model to the query. For example

const group = await Group.find({name : "admin"}).first();
const adminUsers = await Users.find({group : group}).all(); // will fetch all users that belong to admin group

Chaining query

const authors 
    = await Author.find<Author>({active : true})
            .sort("name", "desc")
            .limit(4)
            .skip(2)
            .all()

Joining references

FuseDB can automatically join referenced fields by making optimised requests (collecting all ids and making additional queries to the database) e.g

const books = await Book.find<Book>().with("author", Author).all();

Saving

const author = new Author();
author.name = "john"
await autor.save() 

Removing

const author = await Author.find({name : "john"});
await author.remove()

Model event hooks

Defining the following hooks will allow you to intercept model events

export class Foo extends Model<Foo> {
    @Field()
    public name: string;
    // before updating or creating a record
    async onBeforeSave() {}
    // after creating or updating a record
    async onAfterSave() {}
    // before updating a record
    async onBeforeUpdate() {}
    // after creating a record
    async onBeforeCreate() {}
}

Validators

Validators in FuseDb are quite easy to use and implement. The framework offers a few default validators, in order to enable them call a function in your entry point (before you start importing your models)

import { enableDefaultDecorators } from "fusedb"
enableDefaultDecorators();

Now you can start using them in your models, like that:

class FooBarMax extends Model<FooBarMin> {
    @Field() @Validate({max : 3})
    public name: string;
}

Default validators can assert a custom message

@Validate({nameOftheValidator : { message :"Failed", value : 3}})

Min Symbols Validator

class FooBarMin extends Model<FooBarMin> {
    @Field() @Validate({min : 3})
    public name: string;
}

Max Symbols Validator

class FooBarMax extends Model<FooBarMax> {
    @Field() @Validate({max : 3})
    public name: string;
}

Email Validator

class FooBarEmail extends Model<FooBarEmail> {
    @Field() @Validate({email : true})
    public name: string;
}

RegExp Validator

class FooBarRegExp extends Model<FooBarRegExp> {
    @Field() @Validate({regExp : /\d{2}/})
    public name: string;
}

Enum Validator

const seasons = {
    SUMMER: 'summer',
    WINTER: 'winter',
    SPRING: 'spring'
}
class FooBarEnum extends Model<FooBarEnum> {
    @Field() @Validate({enum : seasons})
    public season: string;
}

Function validator

class FooBarCustom extends Model<FooBarCustom> {
    @Field() 
    @Validate({fn : value => {
        if( value !== "foo") throw new Error("Value should be foo only")
    }})
    public name: string;
}

Your own validators

Define a class with Validator

import { Validator, FieldValidator } from "fusedb";

@Validator()
export class OopsValidator implements FieldValidator {
    validate(field: string, props: any, value: any) {
        throw "Somethign wentWrong"
    }
}

A validator with name oops has be registered, how you can use it in your models

class Hello extends Model<Hello> {
    @Field() @Validate({oops : true})
    public name: string;
}

About

FuseDB - blazing fast ORM with simplicity in mind with love from FuseBox

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published