Merge pull request #93 from PhilippPaoli/master

Feat: Import/export for types with populated components
pull/104/head
Boaz Poolman 2023-10-14 13:11:52 +02:00 committed by GitHub
commit 4581bf1751
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 19 deletions

View File

@ -354,6 +354,21 @@ This property can accept an array of field names from the type. It is meant to s
> `required:` NO | `type:` array > `required:` NO | `type:` array
#### Components
This property can accept an array of component names from the type. Strapi Components can be included in the export/import process. With "." nested components can also be included in the process.
```
customTypes: [{
configName: 'webhook',
queryString: 'webhook',
uid: 'name',
components: ['ParentComponentA', 'ParentComponentA.ChildComponent', 'ParentComponentB']
}],
###### Key: `components`
> `required:` NO | `type:` array
## 🔍 Naming convention ## 🔍 Naming convention
All the config files written in the sync directory have the same naming convention. It goes as follows: All the config files written in the sync directory have the same naming convention. It goes as follows:

View File

@ -3,4 +3,5 @@ PORT=1337
APP_KEYS=SIwLyqu+IpSHIuUBDQfPZg==,Nzqbq2C3ATsR19u5XEAJQA==,/Agk5Sn8M4EzfoSiIHcDlQ==,gSxT2T0k2zbQatKXUV0zCA== APP_KEYS=SIwLyqu+IpSHIuUBDQfPZg==,Nzqbq2C3ATsR19u5XEAJQA==,/Agk5Sn8M4EzfoSiIHcDlQ==,gSxT2T0k2zbQatKXUV0zCA==
API_TOKEN_SALT=reQcUBbGXD2KWG2QpRn7DA== API_TOKEN_SALT=reQcUBbGXD2KWG2QpRn7DA==
ADMIN_JWT_SECRET= 69mzgwRGfEBUhPEaas8EBA== ADMIN_JWT_SECRET= 69mzgwRGfEBUhPEaas8EBA==
TRANSFER_TOKEN_SALT=/LTsSGpC5afHICjZu0oEuQ==
JWT_SECRET=E0TTVdsr+M/FXAjfrNIgXA== JWT_SECRET=E0TTVdsr+M/FXAjfrNIgXA==

View File

@ -5,4 +5,12 @@ module.exports = ({ env }) => ({
watchIgnoreFiles: [ watchIgnoreFiles: [
'**/config/sync/**', '**/config/sync/**',
], ],
apiToken: {
salt: env('API_TOKEN_SALT'),
},
transfer: {
token: {
salt: env('TRANSFER_TOKEN_SALT'),
},
},
}); });

View File

@ -3,7 +3,7 @@ const { logMessage, sanitizeConfig, dynamicSort, noLimit, getCombinedUid, getCom
const { difference, same } = require('../utils/getArrayDiff'); const { difference, same } = require('../utils/getArrayDiff');
const ConfigType = class ConfigType { const ConfigType = class ConfigType {
constructor({ queryString, configName, uid, jsonFields, relations }) { constructor({ queryString, configName, uid, jsonFields, relations, components }) {
if (!configName) { if (!configName) {
strapi.log.error(logMessage('A config type was registered without a config name.')); strapi.log.error(logMessage('A config type was registered without a config name.'));
process.exit(0); process.exit(0);
@ -25,6 +25,7 @@ const ConfigType = class ConfigType {
this.configPrefix = configName; this.configPrefix = configName;
this.jsonFields = jsonFields || []; this.jsonFields = jsonFields || [];
this.relations = relations || []; this.relations = relations || [];
this.components = components || null;
} }
/** /**
@ -68,15 +69,11 @@ const ConfigType = class ConfigType {
}); });
await Promise.all(relations.map(async (relation) => { await Promise.all(relations.map(async (relation) => {
await strapi.query(queryString).delete({ await strapi.entityService.delete(queryString, relation.id);
where: { id: relation.id },
});
})); }));
})); }));
await queryAPI.delete({ await strapi.entityService.delete(this.queryString, existingConfig.id);
where: { id: existingConfig.id },
});
return; return;
} }
@ -89,15 +86,17 @@ const ConfigType = class ConfigType {
// Create entity. // Create entity.
this.relations.map(({ relationName }) => delete query[relationName]); this.relations.map(({ relationName }) => delete query[relationName]);
const newEntity = await queryAPI.create({ data: query }); const newEntity = await strapi.entityService.create(this.queryString, {
data: query,
});
// Create relation entities. // Create relation entities.
await Promise.all(this.relations.map(async ({ queryString, relationName, parentName }) => { await Promise.all(this.relations.map(async ({ queryString, relationName, parentName }) => {
const relationQueryApi = strapi.query(queryString);
await Promise.all(configContent[relationName].map(async (relationEntity) => { await Promise.all(configContent[relationName].map(async (relationEntity) => {
const relationQuery = { ...relationEntity, [parentName]: newEntity }; const relationQuery = { ...relationEntity, [parentName]: newEntity };
await relationQueryApi.create({ data: relationQuery }); await strapi.entityService.create(queryString, {
data: relationQuery,
});
})); }));
})); }));
} else { // Config does exist in DB --> update config in DB } else { // Config does exist in DB --> update config in DB
@ -111,7 +110,16 @@ const ConfigType = class ConfigType {
// Update entity. // Update entity.
this.relations.map(({ relationName }) => delete query[relationName]); this.relations.map(({ relationName }) => delete query[relationName]);
const entity = await queryAPI.update({ where: combinedUidWhereFilter, data: query });
const entity = await queryAPI.findOne({ where: combinedUidWhereFilter });
try {
await strapi.entityService.update(this.queryString, entity.id, {
data: query,
});
} catch (error) {
console.warn(logMessage(`Use Query Engine API instead of Entity Service API for type ${this.configPrefix}`));
await queryAPI.update({ where: combinedUidWhereFilter, data: query });
}
// Delete/create relations. // Delete/create relations.
await Promise.all(this.relations.map(async ({ queryString, relationName, parentName, relationSortFields }) => { await Promise.all(this.relations.map(async ({ queryString, relationName, parentName, relationSortFields }) => {
@ -137,7 +145,7 @@ const ConfigType = class ConfigType {
})); }));
await Promise.all(configToAdd.map(async (config) => { await Promise.all(configToAdd.map(async (config) => {
await relationQueryApi.create({ await strapi.entityService.create(queryString, {
data: { ...config, [parentName]: entity.id }, data: { ...config, [parentName]: entity.id },
}); });
})); }));
@ -192,7 +200,9 @@ const ConfigType = class ConfigType {
* @returns {object} Object with key value pairs of configs. * @returns {object} Object with key value pairs of configs.
*/ */
getAllFromDatabase = async () => { getAllFromDatabase = async () => {
const AllConfig = await noLimit(strapi.query(this.queryString), {}); const AllConfig = await noLimit(strapi.query(this.queryString), {
populate: this.components,
});
const configs = {}; const configs = {};
await Promise.all(Object.values(AllConfig).map(async (config) => { await Promise.all(Object.values(AllConfig).map(async (config) => {

View File

@ -47,11 +47,6 @@ const dynamicSort = (property) => {
}; };
const sanitizeConfig = (config, relation, relationSortFields) => { const sanitizeConfig = (config, relation, relationSortFields) => {
delete config._id;
delete config.id;
delete config.updatedAt;
delete config.createdAt;
if (relation) { if (relation) {
const formattedRelations = []; const formattedRelations = [];
@ -74,6 +69,20 @@ const sanitizeConfig = (config, relation, relationSortFields) => {
config[relation] = formattedRelations; config[relation] = formattedRelations;
} }
const recursiveSanitizeConfig = (recursivedSanitizedConfig) => {
delete recursivedSanitizedConfig._id;
delete recursivedSanitizedConfig.id;
delete recursivedSanitizedConfig.updatedAt;
delete recursivedSanitizedConfig.createdAt;
Object.keys(recursivedSanitizedConfig).map((key, index) => {
if (recursivedSanitizedConfig[key] && typeof recursivedSanitizedConfig[key] === "object") {
recursiveSanitizeConfig(recursivedSanitizedConfig[key]);
}
});
};
recursiveSanitizeConfig(config);
return config; return config;
}; };