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

chore(PO-5274): updated mongoose and mongodb #255

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Fortune.js [![Build Status](https://travis-ci.org/daliwali/fortune.png?branch=master)](https://travis-ci.org/daliwali/fortune)

Hello nerds. Fortune is a web framework for prototyping hypermedia APIs that implement the [JSON API](http://jsonapi.org/) specification. It comes with a modular persistence layer, with adapters for [NeDB](//github.com/louischatriot/nedb) (built-in), [MongoDB](//github.com/daliwali/fortune-mongodb), [MySQL](//github.com/daliwali/fortune-relational), [Postgres](//github.com/daliwali/fortune-relational), & [SQLite](//github.com/daliwali/fortune-relational).
Hello nerds. Fortune is a web framework for prototyping hypermedia APIs that implement the [JSON API](http://jsonapi.org/) specification. It comes with a modular persistence layer, with adapters for [NeDB](//github.com/louischatriot/nedb) (built-in), [MongoDB], [MySQL](//github.com/daliwali/fortune-relational), [Postgres](//github.com/daliwali/fortune-relational), & [SQLite](//github.com/daliwali/fortune-relational).

Get it by installing from npm:
```
Expand Down
2 changes: 1 addition & 1 deletion lib/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const RSVP = require('rsvp');

// Pre-defined adapters
const adapters = {
mongodb: './adapters/mongodb', //'fortune-mongodb',
mongodb: './adapters/mongodb',
mysql: 'fortune-relational',
psql: 'fortune-relational',
postgres: 'fortune-relational',
Expand Down
260 changes: 108 additions & 152 deletions lib/adapters/mongodb.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const adapter = {};
mongoose.Promise = Promise;

adapter._init = function (options) {
mongoose.set('useFindAndModify', false);
let connectionString = options.connectionString;

if (!connectionString || !connectionString.length) {
Expand Down Expand Up @@ -200,37 +199,20 @@ adapter.create = function (model, id, resource) {
if (upsert.status) {
const update = _this._serialize(model, resource);
async function tryUpsert(count) {
const matched = await new Promise((resolve, reject) => {
model.findOne(upsert.match, (err, matched) => {
if (err) return reject(err);
resolve(matched);
});
});
const matched = await model.findOne(upsert.match);

let created = null;
try {
if (matched) {
created = await new Promise((resolve, reject) => {
model.findOneAndUpdate(
{ _id: matched?._id },
{ $set: getFullKeys(update, matched && matched.toObject()) },
_.extend({}, upsert.opts, { new: true }),
function (error, r) {
if (error) return reject(error);
resolve(r);
},
);
});
created = await model.findOneAndUpdate(
{ _id: matched?._id },
{ $set: getFullKeys(update, matched && matched.toObject()) },
_.extend({}, upsert.opts, { new: true }),
);
} else {
created = await new Promise((resolve, reject) => {
model.create(
getFullKeys(update, matched && matched.toObject()),
(err, created) => {
if (err) return reject(err);
resolve(created);
},
);
});
created = await model.create(
getFullKeys(update, matched && matched.toObject()),
);
}
} catch (error) {
if (error.code === 16837 || error.code === 11000)
Expand All @@ -253,9 +235,14 @@ adapter.create = function (model, id, resource) {
},
);
} else {
model.create(resource, function (error, resource) {
_this._handleWrite(model, resource, error, resolve, reject);
});
model.create(resource).then(
function (r) {
_this._handleWrite(model, r, null, resolve, reject);
},
function (err) {
reject(err);
},
);
}
});
};
Expand Down Expand Up @@ -308,29 +295,27 @@ adapter.update = function (model, match, update) {
});

const modifiedRefs = _this._getModifiedRefs(update);
model.findOneAndUpdate(
match,
correctUpdate,
{ new: true },
function (error, resource) {
model
.findOneAndUpdate(match, correctUpdate, { new: true })
.then((resource) => {
if (_.isNull(resource)) return resolve();
if (error) {
console.log(
'error reading back updated resource ',
match,
correctUpdate,
);
}
_this._handleWrite(
model,
resource,
error,
null,
resolve,
reject,
modifiedRefs,
);
},
);
})
.catch((error) => {
console.log(
'error reading back updated resource ',
match,
correctUpdate,
);
reject(error);
});
});
};

Expand All @@ -345,68 +330,58 @@ adapter.markDeleted = function (model, id) {
const match = {};
if (id) match[pk] = id;

model.find(match).exec(function (error, resources) {
if (error) return reject(error);

RSVP.all(
_.map(resources, function (resource) {
return new Promise(function (resolve, reject) {
const references = adapter._getAllReferences(model);

const links = _.reduce(
references,
function (memo, ref) {
memo[ref.path] = resource[ref.path];
return memo;
},
{},
);

const unsetLinks = _.reduce(
references,
function (memo, ref) {
memo[ref.path] = 1;
return memo;
},
{},
);
model
.find(match)
.exec()
.then(function (resources) {
RSVP.all(
_.map(resources, function (resource) {
return new Promise(function (resolve, reject) {
const references = adapter._getAllReferences(model);

const links = _.reduce(
references,
function (memo, ref) {
memo[ref.path] = resource[ref.path];
return memo;
},
{},
);

const update = {
$set: { _links: links, deletedAt: new Date() },
};
if (!_.isEmpty(unsetLinks)) {
update.$unset = unsetLinks;
}
const unsetLinks = _.reduce(
references,
function (memo, ref) {
memo[ref.path] = 1;
return memo;
},
{},
);

model.update(
{ _id: resource._id },
update,
{ multi: true },
function (error) {
if (error) return reject(error);
model.findOne(
{ _id: resource._id },
function (error, updatedResource) {
if (error) {
reject(error);
} else {
resolve(updatedResource);
}
},
);
},
);
});
}),
).then(
function (resources) {
resolve(resources);
},
function (err) {
reject(err);
},
);
});
const update = {
$set: { _links: links, deletedAt: new Date() },
};
if (!_.isEmpty(unsetLinks)) {
update.$unset = unsetLinks;
}

model
.updateMany({ _id: resource._id }, update)
.then(function () {
return model.findOne({ _id: resource._id }).then(resolve);
})
.catch(reject);
});
}),
).then(
function (resources) {
resolve(resources);
},
function (err) {
reject(err);
},
);
})
.catch(reject);
}).then(function (resources) {
return RSVP.all(
_.map(resources, function (resource) {
Expand All @@ -433,19 +408,19 @@ adapter.delete = function (model, id) {
const match = {};
if (id) match[pk] = id;

model.find(match).exec(function (error, resources) {
const ids = resources.map(function (resource) {
return resource._id;
});
model
.find(match)
.exec()
.then(function (resources) {
const ids = resources.map(function (resource) {
return resource._id;
});

model.remove({ _id: { $in: ids } }, function (error) {
if (error) {
reject(error);
} else {
resolve(resources);
}
});
});
return model
.deleteMany({ _id: { $in: ids } })
.then(() => resolve(resources));
})
.catch(reject);
}).then(function () {
return returnValue;
});
Expand Down Expand Up @@ -669,10 +644,7 @@ adapter._findMany = function (model, query, projection, count) {
if (projection && !projection.includeDeleted) query.deletedAt = null;

if (count) {
model.count(query).exec(function (error, result) {
if (error) return reject(error);
resolve(result);
});
model.countDocuments(query).exec().then(resolve).catch(reject);
} else {
const q = model
.find(query)
Expand All @@ -683,11 +655,8 @@ adapter._findMany = function (model, query, projection, count) {
}
q.skip(projection.skip)
.lean(true)
.exec(function (error, resources) {
if (error) {
return reject(error);
}

.exec()
.then(function (resources) {
resources = resources.map(function (resource) {
const temp = _this._deserialize(model, resource);
if (pkNotRequested) {
Expand All @@ -697,7 +666,8 @@ adapter._findMany = function (model, query, projection, count) {
return temp;
});
resolve(resources);
});
})
.catch(reject);
}
});
};
Expand Down Expand Up @@ -736,7 +706,12 @@ adapter._serialize = function (model, resource) {
}

const correctedPkType =
pkType === mongoose.Schema.ObjectId ? mongoose.Types.ObjectId : pkType;
pkType === mongoose.Schema.ObjectId || pkType.toString() === 'ObjectId'
? function (...args) {
return new mongoose.Types.ObjectId(...args);
}
: pkType;

resource[pk] = correctedPkType.call(pkType, resource[pk] || resource.id);

if (!resource[pk]) {
Expand Down Expand Up @@ -892,7 +867,7 @@ adapter._getAllReferences = getAllReferences;
* @param {Array} modifiedRefs
* @return {Promise}
*/
adapter._updateRelationships = function (model, resource, modifiedRefs) {
adapter._updateRelationships = async function (model, resource, modifiedRefs) {
const _this = this;

/**
Expand Down Expand Up @@ -983,16 +958,8 @@ adapter._updateRelationships = function (model, resource, modifiedRefs) {
});
});

return new Promise(function (resolve, reject) {
RSVP.all(promises).then(
function () {
resolve(resource);
},
function (errors) {
reject(errors);
},
);
});
await Promise.all(promises);
return resource;
};

/**
Expand Down Expand Up @@ -1259,12 +1226,7 @@ adapter._shouldUpsert = function (model, resource, opts) {

adapter.aggregate = function (model, options) {
model = typeof model === 'string' ? this.model(model) : model;
return new Promise(function (resolve, reject) {
model.aggregate(options.config, function (err, result) {
if (err) return reject(err);
resolve(result);
});
});
return model.aggregate(options.config);
};

// expose mongoose
Expand All @@ -1276,13 +1238,7 @@ module.exports = adapter;
function wrapAsyncCall(context, fn) {
const args = Array.prototype.slice.call(arguments, 2);
return new Promise(function (resolve, reject) {
args.push(asyncCallback);
fn.apply(context, args);

function asyncCallback(err, result) {
if (err) return reject(err);
resolve(result);
}
fn.apply(context, args).then(resolve).catch(reject);
});
}

Expand Down
2 changes: 1 addition & 1 deletion lib/fortune.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function Fortune() {
* - `cors`: boolean value indicating whether or not to enable Cross Origin Resource Sharing (CORS), or an object that contains additional configuration keys: `headers` (Array), `methods` (Array), `origins` (Array), and `credentials` (Boolean). Default: true.
* - `environment`: if this is set to `"production"`, responses will have whitespace stripped. Default: `process.env.NODE_ENV`.
*
* *Note: in order to use database adapters, you must install `fortune-mongodb` for MongoDB, or `fortune-relational` for relational databases.*
* *Note: in order to use database adapters, you must install `./adapters/mongodb` for MongoDB, or `fortune-relational` for relational databases.*
*/
Fortune.prototype.options = {};

Expand Down
Loading