Merge pull request #138 from pluginpal/beta

Beta
pull/142/head
Boaz Poolman 2024-09-18 18:23:53 +02:00 committed by GitHub
commit 8cca77377a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 9258 additions and 1320 deletions

View File

@ -26,6 +26,14 @@
"strapi": true "strapi": true
}, },
"rules": { "rules": {
"import/no-unresolved": [2, {
"ignore": [
"@strapi/strapi/admin",
"@strapi/icons/symbols",
"@strapi/admin/strapi-admin"
]
}],
"template-curly-spacing" : "off", "template-curly-spacing" : "off",
"indent" : "off", "indent" : "off",

View File

@ -8,6 +8,7 @@ on:
branches: branches:
- master - master
- develop - develop
- beta
jobs: jobs:
lint: lint:

View File

@ -4,15 +4,16 @@ import { useDispatch, useSelector } from 'react-redux';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { Button } from '@strapi/design-system'; import { Button } from '@strapi/design-system';
import { Map } from 'immutable'; import { Map } from 'immutable';
import { useNotification } from '@strapi/helper-plugin'; import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import ConfirmModal from '../ConfirmModal'; import ConfirmModal from '../ConfirmModal';
import { exportAllConfig, importAllConfig } from '../../state/actions/Config'; import { exportAllConfig, importAllConfig } from '../../state/actions/Config';
const ActionButtons = () => { const ActionButtons = () => {
const { post, get } = getFetchClient();
const dispatch = useDispatch(); const dispatch = useDispatch();
const toggleNotification = useNotification(); const { toggleNotification } = useNotification();
const [modalIsOpen, setModalIsOpen] = useState(false); const [modalIsOpen, setModalIsOpen] = useState(false);
const [actionType, setActionType] = useState(''); const [actionType, setActionType] = useState('');
const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS(); const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS();
@ -43,7 +44,7 @@ const ActionButtons = () => {
isOpen={modalIsOpen} isOpen={modalIsOpen}
onClose={closeModal} onClose={closeModal}
type={actionType} type={actionType}
onSubmit={(force) => actionType === 'import' ? dispatch(importAllConfig(partialDiff, force, toggleNotification)) : dispatch(exportAllConfig(partialDiff, toggleNotification))} onSubmit={(force) => actionType === 'import' ? dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get)) : dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
/> />
</ActionButtonsStyling> </ActionButtonsStyling>
); );

View File

@ -3,11 +3,8 @@ import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer-continued';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { import {
ModalLayout, Modal,
ModalBody,
ModalHeader,
Grid, Grid,
GridItem,
Typography, Typography,
} from '@strapi/design-system'; } from '@strapi/design-system';
@ -16,32 +13,32 @@ const ConfigDiff = ({ isOpen, onClose, oldValue, newValue, configName }) => {
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<ModalLayout <Modal.Root
onClose={onClose} onClose={onClose}
labelledBy="title" labelledBy="title"
> >
<ModalHeader> <Modal.Header>
<Typography variant="omega" fontWeight="bold" textColor="neutral800"> <Typography variant="omega" fontWeight="bold" textColor="neutral800">
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName} {formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
</Typography> </Typography>
</ModalHeader> </Modal.Header>
<ModalBody> <Modal.Body>
<Grid paddingBottom={4} style={{ textAlign: 'center' }}> <Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<GridItem col={6}> <Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography> <Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
</GridItem> </Grid.Item>
<GridItem col={6}> <Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography> <Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</GridItem> </Grid.Item>
</Grid> </Grid.Root>
<ReactDiffViewer <ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)} oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)} newValue={JSON.stringify(newValue, null, 2)}
splitView splitView
compareMethod={DiffMethod.WORDS} compareMethod={DiffMethod.WORDS}
/> />
</ModalBody> </Modal.Body>
</ModalLayout> </Modal.Root>
); );
}; };

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Tr, Td, BaseCheckbox } from '@strapi/design-system'; import { Tr, Td, Checkbox } from '@strapi/design-system';
const CustomRow = ({ row, checked, updateValue }) => { const CustomRow = ({ row, checked, updateValue }) => {
const { configName, configType, state, onClick } = row; const { configName, configType, state, onClick } = row;
@ -42,7 +42,7 @@ const CustomRow = ({ row, checked, updateValue }) => {
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
> >
<Td> <Td>
<BaseCheckbox <Checkbox
aria-label={`Select ${configName}`} aria-label={`Select ${configName}`}
value={checked} value={checked}
onValueChange={updateValue} onValueChange={updateValue}

View File

@ -10,7 +10,7 @@ import {
Tr, Tr,
Th, Th,
Typography, Typography,
BaseCheckbox, Checkbox,
Loader, Loader,
} from '@strapi/design-system'; } from '@strapi/design-system';
@ -128,7 +128,7 @@ const ConfigList = ({ diff, isLoading }) => {
<Thead> <Thead>
<Tr> <Tr>
<Th> <Th>
<BaseCheckbox <Checkbox
aria-label={formatMessage({ id: 'config-sync.ConfigList.SelectAll' })} aria-label={formatMessage({ id: 'config-sync.ConfigList.SelectAll' })}
indeterminate={isIndeterminate} indeterminate={isIndeterminate}
onValueChange={(value) => setCheckedItems(checkedItems.map(() => value))} onValueChange={(value) => setCheckedItems(checkedItems.map(() => value))}

View File

@ -4,17 +4,14 @@ import { useSelector } from 'react-redux';
import { import {
Dialog, Dialog,
DialogBody,
DialogFooter,
Flex, Flex,
Typography, Typography,
Stack,
Button, Button,
Checkbox, Checkbox,
Divider, Divider,
Box, Box,
} from '@strapi/design-system'; } from '@strapi/design-system';
import { ExclamationMarkCircle } from '@strapi/icons'; import { WarningCircle } from '@strapi/icons';
const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => { const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false)); const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false));
@ -24,21 +21,21 @@ const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<Dialog <Dialog.Root
onClose={onClose} onClose={onClose}
title={formatMessage({ id: "config-sync.popUpWarning.Confirmation" })} title={formatMessage({ id: "config-sync.popUpWarning.Confirmation" })}
isOpen={isOpen} isOpen={isOpen}
> >
<DialogBody icon={<ExclamationMarkCircle />}> <Dialog.Body icon={<WarningCircle />}>
<Stack size={2}> <Flex size={2}>
<Flex justifyContent="center"> <Flex justifyContent="center">
<Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}> <Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}>
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br /> {formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br />
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })} {formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })}
</Typography> </Typography>
</Flex> </Flex>
</Stack> </Flex>
</DialogBody> </Dialog.Body>
{(soft && type === 'import') && ( {(soft && type === 'import') && (
<React.Fragment> <React.Fragment>
<Divider /> <Divider />
@ -54,7 +51,7 @@ const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
</Box> </Box>
</React.Fragment> </React.Fragment>
)} )}
<DialogFooter <Dialog.Footer
startAction={( startAction={(
<Button <Button
onClick={() => { onClick={() => {
@ -76,7 +73,7 @@ const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })} {formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button> </Button>
)} /> )} />
</Dialog> </Dialog.Root>
); );
}; };

View File

@ -1,14 +1,17 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { NoContent, useNotification } from '@strapi/helper-plugin'; import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { Button } from '@strapi/design-system'; import { Button, EmptyStateLayout } from '@strapi/design-system';
import { EmptyDocuments } from '@strapi/icons/symbols';
import { exportAllConfig } from '../../state/actions/Config'; import { exportAllConfig } from '../../state/actions/Config';
import ConfirmModal from '../ConfirmModal'; import ConfirmModal from '../ConfirmModal';
const FirstExport = () => { const FirstExport = () => {
const toggleNotification = useNotification(); const { post, get } = getFetchClient();
const { toggleNotification } = useNotification();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [modalIsOpen, setModalIsOpen] = useState(false); const [modalIsOpen, setModalIsOpen] = useState(false);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
@ -19,15 +22,12 @@ const FirstExport = () => {
isOpen={modalIsOpen} isOpen={modalIsOpen}
onClose={() => setModalIsOpen(false)} onClose={() => setModalIsOpen(false)}
type="export" type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification))} onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
/> />
<NoContent <EmptyStateLayout
content={{ content={formatMessage({ id: 'config-sync.FirstExport.Message' })}
id: 'emptyState',
defaultMessage:
formatMessage({ id: 'config-sync.FirstExport.Message' }),
}}
action={<Button onClick={() => setModalIsOpen(true)}>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>} action={<Button onClick={() => setModalIsOpen(true)}>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>}
icon={<EmptyDocuments width={160} />}
/> />
</div> </div>
); );

View File

@ -7,14 +7,15 @@
import React, { memo } from 'react'; import React, { memo } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { HeaderLayout, Box } from '@strapi/design-system'; import { Layouts } from '@strapi/admin/strapi-admin';
import { Box } from '@strapi/design-system';
const HeaderComponent = () => { const HeaderComponent = () => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
return ( return (
<Box background="neutral100"> <Box background="neutral100">
<HeaderLayout <Layouts.Header
title={formatMessage({ id: 'config-sync.Header.Title' })} title={formatMessage({ id: 'config-sync.Header.Title' })}
subtitle={formatMessage({ id: 'config-sync.Header.Description' })} subtitle={formatMessage({ id: 'config-sync.Header.Description' })}
as="h2" as="h2"

View File

@ -1,18 +0,0 @@
import React from 'react';
import { NoContent } from '@strapi/helper-plugin';
import { useIntl } from 'react-intl';
const NoChanges = () => {
const { formatMessage } = useIntl();
return (
<NoContent
content={{
id: 'emptyState',
defaultMessage:
formatMessage({ id: 'config-sync.NoChanges.Message' }),
}}
/>
);
};
export default NoChanges;

View File

@ -0,0 +1,16 @@
import React from 'react';
import { EmptyStateLayout } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { EmptyDocuments } from '@strapi/icons/symbols';
const NoChanges = () => {
const { formatMessage } = useIntl();
return (
<EmptyStateLayout
content={formatMessage({ id: 'config-sync.NoChanges.Message', defaultMessage: 'No differences between DB and sync directory. You are up-to-date!' })}
icon={<EmptyDocuments width={160} />}
/>
);
};
export default NoChanges;

View File

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { CheckPagePermissions } from '@strapi/helper-plugin'; import { Page } from '@strapi/strapi/admin';
import pluginPermissions from '../../permissions'; import pluginPermissions from '../../permissions';
import Header from '../../components/Header'; import Header from '../../components/Header';
@ -16,12 +16,12 @@ import ConfigPage from '../ConfigPage';
const App = () => { const App = () => {
return ( return (
<CheckPagePermissions permissions={pluginPermissions.settings}> <Page.Protect permissions={pluginPermissions.settings}>
<Provider store={store}> <Provider store={store}>
<Header /> <Header />
<ConfigPage /> <ConfigPage />
</Provider> </Provider>
</CheckPagePermissions> </Page.Protect>
); );
}; };

View File

@ -3,30 +3,34 @@ import { useDispatch, useSelector } from 'react-redux';
import { Map } from 'immutable'; import { Map } from 'immutable';
import { import {
Box, Box,
ContentLayout,
Alert, Alert,
Typography, Typography,
} from '@strapi/design-system'; } from '@strapi/design-system';
import { useNotification } from '@strapi/helper-plugin'; import { useNotification } from '@strapi/strapi/admin';
import { getFetchClient, Layouts } from '@strapi/admin/strapi-admin';
import { useIntl } from 'react-intl';
import { getAllConfigDiff, getAppEnv } from '../../state/actions/Config'; import { getAllConfigDiff, getAppEnv } from '../../state/actions/Config';
import ConfigList from '../../components/ConfigList'; import ConfigList from '../../components/ConfigList';
import ActionButtons from '../../components/ActionButtons'; import ActionButtons from '../../components/ActionButtons';
const ConfigPage = () => { const ConfigPage = () => {
const toggleNotification = useNotification(); const { toggleNotification } = useNotification();
const { get } = getFetchClient();
const { formatMessage } = useIntl();
const dispatch = useDispatch(); const dispatch = useDispatch();
const isLoading = useSelector((state) => state.getIn(['config', 'isLoading'], Map({}))); const isLoading = useSelector((state) => state.getIn(['config', 'isLoading'], Map({})));
const configDiff = useSelector((state) => state.getIn(['config', 'configDiff'], Map({}))); const configDiff = useSelector((state) => state.getIn(['config', 'configDiff'], Map({})));
const appEnv = useSelector((state) => state.getIn(['config', 'appEnv', 'env'])); const appEnv = useSelector((state) => state.getIn(['config', 'appEnv', 'env']));
useEffect(() => { useEffect(() => {
dispatch(getAllConfigDiff(toggleNotification)); dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
dispatch(getAppEnv(toggleNotification)); dispatch(getAppEnv(toggleNotification, formatMessage, get));
}, []); }, []);
return ( return (
<ContentLayout paddingBottom={8}> <Layouts.Content paddingBottom={8}>
{appEnv === 'production' && ( {appEnv === 'production' && (
<Box paddingBottom={4}> <Box paddingBottom={4}>
<Alert variant="danger"> <Alert variant="danger">
@ -38,7 +42,7 @@ const ConfigPage = () => {
)} )}
<ActionButtons /> <ActionButtons />
<ConfigList isLoading={isLoading} diff={configDiff.toJS()} /> <ConfigList isLoading={isLoading} diff={configDiff.toJS()} />
</ContentLayout> </Layouts.Content>
); );
}; };

View File

@ -1,8 +1,8 @@
const pluginPkg = require('../../../package.json'); import pluginPkg from '../../../package.json';
const pluginId = pluginPkg.name.replace( const pluginId = pluginPkg.name.replace(
/^strapi-plugin-/i, /^strapi-plugin-/i,
'', '',
); );
module.exports = pluginId; export default pluginId;

View File

@ -0,0 +1,11 @@
const prefixPluginTranslations = (trad, pluginId) => {
if (!pluginId) {
throw new TypeError("pluginId can't be empty");
}
return Object.keys(trad).reduce((acc, current) => {
acc[`${pluginId}.${current}`] = trad[current];
return acc;
}, {});
};
export { prefixPluginTranslations };

View File

@ -1,6 +1,6 @@
import { prefixPluginTranslations } from '@strapi/helper-plugin';
import pluginPkg from '../../package.json'; import pluginPkg from '../../package.json';
import pluginId from './helpers/pluginId'; import pluginId from './helpers/pluginId';
import { prefixPluginTranslations } from './helpers/prefixPluginTranslations';
import pluginPermissions from './permissions'; import pluginPermissions from './permissions';
// import pluginIcon from './components/PluginIcon'; // import pluginIcon from './components/PluginIcon';
// import getTrad from './helpers/getTrad'; // import getTrad from './helpers/getTrad';

View File

@ -4,18 +4,16 @@
* *
*/ */
import { request } from '@strapi/helper-plugin'; export function getAllConfigDiff(toggleNotification, formatMessage, get) {
export function getAllConfigDiff(toggleNotification) {
return async function(dispatch) { return async function(dispatch) {
dispatch(setLoadingState(true)); dispatch(setLoadingState(true));
try { try {
const configDiff = await request('/config-sync/diff', { method: 'GET' }); const configDiff = await get('/config-sync/diff');
dispatch(setConfigPartialDiffInState([])); dispatch(setConfigPartialDiffInState([]));
dispatch(setConfigDiffInState(configDiff)); dispatch(setConfigDiffInState(configDiff.data));
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} catch (err) { } catch (err) {
toggleNotification({ type: 'warning', message: { id: 'notification.error' } }); toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} }
}; };
@ -37,40 +35,34 @@ export function setConfigPartialDiffInState(config) {
}; };
} }
export function exportAllConfig(partialDiff, toggleNotification) { export function exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get) {
return async function(dispatch) { return async function(dispatch) {
dispatch(setLoadingState(true)); dispatch(setLoadingState(true));
try { try {
const { message } = await request('/config-sync/export', { const response = await post('/config-sync/export', partialDiff);
method: 'POST', toggleNotification({ type: 'success', message: response.data.message });
body: partialDiff, dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
});
toggleNotification({ type: 'success', message });
dispatch(getAllConfigDiff(toggleNotification));
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} catch (err) { } catch (err) {
toggleNotification({ type: 'warning', message: { id: 'notification.error' } }); toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} }
}; };
} }
export function importAllConfig(partialDiff, force, toggleNotification) { export function importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get) {
return async function(dispatch) { return async function(dispatch) {
dispatch(setLoadingState(true)); dispatch(setLoadingState(true));
try { try {
const { message } = await request('/config-sync/import', { const response = await post('/config-sync/import', {
method: 'POST',
body: {
force, force,
config: partialDiff, config: partialDiff,
},
}); });
toggleNotification({ type: 'success', message }); toggleNotification({ type: 'success', message: response.data.message });
dispatch(getAllConfigDiff(toggleNotification)); dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} catch (err) { } catch (err) {
toggleNotification({ type: 'warning', message: { id: 'notification.error' } }); toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false)); dispatch(setLoadingState(false));
} }
}; };
@ -84,15 +76,13 @@ export function setLoadingState(value) {
}; };
} }
export function getAppEnv(toggleNotification) { export function getAppEnv(toggleNotification, formatMessage, get) {
return async function(dispatch) { return async function(dispatch) {
try { try {
const envVars = await request('/config-sync/app-env', { const envVars = await get('/config-sync/app-env');
method: 'GET', dispatch(setAppEnvInState(envVars.data));
});
dispatch(setAppEnvInState(envVars));
} catch (err) { } catch (err) {
toggleNotification({ type: 'warning', message: { id: 'notification.error' } }); toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
} }
}; };
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "strapi-plugin-config-sync", "name": "strapi-plugin-config-sync",
"version": "1.2.5", "version": "2.0.0-beta.4",
"description": "Migrate your config data across environments using the CLI or Strapi admin panel.", "description": "Migrate your config data across environments using the CLI or Strapi admin panel.",
"strapi": { "strapi": {
"displayName": "Config Sync", "displayName": "Config Sync",
@ -31,6 +31,7 @@
"immutable": "^3.8.2", "immutable": "^3.8.2",
"inquirer": "^8.2.0", "inquirer": "^8.2.0",
"react-diff-viewer-continued": "3.2.6", "react-diff-viewer-continued": "3.2.6",
"react-intl": "6.6.2",
"redux-immutable": "^4.0.0", "redux-immutable": "^4.0.0",
"redux-thunk": "^2.3.0" "redux-thunk": "^2.3.0"
}, },
@ -54,13 +55,13 @@
"strapi-server.js" "strapi-server.js"
], ],
"peerDependencies": { "peerDependencies": {
"@strapi/strapi": "^4.0.0" "@strapi/strapi": "^5.0.0-rc.2"
}, },
"devDependencies": { "devDependencies": {
"@strapi/design-system": "^1.14.1", "@strapi/design-system": "2.0.0-rc.7",
"@strapi/helper-plugin": "^4.19.0", "@strapi/icons": "2.0.0-rc.7",
"@strapi/icons": "^1.14.1", "@strapi/strapi": "5.0.0-rc.2",
"@strapi/utils": "^4.19.0", "@strapi/utils": "5.0.0-rc.2",
"babel-eslint": "9.0.0", "babel-eslint": "9.0.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1", "eslint-config-airbnb": "^18.2.1",
@ -78,7 +79,6 @@
"jest-styled-components": "^7.0.2", "jest-styled-components": "^7.0.2",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"react": "^17.0.2", "react": "^17.0.2",
"react-intl": "^5.20.12",
"react-redux": "^7.2.2", "react-redux": "^7.2.2",
"redux": "^4.0.5", "redux": "^4.0.5",
"styled-components": "^5.2.3" "styled-components": "^5.2.3"

View File

@ -1,7 +1,10 @@
HOST=0.0.0.0 HOST=0.0.0.0
PORT=1337 PORT=1337
APP_KEYS=SIwLyqu+IpSHIuUBDQfPZg==,Nzqbq2C3ATsR19u5XEAJQA==,/Agk5Sn8M4EzfoSiIHcDlQ==,gSxT2T0k2zbQatKXUV0zCA== APP_KEYS=ujfpKPEst1tv0WDxJEhjJw==,MOnFjWYKbWYmtrBZ3cQTFQ==,zQpX70tJw/Mw+Y656kXfVA==,xJT1vbsiz3cgabfgpLu72w==
API_TOKEN_SALT=reQcUBbGXD2KWG2QpRn7DA== API_TOKEN_SALT=5FoJkYoZV8IA6+NnZJDzng==
ADMIN_JWT_SECRET= 69mzgwRGfEBUhPEaas8EBA== ADMIN_JWT_SECRET=tkeg3+HqE+QmTd2ITEivtA==
TRANSFER_TOKEN_SALT=/LTsSGpC5afHICjZu0oEuQ== TRANSFER_TOKEN_SALT=UUMCRQ2cx9qvKw/RkB815Q==
JWT_SECRET=E0TTVdsr+M/FXAjfrNIgXA== # Database
DATABASE_CLIENT=sqlite
DATABASE_FILENAME=.tmp/data.db
JWT_SECRET=Dn/nUGQsREUw4/lfQYOScw==

View File

@ -1,2 +1,7 @@
HOST=0.0.0.0 HOST=0.0.0.0
PORT=1337 PORT=1337
APP_KEYS="toBeModified1,toBeModified2"
API_TOKEN_SALT=tobemodified
ADMIN_JWT_SECRET=tobemodified
TRANSFER_TOKEN_SALT=tobemodified
JWT_SECRET=tobemodified

View File

@ -2,15 +2,15 @@
* This file was automatically generated by Strapi. * This file was automatically generated by Strapi.
* Any modifications made will be discarded. * Any modifications made will be discarded.
*/ */
import i18N from "@strapi/plugin-i18n/strapi-admin";
import usersPermissions from "@strapi/plugin-users-permissions/strapi-admin"; import usersPermissions from "@strapi/plugin-users-permissions/strapi-admin";
import strapiCloud from "@strapi/plugin-cloud/strapi-admin";
import configSync from "strapi-plugin-config-sync/strapi-admin"; import configSync from "strapi-plugin-config-sync/strapi-admin";
import { renderAdmin } from "@strapi/strapi/admin"; import { renderAdmin } from "@strapi/strapi/admin";
renderAdmin(document.getElementById("strapi"), { renderAdmin(document.getElementById("strapi"), {
plugins: { plugins: {
i18n: i18N,
"users-permissions": usersPermissions, "users-permissions": usersPermissions,
"strapi-cloud": strapiCloud,
"config-sync": configSync, "config-sync": configSync,
}, },
}); });

View File

@ -1,4 +1,4 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<!-- <!--
This file was automatically generated by Strapi. This file was automatically generated by Strapi.
@ -58,5 +58,6 @@ Any modifications made will be discarded.
</div> </div>
</div></noscript </div></noscript
> >
<script type="module" src="/.strapi/client/app.js"></script>
</body> </body>
</html> </html>

View File

@ -1,3 +1,57 @@
# Strapi application # 🚀 Getting started with Strapi
A quick description of your strapi application Strapi comes with a full featured [Command Line Interface](https://docs.strapi.io/dev-docs/cli) (CLI) which lets you scaffold and manage your project in seconds.
### `develop`
Start your Strapi application with autoReload enabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-develop)
```
npm run develop
# or
yarn develop
```
### `start`
Start your Strapi application with autoReload disabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-start)
```
npm run start
# or
yarn start
```
### `build`
Build your admin panel. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-build)
```
npm run build
# or
yarn build
```
## ⚙️ Deployment
Strapi gives you many possible deployment options for your project including [Strapi Cloud](https://cloud.strapi.io). Browse the [deployment section of the documentation](https://docs.strapi.io/dev-docs/deployment) to find the best solution for your use case.
## 📚 Learn more
- [Resource center](https://strapi.io/resource-center) - Strapi resource center.
- [Strapi documentation](https://docs.strapi.io) - Official Strapi documentation.
- [Strapi tutorials](https://strapi.io/tutorials) - List of tutorials made by the core team and the community.
- [Strapi blog](https://strapi.io/blog) - Official Strapi blog containing articles made by the Strapi team and the community.
- [Changelog](https://strapi.io/changelog) - Find out about the Strapi product updates, new features and general improvements.
Feel free to check out the [Strapi GitHub repository](https://github.com/strapi/strapi). Your feedback and contributions are welcome!
## ✨ Community
- [Discord](https://discord.strapi.io) - Come chat with the Strapi community including the core team.
- [Forum](https://forum.strapi.io/) - Place to discuss, ask questions and find answers, show your Strapi project and get feedback or just talk with other Community members.
- [Awesome Strapi](https://github.com/strapi/awesome-strapi) - A curated list of awesome things related to Strapi.
---
<sub>🤫 Psst! [Strapi is hiring](https://strapi.io/careers).</sub>

View File

@ -1,11 +1,12 @@
const fs = require('fs'); const fs = require('fs');
const Strapi = require('@strapi/strapi'); const { createStrapi, compileStrapi } = require('@strapi/strapi');
let instance; let instance;
async function setupStrapi() { async function setupStrapi() {
if (!instance) { if (!instance) {
await Strapi().load(); const appContext = await compileStrapi();
await createStrapi(appContext).load();
instance = strapi; instance = strapi;
await instance.server.mount(); await instance.server.mount();

View File

@ -1,10 +1,7 @@
module.exports = ({ env }) => ({ module.exports = ({ env }) => ({
auth: { auth: {
secret: env('ADMIN_JWT_SECRET', 'c27c3833823a12b0761e32b22dc0113a'), secret: env('ADMIN_JWT_SECRET'),
}, },
watchIgnoreFiles: [
'**/config/sync/**',
],
apiToken: { apiToken: {
salt: env('API_TOKEN_SALT'), salt: env('API_TOKEN_SALT'),
}, },
@ -13,4 +10,8 @@ module.exports = ({ env }) => ({
salt: env('TRANSFER_TOKEN_SALT'), salt: env('TRANSFER_TOKEN_SALT'),
}, },
}, },
flags: {
nps: env.bool('FLAG_NPS', true),
promoteEE: env.bool('FLAG_PROMOTE_EE', true),
},
}); });

View File

@ -1,11 +1,12 @@
module.exports = [ module.exports = [
'strapi::logger',
'strapi::errors', 'strapi::errors',
'strapi::security', 'strapi::security',
'strapi::cors', 'strapi::cors',
'strapi::poweredBy', 'strapi::poweredBy',
'strapi::logger',
'strapi::query', 'strapi::query',
'strapi::body', 'strapi::body',
'strapi::session',
'strapi::favicon', 'strapi::favicon',
'strapi::public', 'strapi::public',
]; ];

View File

@ -1,4 +1,10 @@
module.exports = ({ env }) => ({ module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'), host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337), port: env.int('PORT', 1337),
app: {
keys: env.array('APP_KEYS'),
},
webhooks: {
populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),
},
}); });

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

BIN
playground/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

8
playground/jsconfig.json Normal file
View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"moduleResolution": "nodenext",
"target": "ES2021",
"checkJs": true,
"allowJs": true
}
}

View File

@ -1,5 +1,5 @@
{ {
"name": "playground", "name": "strapi-5-beta",
"private": true, "private": true,
"version": "0.1.0", "version": "0.1.0",
"description": "A Strapi application", "description": "A Strapi application",
@ -16,24 +16,24 @@
"supertest": "^6.3.3" "supertest": "^6.3.3"
}, },
"dependencies": { "dependencies": {
"@strapi/plugin-i18n": "^4.19.0", "@strapi/strapi": "5.0.0-rc.2",
"@strapi/plugin-users-permissions": "^4.19.0", "@strapi/plugin-users-permissions": "5.0.0-rc.2",
"@strapi/strapi": "^4.19.0", "@strapi/plugin-cloud": "5.0.0-rc.2",
"better-sqlite3": "^8.6.0", "better-sqlite3": "9.4.3",
"react": "^18.0.0", "react": "^18.0.0",
"react-dom": "^18.0.0", "react-dom": "^18.0.0",
"react-router-dom": "^5.2.0", "react-router-dom": "^6.0.0",
"strapi-plugin-config-sync": "./..", "strapi-plugin-config-sync": "./..",
"styled-components": "^5.2.1" "styled-components": "^6.0.0"
}, },
"author": { "author": {
"name": "A Strapi developer" "name": "A Strapi developer"
}, },
"strapi": { "strapi": {
"uuid": "2e84e366-1e09-43c2-a99f-a0d0acbc2ca5" "uuid": "edadddbd-0f25-4da7-833b-d4cd7dcae2fc"
}, },
"engines": { "engines": {
"node": ">=18.x.x <=20.x.x", "node": ">=18.0.0 <=20.x.x",
"npm": ">=6.0.0" "npm": ">=6.0.0"
}, },
"license": "MIT" "license": "MIT"

View File

@ -1,5 +1,5 @@
import type { Schema, Attribute } from '@strapi/strapi'; import type { Struct, Schema } from '@strapi/strapi';
declare module '@strapi/types' { declare module '@strapi/strapi' {
export module Shared {} export module Public {}
} }

File diff suppressed because it is too large Load Diff

View File

@ -23,21 +23,21 @@ module.exports = async () => {
// The default types provided by the plugin. // The default types provided by the plugin.
defaultTypes(strapi).map((type) => { defaultTypes(strapi).map((type) => {
if (!strapi.config.get('plugin.config-sync.excludedTypes').includes(type.configName)) { if (!strapi.config.get('plugin::config-sync.excludedTypes').includes(type.configName)) {
types[type.configName] = new ConfigType(type); types[type.configName] = new ConfigType(type);
} }
}); });
// The types provided by other plugins. // The types provided by other plugins.
strapi.plugin('config-sync').pluginTypes.map((type) => { strapi.plugin('config-sync').pluginTypes.map((type) => {
if (!strapi.config.get('plugin.config-sync.excludedTypes').includes(type.configName)) { if (!strapi.config.get('plugin::config-sync.excludedTypes').includes(type.configName)) {
types[type.configName] = new ConfigType(type); types[type.configName] = new ConfigType(type);
} }
}); });
// The custom types provided by the user. // The custom types provided by the user.
strapi.config.get('plugin.config-sync.customTypes').map((type) => { strapi.config.get('plugin::config-sync.customTypes').map((type) => {
if (!strapi.config.get('plugin.config-sync.excludedTypes').includes(type.configName)) { if (!strapi.config.get('plugin::config-sync.excludedTypes').includes(type.configName)) {
types[type.configName] = new ConfigType(type); types[type.configName] = new ConfigType(type);
} }
}); });
@ -47,12 +47,12 @@ module.exports = async () => {
strapi.plugin('config-sync').types = registerTypes(); strapi.plugin('config-sync').types = registerTypes();
// Import on bootstrap. // Import on bootstrap.
if (strapi.config.get('plugin.config-sync.importOnBootstrap')) { if (strapi.config.get('plugin::config-sync.importOnBootstrap')) {
if (strapi.server.app.env === 'development') { if (strapi.server.app.env === 'development') {
strapi.log.warn(logMessage(`You can't use the 'importOnBootstrap' setting in the development env.`)); strapi.log.warn(logMessage(`You can't use the 'importOnBootstrap' setting in the development env.`));
} else if (process.env.CONFIG_SYNC_CLI === 'true') { } else if (process.env.CONFIG_SYNC_CLI === 'true') {
strapi.log.warn(logMessage(`The 'importOnBootstrap' setting was ignored because Strapi was started from the config-sync CLI itself.`)); strapi.log.warn(logMessage(`The 'importOnBootstrap' setting was ignored because Strapi was started from the config-sync CLI itself.`));
} else if (fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) { } else 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();
} }
} }

View File

@ -6,7 +6,7 @@ const Table = require('cli-table');
const chalk = require('chalk'); const chalk = require('chalk');
const inquirer = require('inquirer'); const inquirer = require('inquirer');
const { isEmpty } = require('lodash'); const { isEmpty } = require('lodash');
const strapi = require('@strapi/strapi'); // eslint-disable-line const { createStrapi, compileStrapi } = require('@strapi/strapi');
const gitDiff = require('git-diff'); const gitDiff = require('git-diff');
const warnings = require('./warnings'); const warnings = require('./warnings');
@ -15,33 +15,11 @@ const packageJSON = require('../package.json');
const program = new Command(); const program = new Command();
const getStrapiApp = async () => { const getStrapiApp = async () => {
process.env.CONFIG_SYNC_CLI = true; process.env.CONFIG_SYNC_CLI = 'true';
try {
const tsUtils = require('@strapi/typescript-utils'); // eslint-disable-line
const appDir = process.cwd();
const isTSProject = await tsUtils.isUsingTypeScript(appDir);
const outDir = await tsUtils.resolveOutDir(appDir);
const alreadyCompiled = await fs.existsSync(outDir);
if (isTSProject && !alreadyCompiled) {
await tsUtils.compile(appDir, {
watch: false,
configOptions: { options: { incremental: true } },
});
}
const distDir = isTSProject ? outDir : appDir;
const app = await strapi({ appDir, distDir }).load();
const appContext = await compileStrapi();
const app = await createStrapi(appContext).load();
return app; return app;
} catch (e) {
// Fallback for pre Strapi 4.2.
const app = await strapi().load();
return app;
}
}; };
const initTable = (head) => { const initTable = (head) => {
@ -100,7 +78,7 @@ const getConfigState = (diff, configName, syncType) => {
const handleAction = async (syncType, skipConfirm, configType, partials, force) => { const handleAction = async (syncType, skipConfirm, configType, partials, force) => {
const app = await getStrapiApp(); const app = await getStrapiApp();
const hasSyncDir = fs.existsSync(app.config.get('plugin.config-sync.syncDir')); const hasSyncDir = fs.existsSync(app.config.get('plugin::config-sync.syncDir'));
// No import with empty sync dir. // No import with empty sync dir.
if (!hasSyncDir && syncType === 'import') { if (!hasSyncDir && syncType === 'import') {

View File

@ -39,10 +39,10 @@ const ConfigType = class ConfigType {
*/ */
importSingle = async (configName, configContent, force) => { importSingle = async (configName, configContent, force) => {
// Check if the config should be excluded. // Check if the config should be excluded.
const shouldExclude = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => `${this.configPrefix}.${configName}`.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => `${this.configPrefix}.${configName}`.startsWith(option)));
if (shouldExclude) return; if (shouldExclude) return;
const softImport = strapi.config.get('plugin.config-sync.soft'); const softImport = strapi.config.get('plugin::config-sync.soft');
const queryAPI = strapi.query(this.queryString); const queryAPI = strapi.query(this.queryString);
const uidParams = getUidParamsFromName(this.uidKeys, configName); const uidParams = getUidParamsFromName(this.uidKeys, configName);
const combinedUidWhereFilter = getCombinedUidWhereFilter(this.uidKeys, uidParams); const combinedUidWhereFilter = getCombinedUidWhereFilter(this.uidKeys, uidParams);
@ -177,7 +177,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 = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => configName.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => configName.startsWith(option)));
if (shouldExclude) return; if (shouldExclude) return;
const currentConfig = formattedDiff.databaseConfig[configName]; const currentConfig = formattedDiff.databaseConfig[configName];
@ -214,7 +214,7 @@ const ConfigType = class ConfigType {
} }
// Check if the config should be excluded. // Check if the config should be excluded.
const shouldExclude = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => `${this.configPrefix}.${combinedUid}`.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => `${this.configPrefix}.${combinedUid}`.startsWith(option)));
if (shouldExclude) return; if (shouldExclude) return;
const formattedConfig = { ...sanitizeConfig({ config, configName }) }; const formattedConfig = { ...sanitizeConfig({ config, configName }) };

View File

@ -25,7 +25,7 @@ module.exports = {
ctx.send({ ctx.send({
message: `Config was successfully exported to ${strapi.config.get('plugin.config-sync.syncDir')}.`, message: `Config was successfully exported to ${strapi.config.get('plugin::config-sync.syncDir')}.`,
}); });
}, },
@ -37,7 +37,7 @@ module.exports = {
*/ */
importAll: async (ctx) => { importAll: async (ctx) => {
// Check for existance of the config file sync dir. // Check for existance of the config file sync dir.
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) { 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.',
}); });
@ -73,7 +73,7 @@ module.exports = {
*/ */
getDiff: async (ctx) => { getDiff: async (ctx) => {
// Check for existance of the config file sync dir. // Check for existance of the config file sync dir.
if (!fs.existsSync(strapi.config.get('plugin.config-sync.syncDir'))) { 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.',
}); });
@ -91,7 +91,7 @@ module.exports = {
getAppEnv: async () => { getAppEnv: async () => {
return { return {
env: strapi.server.app.env, env: strapi.server.app.env,
config: strapi.config.get('plugin.config-sync'), config: strapi.config.get('plugin::config-sync'),
}; };
}, },
}; };

View File

@ -21,23 +21,23 @@ 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 = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => `${configType}.${configName}`.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => `${configType}.${configName}`.startsWith(option)));
if (shouldExclude) return; if (shouldExclude) return;
// Replace reserved characters in filenames. // Replace reserved characters in filenames.
configName = configName.replace(/:/g, "#").replace(/\//g, "$"); configName = configName.replace(/:/g, "#").replace(/\//g, "$");
// Check if the JSON content should be minified. // Check if the JSON content should be minified.
const json = !strapi.config.get('plugin.config-sync').minify const json = !strapi.config.get('plugin::config-sync').minify
? 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.syncDir'))) { if (!fs.existsSync(strapi.config.get('plugin::config-sync.syncDir'))) {
fs.mkdirSync(strapi.config.get('plugin.config-sync.syncDir'), { 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.syncDir')}${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.
@ -56,13 +56,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 = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => configName.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => configName.startsWith(option)));
if (shouldExclude) return; if (shouldExclude) return;
// Replace reserved characters in filenames. // Replace reserved characters in filenames.
configName = configName.replace(/:/g, "#").replace(/\//g, "$"); configName = configName.replace(/:/g, "#").replace(/\//g, "$");
fs.unlinkSync(`${strapi.config.get('plugin.config-sync.syncDir')}${configName}.json`); fs.unlinkSync(`${strapi.config.get('plugin::config-sync.syncDir')}${configName}.json`);
}, },
/** /**
@ -77,7 +77,7 @@ module.exports = () => ({
configName = configName.replace(/:/g, "#").replace(/\//g, "$"); configName = configName.replace(/:/g, "#").replace(/\//g, "$");
const readFile = util.promisify(fs.readFile); const readFile = util.promisify(fs.readFile);
return readFile(`${strapi.config.get('plugin.config-sync.syncDir')}${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);
}) })
@ -94,11 +94,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.syncDir'))) { if (!fs.existsSync(strapi.config.get('plugin::config-sync.syncDir'))) {
return {}; return {};
} }
const configFiles = fs.readdirSync(strapi.config.get('plugin.config-sync.syncDir')); const configFiles = fs.readdirSync(strapi.config.get('plugin::config-sync.syncDir'));
const getConfigs = async () => { const getConfigs = async () => {
const fileConfigs = {}; const fileConfigs = {};
@ -113,7 +113,7 @@ module.exports = () => ({
if ( if (
configType && configType !== type configType && configType !== type
|| !strapi.plugin('config-sync').types[type] || !strapi.plugin('config-sync').types[type]
|| !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => `${type}.${name}`.startsWith(option))) || !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => `${type}.${name}`.startsWith(option)))
) { ) {
return; return;
} }
@ -219,7 +219,7 @@ module.exports = () => ({
*/ */
importSingleConfig: async (configName, onSuccess, force) => { importSingleConfig: async (configName, onSuccess, force) => {
// Check if the config should be excluded. // Check if the config should be excluded.
const shouldExclude = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => configName.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => configName.startsWith(option)));
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.
@ -244,7 +244,7 @@ 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 = !isEmpty(strapi.config.get('plugin.config-sync.excludedConfig').filter((option) => configName.startsWith(option))); const shouldExclude = !isEmpty(strapi.config.get('plugin::config-sync.excludedConfig').filter((option) => configName.startsWith(option)));
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.

View File

@ -56,6 +56,7 @@ const sanitizeConfig = ({
delete config.id; delete config.id;
delete config.updatedAt; delete config.updatedAt;
delete config.createdAt; delete config.createdAt;
delete config.publishedAt;
if (relation) { if (relation) {
const formattedRelations = []; const formattedRelations = [];
@ -64,6 +65,7 @@ const sanitizeConfig = ({
delete relationEntity._id; delete relationEntity._id;
delete relationEntity.id; delete relationEntity.id;
delete relationEntity.updatedAt; delete relationEntity.updatedAt;
delete config.publishedAt;
delete relationEntity.createdAt; delete relationEntity.createdAt;
relationEntity = sortByKeys(relationEntity); relationEntity = sortByKeys(relationEntity);

View File

@ -1,3 +1,3 @@
'use strict'; import admin from './admin/src';
module.exports = require('./admin/src').default; export default admin;

8755
yarn.lock

File diff suppressed because it is too large Load Diff