Comparing version 5.0.2 to 5.0.3
@@ -0,4 +1,7 @@ | ||
### v5.0.3 | ||
- Update dependencies to address security vulnerabilities | ||
### v5.0.2 | ||
- Fix rare crash when object slips into postgres `escapeValue` ([dresende/node-sql-query#54](dresende/node-sql-query#54)) ([#833](../../pull/833)) | ||
- Fix rare crash when object slips into postgres `escapeValue` ([dresende/node-sql-query#54](https://github.com/dresende/node-sql-query/pull/54)) ([#833](../../pull/833)) | ||
@@ -5,0 +8,0 @@ ### v5.0.1 |
@@ -15,3 +15,3 @@ { | ||
], | ||
"version": "5.0.2", | ||
"version": "5.0.3", | ||
"license": "MIT", | ||
@@ -69,3 +69,3 @@ "homepage": "http://dresende.github.io/node-orm2", | ||
"hat": "0.0.3", | ||
"lodash": "4.17.10", | ||
"lodash": "^4.17.11", | ||
"path-is-absolute": "1.0.1", | ||
@@ -84,3 +84,3 @@ "sql-ddl-sync": "0.3.14", | ||
"should": "13.2.1", | ||
"sinon": "6.0.0", | ||
"sinon": "7.2.3", | ||
"sqlite3": "4.0.1" | ||
@@ -87,0 +87,0 @@ }, |
449
Readme.md
@@ -61,269 +61,33 @@ ## Object Relational Mapping | ||
var Person = db.define("person", { | ||
name : String, | ||
surname : String, | ||
age : Number, // FLOAT | ||
male : Boolean, | ||
continent : [ "Europe", "America", "Asia", "Africa", "Australia", "Antarctica" ], // ENUM type | ||
photo : Buffer, // BLOB/BINARY | ||
data : Object // JSON encoded | ||
}, { | ||
methods: { | ||
fullName: function () { | ||
return this.name + ' ' + this.surname; | ||
} | ||
}, | ||
validations: { | ||
age: orm.enforce.ranges.number(18, undefined, "under-age") | ||
} | ||
}); | ||
// add the table to the database | ||
db.sync(function(err) { | ||
if (err) throw err; | ||
// add a row to the person table | ||
Person.create({ id: 1, name: "John", surname: "Doe", age: 27 }, function(err) { | ||
if (err) throw err; | ||
// query the person table by surname | ||
Person.find({ surname: "Doe" }, function (err, people) { | ||
// SQL: "SELECT * FROM person WHERE surname = 'Doe'" | ||
if (err) throw err; | ||
console.log("People found: %d", people.length); | ||
console.log("First person: %s, age %d", people[0].fullName(), people[0].age); | ||
people[0].age = 16; | ||
people[0].save(function (err) { | ||
// err.msg = "under-age"; | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` | ||
------ | ||
## Promise | ||
- Read documentation about [bluebird](http://bluebirdjs.com/docs/api-reference.html) `Promise` for more advanced knowledge how to use `Promises`. | ||
### Connect | ||
The connection URL has the following syntax: `driver://username:password@hostname/database?option1=value1&option2=value2..` | ||
```javascript | ||
var orm = require('orm'); | ||
orm.connectAsync('mysql://root:password@localhost/test') | ||
.then(function(db) { | ||
// connected | ||
// ... | ||
}) | ||
.catch(function() { | ||
console.error('Connection error: ' + err); | ||
}); | ||
``` | ||
Valid options are: | ||
- `debug` (default: **false**): prints queries to console; | ||
- `pool` (default: **false**): manages a connection pool (only for `mysql` and `postgres`) using built-in driver pool; | ||
- `strdates` (default: **false**): saves dates as strings (only for `sqlite`). | ||
- `timezone` (default: **'local'**): store dates in the database using this timezone (`mysql` and `postgres` only) | ||
```javascript | ||
var orm = require('orm'); | ||
var opts = { | ||
host: host, | ||
database: database, | ||
protocol: 'mysql', | ||
port: '3306', | ||
query: {pool: true} | ||
}; | ||
orm.connectAsync(opts) | ||
.then(function(db) { | ||
// connected | ||
// ... | ||
}) | ||
.catch(function() { | ||
console.error('Connection error: ' + err); | ||
}); | ||
``` | ||
------- | ||
### Model Hooks | ||
If you want to listen for a type of event than occurs in instances of a Model, you can attach a function that | ||
will be called when that event happens. For each hook above implemented Promise support, with backward capability via use next callback. | ||
For use promise you should return `Promise`, look at example. | ||
Currently the following events are supported: | ||
- `beforeValidation` : (no parameters) Before all validations and prior to `beforeCreate` and `beforeSave`; | ||
- `beforeCreate` : (no parameters) Right before trying to save a new instance (prior to `beforeSave`); | ||
- `beforeSave` : (no parameters) Right before trying to save; | ||
- `afterSave` : (bool success) Right after saving; | ||
- `afterCreate` : (bool success) Right after saving a new instance; | ||
- `afterLoad` : (no parameters) Right after loading and preparing an instance to be used; | ||
- `afterAutoFetch` : (no parameters) Right after auto-fetching associations (if any), it will trigger regardless of having associations or not; | ||
- `beforeRemove` : (no parameters) Right before trying to remove an instance; | ||
- `afterRemove` : (bool success) Right after removing an instance; | ||
All hook function are called with `this` as the instance so you can access anything you want related to it. | ||
Here's an example: | ||
```js | ||
var Person = db.define("person", { | ||
name : String, | ||
surname : String | ||
}, { | ||
hooks: { | ||
beforeCreate: function () { | ||
return new Promise(function(resolve, reject) { | ||
if (this.surname == "Doe") { | ||
return reject(new Error("No Does allowed")); | ||
var Person = db.define("person", { | ||
name : String, | ||
surname : String, | ||
age : Number, // FLOAT | ||
male : Boolean, | ||
continent : [ "Europe", "America", "Asia", "Africa", "Australia", "Antarctica" ], // ENUM type | ||
photo : Buffer, // BLOB/BINARY | ||
data : Object // JSON encoded | ||
}, { | ||
methods: { | ||
fullName: function () { | ||
return this.name + ' ' + this.surname; | ||
} | ||
return resolve(); | ||
}); | ||
}, | ||
validations: { | ||
age: orm.enforce.ranges.number(18, undefined, "under-age") | ||
} | ||
} | ||
}); | ||
``` | ||
------- | ||
### Editing Syncing and dropping models | ||
Syncing is an utility method that creates all the necessary tables in the database for your models and associations to work. Tables are not replaced, they are only created if they don't exist. | ||
There are 2 ways of syncing: | ||
1. Calling `Model.syncPromise()` will only synchronize the model | ||
2. Calling `db.syncPromise()` will synchronize all models | ||
Dropping is a similar method but instead it drops all tables involved in your models, even if they were not created by ORM. There also 2 ways of dropping. | ||
```js | ||
var orm = require("orm"); | ||
orm.connectAsync("....") | ||
.then(function (db) { | ||
var Person = db.define("person", { | ||
name : String | ||
}); | ||
return [Person, db.dropAsync()]; | ||
}) | ||
.spread(function(Person) { | ||
return Person.syncPromise(); | ||
}) | ||
.then(function () { | ||
// created tables for Person model | ||
}); | ||
``` | ||
------- | ||
### Finding items | ||
#### findAsync | ||
Find records with matching criteria, can be chained (see below): | ||
```javascript | ||
Person.find({status:'active'}) | ||
.then(function(results) { | ||
// ... | ||
}); | ||
``` | ||
// add the table to the database | ||
db.sync(function(err) { | ||
if (err) throw err; | ||
You can limit your results as well. This limits our results to 10 | ||
```javascript | ||
Person.find({status:'active'}, 10) | ||
.then(function(results) { | ||
// ... | ||
}); | ||
``` | ||
// add a row to the person table | ||
Person.create({ id: 1, name: "John", surname: "Doe", age: 27 }, function(err) { | ||
if (err) throw err; | ||
`Person.all` is an alias to `Person.find` | ||
#### getAsync | ||
Find record by primary key. | ||
```javascript | ||
Person.getAsync(1) | ||
.then(function(person) { | ||
// ... | ||
}); | ||
``` | ||
#### oneAsync | ||
Find one record with similar syntax to find. | ||
```javascript | ||
Person.oneAsync({status:'active'}) | ||
.then(function(person) { | ||
// ... | ||
}); | ||
``` | ||
#### countAsync | ||
Get the number of matching records. | ||
```javascript | ||
Person.countAsync({status:'active'}) | ||
.then(function(activePeopleCount) { | ||
// ... | ||
}); | ||
``` | ||
#### existsAsync | ||
Test a record matching your conditions exists. | ||
```javascript | ||
Person.exists({id:1, status:'active'}) | ||
.then(function(personIsActive) { | ||
// ... | ||
}); | ||
``` | ||
#### Filtering and sorting | ||
We accept 2 objects to perform filtering (first) and aggregate (second). The aggregate object accepts `limit`, `order`, and `groupBy`. | ||
```javascript | ||
Person.findAsync({status:'active'}, {limit:10}) | ||
.then(function(results) { | ||
// ... | ||
}); | ||
``` | ||
#### Conditions for find/count/one etc. | ||
All comma separated key/values are AND'd together in the query. You may prefix a set of conditions with logical operators. | ||
```javascript | ||
Person.findAsync({or:[{col1: 1}, {col2: 2}]}) | ||
.then(function(res) { | ||
// ... | ||
}); | ||
``` | ||
#### Finding with an `IN` | ||
`sql-query` (underlying SQL engine) will automatically coerce any array to an `IN` based query. | ||
```javascript | ||
Person.findAsync({id: [1, 2]}) | ||
.then(function(persons) { | ||
// Finds people with id's 1 and 2 (e.g. `WHERE id IN (1, 2)`) | ||
}); | ||
``` | ||
------- | ||
### Creating and Updating Items | ||
#### createAsync | ||
```javascript | ||
var newRecord = {}; | ||
newRecord.id = 1; | ||
newRecord.name = "John"; | ||
Person.createAsync(newRecord) | ||
.then(function(results) { | ||
// ... | ||
}); | ||
``` | ||
#### saveAsync | ||
```js | ||
Person.findAsync({ surname: "Doe" }) | ||
.then(function (people) { | ||
// query the person table by surname | ||
Person.find({ surname: "Doe" }, function (err, people) { | ||
// SQL: "SELECT * FROM person WHERE surname = 'Doe'" | ||
if (err) throw err; | ||
@@ -334,48 +98,11 @@ console.log("People found: %d", people.length); | ||
people[0].age = 16; | ||
return people[0].saveAsync(); | ||
}) | ||
.then(function () { | ||
// saved | ||
people[0].save(function (err) { | ||
// err.msg == "under-age"; | ||
}); | ||
}); | ||
}); | ||
``` | ||
------- | ||
### Aggregation | ||
If you need to get some aggregated values from a Model, you can use `Model.aggregate()`. Here's an example to better | ||
illustrate: | ||
```js | ||
Person.aggregate({ surname: "Doe" }).min("age").max("age").getAsync() | ||
.then(function(result) { | ||
var [min, max] = result; // you should use destructuring here | ||
console.log(min, max); | ||
}); | ||
}); | ||
``` | ||
An `Array` of properties can be passed to select only a few properties. An `Object` is also accepted to define conditions. | ||
Here's an example to illustrate how to use `.groupBy()`: | ||
```js | ||
//The same as "select avg(weight), age from person where country='someCountry' group by age;" | ||
Person.aggregate(["age"], { country: "someCountry" }).avg("weight").groupBy("age").getAsync() | ||
.then(function (stats) { | ||
// stats is an Array, each item should have 'age' and 'avg_weight' | ||
}); | ||
``` | ||
### Base `.aggregate()` methods | ||
- `.limit()`: you can pass a number as a limit, or two numbers as offset and limit respectively | ||
- `.order()`: same as `Model.find().order()` | ||
### Additional `.aggregate()` methods | ||
- `min` | ||
- `max` | ||
- `avg` | ||
- `sum` | ||
There are more aggregate functions depending on the driver (Math functions for example). | ||
------- | ||
@@ -487,5 +214,5 @@ | ||
db.load("./models", function (err) { | ||
// loaded! | ||
var Person = db.models.person; | ||
var Pet = db.models.pet; | ||
// loaded! | ||
var Person = db.models.person; | ||
var Pet = db.models.pet; | ||
}); | ||
@@ -495,13 +222,13 @@ | ||
module.exports = function (db, cb) { | ||
db.load("./models-extra", function (err) { | ||
if (err) { | ||
return cb(err); | ||
} | ||
db.load("./models-extra", function (err) { | ||
if (err) { | ||
return cb(err); | ||
} | ||
db.define('person', { | ||
name : String | ||
}); | ||
db.define('person', { | ||
name : String | ||
}); | ||
return cb(); | ||
}); | ||
return cb(); | ||
}); | ||
}; | ||
@@ -511,7 +238,7 @@ | ||
module.exports = function (db, cb) { | ||
db.define('pet', { | ||
name : String | ||
}); | ||
db.define('pet', { | ||
name : String | ||
}); | ||
return cb(); | ||
return cb(); | ||
}; | ||
@@ -656,3 +383,3 @@ ``` | ||
Person.aggregate(["age"], { country: "someCountry" }).avg("weight").groupBy("age").get(function (err, stats) { | ||
// stats is an Array, each item should have 'age' and 'avg_weight' | ||
// stats is an Array, each item should have 'age' and 'avg_weight' | ||
}); | ||
@@ -709,3 +436,3 @@ ``` | ||
Person.find({ surname: "Doe" }).count(function (err, people) { | ||
// people = number of people with surname="Doe" | ||
// people = number of people with surname="Doe" | ||
}); | ||
@@ -719,3 +446,3 @@ ``` | ||
Person.find({ surname: "Doe" }).remove(function (err) { | ||
// Does gone.. | ||
// Does gone.. | ||
}); | ||
@@ -1024,6 +751,6 @@ ``` | ||
var Person = db.define('person', { | ||
name : String | ||
name : String | ||
}); | ||
var Animal = db.define('animal', { | ||
name : String | ||
name : String | ||
}); | ||
@@ -1034,6 +761,6 @@ Animal.hasOne("owner", Person); // creates column 'owner_id' in 'animal' table | ||
Animal.get(123, function (err, animal) { | ||
// animal is the animal model instance, if found | ||
animal.getOwner(function (err, person) { | ||
// if animal has really an owner, person points to it | ||
}); | ||
// animal is the animal model instance, if found | ||
animal.getOwner(function (err, person) { | ||
// if animal has really an owner, person points to it | ||
}); | ||
}); | ||
@@ -1068,10 +795,10 @@ ``` | ||
Person.hasMany("friends", { | ||
rate : Number | ||
rate : Number | ||
}, {}, { key: true }); | ||
Person.get(123, function (err, John) { | ||
John.getFriends(function (err, friends) { | ||
// assumes rate is another column on table person_friends | ||
// you can access it by going to friends[N].extra.rate | ||
}); | ||
John.getFriends(function (err, friends) { | ||
// assumes rate is another column on table person_friends | ||
// you can access it by going to friends[N].extra.rate | ||
}); | ||
}); | ||
@@ -1088,6 +815,6 @@ ``` | ||
Person.hasMany("friends", { | ||
rate : Number | ||
rate : Number | ||
}, { | ||
key : true, // Turns the foreign keys in the join table into a composite key | ||
autoFetch : true | ||
key : true, // Turns the foreign keys in the join table into a composite key | ||
autoFetch : true | ||
}); | ||
@@ -1104,3 +831,3 @@ | ||
var Person = db.define('person', { | ||
name : String | ||
name : String | ||
}, { | ||
@@ -1110,3 +837,3 @@ autoFetch : true | ||
Person.hasMany("friends", { | ||
rate : Number | ||
rate : Number | ||
}, { | ||
@@ -1123,17 +850,17 @@ key: true | ||
var Pet = db.define('pet', { | ||
name : String | ||
name : String | ||
}); | ||
var Person = db.define('person', { | ||
name : String | ||
name : String | ||
}); | ||
Pet.hasOne("owner", Person, { | ||
reverse : "pets" | ||
reverse : "pets" | ||
}); | ||
Person(4).getPets(function (err, pets) { | ||
// although the association was made on Pet, | ||
// Person will have an accessor (getPets) | ||
// | ||
// In this example, ORM will fetch all pets | ||
// whose owner_id = 4 | ||
// although the association was made on Pet, | ||
// Person will have an accessor (getPets) | ||
// | ||
// In this example, ORM will fetch all pets | ||
// whose owner_id = 4 | ||
}); | ||
@@ -1147,12 +874,12 @@ ``` | ||
var Pet = db.define('pet', { | ||
name : String | ||
name : String | ||
}); | ||
var Person = db.define('person', { | ||
name : String | ||
name : String | ||
}); | ||
Person.hasMany("pets", Pet, { | ||
bought : Date | ||
bought : Date | ||
}, { | ||
key : true, | ||
reverse : "owners" | ||
key : true, | ||
reverse : "owners" | ||
}); | ||
@@ -1164,2 +891,24 @@ | ||
------ | ||
## Promise support | ||
ORM supports Promises via [bluebird](http://bluebirdjs.com/docs/api-reference.html). | ||
Most methods which accept a callback have a Promise version whith a `Async` postfix. | ||
Eg: | ||
```js | ||
orm.connectAsync().then().catch(); | ||
Person.getAsync(1).then(); | ||
Person.find({ age: 18 }).where("LOWER(surname) LIKE ?", ['dea%']).allAsync( ... ); | ||
Person.aggregate({ surname: "Doe" }).min("age").max("age").getAsync(); | ||
``` | ||
The exception here are hooks, which should return a Promise if they perform asynchronous operations: | ||
```js | ||
beforeCreate: function () { | ||
return new Promise(function(resolve, reject) { | ||
doSomeStuff().then(resolve); | ||
} | ||
``` | ||
## Adding external database adapters | ||
@@ -1166,0 +915,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
264272
911
+ Addedlodash@4.17.21(transitive)
Updatedlodash@^4.17.11