From ca10e972e2b3de910e3d7adfbd8b3cc5e8ba51c5 Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Tue, 19 Nov 2019 15:45:28 +0100 Subject: [PATCH] Handle directory change --- .../services/Components.js | 49 +----- .../schema-manager/component-builder.js | 27 +++- .../services/schema-manager/index.js | 7 +- .../services/schema-manager/schema-handler.js | 143 +++++++++++++----- 4 files changed, 134 insertions(+), 92 deletions(-) diff --git a/packages/strapi-plugin-content-type-builder/services/Components.js b/packages/strapi-plugin-content-type-builder/services/Components.js index 559c7dcb2e..10ff9d7e89 100644 --- a/packages/strapi-plugin-content-type-builder/services/Components.js +++ b/packages/strapi-plugin-content-type-builder/services/Components.js @@ -32,51 +32,6 @@ const formatComponent = component => { }; }; -// /** -// * Updates a component schema file -// * @param {Object} component -// * @param {Object} infos -// */ -// async function updateComponent({ component, infos }) { -// const { uid, __schema__: oldSchema } = component; - -// // don't update collectionName if not provided -// const updatedSchema = { -// ...oldSchema, -// connection: infos.connection || oldSchema.connection, -// collectionName: infos.collectionName || oldSchema.collectionName, -// info: { -// name: infos.name || oldSchema.info.name, -// icon: infos.icon || oldSchema.info.icon, -// description: infos.description || oldSchema.info.description, -// }, -// attributes: convertAttributes(infos.attributes), -// }; - -// await editSchema({ uid, schema: updatedSchema }); - -// if (component.category !== infos.category) { -// const oldDir = path.join(strapi.dir, 'components', component.category); -// const newDir = path.join(strapi.dir, 'components', infos.category); - -// await fse.move( -// path.join(oldDir, component.__filename__), -// path.join(newDir, component.__filename__) -// ); - -// const list = await fse.readdir(oldDir); -// if (list.length === 0) { -// await fse.remove(oldDir); -// } - -// return { -// uid: `${infos.category}.${component.modelName}`, -// }; -// } - -// return { uid }; -// } - /** * Returns a uid from a string * @param {string} str - string to slugify @@ -183,7 +138,7 @@ const updateComponentInModels = (oldUID, newUID) => { * @param {Object} params.component Main component to create * @param {Array} params.components List of nested components to created or edit */ -const createComponent = ({ component, components }) => { +const createComponent = ({ component, components = [] }) => { const componentsToCreate = components.filter(compo => !_.has(compo, 'uid')); const componentsToEdit = components.filter(compo => _.has(compo, 'uid')); @@ -203,7 +158,7 @@ const createComponent = ({ component, components }) => { * @param {Object} params.component Main component to create * @param {Array} params.components List of nested components to created or edit */ -const editComponent = (uid, { component, components }) => { +const editComponent = (uid, { component, components = [] }) => { const componentsToCreate = components.filter(compo => !_.has(compo, 'uid')); const componentsToEdit = components.filter(compo => _.has(compo, 'uid')); diff --git a/packages/strapi-plugin-content-type-builder/services/schema-manager/component-builder.js b/packages/strapi-plugin-content-type-builder/services/schema-manager/component-builder.js index 00a5a5ad52..c63bb9ba14 100644 --- a/packages/strapi-plugin-content-type-builder/services/schema-manager/component-builder.js +++ b/packages/strapi-plugin-content-type-builder/services/schema-manager/component-builder.js @@ -42,8 +42,8 @@ module.exports = function createComponentBuilder({ tmpComponents }) { infos.category )}_${nameToCollectionName(pluralize(infos.name))}`; - handler.uid = uid; handler + .setUID(uid) .set('connection', infos.connection || defaultConnection) .set('collectionName', infos.collectionName || defaultCollectionName) .set(['info', 'name'], infos.name) @@ -52,6 +52,7 @@ module.exports = function createComponentBuilder({ tmpComponents }) { .set('attributes', convertAttributes(infos.attributes)); tmpComponents.set(uid, handler); + return handler; }, @@ -67,9 +68,20 @@ module.exports = function createComponentBuilder({ tmpComponents }) { const handler = tmpComponents.get(uid); - // TODO: handle category change to move the file + const [, nameUID] = uid.split('.'); + + const newCategory = nameToSlug(infos.category); + const newUID = `${newCategory}.${nameUID}`; + + if (newUID !== uid && tmpComponents.has(newUID)) { + throw new Error('component.edit.alreadyExists'); + } + + const newDir = path.join(strapi.dir, 'components', newCategory); handler + .setUID(newUID) + .setDir(newDir) .set('connection', infos.connection) .set('collectionName', infos.collectionName) .set(['info', 'name'], infos.name) @@ -77,8 +89,15 @@ module.exports = function createComponentBuilder({ tmpComponents }) { .set(['info', 'description'], infos.description) .set('attributes', convertAttributes(infos.attributes)); - // TODO: update relations if uid changed - // TODO: update relations if uid changed + if (newUID !== uid) { + this.components.forEach(compo => { + compo.updateComponent(uid, newUID); + }); + + this.contentTypes.forEach(ct => { + ct.updateComponent(uid, newUID); + }); + } return handler; }, diff --git a/packages/strapi-plugin-content-type-builder/services/schema-manager/index.js b/packages/strapi-plugin-content-type-builder/services/schema-manager/index.js index c5cc5b02db..dfb185352d 100644 --- a/packages/strapi-plugin-content-type-builder/services/schema-manager/index.js +++ b/packages/strapi-plugin-content-type-builder/services/schema-manager/index.js @@ -59,14 +59,15 @@ function createSchemaManager() { await builder .flush() .catch(error => { - strapi.log.error('Error writing schema files', error); + strapi.log.error('Error writing schema files'); + strapi.log.error(error); return builder.rollback(); }) .catch(error => { strapi.log.error( - 'Error rolling back schema files. You might need to fix your files manually', - error + 'Error rolling back schema files. You might need to fix your files manually' ); + strapi.log.error(error); throw new Error('Invalid schema edition'); }); diff --git a/packages/strapi-plugin-content-type-builder/services/schema-manager/schema-handler.js b/packages/strapi-plugin-content-type-builder/services/schema-manager/schema-handler.js index 6265044dc1..9482d34ada 100644 --- a/packages/strapi-plugin-content-type-builder/services/schema-manager/schema-handler.js +++ b/packages/strapi-plugin-content-type-builder/services/schema-manager/schema-handler.js @@ -5,48 +5,61 @@ const fse = require('fs-extra'); const _ = require('lodash'); module.exports = function createSchemaHandler(infos) { - const uid = infos.uid; - const dir = infos.dir; - const filename = infos.filename; + const initialState = { + uid: infos.uid, + dir: infos.dir, + filename: infos.filename, + schema: infos.schema || {}, + }; + + const state = _.cloneDeep(initialState); // always keep it the same to rollback - let initialSchema = Object.freeze(infos.schema); - let schema = _.cloneDeep(infos.schema) || {}; + Object.freeze(initialState.schema); let modified = false; let deleted = false; return { - uid, - dir, - filename, - - // Flag schema for deletion - delete() { - deleted = true; + get uid() { + return state.uid; }, - // get a copy of the full schema - get schema() { - return _.cloneDeep(schema); - }, - - // set a new schema object - set schema(val) { + setUID(val) { modified = true; - schema = _.cloneDeep(val); + + state.uid = val; + return this; + }, + + setDir(val) { + modified = true; + + state.dir = val; + return this; + }, + + get schema() { + return _.cloneDeep(state.schema); + }, + + setSchema(val) { + modified = true; + + state.schema = _.cloneDeep(val); + return this; }, // get a particuar path inside the schema get(path) { - return _.get(schema, path); + return _.get(state.schema, path); }, // set a particuar path inside the schema set(path, val) { modified = true; - _.set(schema, path, val || _.get(schema, path)); + _.set(state.schema, path, val || _.get(state.schema, path)); return this; }, @@ -55,15 +68,22 @@ module.exports = function createSchemaHandler(infos) { unset(path) { modified = true; - _.unset(schema, path); + _.unset(state.schema, path); return this; }, + delete() { + deleted = true; + return this; + }, + // utils removeComponent(uid) { - Object.keys(schema.attributes).forEach(key => { - const attr = schema.attributes[key]; + const { attributes } = state.schema; + + Object.keys(attributes).forEach(key => { + const attr = attributes[key]; if (attr.type === 'component' && attr.component === uid) { this.unset(['attributes', key]); @@ -74,7 +94,7 @@ module.exports = function createSchemaHandler(infos) { Array.isArray(attr.components) && attr.components.includes(uid) ) { - const updatedComponentList = schema.attributes[key].components.filter( + const updatedComponentList = attributes[key].components.filter( val => val !== uid ); this.set(['attributes', key, 'components'], updatedComponentList); @@ -84,22 +104,58 @@ module.exports = function createSchemaHandler(infos) { return this; }, + updateComponent(uid, newUID) { + const { attributes } = state.schema; + + Object.keys(attributes).forEach(key => { + const attr = attributes[key]; + + if (attr.type === 'component' && attr.component === uid) { + this.set(['attributes', key, 'component'], newUID); + } + + if ( + attr.type === 'dynamiczone' && + Array.isArray(attr.components) && + attr.components.includes(uid) + ) { + const updatedComponentList = attributes[key].components.map(val => + val === uid ? newUID : uid + ); + + this.set(['attributes', key, 'components'], updatedComponentList); + } + }); + + return this; + }, + // save the schema to disk async flush() { - const filePath = path.join(dir, filename); + const initialPath = path.join(initialState.dir, initialState.filename); + const filePath = path.join(state.dir, state.filename); if (deleted === true) { - await fse.remove(filePath); + await fse.remove(initialPath); - const list = await fse.readdir(dir); + const list = await fse.readdir(initialState.dir); if (list.length === 0) { - await fse.remove(dir); + await fse.remove(initialState.dir); } } - if (modified === true) { await fse.ensureFile(filePath); - return fse.writeJSON(filePath, schema, { spaces: 2 }); + await fse.writeJSON(filePath, state.schema, { spaces: 2 }); + + // remove from oldPath + if (initialPath !== filePath) { + await fse.remove(initialPath); + + const list = await fse.readdir(initialState.dir); + if (list.length === 0) { + await fse.remove(initialState.dir); + } + } } return Promise.resolve(); @@ -107,22 +163,33 @@ module.exports = function createSchemaHandler(infos) { // reset the schema to its initial value async rollback() { - const filePath = path.join(dir, filename); + const initialPath = path.join(initialState.dir, initialState.filename); + const filePath = path.join(state.dir, state.filename); // it was a creation so it needs to be deleted - if (!uid) { + if (!initialState.uid) { await fse.remove(filePath); - const list = await fse.readdir(dir); + const list = await fse.readdir(state.dir); if (list.length === 0) { - await fse.remove(dir); + await fse.remove(state.dir); } return; } if (modified === true || deleted === true) { - await fse.ensureFile(filePath); - return fse.writeJSON(filePath, initialSchema, { spaces: 2 }); + await fse.ensureFile(initialPath); + await fse.writeJSON(initialPath, initialState.schema, { spaces: 2 }); + + // remove + if (initialPath !== filePath) { + await fse.remove(filePath); + + const list = await fse.readdir(state.dir); + if (list.length === 0) { + await fse.remove(state.dir); + } + } } return Promise.resolve();