Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise support #807

Merged
merged 116 commits into from
Sep 19, 2017
Merged
Changes from 7 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
371ce94
add Promise support for connect, now connectAsync use promises
Aug 21, 2017
5d358a0
add dropAsync and syncPromise, add test coverage for this methods
Aug 22, 2017
7c01df4
fix code dublication error
Aug 22, 2017
29d7ff1
remove env var from pkg json
Aug 22, 2017
959faed
fix after review
Aug 22, 2017
9f2f298
restore example file, fix after review
Aug 22, 2017
59dc1af
LazyLoad should return Promise
anton-locomote Aug 22, 2017
5dddc62
addLazyLoadProperty function could add async methods to the Instance
anton-locomote Aug 23, 2017
ef15df3
integraion tests updated
anton-locomote Aug 23, 2017
62dcd08
add pingAsync and connectAsync methods, add test for it, update READM…
Aug 23, 2017
97f2281
Fixes for PR comments
anton-locomote Aug 23, 2017
6d95a05
Async methods will use promisify instead new Promise
anton-locomote Aug 29, 2017
5861ad7
Remove code duplicates in promisify methods
anton-locomote Aug 30, 2017
c05863d
Optimized functions names. Added Async prefix in Settings file
anton-locomote Aug 30, 2017
c146c45
Changed properties names in funcNamesObj and Settings.defaults
anton-locomote Aug 30, 2017
40b4315
Renamed funcNamesObj on functionNames
anton-locomote Aug 30, 2017
ae5519d
Changed promiseFunctionPostfix value. Also small fixes
anton-locomote Aug 30, 2017
5c4b67b
Add promise support to association extend
anton-locomote Aug 28, 2017
1eab7e0
Part of Async methods for Association many
anton-locomote Aug 29, 2017
dee4704
Added promisify instead new Promises for Extend Associations. Revert …
anton-locomote Aug 29, 2017
0a08c6f
Added promisify to Manu and One Associations
anton-locomote Aug 31, 2017
607675e
Added changes to Associations Many. Created tests for Associations Ma…
anton-locomote Aug 31, 2017
8d49582
Fixed indentation in Extend.js file
anton-locomote Sep 1, 2017
60ff735
apply Promise.promisify for callbacks transformation, replace tests f…
Sep 4, 2017
d03fe82
closeAsync and pingAsync generates directly from ORM.prototype
Sep 4, 2017
b8a7f9b
fix after review
Sep 4, 2017
9bfd7c8
create eagerQueryAsync, execQueryAsync -> return a Promise
Aug 22, 2017
9a9d771
remove code , change if statement in execQueryAsync
Aug 23, 2017
2547a14
remove Promise variable, align Promise declaration
Aug 23, 2017
6ced670
transform callbacks use promisify
Sep 4, 2017
ad485a2
remove unnecessary variables
Sep 4, 2017
377b1cf
Promisify support in save, validate, remove
anton-locomote Sep 4, 2017
f050b08
Add Promise support for get aggregation.
ramzamzam Sep 4, 2017
d1237fe
add tests
Sep 4, 2017
3511ad7
Optimized function names. Tests created
anton-locomote Sep 4, 2017
03c47ce
Resolved PR comments
anton-locomote Sep 4, 2017
33fd97c
redo getAsync function to resolve array of arguments
ramzamzam Sep 4, 2017
9e335a1
Resolve PR comments: added spaces after brackets
anton-locomote Sep 4, 2017
35895c0
revert unneeded changes
ramzamzam Sep 4, 2017
0c32586
fix getAsync function
ramzamzam Sep 5, 2017
c6aceb0
Add runAsync method for promise support. Create async tests
anton-locomote Sep 5, 2017
6f7d531
add clearAsync, createAsync, getAsync and test for it
Sep 5, 2017
172e2c6
add promise support to hooks
Sep 6, 2017
45553e8
add Promise checking via chack that "then" is a function
Sep 6, 2017
ecc74a4
adjust code style
Sep 8, 2017
4d09077
Fix broken tests
dxg Sep 11, 2017
c43910f
add useAsync and loadAsync
Sep 11, 2017
049d157
Merge pull request #12 from locomote/feature/LM-2668
tttmaximttt Sep 11, 2017
53db079
Promisified neccessary functions
anton-locomote Sep 12, 2017
41a2d6a
Remove success and fail tests
anton-locomote Sep 12, 2017
986606a
add existAsync, oneAsync, findAsync, countAsync methods
Sep 12, 2017
c06df3e
add existAsync, oneAsync, findAsync, countAsync methods
Sep 12, 2017
28ce120
add test for findAsync mapsto
Sep 12, 2017
5f120b6
Resolve PR comments: add postFix to async methods; rewrite tests
anton-locomote Sep 12, 2017
3b332f8
Merge pull request #15 from locomote/feature/lm-2679-promise-support-…
anton-locomote Sep 12, 2017
faf36f1
remove done from tests which use Promise
Sep 12, 2017
6ff98d2
fix test
Sep 12, 2017
7ed9f5f
Merge pull request #16 from locomote/feature/LM-2669
tttmaximttt Sep 12, 2017
69a950d
add Promise support for connect, now connectAsync use promises
Aug 21, 2017
2e93243
restore example file, fix after review
Aug 22, 2017
e04615b
Add Promise support for get aggregation.
ramzamzam Sep 4, 2017
af712b4
Update Async tests (except Hooks)
anton-locomote Sep 5, 2017
ad4eebe
Add changes to the part of tests
anton-locomote Sep 12, 2017
7ad36dc
Add changes to the part of tests
anton-locomote Sep 12, 2017
c0a00ce
Association hasmany async tests moved to separate
anton-locomote Sep 12, 2017
1e38407
update has meny tests
Sep 13, 2017
373398b
Update part of hasone async tests
anton-locomote Sep 13, 2017
175139e
Merge branch 'update/LM-2592-update-autotests-for-promises-support' o…
anton-locomote Sep 13, 2017
ad12886
update db and extend promise test
Sep 13, 2017
6d49ff0
Update part of hasone async tests
anton-locomote Sep 14, 2017
51de675
Merge branch 'update/LM-2592-update-autotests-for-promises-support' o…
anton-locomote Sep 14, 2017
3d352c3
adjust test code style
Sep 14, 2017
ff245cd
add model save async tests
Sep 14, 2017
c1204cc
Tests changes before branch pull
anton-locomote Sep 14, 2017
1baa067
Merge branch 'update/LM-2592-update-autotests-for-promises-support' o…
anton-locomote Sep 14, 2017
dadc444
Final commit for hasone association async tests
anton-locomote Sep 14, 2017
2900c3d
update instance tests
Sep 14, 2017
58404fe
Merge remote-tracking branch 'origin/update/LM-2592-update-autotests-…
Sep 14, 2017
bf6f37e
update ignore files
Sep 14, 2017
1275d84
Add and update lazyload async methods
anton-locomote Sep 14, 2017
f4fbc83
Merge branch 'update/LM-2592-update-autotests-for-promises-support' o…
anton-locomote Sep 14, 2017
bc2d54a
Add hasone-zeroid async tests; Removed test duplicates
anton-locomote Sep 14, 2017
4257227
Reset test config to default
anton-locomote Sep 14, 2017
ec4d526
Resolve PR comments: format some indents; removed done()
anton-locomote Sep 14, 2017
e9a8a1b
Lazyload global scope variable fix
anton-locomote Sep 15, 2017
f30e56a
fix unused vars
Sep 15, 2017
9074005
Merge pull request #10 from locomote/update/LM-2592-update-autotests-…
anton-locomote Sep 18, 2017
0588a99
fix unused vars
Sep 15, 2017
365d714
add promise documentation
Sep 18, 2017
4812448
4.0.0
Sep 18, 2017
4729f59
fix after review
Sep 18, 2017
fda2787
fix after review
Sep 18, 2017
eb49dc8
fix after review
Sep 18, 2017
ad4870a
Merge pull request #17 from locomote/feature/LM-2606
tttmaximttt Sep 18, 2017
ea8f31c
Merge branch 'master' of github.com:locomote/node-orm2
Sep 18, 2017
031075a
add deprecation message for fail and success
Sep 18, 2017
24d6102
add deprecation log message
Sep 18, 2017
7ec05d1
add deprecated promise backward capability
Sep 18, 2017
e41e1b1
Merge pull request #18 from locomote/feature/add-deprecation-message
tttmaximttt Sep 18, 2017
1934b15
Fixed failed mysql tests
anton-locomote Sep 18, 2017
c4e886d
Fix hasone-zeroid-async test according to old test logic
anton-locomote Sep 18, 2017
9e3ea62
Fixed tests according to sync tests logic
anton-locomote Sep 18, 2017
e2da459
Merge pull request #19 from locomote/fix/lm-2855-fix-tests-for-all-dr…
dxg Sep 19, 2017
ffdaba7
skip eagerQuery test for redshift
Sep 19, 2017
80e07d9
Merge pull request #20 from locomote/fix/lm-2855-fix-tests-for-all-dr…
tttmaximttt Sep 19, 2017
a6e7037
fix code duplication
Sep 19, 2017
ea923e3
fix code duplication
Sep 19, 2017
a3a4313
fix if statement
Sep 19, 2017
d14f41b
Merge pull request #21 from locomote/fix/lm-2855-fix-tests-for-all-dr…
tttmaximttt Sep 19, 2017
3fae37a
fix duplication
Sep 19, 2017
b03cea7
fix indentation
Sep 19, 2017
cf61ef0
Merge pull request #22 from locomote/fix/lm-2855-fix-tests-for-all-dr…
tttmaximttt Sep 19, 2017
dc13731
fix indentation
Sep 19, 2017
fdf6f68
Merge pull request #23 from locomote/fix/lm-2855-fix-tests-for-all-dr…
tttmaximttt Sep 19, 2017
b9809a3
fix duplication
Sep 19, 2017
180a389
Merge pull request #24 from locomote/fix/lm-2855-fix-tests-for-all-dr…
tttmaximttt Sep 19, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -7,4 +7,5 @@ test/config.js
test/coverage.html
lib-cov/
*~
npm-debug.log
.idea
276 changes: 270 additions & 6 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -95,16 +95,280 @@ orm.connect("mysql://username:password@host/database", function (err, db) {
});
});
```
------
## Promise

## Promises
- Read documentation about [bluebird](http://bluebirdjs.com/docs/api-reference.html) `Promise` for more advanced knowledge how to use `Promises`.

The methods what has Async like a postfix, like example `connectAsync`
can apply the same arguments as a original method but return a promise.
Exclusion method `sync` they called `syncPromise`.
More details [wiki](linkToWikiHere). // TODO add link to wiki where described async methods.
### Connect

You can use the [promise enabled wrapper library](https://github.com/rafaelkaufmann/q-orm).
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"));
}
return resolve();
});
}
}
});
```
-------
### 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) {
// ...
});
```

You can limit your results as well. This limits our results to 10
```javascript
Person.find({status:'active'}, 10)
.then(function(results) {
// ...
});
```

`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) {
// SQL: "SELECT * FROM person WHERE surname = 'Doe'"

console.log("People found: %d", people.length);
console.log("First person: %s, age %d", people[0].fullName(), people[0].age);

people[0].age = 16;
return people[0].saveAsync();
})
.then(function () {
// saved
});
```
-------
### 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).

-------

## Express

3 changes: 0 additions & 3 deletions lib/ChainFind.js
Original file line number Diff line number Diff line change
@@ -44,10 +44,8 @@ function ChainFind(Model, opts) {
if (dataItems.length === 0) {
return done(null, []);
}
var pending = dataItems.length;

var eagerLoad = function (err, items) {
var pending = opts.__eager.length;
var idMap = {};

var keys = _.map(items, function (item, index) {
@@ -91,7 +89,6 @@ function ChainFind(Model, opts) {
});
}

var promise = null;
var chain = {
find: function () {
var cb = null;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
"sqlite",
"mongodb"
],
"version": "3.2.4",
"version": "4.0.0",
"license": "MIT",
"homepage": "http://dresende.github.io/node-orm2",
"repository": "http://github.com/dresende/node-orm2.git",