diff --git a/README.md b/README.md index ae38024059..622832bb29 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -# Strapi [![Build Status](https://travis-ci.org/wistityhq/strapi.svg?branch=master)](https://travis-ci.org/wistityhq/strapi) [![Slack Status](http://strapi-slack.herokuapp.com/badge.svg)](http://slack.strapi.io) +# Strapi + +[![npm version](https://img.shields.io/npm/v/strapi.svg)](https://www.npmjs.org/package/strapi) +[![npm downloads](https://img.shields.io/npm/dm/strapi.svg)](https://www.npmjs.org/package/strapi) +[![npm dependencies](https://david-dm.org/wistityhq/strapi.svg)](https://david-dm.org/wistityhq/strapi) +[![Build status](https://travis-ci.org/wistityhq/strapi.svg?branch=master)](https://travis-ci.org/wistityhq/strapi) +[![Slack status](http://strapi-slack.herokuapp.com/badge.svg)](http://slack.strapi.io) [Website](http://strapi.io/) - [Getting Started](#user-content-getting-started-in-a-minute) - [Documentation](http://strapi.io/documentation/introduction) - [Support](http://strapi.io/support) @@ -55,7 +61,6 @@ This will generate a Strapi application without: - the built-in `user`, `email` and `upload` APIs, - the `grant` hook, - the open-source admin panel, -- the Waterline ORM (`waterline` and `blueprints` hooks disabled), - the Strapi Studio connection (`studio` hook disabled). This feature allows you to only use Strapi for your HTTP server structure if you want to. diff --git a/bin/strapi.js b/bin/strapi.js index e07bddfdf1..fcf1db1390 100755 --- a/bin/strapi.js +++ b/bin/strapi.js @@ -39,6 +39,10 @@ cmd = program.command('version'); cmd.description('output your version of Strapi'); cmd.action(program.versionInformation); +/** + * Basic commands + */ + // `$ strapi new ` cmd = program.command('new'); cmd.unknownOption = NOOP; @@ -64,24 +68,16 @@ cmd.unknownOption = NOOP; cmd.description('open the Strapi framework console'); cmd.action(require('./strapi-console')); +/** + * Commands for the Strapi Studio + */ + // `$ strapi link` cmd = program.command('link'); cmd.unknownOption = NOOP; cmd.description('link an existing application to the Strapi Studio'); cmd.action(require('./strapi-link')); -// `$ strapi config` -cmd = program.command('config'); -cmd.unknownOption = NOOP; -cmd.description('extend the Strapi framework with custom generators'); -cmd.action(require('./strapi-config')); - -// `$ strapi update` -cmd = program.command('update'); -cmd.unknownOption = NOOP; -cmd.description('pull the latest updates of your custom generators'); -cmd.action(require('./strapi-update')); - // `$ strapi login` cmd = program.command('login'); cmd.unknownOption = NOOP; @@ -94,6 +90,22 @@ cmd.unknownOption = NOOP; cmd.description('logout your account from the Strapi Studio'); cmd.action(require('./strapi-logout')); +/** + * Customization commands + */ + +// `$ strapi config` +cmd = program.command('config'); +cmd.unknownOption = NOOP; +cmd.description('extend the Strapi framework with custom generators'); +cmd.action(require('./strapi-config')); + +// `$ strapi update` +cmd = program.command('update'); +cmd.unknownOption = NOOP; +cmd.description('pull the latest updates of your custom generators'); +cmd.action(require('./strapi-update')); + /** * Normalize help argument */ diff --git a/lib/configuration/hooks/blueprints/actionUtil.js b/lib/configuration/hooks/blueprints/actionUtil.js deleted file mode 100644 index 1fbf8cee95..0000000000 --- a/lib/configuration/hooks/blueprints/actionUtil.js +++ /dev/null @@ -1,240 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -module.exports = { - - /** - * Populate the query according to the specified or default - * association attributes. - * - * @param {Object} query - * @param {Object} _ctx - * @param {Object} model - * - * @return {Object} populated query - */ - - populateEach: function (query, _ctx, model) { - let shouldPopulate = strapi.config.blueprints.populate; - let aliasFilter = (_ctx.request.query && _ctx.request.query.populate) || (_ctx.request.body && _ctx.request.body.populate); - - // Convert the string representation of the filter list to an array. We - // need this to provide flexibility in the request param. This way both - // list string representations are supported: - // /model?populate=alias1,alias2,alias3 - // /model?populate=[alias1,alias2,alias3] - if (typeof aliasFilter === 'string') { - aliasFilter = aliasFilter.replace(/\[|\]/g, ''); - aliasFilter = (aliasFilter) ? aliasFilter.split(',') : []; - } - - return _(model.associations).reduce(function populateEachAssociation(query, association) { - - // If an alias filter was provided, override the blueprint config. - if (aliasFilter) { - shouldPopulate = _.contains(aliasFilter, association.alias); - } - - // Populate associations and set the according limit. - if (shouldPopulate) { - return query.populate(association.alias, { - limit: strapi.config.blueprints.defaultLimit || 30 - }); - } else { - return query; - } - }, query); - }, - - /** - * Parse the model to use - * - * @param {_ctx} _ctx - * - * @return {WLCollection} - */ - - parseModel: function (_ctx) { - - // Determine the model according to the context. - const model = _ctx.model || _ctx.params.model; - - if (!model) { - throw new Error({ - message: 'Please provide a valid model.' - }); - } - - // Select the Waterline model. - const Model = strapi.orm.collections[model]; - if (!Model) { - throw new Error({ - message: 'Invalid Model.' - }); - } - - Model.name = model; - - return Model; - }, - - /** - * Parse `values` for a Waterline `create` or `update` from all - * request parameters. - * - * @param {Request} _ctx - * - * @return {Object} - */ - - parseValues: function (_ctx) { - const values = _ctx.request.body || _ctx.request.query; - - return values; - }, - - /** - * Parse `criteria` for a Waterline `find` or `update` from all - * request parameters. - * - * @param {Request} _ctx - * - * @return {Object} the where criteria object - */ - - parseCriteria: function (_ctx) { - - // List of properties to remove. - const blacklist = ['limit', 'skip', 'sort', 'populate']; - - // Validate blacklist to provide a more helpful error msg. - if (blacklist && !_.isArray(blacklist)) { - throw new Error('Invalid `_ctx.options.criteria.blacklist`. Should be an array of strings (parameter names.)'); - } - - // Look for explicitly specified `where` parameter. - let where = _ctx.request.query.where; - - // If `where` parameter is a string, try to interpret it as JSON. - if (_.isString(where)) { - try { - where = JSON.parse(where); - } catch (err) { - - } - } - - // If `where` has not been specified, but other unbound parameter variables - // are specified, build the `where` option using them. - if (!where) { - - // Prune params which aren't fit to be used as `where` criteria - // to build a proper where query. - where = _ctx.request.body; - - // Omit built-in runtime config (like query modifiers). - where = _.omit(where, blacklist || ['limit', 'skip', 'sort']); - - // Omit any params with undefined values. - where = _.omit(where, function (p) { - if (_.isUndefined(p)) { - return true; - } - }); - } - - // Merge with `_ctx.options.where` and return. - where = _.merge({}, where) || undefined; - - return where; - }, - - /** - * Parse primary key value - * - * @param {Object} _ctx - * - * @return {Integer|String} pk - */ - - parsePk: function (_ctx) { - let pk = (_ctx.request.body && _ctx.request.body.where && _ctx.request.body.where.id) || _ctx.params.id; - - // Exclude criteria on id field. - pk = _.isPlainObject(pk) ? undefined : pk; - return pk; - }, - - requirePk: function (_ctx) { - const pk = module.exports.parsePk(_ctx); - - // Validate the required `id` parameter. - if (!pk) { - const err = new Error({ - message: 'No `id` provided' - }); - _ctx.status = 400; - throw err; - } - - return pk; - }, - - /** - * Parse sort params. - * - * @param {Object} _ctx - */ - - parseSort: function (_ctx) { - _ctx.options = _ctx.options || {}; - let sort = _ctx.request.query.sort || _ctx.options.sort; - if (typeof sort === 'undefined') { - return undefined; - } - if (typeof sort === 'string') { - try { - sort = JSON.parse(sort); - } catch (err) { - } - } - - return sort; - }, - - /** - * Parse limit params. - * - * @param {Object} _ctx - */ - - parseLimit: function (_ctx) { - _ctx.options = _ctx.options || {}; - let limit = Number(_ctx.request.query.limit) || strapi.config.blueprints.defaultLimit || 30; - if (limit) { - limit = +limit; - } - return limit; - }, - - /** - * Parse skip params. - * - * @param {Object} _ctx - */ - - parseSkip: function (_ctx) { - _ctx.options = _ctx.options || {}; - let skip = _ctx.request.query.skip || 0; - if (skip) { - skip = +skip; - } - return skip; - } -}; diff --git a/lib/configuration/hooks/blueprints/actions/add.js b/lib/configuration/hooks/blueprints/actions/add.js deleted file mode 100644 index 82d5339da9..0000000000 --- a/lib/configuration/hooks/blueprints/actions/add.js +++ /dev/null @@ -1,184 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); -const async = require('async'); - -// Local utils. -const actionUtil = require('../actionUtil'); - -/** - * Add an entry to a specific parent entry - */ - -module.exports = function destroy(_ctx) { - const deferred = Promise.defer(); - - // Ensure a model and alias can be deduced from the request. - const Model = actionUtil.parseModel(_ctx); - const relation = _ctx.params.relation; - if (!relation) { - _ctx.status = 500; - return deferred.reject({ - message: 'Missing required route option, `_ctx.params.relation`.' - }); - } - - // The primary key of the parent record. - const parentPk = _ctx.params.parentId; - - // Find the alias key. - const associationAttr = _.findWhere(strapi.orm.collections[_ctx.model].associations, {alias: relation}); - - // Init the child model. - const ChildModel = strapi.orm.collections[associationAttr.collection]; - const childPkAttr = ChildModel.primaryKey; - - _ctx.options = _ctx.options || {}; - - // The child record to associate is defined by either... - // a primary key or an object of values. - let child; - const supposedChildPk = actionUtil.parsePk(_ctx); - if (supposedChildPk) { - child = {}; - child[childPkAttr] = supposedChildPk; - } else { - _ctx.options.values = _ctx.options.values || {}; - _ctx.options.values.blacklist = _ctx.options.values.blacklist || ['limit', 'skip', 'sort', 'id', 'parentId']; - child = actionUtil.parseValues(_ctx); - } - - if (!child) { - _ctx.status = 400; - deferred.reject({ - message: 'You must specify the record to add (either the primary key of an existing record to link, or a new object without a primary key which will be used to create a record then link it.)' - }); - } - - async.auto({ - - // Look up the parent record. - parent: function (cb) { - Model.findOne(parentPk).exec(function foundParent(err, parentRecord) { - if (err) { - return cb(err); - } - if (!parentRecord) { - return cb({status: 404}); - } - if (!parentRecord[relation]) { - return cb({status: 404}); - } - cb(null, parentRecord); - }); - }, - - // If a primary key was specified in the `child` object we parsed - // from the request, look it up to make sure it exists. Send back its primary key value. - // This is here because, although you can do this with `.save()`, you can't actually - // get ahold of the created child record data, unless you create it first. - actualChildPkValue: ['parent', function (cb) { - - // Below, we use the primary key attribute to pull out the primary key value - // (which might not have existed until now, if the .add() resulted in a `create()`). - // If the primary key was specified for the child record, we should try to find - // it before we create it. - // Otherwise, it must be referring to a new thing, so create it. - if (child[childPkAttr]) { - ChildModel.findOne(child[childPkAttr]).exec(function foundChild(err, childRecord) { - if (err) { - return cb(err); - } - - // Didn't find it? Then try creating it. - if (!childRecord) { - return createChild(); - } - - // Otherwise use the one we found. - return cb(null, childRecord[childPkAttr]); - }); - } else { - return createChild(); - } - - // Create a new instance and send out any required pub/sub messages. - function createChild() { - ChildModel.create(child).exec(function createdNewChild(err, newChildRecord) { - if (err) { - return cb(err); - } - - return cb(null, newChildRecord[childPkAttr]); - }); - } - }], - - // Add the child record to the parent's collection. - add: ['parent', 'actualChildPkValue', function (cb, asyncData) { - - // `collection` is the parent record's collection we - // want to add the child to. - try { - const collection = asyncData.parent[relation]; - collection.add(asyncData.actualChildPkValue); - return cb(); - } catch (err) { - if (err) { - return cb(err); - } - - return cb(); - } - }] - }, - - // Save the parent record. - function readyToSave(err, asyncData) { - if (err) { - _ctx.status = 400; - deferred.reject(err); - } - - asyncData.parent.save(function saved(err) { - - // Ignore `insert` errors for duplicate adds - // (but keep in mind, we should not `publishAdd` if this is the case...) - const isDuplicateInsertError = (err && typeof err === 'object' && err.length && err[0] && err[0].type === 'insert'); - if (err && !isDuplicateInsertError) { - deferred.reject(err); - } - - // Finally, look up the parent record again and populate the relevant collection. - let query = Model.findOne(parentPk); - - query = actionUtil.populateEach(query, _ctx, Model); - query.populate(relation); - - query.exec(function (err, matchingRecord) { - if (err) { - return deferred.reject(err); - } - if (!matchingRecord) { - return deferred.reject({ - message: 'Matching record not found.' - }); - } - if (!matchingRecord[relation]) { - return deferred.reject({ - message: '`matchingRecord[relation]` not found.' - }); - } - - return deferred.resolve(matchingRecord); - }); - }); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/create.js b/lib/configuration/hooks/blueprints/actions/create.js deleted file mode 100644 index 4e48465f04..0000000000 --- a/lib/configuration/hooks/blueprints/actions/create.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -// Local utils. -const actionUtil = require('../actionUtil'); -const associationUtil = require('../associationUtil'); - -/** - * Create an entry - */ - -module.exports = function create(_ctx) { - const deferred = Promise.defer(); - - // Return the model used. - const Model = actionUtil.parseModel(_ctx); - - // Parse the values of the record to create. - const values = actionUtil.parseValues(_ctx); - - // Associations validation. - const associationsValidationPromises = []; - - // Check if the relations are existing for `OneWay` associations. - _.forEach(_.where(Model.associations, {nature: 'oneWay'}), function (association) { - if (values[association.alias] || association.required) { - associationsValidationPromises.push(associationUtil.doesRecordExist(association.model, values[association.alias])); - } - }); - - // Check if the relations are existing for `OneToOne` associations. - _.forEach(_.where(Model.associations, {nature: 'oneToOne'}), function (association) { - if (values[association.alias] || association.required) { - associationsValidationPromises.push(associationUtil.doesRecordExist(association.model, values[association.alias])); - } - }); - - Promise.all(associationsValidationPromises) - .then(function () { - Model.create(values).exec(function created(err, newInstance) { - if (err) { - _ctx.status = 400; - return deferred.reject(err); - } - - // Update `oneToOneRelations`. - const relationPromises = []; - - // Update the `oneToOne` relations. - _.forEach(_.where(Model.associations, {nature: 'oneToOne'}), function (relation) { - relationPromises.push(associationUtil.oneToOneRelationUpdated(_ctx.model || _ctx.params.model, newInstance.id, relation.model, newInstance[relation.alias])); - }); - - Promise.all(relationPromises) - - // Related records updated. - .then(function () { - let query = Model.findOne(newInstance[Model.primaryKey]); - query = actionUtil.populateEach(query, _ctx, Model); - query.exec(function foundAgain(err, populatedRecord) { - if (err) { - _ctx.status = 500; - return deferred.reject(err); - } - - // Entry created. - _ctx.status = 201; - deferred.resolve(populatedRecord); - }); - }) - - // Error during related records update. - .catch(function (err) { - _ctx.status = 400; - deferred.reject(err); - }); - }); - }) - - // Error during related records check. - .catch(function (err) { - _ctx.status = 400; - deferred.reject(err); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/destroy.js b/lib/configuration/hooks/blueprints/actions/destroy.js deleted file mode 100644 index baf4814140..0000000000 --- a/lib/configuration/hooks/blueprints/actions/destroy.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -// Local utils. -const actionUtil = require('../actionUtil'); -const associationUtil = require('../associationUtil'); - -/** - * Destroy an entry - */ - -module.exports = function destroy(_ctx) { - const deferred = Promise.defer(); - - // Return the model used. - const Model = actionUtil.parseModel(_ctx); - - // Locate and validate the required `id` parameter. - const pk = actionUtil.requirePk(_ctx); - - // First, check if the record exists. - const query = Model.findOne(pk); - query.exec(function foundRecord(err, record) { - if (err) { - _ctx.status = 500; - deferred.reject(err); - } - - // Record not found. - if (!record) { - _ctx.status = 404; - deferred.reject({ - message: 'No record found with the specified `id`.' - }); - } - - // Destroy the record. - Model.destroy(pk).exec(function destroyedRecord(err, deletedRecords) { - if (err) { - _ctx.status = 500; - return deferred.reject(err); - } - - // Select the first object of the updated records. - const deletedRecord = deletedRecords[0]; - - // Update the `oneToOne` relations. - const relationPromises = []; - _.forEach(_.where(Model.associations, {nature: 'oneToOne'}), function (relation) { - relationPromises.push(associationUtil.removeRelationsOut(_ctx.model || _ctx.params.model, deletedRecord.id, relation.model)); - }); - - // Update the `oneToMany` relations. - _.forEach(_.where(Model.associations, {nature: 'oneToMany'}), function (relation) { - relationPromises.push(associationUtil.removeRelationsOut(_ctx.model || _ctx.params.model, deletedRecord.id, relation.collection)); - }); - - Promise.all(relationPromises) - - // Related records updated. - .then(function () { - deferred.resolve(deletedRecord); - }) - - // Error during related records update. - .catch(function (err) { - _ctx.status = 500; - deferred.reject(err); - }); - }); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/find.js b/lib/configuration/hooks/blueprints/actions/find.js deleted file mode 100644 index 812bb96560..0000000000 --- a/lib/configuration/hooks/blueprints/actions/find.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Local utils. -const actionUtil = require('../actionUtil'); - -/** - * Find entries - */ - -module.exports = function find(_ctx) { - const deferred = Promise.defer(); - - // Use the `findOne` action if an `id` is specified. - if (actionUtil.parsePk(_ctx)) { - return require('./findOne')(_ctx); - } - - // Look up the model. - const Model = actionUtil.parseModel(_ctx); - - // Init the query. - let query = Model.find() - .where(actionUtil.parseCriteria(_ctx)) - .limit(actionUtil.parseLimit(_ctx)) - .skip(actionUtil.parseSkip(_ctx)) - .sort(actionUtil.parseSort(_ctx)); - - query = actionUtil.populateEach(query, _ctx, Model); - query.exec(function found(err, matchingRecords) { - if (err) { - _ctx.status = 500; - deferred.reject(err); - } - - // Records found. - deferred.resolve(matchingRecords); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/findOne.js b/lib/configuration/hooks/blueprints/actions/findOne.js deleted file mode 100644 index 4009ad2a86..0000000000 --- a/lib/configuration/hooks/blueprints/actions/findOne.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Local utils. -const actionUtil = require('../actionUtil'); - -/** - * Find a specific entry - */ - -module.exports = function destroy(_ctx) { - const deferred = Promise.defer(); - - // Return the model used. - const Model = actionUtil.parseModel(_ctx); - - // Locate and validate the required `id` parameter. - const pk = actionUtil.requirePk(_ctx); - - // Init the query. - let query = Model.findOne(pk); - query = actionUtil.populateEach(query, _ctx, Model); - query.exec(function found(err, matchingRecord) { - if (err) { - _ctx.status = 500; - deferred.reject(err); - } - if (!matchingRecord) { - _ctx.status = 404; - - return deferred.reject({ - message: 'No ' + Model.name + ' found with the specified `id`.' - }); - } - - // Record found. - deferred.resolve(matchingRecord); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/remove.js b/lib/configuration/hooks/blueprints/actions/remove.js deleted file mode 100644 index 1fd50ba3a4..0000000000 --- a/lib/configuration/hooks/blueprints/actions/remove.js +++ /dev/null @@ -1,109 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -// Local utils. -const actionUtil = require('../actionUtil'); -const associationUtil = require('../associationUtil'); - -/** - * Remove an entry to a specific parent entry - */ - -module.exports = function remove(_ctx) { - const deferred = Promise.defer(); - - // Ensure a model and alias can be deduced from the request. - const Model = actionUtil.parseModel(_ctx); - _ctx.options = _ctx.options || {}; - const relation = _ctx.params.relation; - const associationAttr = _.findWhere(strapi.orm.collections[_ctx.model].associations, {alias: relation}); - - if (!associationAttr) { - _ctx.status = 500; - return deferred.reject({ - message: 'Missing required route option, `_ctx.options.alias`.' - }); - } - - // The primary key of the parent record. - const parentPk = _ctx.params.parentId; - - // The primary key of the child record to remove - // from the aliased collection. - let childPk = actionUtil.parsePk(_ctx); - - // Check if the `childPk` is defined. - if (_.isUndefined(childPk)) { - _ctx.status = 400; - return deferred.reject({ - message: 'Missing required child PK.' - }); - } - - // Find the parent object. - Model.findOne(parentPk) - .populate(relation) - .exec(function found(err, parentRecord) { - if (err) { - _ctx.status = 500; - return deferred.reject(err); - } - - // Format `childPk` for the `findWhere` used next. - childPk = isNaN(childPk) ? childPk : Number(childPk); - - if (!parentRecord || !parentRecord[relation] || (!_.findWhere(parentRecord[relation], {id: childPk})) && parentRecord[relation].id !== childPk) { - _ctx.status = 404; - return deferred.reject({ - message: 'Not found' - }); - } - - const relationPromises = []; - - if (parentRecord[relation].id === childPk) { - - // Set to null - parentRecord[relation] = null; - relationPromises.push(associationUtil.removeRelationsOut(_ctx.model || _ctx.params.model, parentRecord.id, relation)); - } else if (_.findWhere(parentRecord[relation], {id: childPk})) { - - // Remove. - parentRecord[relation].remove(childPk); - } - - // Save. - parentRecord.save(function (err) { - if (err) { - _ctx.status = 400; - return deferred.reject(err); - } - - Promise.all(relationPromises) - .then(function () { - - // New query to `findOne` and properly populate it. - let query = Model.findOne(parentPk); - query = actionUtil.populateEach(query, _ctx, Model); - query.exec(function found(err, parentRecord) { - if (err || !parentRecord) { - _ctx.status = 500; - return deferred.reject(err); - } - return deferred.resolve(parentRecord); - }); - }) - .catch(function (err) { - deferred.reject(err); - }); - }); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/actions/update.js b/lib/configuration/hooks/blueprints/actions/update.js deleted file mode 100644 index a2c3ff55e4..0000000000 --- a/lib/configuration/hooks/blueprints/actions/update.js +++ /dev/null @@ -1,119 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -// Local utils. -const actionUtil = require('../actionUtil'); -const associationUtil = require('../associationUtil'); - -/** - * Destroy an entry - */ - -module.exports = function update(_ctx) { - const deferred = Promise.defer(); - - // Return the model used. - const Model = actionUtil.parseModel(_ctx); - - // Locate and validate the required `id` parameter. - const pk = actionUtil.requirePk(_ctx); - - // Parse the values of the record to update. - const values = actionUtil.parseValues(_ctx); - - // No matter what, don't allow changing the `pk` via the update blueprint - // (you should just drop and re-add the record if that's what you really want). - if (typeof values[Model.primaryKey] !== 'undefined' && values[Model.primaryKey] !== pk) { - strapi.log.warn('Cannot change primary key via update action; ignoring value sent for `' + Model.primaryKey + '`'); - } - - // Make sure the primary key is unchanged. - values[Model.primaryKey] = pk; - - Model.findOne(pk).exec(function found(err, matchingRecord) { - if (err) { - _ctx.status = 500; - return deferred.reject(err); - } - if (!matchingRecord) { - _ctx.status = 404; - return deferred.reject('Record not found'); - } - - // Associations validation. - const associationsValidationPromises = []; - - // One way associations. - _.forEach(_.where(Model.associations, {nature: 'oneWay'}), function (association) { - if (values[association.alias] || association.required) { - associationsValidationPromises.push(associationUtil.doesRecordExist(association.model, values[association.alias])); - } - }); - - // One to one associations. - _.forEach(_.where(Model.associations, {nature: 'oneToOne'}), function (association) { - if (values[association.alias] || association.required) { - associationsValidationPromises.push(associationUtil.doesRecordExist(association.model, values[association.alias])); - } - }); - - // Check relations params. - Promise.all(associationsValidationPromises) - .then(function () { - - Model.update(pk, values).exec(function updated(err, records) { - if (err) { - _ctx.status = 400; - return deferred.reject(err); - } - - // Select the first and only one record. - const updatedRecord = records[0]; - - // Update `oneToOneRelations`. - const relationPromises = []; - _.forEach(_.where(Model.associations, {nature: 'oneToOne'}), function (relation) { - relationPromises.push(associationUtil.oneToOneRelationUpdated(_ctx.model || _ctx.params.model, pk, relation.model, updatedRecord[relation.alias])); - }); - - // Update the related records. - Promise.all(relationPromises) - .then(function () { - - // Extra query to find and populate the updated record. - let query = Model.findOne(updatedRecord[Model.primaryKey]); - query = actionUtil.populateEach(query, _ctx, Model); - - query.exec(function foundAgain(err, populatedRecord) { - if (err) { - _ctx.status = 500; - return deferred.reject(err); - } - - deferred.resolve(populatedRecord); - }); - }) - - // Error during related records update. - .catch(function (err) { - _ctx.status = 400; - deferred.reject(err); - }); - }); - }) - - // Error during the new related records check. - .catch(function (err) { - _ctx.status = 400; - deferred.reject(err); - }); - }); - - return deferred.promise; -}; diff --git a/lib/configuration/hooks/blueprints/associationUtil.js b/lib/configuration/hooks/blueprints/associationUtil.js deleted file mode 100644 index ab9c4295fc..0000000000 --- a/lib/configuration/hooks/blueprints/associationUtil.js +++ /dev/null @@ -1,215 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -module.exports = { - - /** - * Helper which returns a promise and then - * the found record - * - * @param {Object} model - * @param {string|int} id - * - * @return {Function|promise} - */ - - doesRecordExist: function doesRecordExist(model, id) { - const deferred = Promise.defer(); - - strapi.orm - .collections[model] - .findOne(id) - .exec(function (err, foundRecord) { - if (err) { - return deferred.reject(err); - } - if (!foundRecord) { - return deferred.reject({ - message: 'No ' + model + ' found with the specified `id`.' - }); - } - - deferred.resolve(foundRecord); - - }); - - return deferred.promise; - }, - - /** - * Helper which remove the relations of a specific entry and - * update the new relation if a relationId is specified - * - * @param originalModelAlias - * @param originalModelId - * @param relationModel - * @param relationId - * - * @return {Function|promise} - */ - - oneToOneRelationUpdated: function oneToOneRelationUpdated(originalModelAlias, originalModelId, relationModel, relationId) { - const deferred = Promise.defer(); - - // First remove all relations - const promises = []; - - // Update the relation of the origin model - promises.push(module.exports.removeRelationsOut(originalModelAlias, originalModelId, relationModel)); - - // Update the entries of the same collection - // of the original model. - promises.push(module.exports.removeRelationsIn(originalModelAlias, originalModelId, relationModel, relationId)); - - Promise.all(promises) - .then(function () { - - // If a relationId is provided, update the new linked entry. - if (relationId) { - strapi.orm.collections[relationModel] - .findOne(relationId) - .exec(function (err, record) { - if (err) { - return deferred.reject(err); - } - if (!record) { - return deferred.reject({ - message: 'Relation not found' - }); - } - record[originalModelAlias] = originalModelId; - record.save(function (err, record) { - if (err) { - return deferred.reject(err); - } - deferred.resolve(record); - }); - }); - } else { - deferred.resolve(); - } - }) - .catch(function (err) { - deferred.reject(err); - }); - - return deferred.promise; - - }, - - /** - * Helper which remove all the relations - * of a specific model - * - * @param originalModelAlias - * @param originalModelId - * @param relationModel - * - * @return {Function|promise} - */ - - removeRelationsOut: function removeRelationsOut(originalModelAlias, originalModelId, relationModel) { - const deferred = Promise.defer(); - - if (!originalModelAlias) { - return deferred.reject({ - message: 'originalModelAlias invalid.' - }); - } - - // Params object used for the `find`function. - const findParams = {}; - findParams[originalModelAlias] = originalModelId; - - // Find all the matching entries of the original model. - strapi.orm.collections[relationModel] - .find(findParams) - .exec(function (err, records) { - if (err) { - return deferred.reject(err); - } - - // Init the array of promises. - const savePromises = []; - - // Set the relation to null. - // Save the entry and add the promise in the array. - _.forEach(records, function (record) { - record[originalModelAlias] = null; - savePromises.push(record.save()); - }); - - Promise.all(savePromises) - .then(function () { - deferred.resolve(records); - }) - .catch(function (err) { - deferred.reject(err); - }); - }); - - return deferred.promise; - }, - - /** - * Helper which remove all the relations - * of a specific model - * - * @param originalModelAlias - * @param originalModelId - * @param relationModel - * @param {number|string}relationId - * - * @return {Function|promise} - */ - - removeRelationsIn: function removeRelationsIn(originalModelAlias, originalModelId, relationModel, relationId) { - const deferred = Promise.defer(); - - // Params object used for the `find` function. - const findParams = {}; - findParams[relationModel] = relationId; - findParams.id = { - '!': originalModelId - }; - - // Find all the matching entries of the original model. - strapi.orm.collections[originalModelAlias] - .find(findParams) - .exec(function (err, records) { - if (err) { - return deferred.reject(err); - } - - // Init the array of promises. - const savePromises = []; - - _.forEach(records, function (record) { - - // Set the relation to null - if (record[relationModel]) { - record[relationModel] = null; - } - - // Save the entry and add the promise in the array - savePromises.push(record.save()); - }); - - Promise.all(savePromises) - .then(function () { - deferred.resolve(); - }) - .catch(function (err) { - deferred.reject(err); - }); - }); - - return deferred.promise; - } -}; diff --git a/lib/configuration/hooks/blueprints/index.js b/lib/configuration/hooks/blueprints/index.js deleted file mode 100644 index f858857ade..0000000000 --- a/lib/configuration/hooks/blueprints/index.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -/** - * Blueprints hook - */ - -module.exports = function () { - const hook = { - - /** - * Default options - */ - - defaults: { - blueprints: { - defaultLimit: 30, - populate: true - } - }, - - /** - * Export functions - */ - - // Utils - actionUtil: require('./actionUtil'), - associationUtil: require('./associationUtil'), - - // Actions - find: require('./actions/find'), - findOne: require('./actions/findOne'), - create: require('./actions/create'), - update: require('./actions/update'), - destroy: require('./actions/destroy'), - remove: require('./actions/remove'), - add: require('./actions/add'), - - /** - * Initialize the hook - */ - - initialize: function (cb) { - cb(); - } - }; - - return hook; -}; diff --git a/lib/configuration/hooks/defaultHooks.js b/lib/configuration/hooks/defaultHooks.js index 93db13464b..1423277090 100755 --- a/lib/configuration/hooks/defaultHooks.js +++ b/lib/configuration/hooks/defaultHooks.js @@ -8,7 +8,6 @@ module.exports = { _config: true, _api: true, responseTime: true, - waterline: true, bodyParser: true, session: true, grant: true, @@ -22,7 +21,6 @@ module.exports = { i18n: true, cron: true, logger: true, - blueprints: true, views: true, router: true, static: true, diff --git a/lib/configuration/hooks/router/index.js b/lib/configuration/hooks/router/index.js index ad2a5bdd91..a026fe8d0a 100644 --- a/lib/configuration/hooks/router/index.js +++ b/lib/configuration/hooks/router/index.js @@ -103,20 +103,6 @@ module.exports = function (strapi) { } }); - // Define GraphQL route with modified Waterline models to GraphQL schema - // or disable the global variable - if (strapi.config.graphql.enabled === true) { - // Wait GraphQL schemas generation - strapi.once('waterline:graphql:ready', function () { - strapi.router.get(strapi.config.graphql.route, strapi.middlewares.graphql({ - schema: strapi.schemas, - pretty: true - })); - }); - } else { - global.graphql = undefined; - } - // Let the router use our routes and allowed methods. strapi.app.use(strapi.router.routes()); strapi.app.use(strapi.router.allowedMethods()); diff --git a/lib/configuration/hooks/waterline/helpers/index.js b/lib/configuration/hooks/waterline/helpers/index.js deleted file mode 100644 index 842074ba2c..0000000000 --- a/lib/configuration/hooks/waterline/helpers/index.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Locale helpers. -const isManyToOneAssociation = require('./isManyToOneAssociation'); -const isOneToOneAssociation = require('./isOneToOneAssociation'); -const isOneWayAssociation = require('./isOneWayAssociation'); -const isOneToManyAssociation = require('./isOneToManyAssociation'); -const isManyToManyAssociation = require('./isManyToManyAssociation'); - -/** - * Helper which returns the association type of the attribute - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = { - getAssociationType: function (currentModel, association) { - let associationType; - - if (association.type === 'model') { - if (isManyToOneAssociation(currentModel, association)) { - associationType = 'manyToOne'; - } else if (isOneToOneAssociation(currentModel, association)) { - associationType = 'oneToOne'; - } else if (isOneWayAssociation(currentModel, association)) { - associationType = 'oneWay'; - } else { - associationType = 'unknown'; - } - } else if (association.type === 'collection') { - if (isOneToManyAssociation(currentModel, association)) { - associationType = 'oneToMany'; - } else if (isManyToManyAssociation(currentModel, association)) { - associationType = 'manyToMany'; - } else { - associationType = 'unknown'; - } - } - - return associationType; - } -}; diff --git a/lib/configuration/hooks/waterline/helpers/isManyToManyAssociation.js b/lib/configuration/hooks/waterline/helpers/isManyToManyAssociation.js deleted file mode 100644 index 8eabdfe341..0000000000 --- a/lib/configuration/hooks/waterline/helpers/isManyToManyAssociation.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -/** - * Helper which returns a boolean. True if the type - * of the relation is `manyToMany`. - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = function isManyToManyAssociation(currentModel, association) { - return _.findWhere(strapi.models[association.collection] && strapi.models[association.collection].associations, { - collection: currentModel - }); -}; diff --git a/lib/configuration/hooks/waterline/helpers/isManyToOneAssociation.js b/lib/configuration/hooks/waterline/helpers/isManyToOneAssociation.js deleted file mode 100644 index f863b8e572..0000000000 --- a/lib/configuration/hooks/waterline/helpers/isManyToOneAssociation.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -/** - * Helper which returns a boolean. True if the type - * of the relation is `manyToOne`. - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = function isManyToOneAssociation(currentModel, association) { - return _.findWhere(strapi.models[association.model] && strapi.models[association.model].associations, { - collection: currentModel - }); -}; diff --git a/lib/configuration/hooks/waterline/helpers/isOneToManyAssociation.js b/lib/configuration/hooks/waterline/helpers/isOneToManyAssociation.js deleted file mode 100644 index b25fa0c4f3..0000000000 --- a/lib/configuration/hooks/waterline/helpers/isOneToManyAssociation.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -/** - * Helper which returns a boolean. True if the type - * of the relation is `oneToMany`. - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = function isOneToManyAssociation(currentModel, association) { - return _.findWhere(strapi.models[association.collection] && strapi.models[association.collection].associations, { - model: currentModel - }); -}; diff --git a/lib/configuration/hooks/waterline/helpers/isOneToOneAssociation.js b/lib/configuration/hooks/waterline/helpers/isOneToOneAssociation.js deleted file mode 100644 index 8394ea5c45..0000000000 --- a/lib/configuration/hooks/waterline/helpers/isOneToOneAssociation.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Public node modules. -const _ = require('lodash'); - -/** - * Helper which returns a boolean. True if the type - * of the relation is `oneToOne`. - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = function isOneToOneAssociation(currentModel, association) { - return _.findWhere(strapi.models[association.model] && strapi.models[association.model].associations, { - model: currentModel - }); -}; diff --git a/lib/configuration/hooks/waterline/helpers/isOneWayAssociation.js b/lib/configuration/hooks/waterline/helpers/isOneWayAssociation.js deleted file mode 100644 index 27879d4bac..0000000000 --- a/lib/configuration/hooks/waterline/helpers/isOneWayAssociation.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Locale helpers. -const isOneToManyAssociation = require('./isOneToManyAssociation'); -const isOneToOneAssociation = require('./isOneToOneAssociation'); - -/** - * Helper which returns a boolean. True if the type - * of the relation is `oneToOne`. - * - * @param {Object} currentModel - * @param {Object} association - * - * @return {boolean} - */ - -module.exports = function isOneWayAssociation(currentModel, association) { - return !(isOneToManyAssociation(currentModel, association) || isOneToOneAssociation(currentModel, association)); -}; diff --git a/lib/configuration/hooks/waterline/index.js b/lib/configuration/hooks/waterline/index.js deleted file mode 100644 index a01d3e54c1..0000000000 --- a/lib/configuration/hooks/waterline/index.js +++ /dev/null @@ -1,302 +0,0 @@ -'use strict'; - -/** - * Module dependencies - */ - -// Node.js core. -const cluster = require('cluster'); -const path = require('path'); -const spawn = require('child_process').spawn; - -// Public node modules. -const _ = require('lodash'); -const async = require('async'); -const Waterline = require('waterline'); -const WaterlineGraphQL = require('waterline-graphql'); - -// Local utilities. -const helpers = require('./helpers/index'); - -/** - * Waterline ORM hook - */ - -module.exports = function (strapi) { - const hook = { - - /** - * Default options - */ - - defaults: { - orm: { - adapters: { - disk: 'sails-disk' - }, - defaultConnection: 'default', - connections: { - default: { - adapter: 'disk', - filePath: '.tmp/', - fileName: 'default.db', - migrate: 'alter' - }, - permanent: { - adapter: 'disk', - filePath: './data/', - fileName: 'permanent.db', - migrate: 'alter' - } - } - }, - globals: { - models: true - } - }, - - /** - * Initialize the hook - */ - - initialize: function (cb) { - if (_.isPlainObject(strapi.config.orm) && !_.isEmpty(strapi.config.orm) && (((cluster.isWorker && strapi.config.reload.workers > 0) || (cluster.isMaster && strapi.config.reload.workers < 1)) || !strapi.config.reload && cluster.isMaster)) { - strapi.adapters = {}; - strapi.collections = []; - - // Expose a new instance of Waterline. - if (!strapi.orm) { - strapi.orm = new Waterline(); - } - - // Prefix every adapter and require them from the - // `node_modules` directory of the application. - _.forEach(strapi.config.orm.adapters, function (adapter, name) { - try { - strapi.adapters[name] = require(path.resolve(strapi.config.appPath, 'node_modules', adapter)); - } catch (err) { - strapi.log.error('The adapter `' + adapter + '` is not installed.'); - process.exit(1); - } - }); - - // Check if the adapter in every connections exists. - _.forEach(strapi.config.orm.connections, function (settings, name) { - if (!_.has(strapi.config.orm.adapters, settings.adapter)) { - strapi.log.error('Unknown adapter `' + settings.adapter + '` for connection `' + name + '`.'); - process.exit(1); - } - }); - - // Parse each models. - _.forEach(strapi.models, function (definition, model) { - _.bindAll(definition); - - // Make sure the model has a connection. - // If not, use the default connection. - if (_.isEmpty(definition.connection)) { - definition.connection = strapi.config.orm.defaultConnection; - } - - // Make sure this connection exists. - if (!_.has(strapi.config.orm.connections, definition.connection)) { - strapi.log.error('The connection `' + definition.connection + '` specified in the `' + model + '` model does not exist.'); - process.exit(1); - } - - // Make sure this connection has an appropriate migrate strategy. - // If not, use the appropriate strategy. - if (!_.has(strapi.config.orm.connections[definition.connection], 'migrate')) { - if (strapi.config.environment === 'production') { - strapi.log.warn('Setting the migrate strategy of the `' + model + '` model to `safe`.'); - strapi.config.orm.connections[definition.connection].migrate = 'safe'; - } else { - strapi.log.warn('Setting the migrate strategy of the `' + model + '` model to `alter`.'); - strapi.config.orm.connections[definition.connection].migrate = 'alter'; - } - } else if (strapi.config.environment === 'production' && strapi.config.orm.connections[definition.connection].migrate === ('alter' || 'drop')) { - strapi.log.warn('Setting the migrate strategy of the `' + model + '` model to `safe`.'); - strapi.config.orm.connections[definition.connection].migrate = 'safe'; - } - - // Apply the migrate strategy to the model. - definition.migrate = strapi.config.orm.connections[definition.connection].migrate; - - // Derive information about this model's associations from its schema - // and attach/expose the metadata as `SomeModel.associations` (an array). - definition.associations = _.reduce(definition.attributes, function (associatedWith, attrDef, attrName) { - if (typeof attrDef === 'object' && (attrDef.model || attrDef.collection)) { - const assoc = { - alias: attrName, - type: attrDef.model ? 'model' : 'collection' - }; - - if (attrDef.model) { - assoc.model = attrDef.model; - } - - if (attrDef.collection) { - assoc.collection = attrDef.collection; - } - - if (attrDef.via) { - assoc.via = attrDef.via; - } - - associatedWith.push(assoc); - } - - return associatedWith; - }, []); - - // Finally, load the collection in the Waterline instance. - try { - const collection = strapi.orm.loadCollection(Waterline.Collection.extend(definition)); - - if (_.isFunction(collection)) { - strapi.collections.push(collection); - } - } catch (err) { - strapi.log.error('Impossible to register the `' + model + '` model.'); - process.exit(1); - } - }); - - // Finally, initialize the Waterline ORM and - // globally expose models. - strapi.orm.initialize({ - adapters: strapi.adapters, - connections: strapi.config.orm.connections, - collections: strapi.collections, - defaults: { - connection: strapi.config.orm.defaultConnection - } - }, function () { - if (strapi.config.globals.models === true) { - _.forEach(strapi.models, function (definition, model) { - const globalName = _.capitalize(strapi.models[model].globalId); - global[globalName] = strapi.orm.collections[model]; - }); - } - - // Parse each models and look for associations. - _.forEach(strapi.orm.collections, function (definition, model) { - _.forEach(definition.associations, function (association) { - association.nature = helpers.getAssociationType(model, association); - }); - }); - - if (strapi.config.graphql.enabled === true) { - // Parse each models and add associations array - _.forEach(strapi.orm.collections, function (collection, key) { - if (strapi.models.hasOwnProperty(key)) { - collection.associations = strapi.models[key].associations || []; - } - }); - - // Expose the GraphQL schemas at `strapi.schemas` - WaterlineGraphQL.getGraphQLSchema({ - collections: strapi.orm.collections, - usefulFunctions: true - }, function (schemas) { - strapi.schemas = schemas; - - strapi.emit('waterline:graphql:ready'); - }); - } - - cb(); - }); - } else { - cb(); - } - }, - - /** - * Reload the hook - */ - - reload: function () { - hook.teardown(function () { - delete strapi.orm; - - hook.initialize(function (err) { - if (err) { - strapi.log.error('Failed to reinitialize the ORM hook.'); - strapi.stop(); - } else { - strapi.emit('hook:waterline:reloaded'); - } - }); - }); - }, - - /** - * Teardown adapters - */ - - teardown: function (cb) { - cb = cb || function (err) { - if (err) { - strapi.log.error('Failed to teardown ORM adapters.'); - strapi.stop(); - } - }; - async.forEach(Object.keys(strapi.adapters || {}), function (name, next) { - if (strapi.adapters[name].teardown) { - strapi.adapters[name].teardown(null, next); - } else { - next(); - } - }, cb); - }, - - /** - * Installation adapters - */ - - installation: function () { - const done = _.after(_.size(strapi.config.orm.adapters), function () { - strapi.emit('hook:waterline:installed'); - }); - - _.forEach(strapi.config.orm.adapters, function (adapter) { - try { - require(path.resolve(strapi.config.appPath, 'node_modules', adapter)); - - done(); - } catch (err) { - if (strapi.config.environment === 'development') { - strapi.log.warn('Installing the `' + adapter + '` adapter, please wait...'); - console.log(); - - const process = spawn('npm', ['install', adapter, '--save']); - - process.on('error', function (error) { - strapi.log.error('The adapter `' + adapter + '` has not been installed.'); - strapi.log.error(error); - process.exit(1); - }); - - process.on('close', function (code) { - if (code !== 0) { - strapi.log.error('The adapter `' + adapter + '` has not been installed.'); - strapi.log.error('Code: ' + code); - process.exit(1); - } - - strapi.log.info('`' + adapter + '` successfully installed'); - done(); - }); - } else { - strapi.log.error('The adapter `' + adapter + '` is not installed.'); - strapi.log.error('Execute `$ npm install ' + adapter + ' --save` to install it.'); - process.exit(1); - } - } - }); - } - }; - - return hook; -}; diff --git a/lib/private/loadHooks.js b/lib/private/loadHooks.js index f833b77096..86186374ea 100755 --- a/lib/private/loadHooks.js +++ b/lib/private/loadHooks.js @@ -39,10 +39,8 @@ module.exports = function (strapi) { // Remove undesired hooks when this is a `dry` application. if (strapi.config.dry) { - delete hooks.blueprints; delete hooks.grant; delete hooks.studio; - delete hooks.waterline; } // Handle folder-defined modules (default to `./lib/index.js`) @@ -130,7 +128,7 @@ module.exports = function (strapi) { // Prepare all other hooks. prepare: function prepareHooks(cb) { - async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router', 'waterline'), function (id, cb) { + async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router'), function (id, cb) { prepareHook(id); process.nextTick(cb); }, cb); @@ -138,7 +136,7 @@ module.exports = function (strapi) { // Apply the default config for all other hooks. defaults: function defaultConfigHooks(cb) { - async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router', 'waterline'), function (id, cb) { + async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router'), function (id, cb) { const hook = hooks[id]; applyDefaults(hook); process.nextTick(cb); @@ -147,7 +145,7 @@ module.exports = function (strapi) { // Load all other hooks. load: function loadOtherHooks(cb) { - async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router', 'waterline'), function (id, cb) { + async.each(_.without(_.keys(hooks), '_config', '_api', 'studio', 'router'), function (id, cb) { loadHook(id, cb); }, cb); }, @@ -160,16 +158,6 @@ module.exports = function (strapi) { prepareHook('router'); applyDefaults(hooks.router); loadHook('router', cb); - }, - - // Load the waterline hook. - waterline: function loadWaterlineHook(cb) { - if (!hooks.waterline) { - return cb(); - } - prepareHook('waterline'); - applyDefaults(hooks.waterline); - loadHook('waterline', cb); } }, diff --git a/lib/restart.js b/lib/restart.js index d8c6f8e158..2ee52de9dd 100644 --- a/lib/restart.js +++ b/lib/restart.js @@ -55,7 +55,6 @@ module.exports = cb => { // Run adapters installation if (cluster.isMaster) { - strapi.hooks.waterline.installation(); ++count; @@ -72,44 +71,34 @@ module.exports = cb => { console.log(); } - // Teardown Waterline adapters and - // reload the Waterline ORM. - strapi.after('hook:waterline:reloaded', () => { - strapi.after('hook:router:reloaded', () => { - process.nextTick(() => cb()); + // Reload the router. + strapi.after('hook:router:reloaded', () => { + process.nextTick(() => cb()); - // Update `strapi` status. - strapi.reloaded = true; - strapi.reloading = false; + // Update `strapi` status. + strapi.reloaded = true; + strapi.reloading = false; - // Finally inform the developer everything seems ok. - if (cluster.isMaster && _.isPlainObject(strapi.config.reload) && !_.isEmpty(strapi.config.reload) && strapi.config.reload.workers < 1) { - strapi.log.info('Application\'s dictionnary updated'); - strapi.log.warn('You still need to restart your server to fully enjoy changes...'); - } + // Finally inform the developer everything seems ok. + if (cluster.isMaster && _.isPlainObject(strapi.config.reload) && !_.isEmpty(strapi.config.reload) && strapi.config.reload.workers < 1) { + strapi.log.info('Application\'s dictionnary updated'); + strapi.log.warn('You still need to restart your server to fully enjoy changes...'); + } - strapi.once('restart:done', function () { - strapi.log.info('Application successfully restarted'); - }); - - if (cluster.isMaster) { - _.forEach(cluster.workers, worker => worker.on('message', () => strapi.emit('restart:done'))); - } - - // Kill every worker processes. - _.forEach(cluster.workers, () => process.kill(process.pid, 'SIGHUP')); + strapi.once('restart:done', function () { + strapi.log.info('Application successfully restarted'); }); - // Reloading the router. - strapi.hooks.router.reload(); + if (cluster.isMaster) { + _.forEach(cluster.workers, worker => worker.on('message', () => strapi.emit('restart:done'))); + } + + // Kill every worker processes. + _.forEach(cluster.workers, () => process.kill(process.pid, 'SIGHUP')); }); - // Reloading the ORM. - strapi.hooks.waterline.reload(); - }); - - strapi.after('hook:waterline:installed', () => { - installed(); + // Reloading the router. + strapi.hooks.router.reload(); }); strapi.after('hook:views:installed', () => { diff --git a/package.json b/package.json index 4216bceb88..ce5b3cee5a 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "security", "socket.io", "sockets", - "waterline", "websockets" ], "directories": { @@ -67,9 +66,9 @@ "node-schedule": "~0.6.0", "prompt": "~0.2.14", "request": "~2.67.0", - "sails-disk": "~0.10.8", "socket.io": "~1.3.7", "socket.io-client": "~1.3.7", + "strapi-bookshelf": "~1.5.0", "strapi-generate": "~1.5.0", "strapi-generate-admin": "~1.5.0", "strapi-generate-api": "~1.5.0", @@ -78,8 +77,6 @@ "strapi-generate-upload": "~1.5.0", "strapi-generate-users": "~1.5.0", "unzip2": "~0.2.5", - "waterline": "~0.10.28", - "waterline-graphql": "~1.1.0", "winston": "~2.1.1" }, "devDependencies": { @@ -167,8 +164,8 @@ "url": "https://github.com/wistityhq/strapi/issues" }, "engines": { - "node": ">= 0.12.0", - "npm": ">= 2.0.0" + "node": ">= 4.0.0", + "npm": ">= 3.0.0" }, "preferGlobal": true, "license": "MIT"