# mgData

[![npm version](https://badge.fury.io/js/mgdata.svg)](https://badge.fury.io/js/mgdata)
[![Build Status](https://secure.travis-ci.org/magnetnation/mgData.svg?branch=master)](https://travis-ci.org/magnetnation/mgData)
[![Coverage Status](https://coveralls.io/repos/github/magnetnation/mgData/badge.svg?branch=master)](https://coveralls.io/github/magnetnation/mgData?branch=master)

Data storage for isomorphic typescript applications

## Examples

### Define your data

```typescript
import * as Core from 'mgcore';
import * as Data from 'mgdata';

let D = Core.Meta.Descriptors;
let meta = Core.Meta.Decorators;

@Core.Serialization.Serializable()
@meta.Entity()
export class User extends Core.Meta.Entity
{
    @meta.Requisite(D.RequisiteType.Text, D.RequisiteOptions.PartOfUniqueKey)
    public code: string;

    @meta.Requisite(D.RequisiteType.Text)
    public name: string;

    @meta.Requisite(D.RequisiteType.Text, D.RequisiteOptions.CaseSensitive)
    public password: string;

    constructor()
    {
        super();
        this.construct(this);   
    }
}

let u = new User();
u.code = "ADM";
u.name = "Administrator"
u.password = "1234";
```
### Save your data

```typescript
let storage = new Data.Storage();
storage.save(u);
storage.dispose();
```

### Find your data

* Simple:

```typescript
let user = await storage.findOne<User>({ $: "User", $out: [ "*" ], code: "ADM"});
```

* Or complex:

```typescript
let query = {
    $: {RootClient: "Client"}, // entity name with explicit alias
    $out: 
    [
        "name", 
        "id", 
        "id - id*2", //Function
        {"ActiveUser": "ModUserInner.code"}, //Alias to real expression
        {$count: "modificationUser.id"}, //Aggregate
        {$sum: "id-disabled"}, //Aggregate + Function
        {$: "Warehouse", $out: [{$max: "id"}], code: "$RootClient.code"}, //output query that refers to parent
        {"MaxWarehouse": {$: "Warehouse", $out: [{$max: "id"}], code: "$RootClient.code"}}//alias to output query that refers to parent
    ],
    $where:
    [
        { name: { "~": "%Dima%" } }, //Like operator
        { id: { $in: [1,2,3] } }, //In array
        { id: { $in: {$: "Client", $where: {id:"123"}}}, code: "sd"}, //In subquery
        { code: "123", name: "ads"}, //Multiple conditions connected by AND
        { $or: //Set of conditions connected by OR 
            [
                {id: {"=": 12}}, 
                {code: "Dima", name: "Kozlov"},
                {creationDate: {"~": "1234"}}
            ] 
        },
        { $not: {id: "123"}}, //Not examples
        { $not: {$or: [ {id: "123"}, {id: "324"} ]} }
    ],
    $orderby: {id: "asc", "modificationUser.code": "desc"},
    $groupby: ["modificationUser", "disabled"],
    $joins:[ 
    {
        $entity: "User",
        $type: "outer",
        $on: { "ModUserOuter.id": "$modificationUser" },
        $alias: "ModUserOuter"
    },
    {
        $entity: "User",
        $type: "inner",
        $on: [{ "ModUserInner.id": "$modificationUser" }, { "ModUserInner.id": "$ModUserOuter.id" }],
        $alias: "ModUserInner"
    },
    {
        $entity: "Warehouse",
        $type: "inner",
        $on: { "WH.client.modificationUser.code": "$ModUserInner.code" },
        $alias: "WH"
    }]}              

let data = await storage.search(query);
```
## More examples

* [Unit tests](https://github.com/magnetnation/mgData/tree/master/spec/unit)
