mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 07:03:38 +00:00
Save plugins models in extensions folder
This commit is contained in:
parent
87857b94be
commit
710e3ab52f
@ -49,4 +49,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
7
examples/getstarted/api/articles/controllers/Articles.js
Normal file
7
examples/getstarted/api/articles/controllers/Articles.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation () to implement custom controller functions
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -1,54 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Lifecycle callbacks for the `Articles` model.
|
||||
* Lifecycle callbacks for the `Test` model.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// Before saving a value.
|
||||
// Fired before an `insert` or `update` query.
|
||||
// beforeSave: async (model) => {},
|
||||
// beforeSave: async (model, attrs, options) => {},
|
||||
|
||||
// After saving a value.
|
||||
// Fired after an `insert` or `update` query.
|
||||
// afterSave: async (model, result) => {},
|
||||
|
||||
// Before fetching all values.
|
||||
// Fired before a `fetchAll` operation.
|
||||
// beforeFetchAll: async (model) => {},
|
||||
|
||||
// After fetching all values.
|
||||
// Fired after a `fetchAll` operation.
|
||||
// afterFetchAll: async (model, results) => {},
|
||||
// afterSave: async (model, response, options) => {},
|
||||
|
||||
// Before fetching a value.
|
||||
// Fired before a `fetch` operation.
|
||||
// beforeFetch: async (model) => {},
|
||||
// beforeFetch: async (model, columns, options) => {},
|
||||
|
||||
// After fetching a value.
|
||||
// Fired after a `fetch` operation.
|
||||
// afterFetch: async (model, result) => {},
|
||||
// afterFetch: async (model, response, options) => {},
|
||||
|
||||
// Before fetching all values.
|
||||
// Fired before a `fetchAll` operation.
|
||||
// beforeFetchAll: async (model, columns, options) => {},
|
||||
|
||||
// After fetching all values.
|
||||
// Fired after a `fetchAll` operation.
|
||||
// afterFetchAll: async (model, response, options) => {},
|
||||
|
||||
// Before creating a value.
|
||||
// Fired before an `insert` query.
|
||||
// beforeCreate: async (model) => {},
|
||||
// beforeCreate: async (model, attrs, options) => {},
|
||||
|
||||
// After creating a value.
|
||||
// Fired after an `insert` query.
|
||||
// afterCreate: async (model, result) => {},
|
||||
// afterCreate: async (model, attrs, options) => {},
|
||||
|
||||
// Before updating a value.
|
||||
// Fired before an `update` query.
|
||||
// beforeUpdate: async (model) => {},
|
||||
// beforeUpdate: async (model, attrs, options) => {},
|
||||
|
||||
// After updating a value.
|
||||
// Fired after an `update` query.
|
||||
// afterUpdate: async (model, result) => {},
|
||||
// afterUpdate: async (model, attrs, options) => {},
|
||||
|
||||
// Before destroying a value.
|
||||
// Fired before a `delete` query.
|
||||
// beforeDestroy: async (model) => {},
|
||||
// beforeDestroy: async (model, attrs, options) => {},
|
||||
|
||||
// After destroying a value.
|
||||
// Fired after a `delete` query.
|
||||
// afterDestroy: async (model, result) => {}
|
||||
// afterDestroy: async (model, attrs, options) => {}
|
||||
};
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
{
|
||||
"connection": "default",
|
||||
"collectionName": "",
|
||||
"collectionName": "articles",
|
||||
"info": {
|
||||
"name": "articles",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"timestamps": true
|
||||
"increments": true,
|
||||
"timestamps": [
|
||||
"created_at",
|
||||
"updated_at"
|
||||
],
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
"content": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
examples/getstarted/api/articles/services/Articles.js
Normal file
7
examples/getstarted/api/articles/services/Articles.js
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Read the documentation () to implement custom service functions
|
||||
*/
|
||||
|
||||
module.exports = {};
|
||||
@ -1 +0,0 @@
|
||||
{"actions":["application.articles.find","application.articles.findone","application.articles.count","application.articles.create","application.articles.update","application.articles.destroy","application.tags.find","application.tags.findone","application.tags.count","application.tags.create","application.tags.update","application.tags.destroy","content-manager.contentmanager.models","content-manager.contentmanager.find","content-manager.contentmanager.count","content-manager.contentmanager.findone","content-manager.contentmanager.create","content-manager.contentmanager.update","content-manager.contentmanager.updatesettings","content-manager.contentmanager.delete","content-manager.contentmanager.deleteall","content-type-builder.contenttypebuilder.getmodels","content-type-builder.contenttypebuilder.getmodel","content-type-builder.contenttypebuilder.getconnections","content-type-builder.contenttypebuilder.createmodel","content-type-builder.contenttypebuilder.updatemodel","content-type-builder.contenttypebuilder.deletemodel","content-type-builder.contenttypebuilder.autoreload","content-type-builder.contenttypebuilder.checktableexists","email.email.send","email.email.getenvironments","email.email.getsettings","email.email.updatesettings","settings-manager.settingsmanager.menu","settings-manager.settingsmanager.environments","settings-manager.settingsmanager.languages","settings-manager.settingsmanager.databases","settings-manager.settingsmanager.database","settings-manager.settingsmanager.databasemodel","settings-manager.settingsmanager.get","settings-manager.settingsmanager.update","settings-manager.settingsmanager.createlanguage","settings-manager.settingsmanager.deletelanguage","settings-manager.settingsmanager.createdatabase","settings-manager.settingsmanager.updatedatabase","settings-manager.settingsmanager.deletedatabase","settings-manager.settingsmanager.autoreload","upload.upload.upload","upload.upload.getenvironments","upload.upload.getsettings","upload.upload.updatesettings","upload.upload.find","upload.upload.findone","upload.upload.count","upload.upload.destroy","upload.upload.search","users-permissions.auth.callback","users-permissions.auth.changepassword","users-permissions.auth.connect","users-permissions.auth.forgotpassword","users-permissions.auth.register","users-permissions.auth.emailconfirmation","users-permissions.user.find","users-permissions.user.me","users-permissions.user.findone","users-permissions.user.create","users-permissions.user.update","users-permissions.user.destroy","users-permissions.user.destroyall","users-permissions.userspermissions.createrole","users-permissions.userspermissions.deleteprovider","users-permissions.userspermissions.deleterole","users-permissions.userspermissions.getpermissions","users-permissions.userspermissions.getpolicies","users-permissions.userspermissions.getrole","users-permissions.userspermissions.getroles","users-permissions.userspermissions.getroutes","users-permissions.userspermissions.index","users-permissions.userspermissions.init","users-permissions.userspermissions.searchusers","users-permissions.userspermissions.updaterole","users-permissions.userspermissions.getemailtemplate","users-permissions.userspermissions.updateemailtemplate","users-permissions.userspermissions.getadvancedsettings","users-permissions.userspermissions.updateadvancedsettings","users-permissions.userspermissions.getproviders","users-permissions.userspermissions.updateproviders","myplugin.test.findone","myplugin.test.find"]}
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"jwtSecret": "1481145e-8625-4032-a4f0-75de2a3f10c9"
|
||||
"jwtSecret": "bb26b371-8957-434c-a313-f35dd6b1813c"
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
{
|
||||
"connection": "default",
|
||||
"info": {
|
||||
"name": "user",
|
||||
"description": ""
|
||||
},
|
||||
"attributes": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
"minLength": 3,
|
||||
"unique": true,
|
||||
"configurable": false,
|
||||
"required": true
|
||||
},
|
||||
"email": {
|
||||
"type": "email",
|
||||
"minLength": 6,
|
||||
"configurable": false,
|
||||
"required": true
|
||||
},
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"configurable": false
|
||||
},
|
||||
"password": {
|
||||
"type": "password",
|
||||
"minLength": 6,
|
||||
"configurable": false,
|
||||
"private": true
|
||||
},
|
||||
"resetPasswordToken": {
|
||||
"type": "string",
|
||||
"configurable": false,
|
||||
"private": true
|
||||
},
|
||||
"confirmed": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"configurable": false
|
||||
},
|
||||
"blocked": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"configurable": false
|
||||
},
|
||||
"role": {
|
||||
"model": "role",
|
||||
"via": "users",
|
||||
"plugin": "users-permissions",
|
||||
"configurable": false
|
||||
}
|
||||
},
|
||||
"collectionName": "users-permissions_user"
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
"type": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"configurable": false
|
||||
"configurable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,11 +772,7 @@ module.exports = function(strapi) {
|
||||
idAttributeBuilder,
|
||||
).join(',\n\r');
|
||||
// Create table
|
||||
await ORM.knex.raw(`
|
||||
CREATE TABLE ${quote}${table}${quote} (
|
||||
${columns}
|
||||
)
|
||||
`);
|
||||
await ORM.knex.raw(`CREATE TABLE ${quote}${table}${quote} (${columns})`);
|
||||
};
|
||||
|
||||
if (!tableExist) {
|
||||
@ -1086,10 +1082,6 @@ module.exports = function(strapi) {
|
||||
}
|
||||
});
|
||||
|
||||
if (_.isEmpty(definition.attributes)) {
|
||||
done();
|
||||
}
|
||||
|
||||
// Add every relationships to the loaded model for Bookshelf.
|
||||
// Basic attributes don't need this-- only relations.
|
||||
_.forEach(definition.attributes, (details, name) => {
|
||||
@ -1418,9 +1410,14 @@ module.exports = function(strapi) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
if (_.isEmpty(definition.attributes)) {
|
||||
done();
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const _ = require('lodash');
|
||||
|
||||
const Service = require('../services/ContentTypeBuilder');
|
||||
const { escapeNewlines } = require('../utils/helpers.js');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Returns the list of models and there details
|
||||
*/
|
||||
getModels: async ctx => {
|
||||
const models = Service.getModels();
|
||||
const arrayOfPromises = [];
|
||||
@ -21,9 +23,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
getModel: async ctx => {
|
||||
const Service = strapi.plugins['content-type-builder'].services.contenttypebuilder;
|
||||
const { source } = ctx.request.query;
|
||||
|
||||
const Service = strapi.plugins['content-type-builder'].services.contenttypebuilder;
|
||||
|
||||
let { model } = ctx.params;
|
||||
|
||||
model = _.toLower(model);
|
||||
@ -44,14 +47,14 @@ module.exports = {
|
||||
},
|
||||
|
||||
createModel: async ctx => {
|
||||
const { name, description, connection, collectionName, attributes = [], plugin } = ctx.request.body;
|
||||
const { name, description, connection, collectionName, attributes = [] } = ctx.request.body;
|
||||
|
||||
if (!name) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.name.missing' }] }]);
|
||||
if (!_.includes(Service.getConnections(), connection)) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.connection.unknow' }] }]);
|
||||
if (strapi.models[name]) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.exist' }] }]);
|
||||
if (!_.isNaN(parseFloat(name[0]))) return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.name' }] }]);
|
||||
|
||||
const [formatedAttributes, attributesErrors] = Service.formatAttributes(attributes, name, plugin);
|
||||
const [formatedAttributes, attributesErrors] = Service.formatAttributes(attributes, name);
|
||||
|
||||
if (!_.isEmpty(attributesErrors)) {
|
||||
return ctx.badRequest(null, [{ messages: attributesErrors }]);
|
||||
@ -63,29 +66,22 @@ module.exports = {
|
||||
|
||||
await Service.appearance(formatedAttributes, name);
|
||||
|
||||
await Service.generateAPI(name, _description, connection, collectionName, []);
|
||||
|
||||
const modelFilePath = await Service.getModelPath(name, plugin);
|
||||
const apiName = _.toLower(name);
|
||||
await Service.generateAPI(apiName, _description, connection, collectionName, []);
|
||||
|
||||
try {
|
||||
const modelJSON = _.cloneDeep(require(modelFilePath));
|
||||
const modelJSON = Service.readModel(name, { api: apiName });
|
||||
|
||||
modelJSON.attributes = formatedAttributes;
|
||||
|
||||
const clearRelationsErrors = Service.clearRelations(name, plugin);
|
||||
|
||||
if (!_.isEmpty(clearRelationsErrors)) {
|
||||
return ctx.badRequest(null, [{ messages: clearRelationsErrors }]);
|
||||
}
|
||||
|
||||
const createRelationsErrors = Service.createRelations(name, attributes, plugin);
|
||||
const createRelationsErrors = Service.createRelations(name, attributes);
|
||||
|
||||
if (!_.isEmpty(createRelationsErrors)) {
|
||||
return ctx.badRequest(null, [{ messages: createRelationsErrors }]);
|
||||
}
|
||||
|
||||
try {
|
||||
fs.writeFileSync(modelFilePath, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||
Service.writeModel(name, modelJSON, { api: apiName });
|
||||
|
||||
if (_.isEmpty(strapi.api)) {
|
||||
strapi.emit('didCreateFirstContentType');
|
||||
@ -97,10 +93,12 @@ module.exports = {
|
||||
|
||||
setImmediate(() => strapi.reload());
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
strapi.emit('didNotCreateContentType', e);
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.write' }] }]);
|
||||
}
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.read' }] }]);
|
||||
}
|
||||
},
|
||||
@ -124,7 +122,7 @@ module.exports = {
|
||||
|
||||
const _description = escapeNewlines(description);
|
||||
|
||||
let modelFilePath = Service.getModelPath(model, plugin);
|
||||
// let modelFilePath = Service.getModelPath(model, plugin);
|
||||
|
||||
strapi.reload.isWatching = false;
|
||||
|
||||
@ -135,7 +133,9 @@ module.exports = {
|
||||
await Service.appearance(formatedAttributes, name, plugin);
|
||||
|
||||
try {
|
||||
const modelJSON = _.cloneDeep(require(modelFilePath));
|
||||
// const modelJSON = _.cloneDeep(require(modelFilePath));
|
||||
const modelData = plugin ? strapi.plugins[plugin].models[model.toLowerCase()] : strapi.models[model.toLowerCase()];
|
||||
const modelJSON = _.cloneDeep(_.pick(modelData, ['connection', 'collectionName', 'info', 'options', 'attributes']));
|
||||
|
||||
modelJSON.connection = connection;
|
||||
modelJSON.collectionName = collectionName;
|
||||
@ -168,19 +168,25 @@ module.exports = {
|
||||
return ctx.badRequest(null, [{ messages: removeModelErrors }]);
|
||||
}
|
||||
|
||||
modelFilePath = Service.getModelPath(name, plugin);
|
||||
// modelFilePath = Service.getModelPath(name, plugin);
|
||||
}
|
||||
|
||||
try {
|
||||
fs.writeFileSync(modelFilePath, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||
if (plugin) {
|
||||
await Service.writeModel(name, modelJSON, { plugin });
|
||||
} else {
|
||||
await Service.writeModel(name, modelJSON, { api: modelData.apiName });
|
||||
}
|
||||
|
||||
ctx.send({ ok: true });
|
||||
|
||||
strapi.reload();
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.write' }] }]);
|
||||
}
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
return ctx.badRequest(null, [{ messages: [{ id: 'request.error.model.read' }] }]);
|
||||
}
|
||||
},
|
||||
|
||||
@ -122,7 +122,10 @@ module.exports = {
|
||||
await pluginStore.set({ key: 'schema', value: schema });
|
||||
},
|
||||
|
||||
getModels: () => {
|
||||
/**
|
||||
* Returns a list of user and plugins models
|
||||
*/
|
||||
getModels() {
|
||||
const models = [];
|
||||
|
||||
_.forEach(strapi.models, (model, name) => {
|
||||
@ -161,7 +164,10 @@ module.exports = {
|
||||
return models.concat(pluginModels);
|
||||
},
|
||||
|
||||
getModel: async (name, source) => {
|
||||
/**
|
||||
* Returns a model info
|
||||
*/
|
||||
async getModel (name, source) {
|
||||
name = _.toLower(name);
|
||||
|
||||
const model = source ? _.get(strapi.plugins, [source, 'models', name]) : _.get(strapi.models, name);
|
||||
@ -221,11 +227,11 @@ module.exports = {
|
||||
};
|
||||
},
|
||||
|
||||
getConnections: () => {
|
||||
getConnections() {
|
||||
return _.keys(strapi.config.currentEnvironment.database.connections);
|
||||
},
|
||||
|
||||
generateAPI: (name, description, connection, collectionName, attributes) => {
|
||||
generateAPI(name, description, connection, collectionName, attributes) {
|
||||
const template = _.get(
|
||||
strapi.config.currentEnvironment,
|
||||
`database.connections.${connection}.connector`,
|
||||
@ -258,33 +264,58 @@ module.exports = {
|
||||
});
|
||||
},
|
||||
|
||||
getModelPath: (model, plugin) => {
|
||||
// Retrieve where is located the model.
|
||||
// Note: The target is not found when we are creating a new API. That's why, we are returning the lowercased model.
|
||||
const target =
|
||||
Object.keys((plugin ? strapi.plugins : strapi.api) || {}).filter(x =>
|
||||
_.includes(
|
||||
Object.keys(_.get((plugin ? strapi.plugins : strapi.api)[x], 'models', [])),
|
||||
model.toLowerCase(),
|
||||
),
|
||||
)[0] || model.toLowerCase();
|
||||
writeModel(name, data, {api, plugin} = {}) {
|
||||
const filepath = this.getModelPath(name, { api, plugin });
|
||||
const content = JSON.stringify(data, null, 2);
|
||||
|
||||
// Retrieve the filename of the model.
|
||||
const filename = fs
|
||||
.readdirSync(
|
||||
plugin
|
||||
? path.join(strapi.config.appPath, 'plugins', target, 'models')
|
||||
: path.join(strapi.config.appPath, 'api', target, 'models'),
|
||||
)
|
||||
.filter(x => x[0] !== '.')
|
||||
.filter(x => x.split('.settings.json')[0].toLowerCase() === model.toLowerCase())[0];
|
||||
|
||||
return plugin
|
||||
? path.resolve(strapi.config.appPath, 'plugins', target, 'models', filename)
|
||||
: path.resolve(strapi.config.appPath, 'api', target, 'models', filename);
|
||||
strapi.fs.ensureFileSync(filepath);
|
||||
return strapi.fs.writeFileSync(filepath, content);
|
||||
},
|
||||
|
||||
formatAttributes: (attributes, name, plugin) => {
|
||||
readModel(name, { api, plugin } = {}) {
|
||||
const filepath = this.getModelPath(name, { api, plugin });
|
||||
|
||||
if (plugin && !strapi.fs.pathExistsSync(filepath)) {
|
||||
return _.cloneDeep(
|
||||
_.pick(strapi.plugins[plugin].models[name], [
|
||||
'collectionName',
|
||||
'connection',
|
||||
'info',
|
||||
'options',
|
||||
'attributes',
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
delete require.cache[filepath];
|
||||
return _.cloneDeep(require(filepath));
|
||||
},
|
||||
|
||||
getModelPath(name, { api, plugin } = {}) {
|
||||
const fileName = `${_.upperFirst(name)}.settings.json`;
|
||||
|
||||
if (plugin) {
|
||||
return path.resolve(
|
||||
strapi.config.appPath,
|
||||
'extensions',
|
||||
plugin,
|
||||
'models',
|
||||
fileName
|
||||
);
|
||||
} else if (api) {
|
||||
return path.resolve(
|
||||
strapi.config.appPath,
|
||||
'api',
|
||||
api,
|
||||
'models',
|
||||
fileName
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error('Expected an api or a plugin, received none');
|
||||
},
|
||||
|
||||
formatAttributes(attributes, name, plugin) {
|
||||
const errors = [];
|
||||
const attrs = {};
|
||||
|
||||
@ -302,6 +333,7 @@ module.exports = {
|
||||
const attributesConfigurable = attributes.filter(
|
||||
attribute => _.get(model, ['attributes', attribute.name, 'configurable'], true) !== false,
|
||||
);
|
||||
|
||||
const attributesNotConfigurable = Object.keys(model.attributes || {})
|
||||
.filter(attribute => _.get(model, ['attributes', attribute, 'configurable'], true) === false)
|
||||
.reduce((acc, attribute) => {
|
||||
@ -379,74 +411,40 @@ module.exports = {
|
||||
return [trimmedNotConfigurableAttributes, errors];
|
||||
},
|
||||
|
||||
clearRelations: (model, source, force) => {
|
||||
clearRelations(model, source, force) {
|
||||
const errors = [];
|
||||
const structure = {
|
||||
models: strapi.models,
|
||||
plugins: Object.keys(strapi.plugins).reduce((acc, current) => {
|
||||
acc[current] = {
|
||||
models: strapi.plugins[current].models,
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
// Method to delete the association of the models.
|
||||
const deleteAssociations = (models, plugin) => {
|
||||
Object.keys(models).forEach(name => {
|
||||
const relationsToDelete = _.get(
|
||||
plugin ? strapi.plugins[plugin].models[name] : strapi.models[name],
|
||||
'associations',
|
||||
[],
|
||||
).filter(association => {
|
||||
if (source) {
|
||||
return (
|
||||
association[association.type] === model &&
|
||||
association.plugin === source &&
|
||||
(association.nature !== 'oneWay' || force)
|
||||
);
|
||||
}
|
||||
const modelData = models[name];
|
||||
const relationsToDelete = _.get(modelData, 'associations',[])
|
||||
.filter(association => {
|
||||
if (source) {
|
||||
return (
|
||||
association[association.type] === model &&
|
||||
association.plugin === source &&
|
||||
(association.nature !== 'oneWay' || force)
|
||||
);
|
||||
}
|
||||
|
||||
return association[association.type] === model && (association.nature !== 'oneWay' || force);
|
||||
});
|
||||
return association[association.type] === model && (association.nature !== 'oneWay' || force);
|
||||
});
|
||||
|
||||
if (!_.isEmpty(relationsToDelete)) {
|
||||
// Retrieve where is located the model.
|
||||
const target = Object.keys((plugin ? strapi.plugins : strapi.api) || {}).filter(x =>
|
||||
_.includes(Object.keys(_.get((plugin ? strapi.plugins : strapi.api)[x], 'models', [])), name),
|
||||
)[0];
|
||||
|
||||
// Retrieve the filename of the model.
|
||||
const filename = fs
|
||||
.readdirSync(
|
||||
plugin
|
||||
? path.join(strapi.config.appPath, 'plugins', target, 'models')
|
||||
: path.join(strapi.config.appPath, 'api', target, 'models'),
|
||||
)
|
||||
.filter(x => x[0] !== '.')
|
||||
.filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0];
|
||||
|
||||
// Path to access to the model.
|
||||
const pathToModel = plugin
|
||||
? path.resolve(strapi.config.appPath, 'plugins', target, 'models', filename)
|
||||
: path.resolve(strapi.config.appPath, 'api', target, 'models', filename);
|
||||
|
||||
// Require the model.
|
||||
const modelJSON = require(pathToModel);
|
||||
const modelJSON = this.readModel(name, { plugin, api: modelData.apiName });
|
||||
|
||||
_.forEach(relationsToDelete, relation => {
|
||||
modelJSON.attributes[relation.alias] = undefined;
|
||||
});
|
||||
|
||||
try {
|
||||
fs.writeFileSync(pathToModel, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||
// fs.writeFileSync(pathToModel, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||
this.writeModel(name, modelJSON, { api: modelData.apiName, plugin});
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
errors.push({
|
||||
id: 'request.error.model.write',
|
||||
params: {
|
||||
filePath: pathToModel,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -454,17 +452,17 @@ module.exports = {
|
||||
};
|
||||
|
||||
// Update `./api` models.
|
||||
deleteAssociations(structure.models);
|
||||
deleteAssociations(strapi.models);
|
||||
|
||||
Object.keys(structure.plugins).forEach(name => {
|
||||
Object.keys(strapi.plugins).forEach(name => {
|
||||
// Update `./plugins/${name}` models.
|
||||
deleteAssociations(structure.plugins[name].models, name);
|
||||
deleteAssociations(strapi.plugins[name].models, name);
|
||||
});
|
||||
|
||||
return errors;
|
||||
},
|
||||
|
||||
createRelations: (model, attributes, source) => {
|
||||
createRelations(model, attributes, source) {
|
||||
const errors = [];
|
||||
const structure = {
|
||||
models: strapi.models,
|
||||
@ -480,6 +478,7 @@ module.exports = {
|
||||
// Method to update the model
|
||||
const update = (models, plugin) => {
|
||||
Object.keys(models).forEach(name => {
|
||||
const modelData = models[name];
|
||||
const relationsToCreate = attributes.filter(attribute => {
|
||||
if (plugin) {
|
||||
return (
|
||||
@ -494,27 +493,7 @@ module.exports = {
|
||||
});
|
||||
|
||||
if (!_.isEmpty(relationsToCreate)) {
|
||||
// Retrieve where is located the model.
|
||||
const target = Object.keys((plugin ? strapi.plugins : strapi.api) || {}).filter(x =>
|
||||
_.includes(Object.keys(_.get((plugin ? strapi.plugins : strapi.api)[x], 'models', [])), name),
|
||||
)[0];
|
||||
|
||||
// Retrieve the filename of the model.
|
||||
const filename = fs
|
||||
.readdirSync(
|
||||
plugin
|
||||
? path.join(strapi.config.appPath, 'plugins', target, 'models')
|
||||
: path.join(strapi.config.appPath, 'api', target, 'models'),
|
||||
)
|
||||
.filter(x => x[0] !== '.')
|
||||
.filter(x => x.split('.settings.json')[0].toLowerCase() === name)[0];
|
||||
|
||||
// Path to access to the model.
|
||||
const pathToModel = plugin
|
||||
? path.resolve(strapi.config.appPath, 'plugins', target, 'models', filename)
|
||||
: path.resolve(strapi.config.appPath, 'api', target, 'models', filename);
|
||||
|
||||
const modelJSON = require(pathToModel);
|
||||
const modelJSON = this.readModel(name, { api: modelData.apiName, plugin});
|
||||
|
||||
_.forEach(relationsToCreate, ({ name, params }) => {
|
||||
const attr = {};
|
||||
@ -548,18 +527,17 @@ module.exports = {
|
||||
}
|
||||
|
||||
modelJSON.attributes[params.key] = attr;
|
||||
|
||||
try {
|
||||
fs.writeFileSync(pathToModel, JSON.stringify(modelJSON, null, 2), 'utf8');
|
||||
} catch (e) {
|
||||
errors.push({
|
||||
id: 'request.error.model.write',
|
||||
params: {
|
||||
filePath: pathToModel,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
try {
|
||||
this.writeModel(name, modelJSON, { api: modelData.apiName, plugin});
|
||||
} catch (e) {
|
||||
strapi.log.error(e);
|
||||
errors.push({
|
||||
id: 'request.error.model.write',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -576,10 +554,11 @@ module.exports = {
|
||||
},
|
||||
|
||||
removeModel: model => {
|
||||
model = _.toLower(model);
|
||||
const modelName = _.toLower(model);
|
||||
const apiName = strapi.models[modelName].apiName;
|
||||
const apiPath = path.join(strapi.config.appPath, 'api', apiName);
|
||||
|
||||
const errors = [];
|
||||
const apiPath = path.join(strapi.config.appPath, 'api');
|
||||
|
||||
const deleteModelFile = (parentPath, fileName) => {
|
||||
const filePath = path.join(parentPath, fileName);
|
||||
|
||||
@ -61,9 +61,9 @@ const reorderList = (manager, list) => {
|
||||
return List(flattenDeep(reordered));
|
||||
};
|
||||
|
||||
const escapeNewlines = (content, placeholder = '\n') => {
|
||||
const escapeNewlines = (content = '', placeholder = '\n') => {
|
||||
return content.replace(/[\r\n]+/g, placeholder);
|
||||
}
|
||||
};
|
||||
|
||||
const deepTrimObject = attribute => {
|
||||
if (Array.isArray(attribute)) {
|
||||
|
||||
@ -286,7 +286,7 @@ const schemaBuilder = {
|
||||
*/
|
||||
|
||||
writeGenerateSchema: schema => {
|
||||
return strapi.fs.writeFile('exports/graphql/schema.graphql', schema);
|
||||
return strapi.fs.writeAppFile('exports/graphql/schema.graphql', schema);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// Dependencies.
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const cluster = require('cluster');
|
||||
const { EventEmitter } = require('events');
|
||||
const Koa = require('koa');
|
||||
@ -36,7 +35,7 @@ const defaultQueries = require('./core-api/queries');
|
||||
*/
|
||||
|
||||
class Strapi extends EventEmitter {
|
||||
constructor({ appPath }) {
|
||||
constructor({ appPath } = {}) {
|
||||
super();
|
||||
|
||||
this.setMaxListeners(100);
|
||||
|
||||
1
packages/strapi/lib/core/bootstrap.js
vendored
1
packages/strapi/lib/core/bootstrap.js
vendored
@ -47,6 +47,7 @@ module.exports = function(strapi) {
|
||||
let model = strapi.api[key].models[index];
|
||||
|
||||
Object.assign(model, {
|
||||
apiName: key,
|
||||
globalId: model.globalId || _.upperFirst(_.camelCase(index)),
|
||||
collectionName: model.collectionName || `${index}`.toLocaleLowerCase(),
|
||||
connection: model.connection || defaultConnection,
|
||||
|
||||
@ -10,7 +10,7 @@ module.exports = strapi => {
|
||||
* @param {Array|string} optPath - file path
|
||||
* @param {string} data - content
|
||||
*/
|
||||
const writeFile = (optPath, data) => {
|
||||
const writeAppFile = (optPath, data) => {
|
||||
const filePath = Array.isArray(optPath) ? optPath.join('/') : optPath;
|
||||
|
||||
const normalizedPath = path.normalize(filePath).replace(/^(\/?\.\.?)+/, '');
|
||||
@ -28,11 +28,11 @@ module.exports = strapi => {
|
||||
*/
|
||||
const writePluginFile = (plugin, optPath, data) => {
|
||||
const newPath = ['extensions', plugin].concat(optPath).join('/');
|
||||
return writeFile(newPath, data);
|
||||
return writeAppFile(newPath, data);
|
||||
};
|
||||
|
||||
return {
|
||||
writeFile,
|
||||
return Object.assign(fs, {
|
||||
writeAppFile,
|
||||
writePluginFile,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@ -5,8 +5,6 @@ const loadConfig = require('../load/load-config-files');
|
||||
const glob = require('../load/glob');
|
||||
const filePathToPath = require('../load/filepath-to-prop-path');
|
||||
|
||||
const overwritableFoldersGlob = 'models';
|
||||
|
||||
module.exports = async function({ appPath }) {
|
||||
const extensionsDir = path.resolve(appPath, 'extensions');
|
||||
|
||||
@ -19,14 +17,20 @@ module.exports = async function({ appPath }) {
|
||||
};
|
||||
};
|
||||
|
||||
const OVERWRITABLE_FOLDERS_GLOB = 'models';
|
||||
// returns a list of path and module to overwrite
|
||||
const loadOverwrites = async extensionsDir => {
|
||||
const files = await glob(`*/${overwritableFoldersGlob}/*.*(js|json)`, {
|
||||
const files = await glob(`*/${OVERWRITABLE_FOLDERS_GLOB}/*.*(js|json)`, {
|
||||
cwd: extensionsDir,
|
||||
});
|
||||
|
||||
return files.map(file => {
|
||||
const mod = require(path.resolve(extensionsDir, file));
|
||||
const absolutePath = path.resolve(extensionsDir, file);
|
||||
|
||||
// load module
|
||||
delete require.cache[absolutePath];
|
||||
const mod = require(absolutePath);
|
||||
|
||||
const propPath = filePathToPath(file);
|
||||
|
||||
return {
|
||||
|
||||
@ -16,9 +16,12 @@ module.exports = async (
|
||||
const files = await glob(pattern, { cwd: dir, ...globArgs });
|
||||
|
||||
for (let file of files) {
|
||||
// TODO: need to figure out the need for clearing the cache
|
||||
delete require.cache[path.resolve(dir, file)];
|
||||
const mod = requireFn(path.resolve(dir, file));
|
||||
const absolutePath = path.resolve(dir, file);
|
||||
|
||||
// load module
|
||||
delete require.cache[absolutePath];
|
||||
const mod = requireFn(absolutePath);
|
||||
|
||||
const propPath = filePathToPath(file, shouldUseFileNameAsKey(file));
|
||||
|
||||
if (propPath.length === 0) _.merge(root, mod);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user