feat: Custom types & refactor of settings
parent
7bae51f34d
commit
cf24889fdd
171
README.md
171
README.md
|
@ -46,7 +46,7 @@ This way your app won't reload when you export the config in development.
|
||||||
module.exports = ({ env }) => ({
|
module.exports = ({ env }) => ({
|
||||||
// ...
|
// ...
|
||||||
watchIgnoreFiles: [
|
watchIgnoreFiles: [
|
||||||
'**/config-sync/files/**',
|
'**/config/sync/**',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -73,8 +73,8 @@ Complete installation requirements are the exact same as for Strapi itself and c
|
||||||
|
|
||||||
**Supported Strapi versions**:
|
**Supported Strapi versions**:
|
||||||
|
|
||||||
- Strapi 4.0.0 (recently tested)
|
- Strapi 4.0.2 (recently tested)
|
||||||
- Strapi ^4.x
|
- Strapi ^4.x (use `strapi-plugin-config-sync@^1.0.0`)
|
||||||
- Strapi ^3.4.x (use `strapi-plugin-config-sync@0.1.6`)
|
- Strapi ^3.4.x (use `strapi-plugin-config-sync@0.1.6`)
|
||||||
|
|
||||||
(This plugin may work with older Strapi versions, but these are not tested nor officially supported at this time.)
|
(This plugin may work with older Strapi versions, but these are not tested nor officially supported at this time.)
|
||||||
|
@ -138,7 +138,7 @@ npm run cs import
|
||||||
npm run cs export
|
npm run cs export
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Flag: `--yes` `-y`
|
##### Flag: `-y`, `--yes`
|
||||||
|
|
||||||
Use this flag to skip the confirm prompt and go straight to syncing the config.
|
Use this flag to skip the confirm prompt and go straight to syncing the config.
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ Use this flag to skip the confirm prompt and go straight to syncing the config.
|
||||||
[command] --yes
|
[command] --yes
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Flag: `--type` `-t`
|
##### Flag: `-t`, `--type`
|
||||||
|
|
||||||
Use this flag to specify the type of config you want to sync.
|
Use this flag to specify the type of config you want to sync.
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ Use this flag to specify the type of config you want to sync.
|
||||||
[command] --type user-role
|
[command] --type user-role
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Flag: `--partial` `-p`
|
##### Flag: `-p`, `--partial`
|
||||||
|
|
||||||
Use this flag to sync a specific set of configs by giving the CLI a comma-separated string of config names.
|
Use this flag to sync a specific set of configs by giving the CLI a comma-separated string of config names.
|
||||||
|
|
||||||
|
@ -218,33 +218,88 @@ Try to avoid making config changes directly on production. You wouldn't want to
|
||||||
|
|
||||||
## 🚀 Config types
|
## 🚀 Config types
|
||||||
|
|
||||||
### Admin role
|
This plugin allows you sync data from any type through the CLI & GUI. By default the plugin will track 4 (official) types. Custom types can be registered by setting some plugin config.
|
||||||
|
|
||||||
> Prefix: `admin-role` | UID: `code` | Query string: `admin::role`
|
### Default types
|
||||||
|
|
||||||
### User role
|
These 4 types are by default registered in the sync process.
|
||||||
|
|
||||||
> Prefix: `user-role` | UID: `type` | Query string: `plugin::users-permissions.role`
|
#### Admin role
|
||||||
|
|
||||||
### Core store
|
> Config name: `admin-role` | UID: `code` | Query string: `admin::role`
|
||||||
|
|
||||||
> Prefix: `core-store` | UID: `key` | Query string: `strapi::core-store`
|
#### User role
|
||||||
|
|
||||||
### I18n locale
|
> Config name: `user-role` | UID: `type` | Query string: `plugin::users-permissions.role`
|
||||||
|
|
||||||
|
#### Core store
|
||||||
|
|
||||||
|
> Config name: `core-store` | UID: `key` | Query string: `strapi::core-store`
|
||||||
|
|
||||||
|
#### I18n locale
|
||||||
|
|
||||||
|
> Config name: `i81n-locale` | UID: `code` | Query string: `plugin::i18n.locale`
|
||||||
|
|
||||||
|
### Custom types
|
||||||
|
|
||||||
|
Your custom types can be registered through the `customTypes` plugin config. This is a setting that can be set in the `config/plugins.js` file in your project.
|
||||||
|
|
||||||
|
You can register a type by giving the `customTypes` array an object which contains at least the following 3 properties:
|
||||||
|
|
||||||
|
```
|
||||||
|
customTypes: [{
|
||||||
|
configName: 'webhook',
|
||||||
|
queryString: 'webhook',
|
||||||
|
uid: 'name',
|
||||||
|
}],
|
||||||
|
```
|
||||||
|
|
||||||
|
_The example above will register the Strapi webhook type._
|
||||||
|
|
||||||
|
_Read more about the `config/plugins.js` file [here](#settings)._
|
||||||
|
|
||||||
|
#### Config name
|
||||||
|
|
||||||
|
The name of the config type. This value will be used as the first part of the filename for all config of this type. It should be unique from the other types and is preferably written in kebab-case.
|
||||||
|
|
||||||
|
###### Key: `configName`
|
||||||
|
|
||||||
|
> `required:` YES | `type:` string
|
||||||
|
|
||||||
|
#### Query string
|
||||||
|
|
||||||
|
This is the query string of the type. Each type in Strapi has its own query string you can use to programatically preform CRUD actions on the entries of the type. Often for custom types in Strapi the format is something like `api::custom-api.custom-type`.
|
||||||
|
|
||||||
|
###### Key: `queryString`
|
||||||
|
|
||||||
|
> `required:` YES | `type:` string
|
||||||
|
|
||||||
|
#### UID
|
||||||
|
|
||||||
|
The UID represents a field on the registered type. The value of this field will act as a unique identifier to identify the entries across environments. Therefor it should be unique and preferably un-editable after initial creation.
|
||||||
|
|
||||||
|
Mind that you can not use an auto-incremental value like the `id` as auto-increment does not play nice when you try to match entries across different databases.
|
||||||
|
|
||||||
|
###### Key: `uid`
|
||||||
|
|
||||||
|
> `required:` YES | `type:` string
|
||||||
|
|
||||||
|
#### JSON fields
|
||||||
|
|
||||||
|
This property can accept an array of field names from the type. It is meant to specify the JSON fields on the type so the plugin can better format the field values when calculating the config difference.
|
||||||
|
|
||||||
|
###### Key: `jsonFields`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` array
|
||||||
|
|
||||||
> Prefix: `i81n-locale` | UID: `code` | Query string: `plugin::i18n.locale`
|
|
||||||
|
|
||||||
## 🔍 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:
|
||||||
|
|
||||||
[config-type].[config-name].json
|
[config-type].[identifier].json
|
||||||
|
|
||||||
- `config-type` - Corresponds to the `prefix` of the config type.
|
- `config-type` - Corresponds to the `configName` of the config type.
|
||||||
- `config-name` - The unique identifier of the config.
|
- `identifier` - Corresponds to the value of the `uid` field of the config type.
|
||||||
- For `core-store` config this is the `key` value.
|
|
||||||
- For `user-role` config this is the `type` value.
|
|
||||||
- For `admin-role` config this is the `code` value.
|
|
||||||
- For `i18n-locale` config this is the `code` value
|
|
||||||
|
|
||||||
## 🔧 Settings
|
## 🔧 Settings
|
||||||
The settings of the plugin can be overridden in the `config/plugins.js` file.
|
The settings of the plugin can be overridden in the `config/plugins.js` file.
|
||||||
|
@ -256,29 +311,73 @@ In the example below you can see how, and also what the default settings are.
|
||||||
'config-sync': {
|
'config-sync': {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
config: {
|
config: {
|
||||||
destination: "extensions/config-sync/files/",
|
syncDir: "config/sync/",
|
||||||
minify: false,
|
minify: false,
|
||||||
importOnBootstrap: false,
|
importOnBootstrap: false,
|
||||||
include: [
|
customTypes: [],
|
||||||
"core-store",
|
excludedTypes: [],
|
||||||
"user-role",
|
excludedConfig: [
|
||||||
"admin-role",
|
|
||||||
"i18n-locale",
|
|
||||||
],
|
|
||||||
exclude: [
|
|
||||||
"core-store.plugin_users-permissions_grant"
|
"core-store.plugin_users-permissions_grant"
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
| Property | Type | Description |
|
|
||||||
| -------- | ---- | ----------- |
|
### Sync dir
|
||||||
| destination | string | The path for reading and writing the sync files. |
|
|
||||||
| minify | bool | When enabled all the exported JSON files will be minified. |
|
The path for reading and writing the sync files.
|
||||||
| importOnBootstrap | bool | Allows you to let the config be imported automaticly when strapi is bootstrapping (on `strapi start`). This setting should only be used in production, and should be handled very carefully as it can unintendedly overwrite the changes in your database. PLEASE USE WITH CARE. |
|
|
||||||
| include | array | Types you want to include in the syncing process. Allowed values: `core-store`, `user-role`, `admin-role`, `i18n-locale`. |
|
###### Key: `syncDir`
|
||||||
| exclude | array | Specify the names of configs you want to exclude from the syncing process. By default the API tokens for users-permissions, which are stored in core_store, are excluded. This setting expects the config names to comply with the naming convention. |
|
|
||||||
|
> `required:` YES | `type:` string | `default:` `config/sync/`
|
||||||
|
|
||||||
|
### Minify
|
||||||
|
|
||||||
|
When enabled all the exported JSON files will be minified.
|
||||||
|
|
||||||
|
###### Key: `minify`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` bool | `default:` `false`
|
||||||
|
|
||||||
|
### Import on bootstrap
|
||||||
|
|
||||||
|
Allows you to let the config be imported automaticly when strapi is bootstrapping (on `strapi start`). This setting should never be used locally and should be handled very carefully as it can unintendedly overwrite the changes in your database. **PLEASE USE WITH CARE**.
|
||||||
|
|
||||||
|
###### Key: `importOnBootstrap`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` bool | `default:` `false`
|
||||||
|
|
||||||
|
### Custom types
|
||||||
|
|
||||||
|
With this setting you can register your own custom config types. This is an array which expects objects with at least the `configName`, `queryString` and `uid` properties. Read more about registering custom types in the [Custom config types](#custom-types) documentation.
|
||||||
|
|
||||||
|
###### Key: `customTypes`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` array | `default:` `[]`
|
||||||
|
|
||||||
|
### Excluded types
|
||||||
|
|
||||||
|
This setting will exclude all the config from a given type from the syncing process. The config types are specified by the `configName` of the type.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
excludedTypes: ['admin-role']
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Key: `excludedTypes`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` array | `default:` `[]`
|
||||||
|
|
||||||
|
### Excluded config
|
||||||
|
|
||||||
|
Specify the names of configs you want to exclude from the syncing process. By default the API tokens for users-permissions, which are stored in core_store, are excluded. This setting expects the config names to comply with the naming convention.
|
||||||
|
|
||||||
|
###### Key: `excludedConfig`
|
||||||
|
|
||||||
|
> `required:` NO | `type:` array | `default:` `["core-store.plugin_users-permissions_grant"]`
|
||||||
|
|
||||||
|
|
||||||
## 🤝 Contributing
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const ConfigType = require('./config/type');
|
||||||
|
const defaultTypes = require('./config/types');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An asynchronous bootstrap function that runs before
|
* An asynchronous bootstrap function that runs before
|
||||||
* your application gets started.
|
* your application gets started.
|
||||||
|
@ -15,11 +18,31 @@ const fs = require('fs');
|
||||||
module.exports = async () => {
|
module.exports = async () => {
|
||||||
// Import on bootstrap.
|
// Import on bootstrap.
|
||||||
if (strapi.config.get('plugin.config-sync.importOnBootstrap')) {
|
if (strapi.config.get('plugin.config-sync.importOnBootstrap')) {
|
||||||
if (fs.existsSync(strapi.config.get('plugin.config-sync.destination'))) {
|
if (fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) {
|
||||||
await strapi.plugin('config-sync').service('main').importAllConfig();
|
await strapi.plugin('config-sync').service('main').importAllConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register config types.
|
||||||
|
const registerTypes = () => {
|
||||||
|
const types = {};
|
||||||
|
|
||||||
|
defaultTypes(strapi).map((type) => {
|
||||||
|
if (!strapi.config.get('plugin.config-sync.excludedTypes').includes(type.configName)) {
|
||||||
|
types[type.configName] = new ConfigType(type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
strapi.config.get('plugin.config-sync.customTypes').map((type) => {
|
||||||
|
if (!strapi.config.get('plugin.config-sync.excludedTypes').includes(type.configName)) {
|
||||||
|
types[type.configName] = new ConfigType(type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return types;
|
||||||
|
};
|
||||||
|
strapi.plugin('config-sync').types = registerTypes();
|
||||||
|
|
||||||
// Register permission actions.
|
// Register permission actions.
|
||||||
const actions = [
|
const actions = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -172,10 +172,10 @@ program
|
||||||
.alias('i')
|
.alias('i')
|
||||||
.option('-t, --type <type>', 'The type of config')
|
.option('-t, --type <type>', 'The type of config')
|
||||||
.option('-p, --partial <partials>', 'A comma separated string of configs')
|
.option('-p, --partial <partials>', 'A comma separated string of configs')
|
||||||
.option('-y', 'Skip the confirm prompt')
|
.option('-y, --yes', 'Skip the confirm prompt')
|
||||||
.description('Import the config')
|
.description('Import the config')
|
||||||
.action(async ({ y, type, partial }) => {
|
.action(async ({ yes, type, partial }) => {
|
||||||
return handleAction('import', y, type, partial);
|
return handleAction('import', yes, type, partial);
|
||||||
});
|
});
|
||||||
|
|
||||||
// `$ config-sync export`
|
// `$ config-sync export`
|
||||||
|
@ -184,10 +184,10 @@ program
|
||||||
.alias('e')
|
.alias('e')
|
||||||
.option('-t, --type <type>', 'The type of config')
|
.option('-t, --type <type>', 'The type of config')
|
||||||
.option('-p, --partial <partials>', 'A comma separated string of configs')
|
.option('-p, --partial <partials>', 'A comma separated string of configs')
|
||||||
.option('-y', 'Skip the confirm prompt')
|
.option('-y, --yes', 'Skip the confirm prompt')
|
||||||
.description('Export the config')
|
.description('Export the config')
|
||||||
.action(async ({ y, type, partial }) => {
|
.action(async ({ yes, type, partial }) => {
|
||||||
return handleAction('export', y, type, partial);
|
return handleAction('export', yes, type, partial);
|
||||||
});
|
});
|
||||||
|
|
||||||
// `$ config-sync diff`
|
// `$ config-sync diff`
|
||||||
|
|
|
@ -2,16 +2,12 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
default: {
|
default: {
|
||||||
destination: "src/extensions/config-sync/files/",
|
syncDir: "config/sync/",
|
||||||
minify: false,
|
minify: false,
|
||||||
importOnBootstrap: false,
|
importOnBootstrap: false,
|
||||||
include: [
|
customTypes: [],
|
||||||
"core-store",
|
excludedTypes: [],
|
||||||
"user-role",
|
excludedConfig: [
|
||||||
"admin-role",
|
|
||||||
"i18n-locale",
|
|
||||||
],
|
|
||||||
exclude: [
|
|
||||||
"core-store.plugin_users-permissions_grant",
|
"core-store.plugin_users-permissions_grant",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,12 +2,21 @@ const { logMessage, sanitizeConfig, dynamicSort, noLimit } = require('../utils')
|
||||||
const difference = require('../utils/getArrayDiff');
|
const difference = require('../utils/getArrayDiff');
|
||||||
|
|
||||||
const ConfigType = class ConfigType {
|
const ConfigType = class ConfigType {
|
||||||
constructor(queryString, configPrefix, uid, jsonFields, relations) {
|
constructor({ queryString, configName, uid, jsonFields, relations }) {
|
||||||
|
if (!configName) {
|
||||||
|
strapi.log.error(logMessage('A config type was registered without a config name.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!queryString) {
|
if (!queryString) {
|
||||||
strapi.log.error(logMessage('Query string is missing for ConfigType'));
|
strapi.log.error(logMessage(`No query string found for the '${configName}' config type.`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!uid) {
|
||||||
|
strapi.log.error(logMessage(`No uid found for the '${configName}' config type.`));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
this.queryString = queryString;
|
this.queryString = queryString;
|
||||||
this.configPrefix = configPrefix;
|
this.configPrefix = configName;
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.jsonFields = jsonFields || [];
|
this.jsonFields = jsonFields || [];
|
||||||
this.relations = relations || [];
|
this.relations = relations || [];
|
||||||
|
@ -22,7 +31,7 @@ const ConfigType = class ConfigType {
|
||||||
*/
|
*/
|
||||||
importSingle = async (configName, configContent) => {
|
importSingle = async (configName, configContent) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${configName}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(`${this.configPrefix}.${configName}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const queryAPI = strapi.query(this.queryString);
|
const queryAPI = strapi.query(this.queryString);
|
||||||
|
@ -125,7 +134,7 @@ const ConfigType = class ConfigType {
|
||||||
const formattedDiff = await strapi.plugin('config-sync').service('main').getFormattedDiff(this.configPrefix);
|
const formattedDiff = await strapi.plugin('config-sync').service('main').getFormattedDiff(this.configPrefix);
|
||||||
|
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${configName}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(`${configName}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const currentConfig = formattedDiff.databaseConfig[configName];
|
const currentConfig = formattedDiff.databaseConfig[configName];
|
||||||
|
@ -151,7 +160,7 @@ const ConfigType = class ConfigType {
|
||||||
|
|
||||||
await Promise.all(Object.values(AllConfig).map(async (config) => {
|
await Promise.all(Object.values(AllConfig).map(async (config) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${this.configPrefix}.${config[this.uid]}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(`${this.configPrefix}.${config[this.uid]}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const formattedConfig = { ...sanitizeConfig(config) };
|
const formattedConfig = { ...sanitizeConfig(config) };
|
||||||
|
|
|
@ -1,49 +1,52 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const ConfigType = require("./type");
|
|
||||||
|
|
||||||
const types = (strapi) => {
|
const types = (strapi) => {
|
||||||
const typesObject = {
|
// Initiate Strapi 'core-store' and 'admin-role' types.
|
||||||
'i18n-locale': new ConfigType('plugin::i18n.locale', 'i18n-locale', 'code'),
|
const typesArray = [
|
||||||
'core-store': new ConfigType('strapi::core-store', 'core-store', 'key', ['value']),
|
{
|
||||||
'user-role': new ConfigType(
|
configName: 'core-store',
|
||||||
'plugin::users-permissions.role',
|
queryString: 'strapi::core-store',
|
||||||
'user-role',
|
uid: 'key',
|
||||||
'type',
|
jsonFields: ['value'],
|
||||||
[],
|
},
|
||||||
[{
|
{
|
||||||
queryString: 'plugin::users-permissions.permission',
|
configName: 'admin-role',
|
||||||
relationName: 'permissions',
|
queryString: 'admin::role',
|
||||||
parentName: 'role',
|
uid: 'code',
|
||||||
relationSortField: 'action',
|
relations: [{
|
||||||
}],
|
|
||||||
),
|
|
||||||
'admin-role': new ConfigType(
|
|
||||||
'admin::role',
|
|
||||||
'admin-role',
|
|
||||||
'code',
|
|
||||||
[],
|
|
||||||
[{
|
|
||||||
queryString: 'admin::permission',
|
queryString: 'admin::permission',
|
||||||
relationName: 'permissions',
|
relationName: 'permissions',
|
||||||
parentName: 'role',
|
parentName: 'role',
|
||||||
relationSortField: 'action',
|
relationSortField: 'action',
|
||||||
}],
|
}],
|
||||||
),
|
},
|
||||||
};
|
];
|
||||||
|
|
||||||
// Remove types for which the corresponding plugin is not installed.
|
// Register plugin users-permissions 'role' type.
|
||||||
Object.keys(typesObject).map((type) => {
|
if (strapi.plugin('users-permissions')) {
|
||||||
if (type === 'i18n-locale' && !strapi.plugin('i18n')) {
|
typesArray.push({
|
||||||
delete typesObject[type];
|
configName: 'user-role',
|
||||||
}
|
queryString: 'plugin::users-permissions.role',
|
||||||
|
uid: 'type',
|
||||||
if (type === 'user-role' && !strapi.plugin('users-permissions')) {
|
relations: [{
|
||||||
delete typesObject[type];
|
queryString: 'plugin::users-permissions.permission',
|
||||||
}
|
relationName: 'permissions',
|
||||||
|
parentName: 'role',
|
||||||
|
relationSortField: 'action',
|
||||||
|
}],
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return typesObject;
|
// Register plugin i18n 'locale' type.
|
||||||
|
if (strapi.plugin('i18n')) {
|
||||||
|
typesArray.push({
|
||||||
|
configName: 'i18n-locale',
|
||||||
|
queryString: 'plugin::i18n.locale',
|
||||||
|
uid: 'code',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return typesArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = types;
|
module.exports = types;
|
||||||
|
|
|
@ -25,7 +25,7 @@ module.exports = {
|
||||||
|
|
||||||
|
|
||||||
ctx.send({
|
ctx.send({
|
||||||
message: `Config was successfully exported to ${strapi.config.get('plugin.config-sync.destination')}.`,
|
message: `Config was successfully exported to ${strapi.config.get('plugin.config-sync.syncDir')}.`,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ module.exports = {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
importAll: async (ctx) => {
|
importAll: async (ctx) => {
|
||||||
// Check for existance of the config file destination dir.
|
// Check for existance of the config file sync dir.
|
||||||
if (!fs.existsSync(strapi.config.get('plugin.config-sync.destination'))) {
|
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) {
|
||||||
ctx.send({
|
ctx.send({
|
||||||
message: 'No config files were found.',
|
message: 'No config files were found.',
|
||||||
});
|
});
|
||||||
|
@ -72,8 +72,8 @@ module.exports = {
|
||||||
* @returns {object} formattedDiff.diff - The diff between the file config and databse config.
|
* @returns {object} formattedDiff.diff - The diff between the file config and databse config.
|
||||||
*/
|
*/
|
||||||
getDiff: async (ctx) => {
|
getDiff: async (ctx) => {
|
||||||
// Check for existance of the config file destination dir.
|
// Check for existance of the config file sync dir.
|
||||||
if (!fs.existsSync(strapi.config.get('plugin.config-sync.destination'))) {
|
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) {
|
||||||
ctx.send({
|
ctx.send({
|
||||||
message: 'No config files were found.',
|
message: 'No config files were found.',
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const types = require('../config/types');
|
|
||||||
const difference = require('../utils/getObjectDiff');
|
const difference = require('../utils/getObjectDiff');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +19,7 @@ module.exports = () => ({
|
||||||
*/
|
*/
|
||||||
writeConfigFile: async (configType, configName, fileContents) => {
|
writeConfigFile: async (configType, configName, fileContents) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${configType}.${configName}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(`${configType}.${configName}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
// Replace ':' with '#' in filenames for Windows support.
|
// Replace ':' with '#' in filenames for Windows support.
|
||||||
|
@ -31,12 +30,12 @@ module.exports = () => ({
|
||||||
? JSON.stringify(fileContents, null, 2)
|
? JSON.stringify(fileContents, null, 2)
|
||||||
: JSON.stringify(fileContents);
|
: JSON.stringify(fileContents);
|
||||||
|
|
||||||
if (!fs.existsSync(strapi.config.get('plugin.config-sync.destination'))) {
|
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) {
|
||||||
fs.mkdirSync(strapi.config.get('plugin.config-sync.destination'), { recursive: true });
|
fs.mkdirSync(strapi.config.get('plugin.config-sync.syncDir'), { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
const writeFile = util.promisify(fs.writeFile);
|
const writeFile = util.promisify(fs.writeFile);
|
||||||
await writeFile(`${strapi.config.get('plugin.config-sync.destination')}${configType}.${configName}.json`, json)
|
await writeFile(`${strapi.config.get('plugin.config-sync.syncDir')}${configType}.${configName}.json`, json)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// @TODO:
|
// @TODO:
|
||||||
// Add logging for successfull config export.
|
// Add logging for successfull config export.
|
||||||
|
@ -55,13 +54,13 @@ module.exports = () => ({
|
||||||
*/
|
*/
|
||||||
deleteConfigFile: async (configName) => {
|
deleteConfigFile: async (configName) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(`${configName}`);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(`${configName}`);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
// Replace ':' with '#' in filenames for Windows support.
|
// Replace ':' with '#' in filenames for Windows support.
|
||||||
configName = configName.replace(/:/g, "#");
|
configName = configName.replace(/:/g, "#");
|
||||||
|
|
||||||
fs.unlinkSync(`${strapi.config.get('plugin.config-sync.destination')}${configName}.json`);
|
fs.unlinkSync(`${strapi.config.get('plugin.config-sync.syncDir')}${configName}.json`);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,7 +75,7 @@ module.exports = () => ({
|
||||||
configName = configName.replace(/:/g, "#");
|
configName = configName.replace(/:/g, "#");
|
||||||
|
|
||||||
const readFile = util.promisify(fs.readFile);
|
const readFile = util.promisify(fs.readFile);
|
||||||
return readFile(`${strapi.config.get('plugin.config-sync.destination')}${configType}.${configName}.json`)
|
return readFile(`${strapi.config.get('plugin.config-sync.syncDir')}${configType}.${configName}.json`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return JSON.parse(data);
|
return JSON.parse(data);
|
||||||
})
|
})
|
||||||
|
@ -93,11 +92,11 @@ module.exports = () => ({
|
||||||
* @returns {object} Object with key value pairs of configs.
|
* @returns {object} Object with key value pairs of configs.
|
||||||
*/
|
*/
|
||||||
getAllConfigFromFiles: async (configType = null) => {
|
getAllConfigFromFiles: async (configType = null) => {
|
||||||
if (!fs.existsSync(strapi.config.get('plugin.config-sync.destination'))) {
|
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const configFiles = fs.readdirSync(strapi.config.get('plugin.config-sync.destination'));
|
const configFiles = fs.readdirSync(strapi.config.get('plugin.config-sync.syncDir'));
|
||||||
|
|
||||||
const getConfigs = async () => {
|
const getConfigs = async () => {
|
||||||
const fileConfigs = {};
|
const fileConfigs = {};
|
||||||
|
@ -111,9 +110,8 @@ module.exports = () => ({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
configType && configType !== type
|
configType && configType !== type
|
||||||
|| !strapi.config.get('plugin.config-sync.include').includes(type)
|
|| !strapi.plugin('config-sync').types[type]
|
||||||
|| !types(strapi)[type]
|
|| strapi.config.get('plugin.config-sync.excludedConfig').includes(`${type}.${name}`)
|
||||||
|| strapi.config.get('plugin.config-sync.exclude').includes(`${type}.${name}`)
|
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -138,12 +136,12 @@ module.exports = () => ({
|
||||||
const getConfigs = async () => {
|
const getConfigs = async () => {
|
||||||
let databaseConfigs = {};
|
let databaseConfigs = {};
|
||||||
|
|
||||||
await Promise.all(strapi.config.get('plugin.config-sync.include').map(async (type) => {
|
await Promise.all(Object.entries(strapi.plugin('config-sync').types).map(async ([name, type]) => {
|
||||||
if (configType && configType !== type || !types(strapi)[type]) {
|
if (configType && configType !== name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = await types(strapi)[type].getAllFromDatabase();
|
const config = await type.getAllFromDatabase();
|
||||||
databaseConfigs = Object.assign(config, databaseConfigs);
|
databaseConfigs = Object.assign(config, databaseConfigs);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -212,7 +210,7 @@ module.exports = () => ({
|
||||||
*/
|
*/
|
||||||
importSingleConfig: async (configName, onSuccess) => {
|
importSingleConfig: async (configName, onSuccess) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(configName);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(configName);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const type = configName.split('.')[0]; // Grab the first part of the filename.
|
const type = configName.split('.')[0]; // Grab the first part of the filename.
|
||||||
|
@ -220,7 +218,7 @@ module.exports = () => ({
|
||||||
const fileContents = await strapi.plugin('config-sync').service('main').readConfigFile(type, name);
|
const fileContents = await strapi.plugin('config-sync').service('main').readConfigFile(type, name);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await types(strapi)[type].importSingle(name, fileContents);
|
await strapi.plugin('config-sync').types[type].importSingle(name, fileContents);
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess(`${type}.${name}`);
|
onSuccess(`${type}.${name}`);
|
||||||
}
|
}
|
||||||
|
@ -238,14 +236,14 @@ module.exports = () => ({
|
||||||
*/
|
*/
|
||||||
exportSingleConfig: async (configName, onSuccess) => {
|
exportSingleConfig: async (configName, onSuccess) => {
|
||||||
// Check if the config should be excluded.
|
// Check if the config should be excluded.
|
||||||
const shouldExclude = strapi.config.get('plugin.config-sync.exclude').includes(configName);
|
const shouldExclude = strapi.config.get('plugin.config-sync.excludedConfig').includes(configName);
|
||||||
if (shouldExclude) return;
|
if (shouldExclude) return;
|
||||||
|
|
||||||
const type = configName.split('.')[0]; // Grab the first part of the filename.
|
const type = configName.split('.')[0]; // Grab the first part of the filename.
|
||||||
const name = configName.split(/\.(.+)/)[1]; // Grab the rest of the filename.
|
const name = configName.split(/\.(.+)/)[1]; // Grab the rest of the filename.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await types(strapi)[type].exportSingle(configName);
|
await strapi.plugin('config-sync').types[type].exportSingle(configName);
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess(`${type}.${name}`);
|
onSuccess(`${type}.${name}`);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue