Save plugins models in extensions folder

This commit is contained in:
Alexandre Bodin 2019-04-12 18:50:25 +02:00
parent 87857b94be
commit 710e3ab52f
19 changed files with 200 additions and 249 deletions

View File

@ -49,4 +49,4 @@
}
}
]
}
}

View File

@ -0,0 +1,7 @@
'use strict';
/**
* Read the documentation () to implement custom controller functions
*/
module.exports = {};

View File

@ -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) => {}
};

View File

@ -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"
}
}
}
}

View File

@ -0,0 +1,7 @@
'use strict';
/**
* Read the documentation () to implement custom service functions
*/
module.exports = {};

View File

@ -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"]}

View File

@ -1,3 +1,3 @@
{
"jwtSecret": "1481145e-8625-4032-a4f0-75de2a3f10c9"
"jwtSecret": "bb26b371-8957-434c-a313-f35dd6b1813c"
}

View File

@ -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"
}

View File

@ -8,7 +8,7 @@
"type": {
"type": "string",
"required": true,
"configurable": false
"configurable": true
}
}
}

View File

@ -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();
}
});
};

View File

@ -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' }] }]);
}
},

View File

@ -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);

View File

@ -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)) {

View File

@ -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);
}
};

View File

@ -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);

View File

@ -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,

View File

@ -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,
};
});
};

View File

@ -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 {

View File

@ -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);