Giter VIP home page Giter VIP logo

openrecord's Introduction

OpenRecord

Build Status Coverage Status npm package version Package Quality Code Quality: Javascript Total Alerts

OPENRECORD is an ActiveRecord inspired ORM for nodejs.

Currently it supports the following databases/datastores: SQLite3, MySQL, Postgres, Oracle, REST and LDAP (+ ActiveDirectory)
If you want to build a GraphQL endpoint for any of these databases, OPENRECORD has some built in features to support you!

As the name imply, it's open and very easy to extend. The whole package was build that way.

It has a lot of features, just take a look at the docs!

Usage example

Here is an example how to get a single post from an existing sqlite3 file (by primary key).

const Store = require('openrecord/store/sqlite3')

const store = new Store({
  file: './my-posts-db.sqlite3',
  autoLoad: true
})

store.ready(async () => {
  const post = await store.Model('Post').find(1)
  console.log(post)
})

You don't have to define your model (optional) and you also don't have to define your model's attributes (optional).
Take a look at the docs to get started!

Contributing

If you've found a bug please report it via the issues page.
Before you submit a pull request, please make sure all tests still pass.


Sponsored by digitalbits.at

openrecord's People

Contributors

amir-s avatar bjpirt avatar chnied avatar dependabot[bot] avatar dineshgadge avatar firede avatar gtramontina avatar i4h avatar idma88 avatar mikeyusc avatar philwaldmann avatar sampsoncrowley avatar shreeve avatar xcorail avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openrecord's Issues

validatesUniquenessOf not called

validatesUniquenessOf never seems to run. I'm getting database level errors of unique index violations on an email column

module.exports = function (){
  this.filteredChanges = function filteredChanges(changes){
    return Object.keys(changes)
    .filter(key => key.toLowerCase() !== 'password')
    .reduce((obj, key) => {
      obj[key] = changes[key];
      return obj;
    }, {})
  }

  this.forCookie = function forCookie(){
    return {id: this.id, email: this.email}
  }

  this
  .validatesUniquenessOf(['email', 'athlete_id'])
  .validatesFormatOf('email', /^[^@\s\;]+@[^@\s\;]+\.[^@\s\;]+$/)
  .belongsTo('athlete')
  .hasMany('accounts_users')
  .hasMany('users', {through: 'accounts_users'})
  .hasMany('infokits')
  .hasMany('account_audits')
  .beforeSave(function(){
    let action;
    if(!this.__exists){
      action = 'create';
    } else if(this.hasChanges()){
      action = 'update';
    }
    if(action) console.log(this.account_audits.new({action: action, audited_changes: this.filteredChanges(this.changes), remote_address: this.context.current_ip || '127.0.0.1'}))
    return true
  })
}

Installation error

Hi.
When i try to install, these error messages are presented:
npm WARN git config --get remote.origin.url returned wrong result (https://git
hub.com/tgriesser/knex.git) undefined
npm WARN git config --get remote.origin.url returned wrong result (https://git
hub.com/tgriesser/knex.git) undefined
npm ERR! git clone https://github.com/tgriesser/knex.git undefined
npm ERR! git clone https://github.com/tgriesser/knex.git undefined
npm ERR! not found: git
npm ERR!
npm ERR! Failed using git.
npm ERR! This is most likely not a problem with npm itself.
npm ERR! Please check if you have git installed and in your PATH.

Something wrong with git url of knex.
I'm very sad, I really liked what I saw, =\

add get(id)

if find(id) can't find the record, it returns null.
use get(id) to throw an error if the record does not exist!

validates uniqueness of fails with UUID pk

{ [SQLError: error: select count(*) as "count" from "accounts" where "accounts"."email" = $1 and "accounts"."id" != $2 - invalid input syntax for uuid: "1"]
  message:
   { error: invalid input syntax for uuid: "1"
       at Connection.parseE (/home/samps/sites/personal/dus/office.downundersports.com/node/node_modules/pg/lib/connection.js:567:11)
       at Connection.parseMessage (/home/samps/sites/personal/dus/office.downundersports.com/node/node_modules/pg/lib/connection.js:391:17)

MySQL Documentation Incorrect

In the example listed to connect to a MySQL data source, the user ID property is listed as username, however, that doesn't work; if you look in the MySQL connection code in lib, it's actually looking for the "user" parameter.

Unable to save record without setting id when not using autoincrementing integer (serial)

I have a table column id of type UUID, as primary key (not null constraint), with a default set to gen_random_uuid() from pgcrypto extension

It works if i use sql like:
insert into test_table ("id") values ('84df10c9-517a-4dff-a96a-5799c30af0c4');
insert into test_table ("id") values (gen_random_uuid());
insert into test_table ("id") values (DEFAULT);
insert into test_table ("another_column") values ('i am not setting uuid');

Won't work when i do:

var test = new Test({ name: 'i am not setting uuid' })
test.save(function (e) {
  console.log(e)       // false
  console.log(this.id) // null
})

Possibly a bug similar to this issue

SortedList Plugin options bug

TypeError: Cannot read property 'scope' of undefined
at exports.definition.sortedList (../node_modules/ah-openrecord-plugin/node_modules/openrecord/lib/stores/sql/plugins/sorted_list.js:15:15)

when no options are provided in the model at this.sortedList();

Roadmap for v2

It has been a while since the last major update of openrecord. The reason is, it's running in production for for almost 3 years without problems. And is has all the features that we needed.

openrecord was originally written for node 0.10 and a lot has changed in the javascript world since then.

Things I like to change/add for version 2.0 (v2 branch):

  • Use ES6 import/export use babel...
  • async/await support
  • Add support for NoSQL stores (e.g. DynamoDB) => V2.1
  • Better support for transforming result data => V2.1
  • more declarative model definition syntax
  • Browser support #28. e.g. with a thin wrapper over rxdb and the rest-store, combined with cross store relations. #28 (comment)
  • Graphql support
  • Real docs!!
  • ESLint (instead of jshint)
  • remove async in favor of promises (#36 (comment))
  • Oracle support (#53)
  • Cordova SQLite native support (#28 (comment)) knex/knex#1845

deeply nested relations do not inherit context

functions from an inherited Model don't have context

return Model
.join({athlete: 'user'})
.get(invId)
.exec()
.then((result) => {
  account = result;
  console.log(account.context); //HAS CONTEXT
  console.log(account.athlete.context); //HAS CONTEXT
  console.log(account.athlete.user.context); //DOES NOT HAVE CONTEXT
  return user = account.athlete.user;
})

include() enhancements

Model.include() should support the following:

Model.include('$count').exec(function(records){
  console.log(records.$count);
});

or

Model.include('relation.$count').exec(function(records){
  console.log(records[0].relation.$count);
});

or just with a custom scope

Model.include('relation.my_scope').exec(function(records){

});

and with params

Model.include({'relation.$sum':'salary'}).exec(function(records){
  console.log(records[0].relation.$sum);
});

or with a single record

Model.find(1).include('$count').exec(function(record){
  console.log(record.$count);
});

.toSql() return query string with double quotes

Calling .toSql() method I'm getting the string with double quotes instead of backquotes, which cause a syntax error. In lib/stores/sql/exec.js in 42 line I found a function, replacing backquotes with double quotes. What's the reason of this replacement? Basically, It turns initially correct SQL string to an incorrect one.

Test Failures

Hi @PhilWaldmann

I am evaluating Node based ORM systems for use with a multi-database system that includes both traditional SQL (PG to be specific) and Redis (for caching) and OpenRecord looks great.

The only concern I have is the fact that your test suite is currently flagged as failing. A quick look at the Travis report shows test fails for assigning of primary_keys which is a bit of a concern.

  1. Do you expect these test failures to be resolved soon?
  2. Is there a stable version I ought to be looking at?
  3. Can you let me know of other users of OpenRecord I could speak to about their experiences?

Thanks

Dave

Can't find relation error

I have two tables - products and prices. Prices is belong to products via product_id column.

My code:

var config = require('./config.json'); var OpenRecord = require('openrecord');

var db = new OpenRecord({ type: 'mysql',
host: config.host, database: config.db,
user: config.user, password: config.password,
port: 3306});

db.Model('Products', function(){ this.hasMany('Prices');
});
db.Model('Prices', function(){ this.belongsTo('Products')
});
db.ready(function(){ var Prices = db.Model('Prices');
Prices.include('Products').exec(function(prices){ console.log(prices[0].products);
})});

After execute i got error:
RelationNotFoundError: Can't find relation "Products" for Prices

Why?

Connection Issues in Production

I have singled out the reason I was having connection issues in #43

node-pg and node-pg-native do not work with the semi-popular pgpool load balancer. there is something about the way it handles prepared statements that node-pg never becomes aware that an error has been returned

You should add a disclaimer that your library won't work when used with pgpool

Unable to install this very package

Hello.

I'm from South East Asia and I have tried installing this over

npm install --save openrecord pg

It hangs and npm won't continue

As a work around, I tried:

cd node_modules
git clone [email protected]:PhilWaldmann/openrecord.git
cd openrecord
npm install

I think one of the packages within your package.json is causing the install to hang. Can I get some help identifying which, and what to do? I'd also like if installing it in your region works, after you have cleaned your npm cache.

relations

There is no documentation on how to actually retrieve a relationship.

for instance:

module.exports = function (){
  this
  .validatesUniquenessOf('athlete_id')
  .validatesUniquenessOf('email')
  .validatesFormatOf('email', /^[^@\s\;]+@[^@\s\;]+\.[^@\s\;]+$/)
  .belongsTo('athlete')
  .hasMany('accountsUsers')
  .hasMany('users', {through: 'accountUsers'})
  .hasMany('infokits')
  .hasMany('account_audits')
}

how would I retrieve the 'users' for the above model?
how do I get the athlete?

Crash before successful uniqueness validation

affected file: validations.js

// ...
      self.model.count().where(condition).exec(function(result){
        if(result.count > 0){
          records.errors.add(field, 'not uniq');
          return next(false);
        }
        next(true);
      });
// ...

If no record is found, i.e. the new record is unique, the process crashes because result is null (null.count is not possible).

Model.create() should return the created instance

given the following code:

Account.create({email: '[email protected]', password: 'password'}))
.then(function(account){
  console.log(account) //true, should be {id: NEW_ID, email: ..., etc})
})

the returned account is true instead of the object that was created

this will create race conditions if I need that newly created record as relying on 'last insert' is not thread safe. postgres has the option RETURNING in Insert calls. that should be used to return the id of the object at least

Find query nested inside a beforeCreate hook: "Error: A transaction has already been set for the current query chain"

How to reproduce the error

Create two models:

models/domain.js

module.exports = function(){
  this.hasMany('mailboxes');
}

models/mailbox.js

module.exports = function(){
  this.belongsTo('domain');
  var _this = this;
  this.beforeCreate(function(transaction, done){
    var data = JSON.parse(this.context.params.data);
    _this.store.models.Domain.find(data.domain_id).exec(function(domain){      
      console.log('domain found');
      done(true);
    });
  });
}

actions/actions.js

var Actions = require(__dirname + '/../lib/actions.js');
module.exports = Actions.create({
  'Domain': {
    actions: ['create', 'get', 'list', 'update', 'destroy']
  },
  'Mailbox': {
    actions: ['create', 'get', 'list', 'update', 'destroy']
  }
});

The database must contain two tables:

  • domains with column id, must contain a record with id 1
  • mailboxes with columns id and domain_id
  1. Launch Actionhero with npm start.
  2. Request http://localhost:8080/api/mailboxes:create?data={%22domain_id%22:%221%22} through the browser.
  3. The Actionhero process crashes. Switch back to the console to see the error message and stacktrace.

how to use alias in requests

if i write myBase.Model('good').select("goods.id AS 'sku'").exec()
i receive result with out field 'sku', and field goods.id = null

Custom table name?

Thanks for a great library. Is there a way to specify the table name? From the relevant code it looks like the inflection can be overridden in the config - but not in the model definition?

How can I set primary key?

Some of my tables use 'bar_code' instead of 'id' for primary key name. and varchar type.

This case,

..
model.bar_code = req.body.bar_code; //--- user input value but "0"
..

model.save(function() {
model.bar_code === "0" //--- true!!!
}

How can I avoid this problem?

order with multiple columns causes `attribute.split` is not a function

If i try to order by multiple columns
WORKS

School
      .select('schools.id as id', 'name', 'address.city as city', 'address_state.abbr as state')
      .join({address: 'state'}, 'inner')
      .order('name')

ERROR

School
      .select('schools.id as id', 'name', 'address.city as city', 'address_state.abbr as state')
      .join({address: 'state'}, 'inner')
      .order(['name', 'city'])

I get the error:

TypeError: attribute.split is not a function
    at Array.<anonymous> (/home/samps/sites/personal/dus/office.downundersports.com/node/node_modules/openrecord/lib/stores/sql/order.js:68:31)

sql/order.js

...
...
order: function(columns, desc){
    var self = this.chain()

    if(columns){
      if(typeof desc === 'boolean'){
        if(!Array.isArray(columns)) columns = [columns]
      }else{
        columns = Utils.args(arguments)
        desc = false
      }

      for(var i in columns){ 
        //MOST LIKELY NOT PROPERLY ADDING TO INTERNAL HERE
        self.addInternal('order', {column: columns[i], order: desc ? 'DESC' : 'ASC'})
      }
    }else{
      self.clearInternal('order')
    }

    return self
  },
...
...
exports.definition = {
  mixinCallback: function(){
    this.beforeFind(function(query){
      var order = this.getInternal('order')
...
...
      for(i in order){
          var attribute = order[i].column
          var tmp = attribute.split('.') //ERROR IS HERE
...
...
}

Subquery

Hi again. how to do subquery like this
select from (select from....) left join (select * .....)

Error: Cannot find module "."

Hi, I'm getting this error when instantiating a new store with new OpenRecord(...)

/node_modules/openrecord/lib/utils.js:88
    var plugin = require(files[i])
^
Error: Cannot find module "."

This is my code:

const OpenRecord = require('openrecord')

module.exports = new OpenRecord({
    type: 'mysql',
    host: '127.0.0.1',
    database: 'database',
    username: 'user',
    password: 'secret'
})

Am I doing something wrong?

I'm using webpack.

Change validations/beforehook execution order

Server middleware may test if a user is currently logged-in.

But if an application allows different users to have different roles, a database model may want to decide whether the currently logged-in user is allowed to access or write something. Therefore, for instance a before create hook decides if the user may create a new record. This should be the the first thing the model does after the post request came in. But in fact the first thing that happens is the model going through its validation tests. If one of the validation tests fails, e.g. a uniqueness test, even though the user is not authorized to create a new record because of their role, the response to the client contains a uniqueness validation error ("not uniq") instead of an authorization error.

=> Please allow for hooks that execute before the first validation test is applied.

add autoJoin([limit])

to automatically join tables which are referenced in the where conditions.

User.where({posts:{message_like: 'Foo'}})

Can't get relations to work

Hi! I'm just starting to use this package, but I need some help since the docs are not complete as stated in other issues. I'm getting a "Can't find relation" error. Here is my setup:

// ClutchUsers.model.js
module.exports = function ClutchUsers() {
  this.hasMany('clutch_user_permission')
      .hasMany('clutch_module', {through: 'clutch_user_permissions', primary_key: 'id', foreign_key: 'user'})

      .scope('active', function () {
        this.where({status: 1})
      })
}

// ClutchUserPermissions.model.js
module.exports = function ClutchUserPermissions () {
  this.belongsToMany('clutch_user')
      .belongsToMany('clutch_module')
}

// ClutchModules.model.js
module.export = function ClutchModules () {
  this.hasMany('clutch_user_permission')
      .hasMany('clutch_user', {through: 'clutch_user_permissions', primary_key: 'id', foreign_key: 'module'})
}

I tried following the examples but it is not working when I run something like this:

store.ready(() => {
  const ClutchUsers = store.Model('ClutchUsers')
  ClutchUsers.active().include('clutch_modules').exec((records) => {
    console.log(records)
  })
})

For reference: table names are clutch_users, clutch_user_permissions, clutch_modules. Both users and modules have an id pk column, and the permissions table has user and module columns for each of them as fk.

Without include it works, but I also want the modules that each user has. What am I doing wrong?

Thank you and congratulations on this awesome package!

Oracle support

Would it be difficult to add/include Oracle's RDBMS support through node-oracledb?
Apparently, Oracle is already supported in Knex.
Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.