Socket
Socket
Sign inDemoInstall

cormo

Package Overview
Dependencies
0
Maintainers
1
Versions
169
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.6.3 to 0.6.4

crojsdoc.yaml

8

GLOSSARY.md
The list of terms used in this project.
Table
-----
Other candidates:
* collection
Record

@@ -11,2 +18,3 @@ ------

* tuple
* document

@@ -13,0 +21,0 @@ Column

4

lib/model/query.js

@@ -29,2 +29,6 @@ // Generated by CoffeeScript 1.6.2

ModelQuery.query = function() {
return new Query(this);
};
ModelQuery.find = function(id, callback) {

@@ -31,0 +35,0 @@ return this._createQueryAndRun('find', id, 'exec', callback);

3

package.json
{
"name": "cormo",
"description": "ORM framework for Node.js",
"version": "0.6.3",
"version": "0.6.4",
"keywords": [

@@ -17,2 +17,3 @@ "orm",

"author": "Sangmin Yoon <sangmin.yoon@croquis.com>",
"license": "MIT",
"bin": {

@@ -19,0 +20,0 @@ "cormo": "./bin/cormo"

@@ -7,3 +7,3 @@ # About

* multi-DB: MySQL, MongoDB, SQLite3, PostgreSQL, Redis
* multi-DB: MySQL, MongoDB, SQLite3, PostgreSQL
* constraints

@@ -13,272 +13,117 @@ * validations

* geospatial query
* callbacks
* aggregation
* nested column
Will support:
See https://github.com/croquiscom/cormo/wiki/Future-Plans for future plans.
* auto table migration
* more DB, validations, associations, ...
# Overview
This project is not yet stabilized.
API can be changed.
You can see detail guides on http://croquiscom.github.io/cormo/.
# Usage
## Connect to DB
## Define models
```coffeescript
Connection = require('cormo').Connection
cormo = require 'cormo'
connection = new cormo.Connection 'mysql', database: 'test'
connection = new Connection 'mysql', database: 'test'
# this will create two tables - users, posts - in the database.
another = new Connection 'mongodb', database: 'test'
```
class User extends cormo.Model
@column 'name', type: String
@column 'age', type: cormo.types.Integer
See documents for each adapter([[#AdapterBase]]) for detail options.
## Define models
```coffeescript
# this will create two tables - users, posts.
# using model method
User = connection.model 'User',
name: { type: String }
age: { type: Number }
# using CoffeeScript extends keyword
class Post extends cormo.Model
@connection connection # if omitted, Connection.defaultConnection will be used instead
@column 'title', String # 'String' is the same as '{ type: String }'
@column 'body', 'string' # you can also use 'string' to specify a string type
# apply defined models to Database. This can be omitted
connection.applySchemas (error) ->
console.log error
@column 'title', String # `String` is the same as `type: String`
@column 'body', 'string' # you can also use `string` to specify a string type
@column 'date', Date
```
You can use any of cormo.types.String, 'string', or String
(native JavaScript Function, if exists) to specify a type.
## Create records
Currently supported types:
* String
* Number
* Integer
* Date
* GeoPoint (MySQL, MonogoDB only)
See [[#Connection::model]], [[#Connection::applySchemas]] for more details.
## Create a record
```coffeescript
# new with no data
user1 = new User()
user1.name = 'John Doe'
user1.age = 27
user1 = new User name: 'John Doe', age: 27
user1.save (error) ->
console.log error
# new with data
user2 = new User name: 'John Doe', age: 27
user2.save (error) ->
User.create name: 'John Doe', age: 27, (error, user2) ->
console.log error
# build is the same as new
user3 = User.build name: 'John Doe', age: 27
user3.save (error) ->
console.log error
# create is the same as build and save
User.create { name: 'John Doe', age: 27 }, (error, user) ->
console.log error
```
See [[#Model::constructor]], [[#ModelPersistence::save]], [[#Model.build]], [[#ModelPersistence.create]] for more details.
## Retreive records
## Query
```coffeescript
# simple query
# the same as "SELECT * FROM users WHERE age=27"
User.where age: 27, (error, users) ->
console.log users
User.find 1, (error, user) ->
# else you can use query chain
User.where(age: 27).exec (error, users) ->
console.log users
User.where name: 'John Doe', (error, users) ->
# select partial columns
# the same as "SELECT name,age FROM users"
User.select 'name age', (error, users) ->
console.log users
User.where(age: 27)
.select('name')
.order('name')
.limit(5)
.skip(100)
.exec (error, users) ->
# sort result
# the same as "SELECT * FROM users ORDER BY age ASC, name DESC"
User.order 'age -name', (error, users) ->
console.log users
User.where($or: [ { age: { $lt: 20 } }, { age: { $gt: 60 } } ])
.where(name: { $contains: 'smi' })
.exec (error, users) ->
```
# two condition
# the same as "SELECT * FROM users WHERE name='John Doe' AND age=27"
User.where name: 'John Doe', age: 27, (error, users) ->
console.log users
## Count records
# using query chain
User.where(name: 'John Doe').where(age: 27).exec (error, users) ->
console.log users
# find by id, return a single record
User.find 1, (error, user) ->
console.log user
# find multiple ids
# will return error unless records are found for all ids
User.find [1,2,3], (error, users) ->
console.log users
# find multiple ids with same order
User.findPreserve [2,1,2,3], (error, users) ->
# users[0].id is 2 and users[1].id is 1 and users[2].id is 2 and users[3].id is 3
console.log users
# get count of all records
# the same as "SELECT COUNT(*) FROM users"
```coffeescript
User.count (error, count) ->
console.log count
# get count of matched records
# the same as "SELECT COUNT(*) FROM users WHERE age=27"
User.count age: 27, (error, count) ->
console.log count
```
# update records that match conditions
# the same as "UPDATE users SET age=10 WHERE age=27"
User.update { age: 10 }, age: 27, (error, count) ->
console.log count
## Update records
# using query chain
User.where(age: 27).update age:10, (error, count) ->
console.log count
```coffeescript
User.find 1, (error, user) ->
user.age = 30
user.save (error) ->
# delete records that match conditions
# the same as "DELETE FROM users WHERE age=27"
User.delete age: 27, (error, count) ->
console.log count
User.find(1).update age: 10, (error, count) ->
# or condition, similar syntax with MongoDB
# the same as "SELECT * FROM users WHERE name='John Doe' OR age=27"
User.where $or: [ { name: 'John Doe' }, { age: 27 } ], (error, users) ->
console.log users
User.where(age: 27).update age:10, (error, count) ->
```
# comparison
# the same as "SELECT * FROM users WHERE age > 30 AND age <= 45"
User.where [ { age: { $gt: 30 } }, { age: { $lte: 45 } } ], (error, users) ->
console.log users
## Delete records
# containing some text in case insensitive
# the same as "SELECT * FROM users WHERE name LIKE '%smi%'"
User.where { name: { $contains: 'smi' } }, (error, users) ->
console.log users
# subset
# the same as "SELECT * FROM users WHERE age IN (10,20,30)"
User.where { age: { $in: [ 10, 20, 30 ] } }, (error, users) ->
console.log users
# you can omit the $in keyword (implicit $in)
User.where { age: [ 10, 20, 30 ] }, (error, users) ->
console.log users
# limit records
# the same as "SELECT * FROM users WHERE age<40 LIMIT 3"
User.where(age: { $lt: 40 }).limit(3).exec (error, users) ->
console.log users
```coffeescript
User.delete age: 27, (error, count) ->
```
See [[#ModelQuery]], [[#Query]] for more details.
## Constraint
## Constraints
Currently supports 'unique' and 'required'(not null).
'unique' is supported on the database layer.
'required' is supported on the CORMO layer(while validating).
The column unique but not required can have multiple null values.
```coffeescript
User = connection.model 'User',
name: { type: String, required: true }
age: { type: Number, required: true }
email: { type: String, unique: true, required: true }
User.create { name: 'Bill Smith', age: 45, email: 'bill@foo.org' }, (error, user1) ->
User.create { name: 'Bill Simpson', age: 38, email: 'bill@foo.org' }, (error, user2) ->
# error.message will be 'duplicated email' or 'duplicated'
class User extends cormo.Model
@column 'name', type: String, required: true
@column 'age', type: Number, required: true
@column 'email', type: String, unique: true, required: true
```
See [[#Connection::model]] for more details.
## Validation
## Validations
If you want validations, adds a validator using [[#ModelValidate.addValidator]].
If a record is invalid, throws an error, or returns false or an error string in the validator.
```coffeescript
User = models.User = connection.model 'User',
name: String
age: Number
email: String
class User extends cormo.Model
@column 'name', String
@column 'age', Number
@column 'email', String
# checkes age validity
User.addValidator (record) ->
if record.age < 18
return 'too young'
# checkes email validity
User.addValidator (record) ->
if record.email and not /^\w+@.+$/.test record.email
throw new Error 'invalid email'
return true
User.create { name: 'John Doe', age: 10, email: 'invalid' }, (error, user) ->
# error.message will be 'invalid email,too young' or 'too young,invalid email'
@addValidator (record) ->
if record.age < 18
return 'too young'
```
See [[#ModelValidate.addValidator]] for more details.
## Callbacks
CORMO supports following callbacks:
* afterInitialize
* afterFind
* beforeValidate
* afterValidate
* beforeSave
* afterSave
* beforeCreate
* afterCreate
* beforeUpdate
* afterUpdate
* beforeDestroy
* afterDestroy
```coffeescript
# using method name
User.afterInitialize 'onAfterInitialie'
User::onAfterInitialie = ->
console.log 'initialized'
class User extends cormo.Model
@column 'name', String
@column 'age', Number
# using anonymous function
User.afterCreate ->
console.log 'created'
# while defining a model
class Post extends cormo.Model
@column 'title', String # 'String' is the same as '{ type: String }'
@column 'body', 'string' # you can also use 'string' to specify a string type
@afterSave 'onAfterSave'
onAfterSave: ->
console.log 'saved'
@beforeSave ->
@name = @name.trim()
```

@@ -289,75 +134,19 @@

```coffeescript
User = connection.model 'User',
name: String
age: Number
class User extends cormo.Model
@column 'name', String
@column 'age', Number
@hasMany 'posts'
Post = connection.model 'Post',
title: String
body: String
# one-to-many association
# this will add 'user_id' to the Post model
User.hasMany Post
Post.belongsTo User
# one-to-many association with 'as'
# this will add 'parent_post_id' to the Post model
Post.hasMany Post, as: 'comments', foreign_key: 'parent_post_id'
Post.belongsTo Post, as: 'parent_post'
# get associated objects
user.posts (error, records) ->
console.log records
post.user (error, record) ->
console.log record
post.comments (error, records) ->
console.log records
post.parent_post (error, record) ->
console.log record
# returned objects are cached, give true to reload
user.posts true, (error, records) ->
console.log records
# two ways to create an associated object
Post.create { title: 'first post', body: 'This is the 1st post.', user_id: user.id }, (error, post) ->
console.log post
post = user.posts.build title: 'first post', body: 'This is the 1st post.'
post.save (error) ->
console.log error
class Post extends cormo.Model
@column 'title', String
@column 'body', String
@belongsTo 'user'
```
See [[#Model.hasMany]], [[#Model.belongsTo]] for more details.
### keep data consistent
CORMO supports foreign key constraints by DBMS for SQL-based DBMS or by framework for MongoDB.
(CORMO does not guarantee integrity for MongoDB even if using this feature)
To use constraints, give an integrity options on [[#Model.hasMany]].
```coffeescript
# the same as "CREATE TABLE posts ( user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL"
User.hasMany Post, integrity: 'nullify'
# the same as "CREATE TABLE posts ( user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT"
User.hasMany Post, integrity: 'restrict'
# the same as "CREATE TABLE posts ( user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE"
User.hasMany Post, integrity: 'delete'
# no option means no foreign key constraint
# so there may be a post with invalid user_id
User.hasMany Post
```
## Geospatial query
Currently, we supports only near query of 2D location in MongoDB and MySQL.
```coffeescript
Place = connection.model 'Place',
name: String
location: cormo.types.GeoPoint
class Place extends cormo.Model
@column 'name', String
@column 'location', cormo.types.GeoPoint

@@ -368,31 +157,28 @@ # create

# query
Place.where().near(location: [-5, 45]).limit(4).exec (error, places) ->
Place.query().near(location: [-5, 45]).limit(4).exec (error, places) ->
console.log places
```
See [[#Query::near]] for more details.
# License
## Other features
The MIT License (MIT)
Use [[#ModelTimestamp.timestamps]] to add created_at and updated_at to the table.
Copyright (c) 2012-2013 Sangmin Yoon &lt;sangmin.yoon@croquis.com&gt;
```coffeescript
User.timestamps()
```
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Use [[#ModelPersistence.createBulk]] to create many records at once.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
```coffeescript
User.createBulk [ { name: 'John Doe', age: 27 }, { name: 'Bill Smith', age: 45 } ], (error, users) ->
console.log users
```
If [[#Model.archive]] is true, deleted records are archived in the _Archive table.
```coffeescript
User.archive = true
User.delete age: 27, (error, count) ->
# _Archive will have delete records as
# { model: 'User', data: <deleted user 1> },
# { model: 'User', data: <deleted user 2> }, ...
```
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc