New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

js-core-data

Package Overview
Dependencies
Maintainers
1
Versions
176
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

js-core-data

ORM inspired by Apple's Objective-C CoreData

  • 1.4.3
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
8
decreased by-85.19%
Maintainers
1
Weekly downloads
 
Created
Source

js-core-data

Build Status NPM Version NPM Downloads

dependencies devdependencies

==============

CoreData is very powerful framework created by Apple for working with data. This module is heavily inspired by it's principles and simplifies usage by implementing methods to fit server environment. Providing easy interface for defining data model, version migration, working with entities and persisting data to persistent store.

Currently supported persistent stores: MySQL, PostgreSQL, SQLite

Important

This module is now used in few medium scale projects heading to production in few weeks. There are still some tasks to improve performance and abilities of data fetching. If you are using this module and consider it useful, any feedback or help is very appreciated.

Example

var CoreData = require('js-core-data');

var db = new CoreData('sqlite://:memory:');

var User = db.define('User',{username:'string'});
var Company = db.define('Company',{name:'string'});

db.defineRelationship(User,Company,'company',{inverse:'users'});
db.defineRelationship(Company,User,'users',{inverse:'company',toMany:true});

db.syncSchema({force:true}).then(function(){
    console.log('schema synced')

    var context = db.createContext();

    var user1 = context.create('User',{username:'user1'});
    var user2 = context.create('User',{username:'user2'});

    var company = context.create('Company',{name:'test company'});

    user1.setCompany(company);
    company.addUser(user2);

    context.save().then(function(){
        context.destroy();
    })
})

For more examples see /examples, especially TODO list REST backend example.

Context

When you create/update/access/delete data you always use context. Every time you create or fetch some object (entity instance) it's stored in context. Every updated attribute or relationship is stored in memory. After everything is ready, you just save the context.

The best thing about the context is that all changes are stored in memory until you save them into persistent store in one transaction.

Working with objects

Objects are created in contexts. Every object exists in one instance per context (every time you fetch object twice, it's still the same instance).

var db = new CoreData(...);
var context = db.createContext();
var userId = 123;
context.getObjectWithId('User',userid).then(function(user1){
    context.getObjectWithId('User',userid).then(function(user2){
        console.log(user1 === user2); // true
    })
})

Every change to objects are made in memory (attributes and relationships). All changes are stored in persistent store (database) after save in one transaction.

Fetching objects

...
var User = db.define('User',{username:'string'});
var Company = db.define('Company',{name:'string'});

db.defineRelationship(User,Company,'company',{inverse:'users'});
db.defineRelationship(Company,User,'users',{inverse:'company',toMany:true});

var context = db.createContext();
context.getObjects('User',{
    where:['SELF.company.name = %s','test company'],
    sort:'username'
}).then(function(users){
    console.log(users);
    context.destroy();
})

Where (Predicate)

Where condition is array with format ['format',arg1,arg2,arg3] supports joins so you can query:

['SELF.accessTokens.token = %s',req.params.token] // find user(s) with access token

['SELF.company.name = %s','test'] // find user(s) in company named 'test'

You can also use object format:

{'SELF.accessTokens.token':req.params.token}

{'SELF.company.name':'test'}

Relationships

There are two types of relationships toMany and toOne. Every relationship should have it's inverse (only in few cases it's possible do ignore inverse relationship).

Methods for accessing relationships are automaticaly defined for model.

...
db.define('User',{username:'string'});
db.define('Company',{name:'string'});

db.defineRelationshipManyToOne('User','Company','company','users');

var context = db.createContext();
var user = context.create('User');
var company = context.create('Company');

// generated methods
user.setCompany(company);
company.addUser(user);
company.addUsers([user,...]);
company.removeUser(user);
company.removeUsers([user,...]);

Note: using SQL functions in predicate is store dependent (different set of functions for each store)

Raw fetch

You can fetch raw data from entities.

context.fetch('User',{
        fields:{
            companyName:'SELF.company.name',
            firstname:'SELF.firstname',
            lastname:'SELF.lastname',
            name:'SELF.firstname'
        },
        order:'SELF.firstname'
    })
    .then(function(data){
        console.log(data) // [{companyName:'...',firstname:'...',lastname:'...',name:'...'}]
    })

Note: using SQL functions in raw fetch is store dependent (different set of functions for each store)

Counting objects

When you need to count how many object of specific (with firstname John) entity you have, you can use this method.

context.getObjectsCount('Car',{where:['SELF.firstname = %s','John']}).then(function(count){
    console.log(count)
});

Schema synchronization and migration

You can specify multiple model schemas each with specific version. You can also specify schema migration from and to specific model version.

When you don't need model versioning, the default version is used.

To sync model schema use syncSchema method.

var CoreData = require('js-core-data');
var express = require('express');

var db = new CoreData(DATABASE_URL);

db.defineEntity('MyEntity',{attribute1:'string',attribute2:'string'});

db.syncSchema({force:true}).then(function(){ // force option drops existing tables
    console.log('schema synced');
});

For migrations and multiple version model use createModel, createMigrationFrom and setVersionModel methods

...
model1 = db.createModel('0.1');
model1.defineEntity('User',{username:{type:'string',unique:true}})

model2 = db.createModel('0.2');
model2.defineEntity('User',{username:{type:'string',unique:true},password:'string'})

migration1to2 = model2.createMigrationFrom(model1);
migration1to2.addAttribute('User','password');

// build schema for version 0.1
db.setModelVersion('0.1');
db.syncSchema().then(function(){
    // migrate schema to version 0.2
    db.setModelVersion('0.2');
    db.syncSchema().then(function(){
        // now model version is 0.2
    })
});

Every persistent store (data) has schema version stored in table _meta, during syncSchema every store checks it's model version, finds migrations needed to be performed and executes them. This way you don't need to take care about model version of each store.

Migrations can add/remove/rename attributes/relationships/entities.

Note: currently store cannot join migrations (eg. 0.1=>0.2=>...=>0.8=>0.9)

Express middleware

Middleware takes care about creatint, destroying and assigning context to req.context. Context is destroyed on res.once('finish')

var CoreData = require('js-core-data');
var express = require('express');

var db = new CoreData('sqlite://:memory:');
var app = new express();

// creates context and assigns it to req.context; context is automatically destroyed when response is finished
app.use(db.middleware());

app.get('/users',function(req,res,next){
    req.context.getObjects('User').then(function(users){
        res.send(users);
    }).catch(next)
})

app.listen(process.env.PORT)

TO-DO

  • more detailed documentation (object subclasses, transient/private attributes etc.)
  • more examples
  • multiple migrations in one transaction
  • sofisticated (store parsed) predicate
  • caching mechanism (redis)

Keywords

FAQs

Package last updated on 24 Jun 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc