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
The project is at a very early stage of development, so please, feel free to contribute and extend the functionality. Besides, we don't have any other drivers but nedb
. MongoDb
Adapter is required.
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
import { FuseDB, FileAdapter } from "fusedb"
FuseDB.setup({ adapter : FileAdapter({ path: "/path/to/folder/", database: "test" }) });
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:
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
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();
const authors
= await Author.find<Author>({active : true})
.sort("name", "desc")
.limit(4)
.skip(2)
.all()
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();
const author = new Author();
author.name = "john"
await autor.save()
const author = await Author.find({name : "john"});
await author.remove()
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}})
class FooBarMin extends Model<FooBarMin> {
@Field() @Validate({min : 3})
public name: string;
}
class FooBarMax extends Model<FooBarMax> {
@Field() @Validate({max : 3})
public name: string;
}
class FooBarEmail extends Model<FooBarEmail> {
@Field() @Validate({email : true})
public name: string;
}
class FooBarRegExp extends Model<FooBarRegExp> {
@Field() @Validate({regExp : /\d{2}/})
public name: string;
}
const seasons = {
SUMMER: 'summer',
WINTER: 'winter',
SPRING: 'spring'
}
class FooBarEnum extends Model<FooBarEnum> {
@Field() @Validate({enum : seasons})
public season: string;
}
class FooBarCustom extends Model<FooBarCustom> {
@Field()
@Validate({fn : value => {
if( value !== "foo") throw new Error("Value should be foo only")
}})
public name: string;
}
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;
}