Init schema manager

This commit is contained in:
Alexandre Bodin 2019-11-18 17:00:18 +01:00
parent 605fcdd530
commit 6b9ca4f794
3 changed files with 227 additions and 10 deletions

View File

@ -1,12 +1,14 @@
'use strict';
const path = require('path');
const _ = require('lodash');
const {
validateComponentInput,
validateUpdateComponentInput,
} = require('./validation/component');
const _ = require('lodash');
const componentService = require('../services/Components');
const createSchemaManager = require('../services/schema-manager');
/**
* Components controller
@ -63,16 +65,50 @@ module.exports = {
return ctx.send({ error: 'component.alreadyExists' }, 400);
}
strapi.reload.isWatching = false;
const manager = createSchemaManager({
components: Object.keys(strapi.components).map(key => {
const compo = strapi.components[key];
const newComponent = await componentService.createComponent({
uid,
infos: body.component,
return {
uid: compo.uid,
filename: compo.__filename__,
dir: path.join(strapi.dir, 'components'),
schema: compo.__schema__,
};
}),
contentTypes: Object.keys(strapi.contentTypes).map(key => {
const contentType = strapi.contentTypes[key];
let dir;
if (contentType.plugin) {
dir = `./extensions/${contentType.plugin}/models`;
} else {
dir = `./api/${contentType.apiName}/models`;
}
return {
uid: contentType.uid,
filename: contentType.__filename__,
dir: path.join(strapi.dir, dir),
schema: contentType.__schema__,
};
}),
});
strapi.reload();
await manager.edit(ctx => {
ctx.createComponent(uid, body.component);
});
ctx.send({ data: newComponent }, 201);
// strapi.reload.isWatching = false;
// const newComponent = await componentService.createComponent({
// uid,
// infos: body.component,
// });
// strapi.reload();
ctx.send({ data: uid }, 201);
},
/**

View File

@ -59,11 +59,11 @@ module.exports = {
strapi.reload.isWatching = false;
try {
const contentType = contentTypeService.createContentTypeSchema(
const contentTypeSchema = contentTypeService.createContentTypeSchema(
body.contentType
);
await contentTypeService.generateAPI(modelName, contentType);
await contentTypeService.generateAPI(modelName, contentTypeSchema);
await contentTypeService.generateReversedRelations({
attributes: body.contentType.attributes,

View File

@ -0,0 +1,181 @@
'use strict';
const path = require('path');
const fse = require('fs-extra');
const _ = require('lodash');
const pluralize = require('pluralize');
const { convertAttributes } = require('../../utils/attributes');
const { nameToSlug, nameToCollectionName } = require('../../utils/helpers');
const createSchema = infos => {
const uid = infos.uid;
const dir = infos.dir;
const filename = infos.filename;
// always keep it the same to rollback
let initialSchema = Object.freeze(infos.schema);
let schema = _.cloneDeep(infos.schema);
let modified = false;
return {
get schema() {
return _.cloneDeep(schema);
},
set schema(val) {
modified = true;
schema = val;
},
get(path) {
return _.get(schema, path);
},
set(path, val) {
modified = true;
_.set(schema, path, val);
return this;
},
unset(path) {
modified = true;
_.unset(schema, path);
return this;
},
flush() {
if (modified === true) {
return fse.writeJSON(path.join(dir, filename), schema, { spaces: 2 });
}
return Promise.resolve();
},
rollback() {
// it is a creating
if (!uid) {
return fse.remove(path.join(dir, filename));
}
if (modified === true) {
return fse.writeJSON(path.join(dir, filename), initialSchema, {
spaces: 2,
});
}
return Promise.resolve();
},
};
};
const createTransaction = ({ components, contentTypes }) => {
const tmpComponents = new Map();
const tmpContentTypes = new Map();
// init temporary ContentTypes:
Object.keys(contentTypes).forEach(key => {
tmpContentTypes.set(key, createSchema(contentTypes[key]));
});
// init temporary components:
Object.keys(components).forEach(key => {
tmpComponents.set(key, createSchema(components[key]));
});
const ctx = {
get components() {
return Array.from(tmpComponents.values());
},
get contentTypes() {
return Array.from(tmpComponents.values());
},
get allSchemas() {
return [...this.components, ...this.contentTypes];
},
/**
* create a component in the tmpComponent map
*/
createComponent(uid, infos) {
const {
name,
icon,
category,
connection = _.get(
strapi,
['config', 'currentEnvironment', 'database', 'defaultConnection'],
'default'
),
description = '',
collectionName,
attributes,
} = infos;
const componentSchema = {
info: {
name,
description,
icon,
},
connection,
collectionName:
collectionName ||
`components_${nameToCollectionName(category)}_${nameToCollectionName(
pluralize(name)
)}`,
attributes: convertAttributes(attributes),
};
const schema = createSchema({
dir: path.join(strapi.dir, 'components', nameToSlug(category)),
filename: `${nameToSlug(name)}.json`,
scehma: componentSchema,
});
tmpComponents.set(uid, schema);
},
flush() {
const flushOps = this.allSchemas.map(schema => {
return schema.flush();
});
return Promise.all(flushOps);
},
rollback() {
const rollbackOps = this.allSchemas.map(schema => {
return schema.rollback();
});
return Promise.all(rollbackOps);
},
};
return ctx;
};
module.exports = function createSchemasManager({ components, contentTypes }) {
return {
async edit(editorFn) {
const trx = createTransaction({
components,
contentTypes,
});
try {
await editorFn(trx);
await trx.flush();
} catch (error) {
await trx.rollback();
throw error;
}
},
};
};