Compare commits

...

530 Commits

Author SHA1 Message Date
Boaz Poolman 047af45cc1
Merge pull request #189 from pluginpal/dependabot/npm_and_yarn/form-data-4.0.4
chore(deps): bump form-data from 4.0.1 to 4.0.4
2025-07-22 14:25:59 +02:00
dependabot[bot] 355b3d2c9c
chore(deps): bump form-data from 4.0.1 to 4.0.4
Bumps [form-data](https://github.com/form-data/form-data) from 4.0.1 to 4.0.4.
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v4.0.1...v4.0.4)

---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-22 12:23:55 +00:00
boazpoolman 7140fac0af chore: Bump version to 3.1.2 2025-06-30 07:26:35 +00:00
Boaz Poolman 6a060c9b11
Merge pull request #185 from pluginpal/dependabot/npm_and_yarn/pbkdf2-3.1.3
chore(deps): bump pbkdf2 from 3.1.2 to 3.1.3
2025-06-30 07:49:50 +02:00
Boaz Poolman 10c3a80a7d Merge branch 'master' of github.com:pluginpal/strapi-plugin-config-sync 2025-06-30 07:36:41 +02:00
Boaz Poolman fc82cc962f fix: add /config/sync folder to the watchIgnoreFiles 2025-06-30 07:36:31 +02:00
boazpoolman daec71f7eb chore: Bump version to 3.1.2-beta.2 2025-06-30 05:29:33 +00:00
Boaz Poolman bb944efb16 chore: update lockfile 2025-06-30 07:27:17 +02:00
Boaz Poolman b55dc1864d fix: add @strapi/typescript-utils to peerDependencies to prevent it from being bundled 2025-06-30 07:24:29 +02:00
dependabot[bot] db6659ce4b
chore(deps): bump pbkdf2 from 3.1.2 to 3.1.3
Bumps [pbkdf2](https://github.com/crypto-browserify/pbkdf2) from 3.1.2 to 3.1.3.
- [Changelog](https://github.com/browserify/pbkdf2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/pbkdf2/compare/v3.1.2...v3.1.3)

---
updated-dependencies:
- dependency-name: pbkdf2
  dependency-version: 3.1.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-30 05:17:05 +00:00
boazpoolman 432b0c1aec chore: Bump version to 3.1.2-beta.1 2025-06-30 05:15:01 +00:00
Boaz Poolman 75e9f4cb04 Merge branch 'master' of github.com:pluginpal/strapi-plugin-config-sync 2025-06-30 07:07:57 +02:00
Boaz Poolman 5fc0aea585 feat: ability to create automated alpha & beta releases 2025-06-30 07:07:42 +02:00
Boaz Poolman 748a31a0b6
Merge pull request #187 from gboutte/master
Avoid CLI re building the project if it's already built
2025-06-29 20:27:53 +02:00
gboutte 0b71235389 test: restore dist folder after the tests are done 2025-06-29 19:03:27 +02:00
Boaz Poolman 8b0f41bcd1 chore: update playground 2025-06-29 11:35:04 +02:00
Boaz Poolman a31a06cd72 chore: playground typescript cleanup 2025-06-29 11:20:27 +02:00
gboutte b45ec9c8d1 test: cli compile strapi only when not already built 2025-06-28 17:37:38 +02:00
gboutte c0253b5498 feat: migrate playground to typescript 2025-06-28 17:21:16 +02:00
gboutte 1e78cca1d3 fix: app context dist directory 2025-06-26 21:45:17 +02:00
gboutte 251d8df336 feat: avoid compilation is project already compiled 2025-06-26 13:49:39 +02:00
Boaz Poolman 8a7d4baca8 chore: update github action workflows 2025-05-29 17:22:35 +02:00
Boaz Poolman 8becc53ddf
Merge pull request #184 from mccrackend/patch-1
Documentation typo, fixing broken link
2025-05-29 17:19:56 +02:00
Dan McCracken a2a136a336
fixing broken image ref
See docs state <img..> tags in .md https://docusaurus.io/docs/static-assets#in-markdown
2025-05-27 13:05:30 -04:00
Dan McCracken 3835908542
fixing typo 2025-05-27 12:21:57 -04:00
Boaz Poolman c6e865bec1
Merge pull request #183 from pluginpal/dependabot/npm_and_yarn/docs/prismjs-1.30.0
chore(deps): bump prismjs from 1.29.0 to 1.30.0 in /docs
2025-04-29 10:38:56 +02:00
dependabot[bot] 5fa1fc7a1f
chore(deps): bump prismjs from 1.29.0 to 1.30.0 in /docs
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.29.0 to 1.30.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/v2/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.29.0...v1.30.0)

---
updated-dependencies:
- dependency-name: prismjs
  dependency-version: 1.30.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-29 08:24:24 +00:00
Boaz Poolman 07ee4ebd90
Merge pull request #182 from pluginpal/dependabot/npm_and_yarn/docs/http-proxy-middleware-2.0.9
chore(deps): bump http-proxy-middleware from 2.0.7 to 2.0.9 in /docs
2025-04-29 10:22:44 +02:00
dependabot[bot] 60b7cb9614
chore(deps): bump http-proxy-middleware from 2.0.7 to 2.0.9 in /docs
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-version: 2.0.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-29 02:13:11 +00:00
Boaz Poolman 1ae52f0ebd
Merge pull request #181 from pluginpal/dependabot/npm_and_yarn/docs/estree-util-value-to-estree-3.3.3
chore(deps): bump estree-util-value-to-estree from 3.1.2 to 3.3.3 in /docs
2025-04-09 17:54:49 +02:00
dependabot[bot] 18856cc719
chore(deps): bump estree-util-value-to-estree in /docs
Bumps [estree-util-value-to-estree](https://github.com/remcohaszing/estree-util-value-to-estree) from 3.1.2 to 3.3.3.
- [Release notes](https://github.com/remcohaszing/estree-util-value-to-estree/releases)
- [Commits](https://github.com/remcohaszing/estree-util-value-to-estree/compare/v3.1.2...v3.3.3)

---
updated-dependencies:
- dependency-name: estree-util-value-to-estree
  dependency-version: 3.3.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 02:05:46 +00:00
Boaz Poolman 7317a3e14d
Merge pull request #176 from pluginpal/dependabot/npm_and_yarn/docs/babel/runtime-7.27.0
chore(deps): bump @babel/runtime from 7.25.6 to 7.27.0 in /docs
2025-04-07 10:11:10 +02:00
Boaz Poolman fefe1bd93a
Merge pull request #177 from pluginpal/dependabot/npm_and_yarn/docs/cross-spawn-7.0.6
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /docs
2025-04-07 10:11:01 +02:00
Boaz Poolman 954c3fb1d1
Merge pull request #178 from pluginpal/dependabot/npm_and_yarn/docs/http-proxy-middleware-2.0.7
chore(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7 in /docs
2025-04-07 10:10:52 +02:00
Boaz Poolman 69b1633af8
Merge pull request #179 from pluginpal/dependabot/npm_and_yarn/docs/mermaid-10.9.3
chore(deps): bump mermaid from 10.9.1 to 10.9.3 in /docs
2025-04-07 10:10:44 +02:00
Boaz Poolman 790228f9e4
Merge pull request #180 from pluginpal/dependabot/npm_and_yarn/docs/image-size-1.2.1
chore(deps): bump image-size from 1.1.1 to 1.2.1 in /docs
2025-04-07 10:10:31 +02:00
dependabot[bot] d330a80e60
chore(deps): bump image-size from 1.1.1 to 1.2.1 in /docs
Bumps [image-size](https://github.com/image-size/image-size) from 1.1.1 to 1.2.1.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v1.1.1...v1.2.1)

---
updated-dependencies:
- dependency-name: image-size
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 15:10:22 +00:00
dependabot[bot] 68fd241829
chore(deps): bump mermaid from 10.9.1 to 10.9.3 in /docs
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.9.1 to 10.9.3.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.9.1...v10.9.3)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 19:22:18 +00:00
dependabot[bot] 2e54e4461f
chore(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7 in /docs
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.7/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 19:21:50 +00:00
dependabot[bot] c70db6153b
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /docs
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 19:21:39 +00:00
dependabot[bot] a8808f2e1c
chore(deps): bump @babel/runtime from 7.25.6 to 7.27.0 in /docs
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.25.6 to 7.27.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.27.0/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-25 19:21:32 +00:00
Boaz Poolman d3382d172a
Merge pull request #169 from pluginpal/dependabot/npm_and_yarn/prismjs-1.30.0 2025-03-25 20:21:04 +01:00
Boaz Poolman 67b6b0e511
Merge pull request #170 from pluginpal/dependabot/npm_and_yarn/docs/nanoid-3.3.10 2025-03-25 20:20:54 +01:00
Boaz Poolman a6df4bf396
Merge pull request #171 from pluginpal/dependabot/npm_and_yarn/docs/babel/runtime-corejs3-7.26.10 2025-03-25 20:20:45 +01:00
Boaz Poolman 7bf7e41d7f
Merge pull request #172 from pluginpal/dependabot/npm_and_yarn/babel/runtime-7.26.10 2025-03-25 20:20:28 +01:00
Boaz Poolman a41f4ddc5e
Merge pull request #173 from pluginpal/dependabot/npm_and_yarn/docs/dompurify-3.2.4 2025-03-25 20:20:08 +01:00
Boaz Poolman ba5552830e
Merge pull request #174 from pluginpal/dependabot/npm_and_yarn/docs/babel/helpers-7.26.10 2025-03-25 20:19:58 +01:00
Boaz Poolman 3fe2f7aff0
Merge pull request #175 from pluginpal/dependabot/npm_and_yarn/docs/katex-0.16.21 2025-03-25 20:19:43 +01:00
Boaz Poolman a96ed745cc chore: deploy docs only on release 2025-03-17 21:06:50 +01:00
Boaz Poolman 53436c2c03 feat: add algolia search to docs 2025-03-17 21:06:21 +01:00
Boaz Poolman 44471af96e feat: configs-ync branding for docs 2025-03-17 14:33:01 +01:00
Boaz Poolman 7ee80fd923 fix: update docs logo 2025-03-17 11:45:43 +01:00
Boaz Poolman c51568fdde fix: correctly set the baseUrl for config-sync docs 2025-03-17 11:31:21 +01:00
Boaz Poolman 307d5c179b fix: set the baseUrl for docusaurus 2025-03-17 10:55:12 +01:00
Boaz Poolman eb0024c8cc fix: docs build 2025-03-17 09:31:24 +01:00
dependabot[bot] 516c1068a3
chore(deps): bump katex from 0.16.11 to 0.16.21 in /docs
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.11 to 0.16.21.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.11...v0.16.21)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:24:40 +00:00
dependabot[bot] 2039105c88
chore(deps): bump @babel/helpers from 7.25.6 to 7.26.10 in /docs
Bumps [@babel/helpers](https://github.com/babel/babel/tree/HEAD/packages/babel-helpers) from 7.25.6 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-helpers)

---
updated-dependencies:
- dependency-name: "@babel/helpers"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:24:22 +00:00
dependabot[bot] cf35548edf
chore(deps): bump dompurify from 3.1.6 to 3.2.4 in /docs
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.6 to 3.2.4.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.6...3.2.4)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:24:21 +00:00
dependabot[bot] fb4a28c068
chore(deps): bump @babel/runtime from 7.26.0 to 7.26.10
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.26.0 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:24:08 +00:00
Boaz Poolman c17ea4234c fix: docs deploy 2025-03-17 09:23:58 +01:00
Boaz Poolman b54537cd34 style: don't lint the docs source code 2025-03-17 09:23:49 +01:00
dependabot[bot] 3da9ad26c5
chore(deps): bump @babel/runtime-corejs3 from 7.25.6 to 7.26.10 in /docs
Bumps [@babel/runtime-corejs3](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime-corejs3) from 7.25.6 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime-corejs3)

---
updated-dependencies:
- dependency-name: "@babel/runtime-corejs3"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:23:44 +00:00
dependabot[bot] 0168a343d3
chore(deps): bump nanoid from 3.3.7 to 3.3.10 in /docs
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.10.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.10)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 08:23:38 +00:00
Boaz Poolman c2dafa17c4 fix: use explicit node version for docusaurus build 2025-03-17 09:19:51 +01:00
Boaz Poolman 8c839138f6 chore: add auto deploy for config-sync docs 2025-03-17 09:08:39 +01:00
Boaz Poolman 6c65d64b81 chore: move docs into the config-sync repo 2025-03-17 09:08:26 +01:00
dependabot[bot] bd2805b23b
chore(deps): bump prismjs from 1.29.0 to 1.30.0
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.29.0 to 1.30.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.29.0...v1.30.0)

---
updated-dependencies:
- dependency-name: prismjs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-10 22:38:25 +00:00
Boaz Poolman 10ef97a4d4 fix: ci 2025-01-25 11:26:59 +00:00
Boaz Poolman cbe5ed9386 fix: ci 2025-01-25 11:05:41 +00:00
Boaz Poolman f738ca5cf5 Merge branch 'master' of github.com:pluginpal/strapi-plugin-config-sync 2025-01-03 10:54:17 +00:00
Boaz Poolman 5947a1ba42 chore: have dependabot do scheduled updates of Strapi 2025-01-03 10:53:55 +00:00
Boaz Poolman 05941739bf
Merge pull request #166 from pluginpal/feature/e2e-tests
Feature/e2e tests
2024-12-30 22:05:23 +00:00
Boaz Poolman b25fe0cefb feat: add a e2e test for partial import/export from the gui 2024-12-30 21:47:02 +00:00
Boaz Poolman 54bec393bf fix: recursive loggin in upon failed login attempt 2024-12-30 20:54:54 +00:00
Boaz Poolman 7a0d228f77 fix: only reload after login, not after register 2024-12-30 20:26:14 +00:00
Boaz Poolman 4e81ebe622 fix: cypress flakyness by reloading after logging in 2024-12-30 20:18:44 +00:00
Boaz Poolman 83cf8ed165 fix: up the cypress timeout time 2024-12-30 19:59:39 +00:00
Boaz Poolman f0d9ab32bb fix: upload video artifacts on runner failure 2024-12-30 18:32:06 +00:00
Boaz Poolman c46fcc9db8 chore: upload cypress video's as artifacts in debug mode of github actions 2024-12-30 17:55:08 +00:00
Boaz Poolman e22906afa4 fix: up the timeout time of cypress 2024-12-30 15:10:14 +00:00
Boaz Poolman b7d31ddb0c fix: diff viewer 2024-12-30 15:09:52 +00:00
Boaz Poolman f731691cd1 chore: try to fail the diff viewer test 2024-12-30 13:05:04 +00:00
Boaz Poolman 11cde0b638 fix: disable unfinished test 2024-12-30 13:04:25 +00:00
Boaz Poolman fc5df403af fix: add missing playground:start command 2024-12-30 12:37:38 +00:00
Boaz Poolman 4e4613d8ab fix: updated eslint rules for cypress files 2024-12-30 10:43:38 +00:00
Boaz Poolman 24bbf0788b fix: add the /dist folder to eslintignore 2024-12-30 10:43:18 +00:00
Boaz Poolman 35463b9631 chore: run the e2e tests in the pipeline 2024-12-29 22:41:44 +00:00
Boaz Poolman f194c394d2 feat: add cypress and e2e tests 2024-12-29 22:41:05 +00:00
Boaz Poolman 592e934fe8 chore: add config/sync to the watch ignore files 2024-12-29 22:38:38 +00:00
Boaz Poolman c30f034cf2 chore: disable rate limiting in the playground 2024-12-29 22:38:20 +00:00
Boaz Poolman 4193e13c7c chore: update the generated content types in the playground 2024-12-29 22:36:48 +00:00
boazpoolman 14ed79b7b9 chore: Bump version to 3.1.1 2024-12-24 14:00:06 +00:00
Boaz Poolman acbfdbb89d
Merge pull request #165 from pluginpal/feature/fix-diff-viewer
fix: workaround for ssr issue of react diff-viewer lib
2024-12-24 14:57:11 +01:00
Boaz Poolman 2261b9915a fix: workaround for ssr issue of react diff-viewer lib 2024-12-24 13:51:06 +00:00
boazpoolman dbed0cb27d chore: Bump version to 3.1.0 2024-12-20 10:00:34 +00:00
Boaz Poolman 8990c9971a
Merge pull request #163 from pluginpal/feature/strapi-range
refactor: move @strapi packages from dependencies to peerDependencies
2024-12-19 22:17:20 +01:00
Boaz Poolman 750f2c3fe0 fix: add rc versions of @strapi/icons and @strapi/design-system 2024-12-19 21:07:10 +00:00
Boaz Poolman e0211d2164 refactor: move @strapi packages from dependencies to peerDependencies 2024-12-19 21:00:25 +00:00
Boaz Poolman 78acb059c2
Merge pull request #162 from pluginpal/dependabot/npm_and_yarn/nanoid-3.3.8 2024-12-18 14:13:36 +01:00
dependabot[bot] fc32b5b54c
chore(deps): bump nanoid from 3.3.7 to 3.3.8
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 17:31:33 +00:00
Boaz Poolman f01398e80a
Merge pull request #159 from pluginpal/dependabot/npm_and_yarn/cross-spawn-7.0.6
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6
2024-11-21 09:15:01 +01:00
dependabot[bot] 9b83d227db
chore(deps): bump cross-spawn from 7.0.3 to 7.0.6
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-21 00:11:49 +00:00
boazpoolman 89ff246e64 chore: Bump version to 3.0.4 2024-11-11 19:05:38 +00:00
Boaz Poolman d9198099a7 chore: fix deprecated strapi config annotation 2024-11-11 19:58:29 +01:00
Boaz Poolman 5e0ccf8e3d
Merge pull request #157 from pluginpal/feature/node-zip
feat: use adm-zip instead of 'zip' command
2024-11-11 19:56:51 +01:00
Boaz Poolman c1ad39d7ad feat: use adm-zip instead of 'zip' command 2024-11-11 19:31:31 +01:00
boazpoolman 39c4a66b75 chore: Bump version to 3.0.3 2024-11-08 19:48:22 +00:00
Boaz Poolman 79ca64ab34 Merge branch 'master' of github.com:pluginpal/strapi-plugin-config-sync 2024-11-08 20:45:59 +01:00
Boaz Poolman 0d630b21ec fix: update peer dependencies 2024-11-08 20:45:44 +01:00
boazpoolman 14a0ae877b chore: Bump version to 3.0.2 2024-11-06 19:01:31 +00:00
Boaz Poolman 02d5c20616 Merge branch 'master' of github.com:pluginpal/strapi-plugin-config-sync 2024-11-06 19:58:32 +01:00
Boaz Poolman d9fd9585ad fix: console warnings 2024-11-06 19:58:20 +01:00
boazpoolman 7ccf4cd274 chore: Bump version to 3.0.1 2024-11-06 14:00:06 +00:00
Boaz Poolman 16529e049c fix: actually build the plugin during the publish workflow 2024-11-06 14:58:06 +01:00
boazpoolman 1072afb31a chore: Bump version to 3.0.0 2024-11-06 13:52:10 +00:00
Boaz Poolman 775733eff8 fix: add @strapi/strapi as a devDependency 2024-11-06 14:30:59 +01:00
Boaz Poolman 0f6ac10c91 fix: remove @strapi/strapi as a dependency 2024-11-06 14:26:08 +01:00
Boaz Poolman a34246352e fix: add react-query as a dependency 2024-11-06 13:24:53 +01:00
Boaz Poolman c989e3f371 fix: shrink bundle size 2024-11-06 12:38:28 +01:00
Boaz Poolman 5de1accc77 refactor: updated dependency management 2024-11-06 12:29:16 +01:00
Boaz Poolman abfaaa8e5a chore: dependency updates 2024-11-06 12:12:36 +01:00
Boaz Poolman 20794eaa21 style: fix eslint issue 2024-11-06 12:01:37 +01:00
Boaz Poolman cc0e71988a refactor: use pack-up for bundling 2024-11-06 11:59:15 +01:00
boazpoolman 203fb4e7d1 chore: Bump version to 2.1.0 2024-10-18 20:09:31 +00:00
Boaz Poolman c02262184f
Merge pull request #150 from michaelrazmgah/feature/fix-issue-where-locale-is-not-found
fix: Fixing bug where Strapi UI is crashing when no locale is found
2024-10-18 22:00:59 +02:00
Boaz Poolman 829cbb0ae2 fix: eslint issue 2024-10-18 21:56:10 +02:00
Michael Razmgah 2a72cb1bb5
fix: Adding require into try catch to simplify by catching error inside single try-catch 2024-10-18 20:31:07 +02:00
Boaz Poolman 8ba4dbb728
Merge pull request #94 from The-Real-Established/master
feat: added option to download zip
2024-10-16 22:48:38 +02:00
Alexander Engel a794d30892
Merge pull request #1 from TMSchipper/fix/response-data
feat: add response.data and fix styling for layout with download zip …
2024-10-16 09:34:16 -07:00
Tim Schipper 9911e78b50 feat: add response.data and fix styling for layout with download zip button 2024-10-16 09:55:19 +02:00
Alexander Engel 3a71083a05 chore: fixed linting, moved helper function 2024-10-14 12:27:22 -07:00
Alexander Engel 6e6b6cfba7 fix: moved button to new file 2024-10-14 12:07:17 -07:00
Alexander Engel d735151d9b Merge branch 'master' of github.com:boazpoolman/strapi-plugin-config-sync 2024-10-14 12:07:03 -07:00
Alexander Engel 38563dbe6d fix: do not store config file 2024-10-14 11:58:53 -07:00
Michael Razmgah e74594a970
fix: Fixing bug where Strapi UI is crashing when no locale is found 2024-10-14 09:49:14 +02:00
Boaz Poolman 79a4a0b41c
Merge pull request #148 from pluginpal/feature/document-service
refactor: replace the entity service with the document service
2024-10-12 23:07:42 +02:00
Boaz Poolman fff5a765fe refactor: replace the entity service with the document service 2024-10-12 22:46:32 +02:00
Boaz Poolman 4f0ceccb85
Merge pull request #147 from pluginpal/feature/beta-fixes
Feature/beta fixes
2024-10-12 20:13:45 +02:00
Boaz Poolman d41f292e2d fix: push to the yalc registry in CI before starting the integration tests 2024-10-12 20:09:29 +02:00
Boaz Poolman 2b6bf4de94 fix: use yalc 'file' instead of yalc 'link' in CI for a more real-life package installation scenario 2024-10-12 20:01:43 +02:00
Boaz Poolman 75f53344d2 style: fix eslint issues 2024-10-12 19:52:13 +02:00
Boaz Poolman b14ee74c36 fix: config checkbox selection in the admin panel 2024-10-12 19:44:39 +02:00
Boaz Poolman 00da5012d8 fix: modal, dialog & typography styling 2024-10-12 18:46:42 +02:00
Boaz Poolman 11662c8421 chore: don't install just --production depdencies in ci, this case is handled by using the yalc registry 2024-10-12 17:18:40 +02:00
Boaz Poolman a6444d411d fix: add yalc as dependency to the playground also 2024-10-12 17:14:26 +02:00
Boaz Poolman e3e2d3e0af chore: update auto generated files 2024-10-12 16:47:00 +02:00
Boaz Poolman e69e39e436 docs: update contributing docs 2024-10-12 16:46:48 +02:00
Boaz Poolman e1aefbf5b6 chore: use yalc for playground development 2024-10-12 16:46:36 +02:00
Boaz Poolman 750c1a2895 chore: update strapi dependencies to 5.0.4 2024-10-12 16:22:33 +02:00
Boaz Poolman da2f064383
Merge pull request #146 from pluginpal/feature/update-readme
docs: update the README to refer to the docs website
2024-10-05 14:01:46 +02:00
Boaz Poolman 5c6ac137f2 docs: update the README to refer to the docs website 2024-10-05 14:01:01 +02:00
Boaz Poolman 3a635e2d44
Merge pull request #145 from pluginpal/dependabot/npm_and_yarn/rollup-4.22.4
chore(deps): bump rollup from 4.18.0 to 4.22.4
2024-09-24 07:39:46 +02:00
dependabot[bot] 767b409886
chore(deps): bump rollup from 4.18.0 to 4.22.4
Bumps [rollup](https://github.com/rollup/rollup) from 4.18.0 to 4.22.4.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.18.0...v4.22.4)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 23:59:01 +00:00
Boaz Poolman c29660bf5d
Merge pull request #143 from pluginpal/dependabot/npm_and_yarn/path-to-regexp-6.3.0
chore(deps): bump path-to-regexp from 6.2.1 to 6.3.0
2024-09-18 19:08:03 +02:00
Boaz Poolman 5d8ce7a028
Merge pull request #142 from pluginpal/dependabot/npm_and_yarn/webpack-5.94.0
chore(deps): bump webpack from 5.91.0 to 5.94.0
2024-09-18 19:07:54 +02:00
dependabot[bot] af9427823d
chore(deps): bump path-to-regexp from 6.2.1 to 6.3.0
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 6.2.1 to 6.3.0.
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v6.2.1...v6.3.0)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-18 16:25:58 +00:00
dependabot[bot] 46c9f83508
chore(deps): bump webpack from 5.91.0 to 5.94.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.91.0 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.91.0...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-18 16:25:58 +00:00
Boaz Poolman 8cca77377a
Merge pull request #138 from pluginpal/beta
Beta
2024-09-18 18:23:53 +02:00
Boaz Poolman 0a239323f1 fix: conflicts 2024-09-18 17:59:49 +02:00
Boaz Poolman e445967d82
Merge pull request #137 from pluginpal/dependabot/npm_and_yarn/elliptic-6.5.7
chore(deps): bump elliptic from 6.5.4 to 6.5.7
2024-09-01 10:47:15 +02:00
dependabot[bot] 1dea4bda2f
chore(deps): bump elliptic from 6.5.4 to 6.5.7
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.5.7.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.5.7)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 08:41:15 +00:00
Boaz Poolman e987b8d710
Merge pull request #136 from pluginpal/dependabot/npm_and_yarn/micromatch-4.0.8
chore(deps): bump micromatch from 4.0.5 to 4.0.8
2024-09-01 10:40:16 +02:00
dependabot[bot] 3c2d27310d
chore(deps): bump micromatch from 4.0.5 to 4.0.8
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 01:25:07 +00:00
Boaz Poolman 7374c2758e
Merge pull request #135 from pluginpal/feature/fix-tests-ci
fix: run tests twice in CI, allowing the first try to fail
2024-08-28 22:51:26 +02:00
Boaz Poolman 645580b5ca fix: integration tests 2024-08-28 22:42:05 +02:00
Boaz Poolman 3b91e4b035 v2.0.0-beta.4 2024-08-13 20:30:25 +02:00
Boaz Poolman 8ef3217f5f fix: recursive config sanitization 2024-08-13 20:29:46 +02:00
Boaz Poolman c913705752
Merge pull request #132 from pluginpal/feature/fix-component-syncing
chore: setup components in the playground
2024-08-12 11:14:17 +02:00
Boaz Poolman 75634a30d2 fix: recursively santize all config except for content_manager_configuration items 2024-08-08 12:35:57 +02:00
Boaz Poolman e4e3825def chore: setup components in the playground 2024-08-05 18:37:56 +02:00
Boaz Poolman e9628ec2ba
Merge pull request #128 from pluginpal/dependabot/npm_and_yarn/braces-3.0.3
chore(deps): bump braces from 3.0.2 to 3.0.3
2024-07-18 22:12:36 +02:00
dependabot[bot] ceb504bb5f
chore(deps): bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-18 19:57:10 +00:00
Boaz Poolman 5e1e2a6386 v2.0.0-beta.3 2024-07-11 10:10:20 +02:00
Boaz Poolman dc3ab4b1b6
Merge pull request #130 from pluginpal/feature/update-to-rc
Update strapi to 5.0.0-rc.2
2024-07-10 10:33:46 +02:00
Boaz Poolman e8db8c6107 fix: rename design-system components for migtration to v2 2024-07-10 10:23:57 +02:00
Boaz Poolman 1ccd3d28f2 chore: update the .strapi/client/app.js to include config-sync 2024-07-10 10:23:10 +02:00
Boaz Poolman 9387c810ba chore: update design-system to 2.0.0-rc.7 2024-07-10 10:03:23 +02:00
Boaz Poolman dfb6852eb3 chore: update strapi to 5.0.0-rc.2 2024-07-10 09:57:14 +02:00
Boaz Poolman b2299346f8 v2.0.0-beta.2 2024-05-31 15:39:30 +02:00
Boaz Poolman 00bc2dde8a
Merge pull request #127 from pluginpal/feature/beta-testing
Beta testing
2024-05-31 13:49:42 +02:00
Boaz Poolman fb897c79b8 chore: update styled-components in the playground 2024-05-31 08:34:23 +02:00
Boaz Poolman 7ab1ad86e9 refactor: migrate design-system components for Strapi 5 2024-05-31 08:26:15 +02:00
Boaz Poolman e3f551e965 chore: update playground dependencies 2024-05-31 08:19:56 +02:00
Boaz Poolman 0965a94fe6 chore: update dependencies 2024-05-31 08:04:35 +02:00
Boaz Poolman 980593dc54
Merge pull request #126 from pluginpal/feature/migrate-v5
feat: initial v5 migration
2024-05-08 23:04:40 +02:00
Boaz Poolman 9c729759a2 fix: sanitize publishedAt fields 2024-05-08 23:00:03 +02:00
Boaz Poolman 943b83be90 fix: integration tests 2024-05-08 22:50:04 +02:00
Boaz Poolman 5ad9e8f0f6 fix: add testing libraries to the playground 2024-05-08 21:45:04 +02:00
Boaz Poolman fd63444630 chore: migrate the playground to v5 beta 2024-05-08 21:38:32 +02:00
Boaz Poolman 1c6f990d4d fix: use createStrapi in the tests helpers 2024-05-08 21:21:45 +02:00
Boaz Poolman b76187562d chore: test with beta.5 2024-05-08 21:21:29 +02:00
Boaz Poolman ab68450bea chore: run tests workflow for the beta branch 2024-05-08 21:16:14 +02:00
Boaz Poolman 60e2a1a7ea fix: use createStrapi instead of strapi default export 2024-05-08 21:12:18 +02:00
Boaz Poolman 4ee4e74bd7 style: fix eslint issue 2024-05-08 20:52:31 +02:00
Boaz Poolman 2a59690aae fix: merge conflicts 2024-05-08 20:50:28 +02:00
Boaz Poolman ab82a0dbf6 fix: deprecation warning regarding plugin config 2024-05-08 20:48:33 +02:00
Boaz Poolman 9178f1e902 fix: admin requests 2024-05-08 20:46:09 +02:00
Boaz Poolman 0b4974a338 fix: missing import 2024-05-08 19:51:35 +02:00
Boaz Poolman 6212b949ab fix: eslint no-unresolved 2024-05-08 19:49:40 +02:00
Boaz Poolman 60fca4899f chore: update lock file 2024-05-08 16:04:17 +02:00
Boaz Poolman ae6402803a refactor: update EmptyStateLayout to conform to it's new props 2024-05-08 15:58:30 +02:00
Boaz Poolman dfb5522024 chore: update to strapi beta.6 2024-05-08 15:57:35 +02:00
boazpoolman f8631f9685 chore: Bump version to 1.2.5 2024-04-18 21:12:12 +00:00
Boaz Poolman 15b265a37c Merge branch 'master' of github.com:boazpoolman/strapi-plugin-config-sync 2024-04-18 23:09:25 +02:00
Boaz Poolman 769e2c3be3 fix: check for process.env.CONFIG_SYNC_CLI with 'true' instead of true 2024-04-18 23:09:12 +02:00
boazpoolman e06ed0b968 chore: Bump version to 1.2.4 2024-04-18 20:36:03 +00:00
Boaz Poolman 6821110d7e feat: don't importOnBootstrap when using the config-sync CLI to start Strapi 2024-04-18 21:21:32 +02:00
Boaz Poolman 2063f88507 chore: move react-intl to the dependencies, rather then the devDependencies 2024-04-03 20:59:30 +02:00
Boaz Poolman c2ab9288c1 feat: initial v5 migration 2024-04-03 20:55:53 +02:00
Boaz Poolman 0f527048cc fix: update github URL in package.json 2024-03-27 16:21:39 +01:00
Boaz Poolman 9ad372ff59 chore: update the author & homepage info in the package.json 2024-03-27 16:15:05 +01:00
Boaz Poolman 338ed7ce39
Merge pull request #123 from pluginpal/dependabot/npm_and_yarn/follow-redirects-1.15.6
chore(deps): bump follow-redirects from 1.15.4 to 1.15.6
2024-03-18 19:50:12 +01:00
dependabot[bot] 65cc1caba1
chore(deps): bump follow-redirects from 1.15.4 to 1.15.6
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-16 22:59:50 +00:00
Mathijs Schouten 8f6e9da135
Merge pull request #121 from boazpoolman/feature/update-strapi
chore: update strapi to 4.19.0
2024-02-04 15:28:37 +01:00
Boaz Poolman af666ee2e5 chore: update strapi to 4.19.0 2024-01-27 10:24:45 +01:00
Boaz Poolman f828a9c198
Merge pull request #119 from boazpoolman/dependabot/npm_and_yarn/follow-redirects-1.15.4
chore(deps): bump follow-redirects from 1.15.3 to 1.15.4
2024-01-11 08:48:16 +01:00
dependabot[bot] 7ac23fb2be
chore(deps): bump follow-redirects from 1.15.3 to 1.15.4
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.4.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.4)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-11 03:09:51 +00:00
Boaz Poolman 8930a537b9
Merge pull request #118 from boazpoolman/feature/update-strapi-dependencies
chore: update @strapi devDependencies
2023-12-02 12:03:44 +01:00
Boaz Poolman 200f4f276c chore: update @strapi devDependencies 2023-12-02 11:59:59 +01:00
Boaz Poolman 3d5680e2c9
Merge pull request #116 from boazpoolman/dependabot/npm_and_yarn/adobe/css-tools-4.3.2
chore(deps): bump @adobe/css-tools from 4.3.1 to 4.3.2
2023-12-02 11:54:37 +01:00
dependabot[bot] a5c6bf15dd
chore(deps): bump @adobe/css-tools from 4.3.1 to 4.3.2
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.3.1 to 4.3.2.
- [Changelog](https://github.com/adobe/css-tools/blob/main/History.md)
- [Commits](https://github.com/adobe/css-tools/commits)

---
updated-dependencies:
- dependency-name: "@adobe/css-tools"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-02 10:51:39 +00:00
Boaz Poolman 3872a19c58
Merge pull request #117 from boazpoolman/feature/upgrade-playground
chore: add missing dependencies in playground
2023-12-02 11:48:27 +01:00
Boaz Poolman c77d2988b9 chore: add missing dependencies in playground 2023-12-02 11:42:48 +01:00
boazpoolman 1585fbfa45 chore: Bump version to 1.2.3 2023-11-04 13:39:43 +00:00
Boaz Poolman b51c2e91ec
Merge pull request #115 from boazpoolman/dependabot/npm_and_yarn/browserify-sign-4.2.2
chore(deps): bump browserify-sign from 4.2.1 to 4.2.2
2023-10-30 20:32:56 +01:00
dependabot[bot] 3318c4589d
chore(deps): bump browserify-sign from 4.2.1 to 4.2.2
Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2.
- [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2)

---
updated-dependencies:
- dependency-name: browserify-sign
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-28 04:56:23 +00:00
Boaz Poolman 7e78f04c24
Merge pull request #114 from boazpoolman/feature/update-query-fallback
fix: queryFallback utility
2023-10-23 21:13:58 +02:00
Boaz Poolman e2147ea5b6 fix: queryFallback utility 2023-10-23 21:06:04 +02:00
Boaz Poolman dd6e2f6c81 chore: Add more integration tests for create/update/delete in CLI 2023-10-22 12:36:28 +02:00
Mathijs Schouten a4b767f412
Merge pull request #111 from boazpoolman/feature/fix-import-on-bootstrap
Feature/fix import on bootstrap
2023-10-21 12:17:50 +02:00
Mathijs Schouten 88a40e7dfb
Merge pull request #113 from boazpoolman/feature/fix-config-sanitization-utility
fix: Remove recursive config sanitisation
2023-10-21 12:14:44 +02:00
Boaz Poolman a8e2180713 fix: Remove recursive config sanitisation 2023-10-20 16:59:38 +02:00
Boaz Poolman 19f5ba15f8 chore: More frequent database cleanups in between integration tests 2023-10-19 19:23:50 +02:00
Boaz Poolman 991da15d52 fix: Don't return promises in the queryFallback util 2023-10-19 19:08:30 +02:00
Boaz Poolman 5b9eaee29f fix: Use sed in ci 2023-10-19 09:15:39 +02:00
Boaz Poolman 81f22c6c93 fix: Add fallback for entitySerivce 2023-10-19 08:51:29 +02:00
Boaz Poolman 1acf0eee19 fix: Use sed in pipeline 2023-10-19 08:51:19 +02:00
Boaz Poolman 9333e8518b fix: Try using sed in pipeline 2023-10-19 08:33:57 +02:00
Boaz Poolman 3b7084fa87 chore: Add integration test for the importOnBootstrap setting 2023-10-19 08:19:06 +02:00
Boaz Poolman 7573cfd75c chore: Update test command 2023-10-19 08:18:42 +02:00
Boaz Poolman 27b349a82a chore: Update testing libraries 2023-10-19 07:49:52 +02:00
Boaz Poolman d101e3cc43 fix: Update tests workflow 2023-10-17 21:24:56 +02:00
Boaz Poolman 3be7479750 chore: Update lockfile 2023-10-17 21:22:13 +02:00
Boaz Poolman 28b7ba5811
Merge pull request #107 from boazpoolman/hotfix/lock-rdvc
fix: lock the react-diff-viewer-continued dependency to 3.2.6
2023-10-17 21:14:21 +02:00
Boaz Poolman 12970ae0d8 fix: lock the react-diff-viewer-continued dependency to 3.2.6 2023-10-17 20:51:59 +02:00
Boaz Poolman 08437acb0b fix: Only use the --no-lockfile for the integration tests 2023-10-17 20:48:20 +02:00
Boaz Poolman eb97eaeb38 feat: Add --no-lockfile to the yarn install step in the pipeline 2023-10-17 20:45:29 +02:00
Boaz Poolman efe6834d99 Revert "fix: Remove and gitignore the yarn.lock file"
This reverts commit 89599dd1b2.
2023-10-17 20:43:52 +02:00
Boaz Poolman 4da4952695 fix: Try running the CI without yarn cache 2023-10-17 20:35:00 +02:00
Boaz Poolman 58654fc769 fix: CI 2023-10-17 18:34:47 +02:00
Boaz Poolman 89599dd1b2 fix: Remove and gitignore the yarn.lock file 2023-10-17 18:33:30 +02:00
Boaz Poolman 301e5d742a
Merge pull request #106 from boazpoolman/dependabot/npm_and_yarn/babel/traverse-7.23.2
chore(deps): bump @babel/traverse from 7.22.6 to 7.23.2
2023-10-17 18:30:30 +02:00
Boaz Poolman 80e2b3c4b2 fix: Remove manually trigger of tests workflow 2023-10-17 18:29:57 +02:00
dependabot[bot] 9f6ae048da
chore(deps): bump @babel/traverse from 7.22.6 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.6 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-17 16:25:44 +00:00
Boaz Poolman e882e848f1 feat: Allow triggering the tests workflow manually 2023-10-17 18:25:09 +02:00
Boaz Poolman c1ab9abd47 docs: Update README 2023-10-15 11:02:00 +02:00
Boaz Poolman c8d7237446 chore: Bump version to 1.2.0 2023-10-15 10:27:25 +02:00
Boaz Poolman c959e957f2
Merge pull request #102 from joker-x/master
Add spanish translation
2023-10-15 10:09:50 +02:00
Iván Eixarch 4e2820fcdf Fix Eslint 2023-10-15 03:53:57 +02:00
Boaz Poolman c28542949c
Merge pull request #104 from MSACC/master
chore: Drop node 16 support and update @strapi packages
2023-10-14 19:51:22 +02:00
Mathijs Schouten e16417537d Node versions 2023-10-14 19:48:01 +02:00
Mathijs Schouten 2fa41164dc Node versions 2023-10-14 19:47:06 +02:00
Mathijs Schouten fbe19433eb Added good versions 2023-10-14 19:02:16 +02:00
Mathijs Schouten 1ebf191c6e chore: Drop node 16 support and update @strapi packages 2023-10-14 18:03:16 +02:00
Boaz Poolman a153f87fba docs: Fix issue in readme 2023-10-14 17:49:31 +02:00
Boaz Poolman 4581bf1751
Merge pull request #93 from PhilippPaoli/master
Feat: Import/export for types with populated components
2023-10-14 13:11:52 +02:00
ppaoli d3bcb1cd7c Update type.js
Update Query String
2023-10-14 11:01:39 +02:00
Iván Eixarch c9f6843f96 Add spanish translation 2023-10-11 20:46:51 +02:00
ppaoli 10ea389822 Update type.js
Resolved Integration Test Error
2023-10-11 18:17:53 +02:00
Boaz Poolman a63cfa23bf
Update README.md 2023-10-10 11:33:13 +02:00
Boaz Poolman ca41ec07a4 Merge branch 'master' of github.com:PhilippPaoli/strapi-plugin-config-sync into comp 2023-10-10 11:20:32 +02:00
Boaz Poolman b35817e074 fix: Add missing env vars to playground 2023-10-10 11:20:08 +02:00
Boaz Poolman c0582bd756 fix: Use strapi.log.warn instead of logging warnings with console.log 2023-10-10 11:20:08 +02:00
Boaz Poolman 0c2086e33a fix: No need to additionally sanitize the components. They've allready been sanitized because their parent was santized. 2023-10-10 11:20:08 +02:00
ppaoli c269b4847e Fixed ESLint warnings, change property naming
Fixed ESLint Warnings
Add Documentation for Components under "Custom types"
Change property populate to components
2023-10-10 11:20:08 +02:00
ppaoli 378cd7bb58 Fix small comments 2023-10-10 11:20:08 +02:00
ppaoli 69597c7464 Modified Strapi Api calls for components
Change Strapi Query Engine Api to Strapi entityService Api.
Add parameter "populate" to plugin config.
Use import and export with components logic.
2023-10-10 11:20:08 +02:00
Boaz Poolman f6677886c3 docs: Write docs about the relations feature 2023-09-06 16:58:04 +02:00
Boaz Poolman 8e9cbdd6aa fix: Add missing env vars to playground 2023-09-06 16:22:56 +02:00
Boaz Poolman 5199e7adc8 fix: Use strapi.log.warn instead of logging warnings with console.log 2023-09-06 16:16:48 +02:00
Boaz Poolman b9527532b6 fix: No need to additionally sanitize the components. They've allready been sanitized because their parent was santized. 2023-09-06 16:09:23 +02:00
Boaz Poolman 0a10b1907d Merge branch 'master' of github.com:boazpoolman/strapi-plugin-config-sync into comp 2023-09-06 15:08:14 +02:00
Boaz Poolman 724233cbb5 chore: Drop node 14 support. Add node 20 support. 2023-09-04 22:34:29 +02:00
ppaoli 34426f5172 Fixed ESLint warnings, change property naming
Fixed ESLint Warnings
Add Documentation for Components under "Custom types"
Change property populate to components
2023-09-04 13:04:08 +02:00
Boaz Poolman 5776400033
Merge pull request #101 from boazpoolman/dependabot/npm_and_yarn/adobe/css-tools-4.3.1
chore(deps): bump @adobe/css-tools from 4.2.0 to 4.3.1
2023-08-31 08:10:49 +02:00
Boaz Poolman 0915e28fc8
Merge pull request #100 from karlkeefer/update-admin-gui-screenshot
Replace the readme image with a newer one that reflects current GUI
2023-08-31 07:59:20 +02:00
Karl Keefer 151b1b4eba replace the readme image with a newer one that reflects current GUI 2023-08-30 12:36:24 -07:00
dependabot[bot] 6771a17e70
chore(deps): bump @adobe/css-tools from 4.2.0 to 4.3.1
Bumps [@adobe/css-tools](https://github.com/adobe/css-tools) from 4.2.0 to 4.3.1.
- [Changelog](https://github.com/adobe/css-tools/blob/main/History.md)
- [Commits](https://github.com/adobe/css-tools/commits)

---
updated-dependencies:
- dependency-name: "@adobe/css-tools"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-30 07:39:18 +00:00
ppaoli 510312d347 Fix small comments 2023-08-10 10:58:55 +02:00
boazpoolman e6c2db66de chore: Bump version to 1.1.3 2023-07-29 17:53:34 +00:00
Boaz Poolman c2f3561263 fix: Exclude 'core-store.plugin_upload_api-folder' by default (#92) 2023-07-29 19:43:38 +02:00
Boaz Poolman 7cc8ed3526 fix: Commit version bump from publish workflow 2023-07-29 19:41:36 +02:00
Boaz Poolman e9d0911cf9
Merge pull request #95 from boazpoolman/dependabot/npm_and_yarn/semver-5.7.2 2023-07-18 07:52:19 +02:00
dependabot[bot] 15c14fc081
chore(deps): bump semver from 5.7.1 to 5.7.2
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 10:04:18 +00:00
Boaz Poolman 39d4dc81cf chore: Sec updates 2023-07-05 21:53:58 +02:00
Alexander Engel 761024cc74 feat: added option to download zip 2023-06-15 16:33:56 -07:00
ppaoli 879e8908a0
Modified Strapi Api calls for components
Change Strapi Query Engine Api to Strapi entityService Api.
Add parameter "populate" to plugin config.
Use import and export with components logic.
2023-05-03 11:19:53 +02:00
Boaz Poolman 6312517dba Merge branch 'master' of github.com:boazpoolman/strapi-plugin-config-sync 2023-04-28 18:54:19 +02:00
Boaz Poolman 1c3d6b8ff5 chore: Version bump to 1.1.2 2023-04-28 18:54:06 +02:00
Boaz Poolman 3591cfaec5
Merge pull request #91 from yonghunJ/fix/readme-typo 2023-04-26 14:57:55 +02:00
yonghunj 473fd60d99 fix typo 2023-04-26 00:01:18 -04:00
Boaz Poolman 61e9ff1b2f
Merge pull request #89 from LucaNerlich/LucaNerlich-patch-1
Add core-store.ee_information to default excludes
2023-03-01 13:17:46 +01:00
Luca Nerlich a41cf84083
Update README.md 2023-03-01 12:42:31 +01:00
Luca Nerlich a9169268d2
Add "core-store.ee_information", to readme.md excluded config section 2023-03-01 12:31:46 +01:00
Luca Nerlich b4f20185e0
Add core-store.ee_information to default excludes
Prevent licence codes from being written to the rep.
2023-03-01 11:56:26 +01:00
boazpoolman 8f11f7eefd feat: Exclude 'core-store.strapi_content_types_schema' by default (#87) 2023-02-15 19:22:09 +01:00
boazpoolman 97439432cc chore: Push version update after successful publish workflow run 2023-02-10 18:46:56 +01:00
boazpoolman af0eabdf2f chore: Try fix publish workflow 2023-02-10 18:32:55 +01:00
boazpoolman b419c90924 chore: Add npm registery to package.json 2023-02-10 18:28:26 +01:00
boazpoolman b9e9dab146 chore: Try fix publish workflow 2023-02-09 22:35:34 +01:00
boazpoolman 99ca73d6b4 chore: Try fix publish workflow 2023-02-09 22:31:42 +01:00
Boaz Poolman 6e72ae02b9
Merge pull request #58 from Techwolf12/Techwolf12-patch-1
Add a Github workflow to publish releases
2023-02-09 22:17:07 +01:00
boazpoolman 3eb063f81a chore: Update json5 2023-02-08 20:38:39 +01:00
Boaz Poolman 3cd0ca29b6
Merge pull request #86 from liarco/patch-1
Fixing default for excludedConfig (README.md)
2023-02-07 14:03:16 +01:00
Marco Lipparini eeeb8cd11a
Adding missing entry in the example code 2023-02-07 13:59:15 +01:00
Marco Lipparini 948cf7cedb
Fixing default for excludedConfig (README.md)
Hi, I noticed the default value for `excludedConfig` was updated in 4d44e03a18

I also replaced double-quotes with single-quotes to match the lines above (e.g. line `413` is `excludedTypes: ['admin-role']`).
2023-02-07 13:45:51 +01:00
boazpoolman ceadfbbdc6 chore: Remove fontawesome 2022-12-31 14:19:17 +01:00
boazpoolman c8edb09ff1 chore: Update node version in playground to allow node 18 2022-12-31 13:47:08 +01:00
boazpoolman c17a87fdb0 chore: Run tests CI also for node 18 2022-12-31 13:42:21 +01:00
boazpoolman 91b589917a chore: Dependency updates 2022-12-31 13:39:19 +01:00
boazpoolman 5d2f8b6c09 chore: Update test command in CI 2022-12-30 14:25:20 +01:00
boazpoolman ae0d5b18a4 chore: Update test command in CI 2022-12-30 14:16:04 +01:00
boazpoolman d64af3f022 chore: Enhance integration tests with --production flag 2022-12-30 14:08:34 +01:00
boazpoolman f7a64d562d chore: Add build step to integration tests 2022-12-30 14:01:34 +01:00
boazpoolman 468303cb81 fix: CI build status shield in README 2022-12-30 13:53:27 +01:00
boazpoolman 68ad03a2da v1.1.0 2022-12-06 10:09:13 +01:00
boazpoolman a9761955fe fix: Exit when trying to delete the super-admin role 2022-12-05 18:55:49 +01:00
Boaz Poolman b7cc366312
Merge pull request #78 from boazpoolman/feature/soft-setting
feat: Addition of the 'soft' setting
2022-12-05 18:54:18 +01:00
boazpoolman f300183630 style: Fix eslint issues 2022-11-28 18:40:44 +01:00
Boaz Poolman 3f02eca41a
Merge pull request #77 from funatic-nl/dont-recompile-typescript-project
Don't recompile typescript project if already compiled
2022-11-28 17:04:55 +01:00
boazpoolman eef725684d feat: Addition of the 'soft' setting 2022-11-28 17:00:35 +01:00
Tim Raasveld 63ff9bb2e4 Merge branch 'master' of https://github.com/boazpoolman/strapi-plugin-config-sync into dont-recompile-typescript-project 2022-11-28 07:04:09 +00:00
boazpoolman ad7fc93b84 chore: Move to 'Aeolun/react-diff-viewer-continued' 2022-11-27 15:11:28 +01:00
boazpoolman 8ef4b7bc8b chore: Update playground sqlite db to 'better-sqlite' 2022-11-27 14:50:13 +01:00
boazpoolman ca910cfdaf chore: Update @strapi packages and alter imports accordingly 2022-11-27 14:35:11 +01:00
Tim Raasveld adae7af409 feat: Don't recompile typescript project if already compiled 2022-11-24 13:11:10 +01:00
Boaz Poolman 7206577eed v1.0.4 2022-09-06 22:01:47 +02:00
Boaz Poolman bfd571a7a9
Merge pull request #67 from goodhoko/feat-diff-exit-status
feat(CLI): Exit with 1 when diff is not empty.
2022-09-06 21:39:05 +02:00
Jen Tak 78c812d31f Link to local version of strapi-plugin-config-sync.
Linking to "boazpoolman/strapi-plugin-config-sync" resolves to the
version of strapi-plugin-config-sync currently on master branch on
GitHub. Which prevents running tests in the playground against the local
version.
2022-09-05 14:53:41 +02:00
Jen Tak 3c0c6d7fdb feat(CLI): Exit with 1 when diff is not empty.
To make it easier to use the diff command in scripts and CI and to align
its API with POSIX diff and diffs on most systems exit with 1 when the
diff is not empty. Keep exiting with 0 when it is.

Fixes #66.
2022-09-04 11:27:01 +02:00
Jen Tak 8f9b344604 Cleanup after integration tests.
Running the tests repeatedly failed as the DB was left in an altered
state which interfered with the subsequent test invocation.

Remove the DB and generated config files after all the tests run.
2022-09-04 11:27:01 +02:00
Jen Tak 0e25b7ad6d Git-ignore sync files generated by tests. 2022-09-04 11:27:01 +02:00
Boaz Poolman dc2ea316c5 chore: Add more declarative CLI error logging 2022-08-15 13:22:31 +02:00
Boaz Poolman 1dfc90a9c0 v1.0.3 2022-08-08 23:00:27 +02:00
Boaz Poolman 76ab9949aa chore: Delete plugins.js from playground 2022-08-08 22:56:34 +02:00
Boaz Poolman 4d44e03a18 fix: Exclude 'core-store.plugin_upload_metrics' by default 2022-08-08 22:48:48 +02:00
Boaz Poolman daf073e418 docs: Update README 2022-08-02 20:14:05 +02:00
Boaz Poolman 345e55feb7 docs: Update README 2022-07-21 13:47:48 +02:00
Boaz Poolman 3c8869007c fix: Readme 2022-06-19 22:58:15 +02:00
Boaz Poolman f5c5f79b56 docs: Update readme 2022-06-19 22:53:56 +02:00
Boaz Poolman 5b7f4f3d9d docs: Textual changes 2022-06-19 22:32:57 +02:00
Boaz Poolman 27b0c9b65c v1.0.2 2022-06-14 19:01:37 +02:00
Boaz Poolman d7009289a8
Merge pull request #59 from boazpoolman/feature/typescript-support
Feature/typescript support
2022-06-14 18:50:39 +02:00
Boaz Poolman a6035e16ae fix: Character escaping 2022-06-14 18:47:28 +02:00
Boaz Poolman 829a50492c
Merge pull request #57 from boazpoolman/fix/invalid-filename-character
feat: Escape '/' with '$' in filenames
2022-06-14 18:40:43 +02:00
Boaz Poolman 56ee854e71 fix: Fallback for pre Strapi 4.2 2022-06-14 18:38:05 +02:00
Boaz Poolman 43ca2e68a8 chore: Drop node 12 support 2022-06-09 12:22:27 +02:00
Boaz Poolman a7bfd3fd4b feat: Allow other plugin to register their own config types 2022-06-09 12:17:13 +02:00
Boaz Poolman c9e45c3909 feat: Support for typescript in Strapi v4.2.0 2022-06-08 22:43:55 +02:00
Christiaan de Die le Clercq ee6fbbcfc7
Add a Github workflow to publish releases 2022-05-19 21:04:38 +02:00
Boaz Poolman 6cd9a55a52 chore: Drop node 12 support 2022-05-13 10:31:48 +02:00
Boaz Poolman 0869b37c0d feat: Escape '/' with '$' in filenames 2022-05-13 10:22:31 +02:00
Boaz Poolman fea127f7b2 v1.0.1 2022-04-25 17:28:11 +02:00
Boaz Poolman 2adc044c9a
Merge pull request #52 from boazpoolman/fix/warning-for-missing-data
Gracefully warn about corrupt data
2022-04-25 14:30:03 +02:00
Boaz Poolman 47f84385e1 feat: Git-style diff viewer in CLI for single files (#27) 2022-04-24 14:07:39 +02:00
Boaz Poolman a44db2781d fix: Warn about an empty config file 2022-04-24 09:07:18 +02:00
Boaz Poolman f4d689e431 fix: Filter records with missing data and register a warning about it in the Strapi logs. 2022-04-23 14:49:13 +02:00
Boaz Poolman c0445de79a fix: Order findMany queries by id 2022-04-22 09:46:51 +02:00
Boaz Poolman 5e40de20b9 fix: Add .env to playground 2022-04-13 20:56:06 +02:00
Boaz Poolman a375d707cd chore: Update dependencies 2022-04-13 20:44:40 +02:00
Boaz Poolman 4f0b28ebb8 docs: Update README.md (#50) 2022-04-02 10:01:24 +02:00
Boaz Poolman 59e23e02ab chore: Update dependencies & CONTRIBUTING.md 2022-04-02 10:01:01 +02:00
Boaz Poolman ffe78a67d2 v1.0.0 2022-03-16 22:21:17 +01:00
Boaz Poolman 8ad30f8301
Merge pull request #47 from boazpoolman/release/stable
Release/stable
2022-03-16 22:14:44 +01:00
Boaz Poolman 7573a07d76 chore: Prep stable release 2022-03-16 22:10:24 +01:00
Boaz Poolman 63ac38c926 feat: Move admin page to settings 2022-03-16 22:09:46 +01:00
Boaz Poolman 37ef6f6c69 fix: Frontend issues 2022-03-16 21:29:54 +01:00
Boaz Poolman df61e0c5a0 chore: Fix audit log 2022-02-12 23:03:47 +01:00
Boaz Poolman 651d01031c chore: Update dependencies 2022-02-12 19:34:04 +01:00
Boaz Poolman 30c678e770 docs: Update readme 2022-01-27 16:04:05 +01:00
Boaz Poolman 5b1a7bc301 v1.0.0-beta.8 2022-01-26 19:27:56 +01:00
Boaz Poolman 010ae19bc4 fix: Bootstrap function 2022-01-26 19:27:09 +01:00
Boaz Poolman ae329b91a3 chore: Remove funding in favor of default 2022-01-26 10:11:13 +01:00
Boaz Poolman a83607ada3 feat: Setup sponsor button 2022-01-25 19:57:17 +01:00
Boaz Poolman c1899b5689 feat: Disallow use of importOnBootstrap in develop 2022-01-25 17:35:37 +01:00
Boaz Poolman 1d2f1760c9 chore: Update to Strapi 4.0.5 2022-01-25 11:08:44 +01:00
Boaz Poolman 2a8218d99f v1.0.0-beta.6 2022-01-25 11:00:19 +01:00
Boaz Poolman ef74b725cc
Merge pull request #43 from boazpoolman/feature/multi-sort-relations
Update relation on import
2022-01-25 10:41:41 +01:00
Boaz Poolman dbbdeb5f5b feat: Update relations entities on import 2022-01-24 20:48:59 +01:00
Boaz Poolman dbe3ea8c88 fix: More specific selection of relation entities 2022-01-21 17:33:14 +01:00
Boaz Poolman 8abf651a46 feat: Sort relations on more than 1 field 2022-01-21 16:21:00 +01:00
Boaz Poolman 6a05393c11
Merge pull request #40 from trieb-work/feat-combined-uids
feat: add combined uid feature
2022-01-19 17:49:50 +01:00
Boaz Poolman f28d80d920 refactor: Change uid escape string 2022-01-18 16:39:35 +01:00
Boaz Poolman d0982f6390 fix: Some bugs 2022-01-17 21:02:50 +01:00
tilman 02e0d5bd13 fix: package json 2022-01-17 17:55:07 +01:00
tilman c983f416eb fix: yarn lock file 2022-01-17 17:53:30 +01:00
tilman 87cb4a3ea8 fix: yarn lock file 2022-01-17 17:53:22 +01:00
tilman 5b1d0fc50d fix: discussions 2022-01-17 17:50:33 +01:00
tilman 4b9687a454 fix: discussions 2022-01-17 17:46:02 +01:00
tilman 997badd17c fix: elint 2022-01-15 19:34:28 +01:00
tilman 3aa1497786 feat: add combined uid feature and update docs 2022-01-15 19:17:19 +01:00
Boaz Poolman 3678c8e3c1 v1.0.0-beta.4 2022-01-13 19:54:28 +01:00
Boaz Poolman a0b43f392a
Merge pull request #38 from boazpoolman/feature/fix-import-on-bootstrap
fix: Code order in bootstrap function
2022-01-13 19:53:37 +01:00
Boaz Poolman c71531eb5c fix: Code order in bootstrap function 2022-01-13 19:47:00 +01:00
Boaz Poolman 05f037cb64 v1.0.0-beta.3 2022-01-07 12:53:07 +01:00
Boaz Poolman da88e5c957 chore: Consistency in dependencies 2022-01-07 12:29:57 +01:00
Boaz Poolman dddce06dea v1.0.0-beta.2 2022-01-07 10:19:37 +01:00
Boaz Poolman 51445a4ac9 chore: Update lockfile 2022-01-07 10:15:17 +01:00
Boaz Poolman 215b4e1e71 fix: Add redux-immutable as a plugin dependency 2022-01-07 10:13:04 +01:00
Boaz Poolman 7a4f6c329a chore: Remove immutable as devDevepency 2022-01-07 10:09:43 +01:00
Boaz Poolman c53cf0a319 chore: Remove build step from pipeline 2022-01-07 10:06:54 +01:00
Boaz Poolman db51be5b8f fix: Add immutable as plugin dependency 2022-01-07 09:59:35 +01:00
Boaz Poolman 2826c97756 chore: Add build step in integration pipeline 2022-01-07 09:55:43 +01:00
Boaz Poolman 2c161ccfb3 chore: Update readme & dependencies 2022-01-05 18:05:37 +01:00
Boaz Poolman 1ca5152665 chore: Always use latests Strapi version in playground 2021-12-31 14:19:51 +01:00
Boaz Poolman 9ac2167ff3 fix: Pipeline 2021-12-31 14:02:11 +01:00
Boaz Poolman 6183ad0818 chore: Change integration pipeline 2021-12-31 13:57:20 +01:00
Boaz Poolman a40f8542f0 chore: Remove yarn.lock from playground 2021-12-31 13:49:05 +01:00
Boaz Poolman 6468044213 chore: Try and break pipeline 2021-12-31 13:35:08 +01:00
Boaz Poolman 5bea30b700
Merge pull request #33 from boazpoolman/feature/integration-tests
chore: Integration tests
2021-12-31 13:31:09 +01:00
Boaz Poolman 2b61463060 chore: Integration tests 2021-12-31 13:28:04 +01:00
Boaz Poolman e31d1ebca0 v1.0.0-beta.1 2021-12-29 02:15:41 +01:00
Boaz Poolman c93546b594 feat: Allow excluding configs by giving part of the config name 2021-12-29 00:38:25 +01:00
Boaz Poolman 724f56f20b feat: Finalize CLI logging 2021-12-29 00:05:01 +01:00
Boaz Poolman c2768194cd feat: Finalize CLI logging 2021-12-29 00:02:38 +01:00
Boaz Poolman 31ab881b05 fix: Change CLI notice color 2021-12-28 23:50:25 +01:00
Boaz Poolman 08a962cf48 feat: Enhance CLI with more logging and descriptive actions 2021-12-28 23:46:48 +01:00
Boaz Poolman d8185bde99 docs: Fix typo in readme 2021-12-28 22:24:11 +01:00
Boaz Poolman 4e62cf6ee8 docs: Update readme 2021-12-28 22:15:49 +01:00
Boaz Poolman cf24889fdd feat: Custom types & refactor of settings 2021-12-28 22:10:04 +01:00
Boaz Poolman 7bae51f34d chore: Add install-local script 2021-12-28 22:07:43 +01:00
Boaz Poolman 2e1cf3f92e chore: Update dependencies 2021-12-22 11:03:26 +01:00
Boaz Poolman 96bd32226f chore: Run tests with node 12, 14 & 16 2021-12-21 19:47:19 +01:00
Boaz Poolman f8f620a13e v1.0.0-alpha.5 2021-12-13 17:10:44 +01:00
Boaz Poolman 4eaf565ee4 fix: Correctly splitting filename into 'type' & 'name' 2021-12-13 17:07:06 +01:00
Boaz Poolman 453ba13514 fix: Remove postinstall script 2021-12-13 11:54:24 +01:00
Boaz Poolman c9a5ce81ba
Merge pull request #31 from nihey/minor-readme-docs-fix 2021-12-11 14:58:38 +01:00
Nihey Takizawa 6748253759 Fix README.md default settings not having some commas 2021-12-11 10:47:38 -03:00
Boaz Poolman dc51405ee1 v1.0.0-alpha.3 2021-12-10 08:22:38 +01:00
Boaz Poolman 5cdf4de4fb feat: Dynamically use types based on plugin dependency 2021-12-10 00:49:12 +01:00
Boaz Poolman b8b187acf7 v1.0.0-alpha.2 2021-12-09 22:17:40 +01:00
Boaz Poolman f081c23e6d chore: Add strapi as a peerDependency 2021-12-09 21:46:29 +01:00
Boaz Poolman bfccce21de fix: Fetching the Strapi app env 2021-12-09 09:20:46 +01:00
Boaz Poolman 1734977a11 chore: Downgrade chalk to 4 2021-12-08 16:13:25 +01:00
Boaz Poolman 14eddc5459 fix: Production warning in admin 2021-12-08 16:05:45 +01:00
Boaz Poolman 7b9b664cdf chore: Update to eslint 7 2021-12-08 16:05:12 +01:00
Boaz Poolman 75197b9070
Merge pull request #29 from boazpoolman/develop
Develop
2021-12-08 14:06:01 +01:00
Boaz Poolman 00a2c4af34
Merge pull request #28 from boazpoolman/feature/no-limit
feat: Itterate through findMany queries limited with 100
2021-12-08 14:03:32 +01:00
Boaz Poolman 3644a03338 feat: Itterate through findMany queries limited with 100 2021-12-08 13:35:47 +01:00
Boaz Poolman 776eda5355 docs: Update readme 2021-12-07 21:13:37 +01:00
Boaz Poolman 32a12b884f docs: Update readme 2021-12-02 13:13:31 +01:00
Boaz Poolman 6dd1f4556f fix: Typo in the export CLI error handling 2021-12-01 17:42:17 +01:00
Boaz Poolman eae79c1684 feat: Alert on sync page in production 2021-12-01 17:08:36 +01:00
Boaz Poolman 50d691f76d fix(v4): Import on bootstrap 2021-12-01 14:01:56 +01:00
Boaz Poolman f167e664e3 chore: Prep 1.0.0-alpha.1 release 2021-11-30 09:50:22 +01:00
Boaz Poolman 99a6d46777 chore: Merge master into develop 2021-11-28 16:04:03 +01:00
Boaz Poolman 60e300ff31 fix: import CLI 2021-11-27 23:00:26 +01:00
Boaz Poolman 50c5934e83 docs: Update readme 2021-11-23 19:17:31 +01:00
Boaz Poolman 9b37c81336 docs: Update readme 2021-11-21 21:47:58 +01:00
Boaz Poolman c7559082c3 docs: Update readme 2021-11-21 21:44:30 +01:00
Boaz Poolman b0f709695b feat: Windows support 2021-11-21 21:16:42 +01:00
Boaz Poolman 90ccde4601 docs: Update readme 2021-11-21 20:49:39 +01:00
Boaz Poolman fcdcdf9919 docs: Update readme 2021-11-21 20:47:09 +01:00
Boaz Poolman 4783b42d0f feat: Add some padding to the bottom of the table 2021-11-20 20:33:31 +01:00
Boaz Poolman 1d9c834c9d feat: Add loader 2021-11-20 20:29:33 +01:00
Boaz Poolman c88f6f02e3 fix: Initial export in admin 2021-11-20 20:24:57 +01:00
Boaz Poolman 4efa1f30ff chore: Update package.json descriptions 2021-11-20 20:09:45 +01:00
Boaz Poolman 792a58722d fix: Bugs in admin 2021-11-20 19:51:03 +01:00
Boaz Poolman 17c68c2c36 feat: Partial export/import in admin 2021-11-20 19:06:01 +01:00
Boaz Poolman 187a090866 feat: Partial export in CLI 2021-11-20 14:28:17 +01:00
Boaz Poolman 15c770e9d0 feat: Add titles to the diff viewer 2021-11-19 20:39:32 +01:00
Boaz Poolman b07ffa6281 fix: Issue of duplicate key prop in array of components 2021-11-19 20:05:25 +01:00
Boaz Poolman a1d9d53517 chore: Update to @strapi/strapi 4.0.0-beta.14 2021-11-19 19:39:57 +01:00
Boaz Poolman 962952f662 feat: Partial import in CLI 2021-11-18 22:45:20 +01:00
Boaz Poolman 7af07bfcf0 refactor: Move all type stuff into its own folder 2021-11-18 21:41:48 +01:00
Boaz Poolman ccef257c32 feat: Empty states in admin 2021-11-13 14:30:16 +01:00
Boaz Poolman 3be97749f9 refactor(v4): Implement @strapi/design-system 2021-11-13 14:15:31 +01:00
Boaz Poolman b3d9ad640b docs: Update contributing.md 2021-11-11 22:55:31 +01:00
Boaz Poolman 6f8268f3ac refactor: Rename permission menu-item to menu-link 2021-11-11 22:43:52 +01:00
Boaz Poolman 35081eb85d style: Update copy in CLI 2021-11-10 22:53:26 +01:00
Boaz Poolman 7c5a337037 style: Update copy in CLI 2021-11-10 22:50:46 +01:00
Boaz Poolman 5a5df08fca feat: Update CLI colors 2021-11-10 22:45:48 +01:00
Boaz Poolman 68aa8b57e0 chore: Grab plugin icon name from package.json 2021-11-10 19:57:29 +01:00
Boaz Poolman d11d1f0de6
Merge pull request #26 from boazpoolman/feature/managed-admin-access
feat: Managed access for the settings page (RBAC)
2021-11-10 19:52:44 +01:00
Boaz Poolman ad68519ac2 feat: Managed access for the settings page (RBAC) 2021-11-10 19:51:00 +01:00
Boaz Poolman ab8b6699d8 docs: Update contributing.md 2021-11-10 18:52:07 +01:00
Boaz Poolman d20f82faa9 fix: Build problem with @strapi/helper-plugin 2021-11-10 18:45:06 +01:00
Boaz Poolman 5411c68538 chore: Add bin folder to the build 2021-11-10 16:53:57 +01:00
Boaz Poolman 17aa9b4cbd feat: Add aliases for CLI 2021-11-10 16:48:17 +01:00
Boaz Poolman c62eeec1d8 fix: Make action row in CLI table wider 2021-11-10 16:43:33 +01:00
Boaz Poolman 7609cf4ecf fix: Make CLI table wider 2021-11-10 16:42:44 +01:00
Boaz Poolman 6282e4e401 chore: Add full stop to 'no diff' notice for import/export commands 2021-11-10 16:38:09 +01:00
Boaz Poolman f408122d82 fix: 'no diff' notice for diff command 2021-11-10 16:36:30 +01:00
Boaz Poolman 160ce5216a fix: CLI as package.json script 2021-11-10 16:34:08 +01:00
Boaz Poolman e1a9e016e9
Merge pull request #25 from boazpoolman/feature/cli
feat: CLI 🎉
2021-11-10 16:31:47 +01:00
Boaz Poolman a08b2a2f01 chore: Cleanup 2021-11-10 16:29:48 +01:00
Boaz Poolman 7748ca0d43 chore: Move @strapi/strapi to dev dependencies 2021-11-10 16:28:47 +01:00
Boaz Poolman 15eb3df690 style: Fix eslint warnings 2021-11-10 16:27:15 +01:00
Boaz Poolman cd8a71f584 feat: CLI 🎉 2021-11-10 16:22:52 +01:00
Boaz Poolman dea1963199 feat: Basic CLI visualisation 2021-11-02 19:03:58 +01:00
Boaz Poolman eff6cb50eb feat: integrate relation syncing in default config type (permission relations) 2021-11-02 00:33:13 +01:00
Boaz Poolman db9745ef81 refactor(v4): plugin icon as react component 2021-10-27 16:04:58 +02:00
Boaz Poolman 3d6bd45a6d chore: downgrade to @strapi/design-system 0.0.1-alpha.51 2021-10-27 14:04:10 +02:00
Boaz Poolman cc2a7b0a39 chore: downgrade to @strapi/icons 0.0.1-alpha.50 2021-10-27 14:00:21 +02:00
Boaz Poolman ecb580ec95 refactor: Rename @strapi/icons imports 2021-10-27 13:45:55 +02:00
Boaz Poolman 835fbe17af chore: Migtate @strapi/parts to @strapi/design-system 2021-10-27 13:28:06 +02:00
Boaz Poolman 2477bdd345 chore: Wait for importAllConfig to finish 2021-10-22 13:56:58 +02:00
Boaz Poolman 17b4be7f7d
Merge pull request #23 from boazpoolman/feature/fix-import-on-bootstrap
feat: Wait for importAllConfig to finish
2021-10-22 13:53:07 +02:00
Boaz Poolman 05433c9c8c feat: Wait for importAllConfig to finish 2021-10-16 11:47:44 +02:00
Boaz Poolman c9dd10762f fix: Use Strapi service for assignPermissions 2021-10-15 15:02:34 +02:00
Boaz Poolman 74498e6d1c feat: Admin roles (wip) 2021-10-15 14:54:58 +02:00
Boaz Poolman 52dd4b4f55 chore: Disable unit tests pipeline 2021-10-14 17:41:55 +02:00
Boaz Poolman 10c361b27e style: Fix eslint warnings 2021-10-14 17:39:53 +02:00
Boaz Poolman d5b8b0b719 refactor(v4): Get config diff in admin 2021-10-14 17:33:21 +02:00
Boaz Poolman 41a9bfdf6c refactor(v4): Base admin migration 2021-10-14 17:13:12 +02:00
Boaz Poolman 75711f7da4 feat: Abstract types 2021-10-14 16:37:32 +02:00
Boaz Poolman 8c3c2e7e3f refactor(v4): Base migration 2021-10-14 14:37:00 +02:00
Boaz Poolman 9028adde12 docs: Update readme 2021-10-13 17:34:57 +02:00
Boaz Poolman f771baf2c0 chore: Miscellaneous 2021-10-13 17:31:16 +02:00
Boaz Poolman 86b6c8e70f
Merge pull request #16 from alexzrp/master
Added replace by double-colon in filename
2021-10-13 17:23:00 +02:00
alexzrp 7a5a8843e3 🐛 fix: added windows support 2021-09-21 17:53:08 -03:00
Alex Gotardi 2ab3909bae
Merge pull request #1 from alexzrp/windows
Windows
2021-09-21 10:54:20 -03:00
alexzrp 93863f99d1 :fix: Added windows support 2021-09-21 10:48:30 -03:00
Boaz Poolman f78d6643b7 🐛 🔧 chore: husky git hooks
fix: added windows support
2021-09-21 10:43:28 -03:00
Boaz Poolman 9f358cb80b feat: new i18n-locale config type 2021-06-02 15:23:01 +02:00
Boaz Poolman 965ef42eac 🎨 style: add missing semicolon 2021-06-02 15:18:28 +02:00
Boaz Poolman 821a6a02bf 🔧 chore: husky git hooks 2021-05-12 17:24:42 +02:00
Boaz Poolman 9c33ed50de chore: remove test file 2021-05-12 17:11:16 +02:00
Boaz Poolman c1d48d752c chore: add husky 2021-05-12 17:08:28 +02:00
Boaz Poolman 54a47d42bd waa 2021-05-12 17:04:26 +02:00
317 changed files with 34064 additions and 1396 deletions

View File

@ -1,7 +1,12 @@
root = true
[*]
end_of_line = lf
insert_final_newline = false
indent_style = space
indent_size = 2
end_of_line = LF
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

8
.eslintignore Normal file
View File

@ -0,0 +1,8 @@
**/node_modules
**/public
**/build
**/dist
**/config
**/scripts
**/docs
**/playground

529
.eslintrc Normal file
View File

@ -0,0 +1,529 @@
{
"root": true,
"extends": ["react-app", "airbnb"],
"parser": "babel-eslint",
"plugins": [
"babel",
"react",
"jsx-a11y",
"import",
"react-hooks"
],
"env": {
"browser": true,
"es6": true,
"commonjs": true,
"node": true
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"globals": {
"strapi": true
},
"overrides": [
{
"files": [
"**/*.cy.*",
"./cypress/**/*.*"
],
"extends": [
"plugin:cypress/recommended"
],
"parserOptions": {
"project": "./tsconfig.cypress.json"
}
}
],
"rules": {
"import/no-unresolved": [2, {
"ignore": [
"@strapi/strapi/admin",
"@strapi/icons/symbols",
"@strapi/admin/strapi-admin"
]
}],
"template-curly-spacing" : "off",
"indent" : "off",
"react/jsx-fragments": "off",
"react/jsx-props-no-spreading": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "off",
"react/no-unused-prop-types": "warn",
"react/jsx-no-target-blank": "error",
"no-invalid-this": "off",
"babel/no-invalid-this": "error",
"arrow-spacing": "warn",
"implicit-arrow-linebreak": "warn",
"react/no-unused-state": "warn",
"react/boolean-prop-naming": "off",
"react/destructuring-assignment": ["warn", "always", { "ignoreClassFields": true }],
"react/no-access-state-in-setstate": "warn",
"operator-linebreak": "warn",
"no-useless-constructor": "warn",
"react/no-danger": "off",
"react/jsx-indent-props": "warn",
"react/jsx-curly-brace-presence": "warn",
"react/jsx-key": "error",
"react/jsx-boolean-value": "warn",
"react/jsx-closing-tag-location": "warn",
"import/extensions": "error",
"newline-per-chained-call": "warn",
"prefer-arrow-callback": "warn",
"block-spacing": "warn",
"one-var-declaration-per-line": "warn",
"prefer-const": "warn",
"import/first": "off",
"react/jsx-max-props-per-line": 1,
"react/jsx-first-prop-new-line": "warn",
"react/jsx-equals-spacing": "warn",
"react/jsx-indent": "warn",
"react/jsx-closing-bracket-location": "off",
"import/no-mutable-exports": "error",
"import/no-extraneous-dependencies": "off",
"object-shorthand": ["off", "never"],
"object-curly-newline": "off",
"arrow-body-style": "off",
"comma-dangle": ["warn", "always-multiline"],
"import/prefer-default-export": "off",
"no-cond-assign": "warn",
"no-confusing-arrow": "off",
"no-console": "off",
"no-constant-condition": "warn",
"no-control-regex": "warn",
"no-continue": "warn",
"react/forbid-prop-types": "warn",
"no-debugger": "warn",
"no-dupe-args": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty": "warn",
"no-empty-character-class": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "warn",
"no-extra-semi": "warn",
"no-func-assign": "error",
"no-inner-declarations": "error",
"no-invalid-regexp": "error",
"no-mixed-operators": "off",
"no-irregular-whitespace": "error",
"no-negated-in-lhs": "error",
"no-obj-calls": "error",
"no-regex-spaces": "warn",
"no-sparse-arrays": "error",
"no-unreachable": "warn",
"use-isnan": "error",
"valid-jsdoc": "warn",
"valid-typeof": "error",
"array-callback-return": "off",
"block-scoped-var": "off",
"prefer-destructuring": "warn",
"complexity": "off",
"consistent-return": "off",
"curly": "warn",
"default-case": "warn",
"dot-notation": "off",
"eqeqeq": "warn",
"guard-for-in": "off",
"no-alert": "warn",
"no-caller": "error",
"no-div-regex": "off",
"no-else-return": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-fallthrough": "error",
"no-floating-decimal": "error",
"no-implied-eval": "error",
"no-iterator": "error",
"no-labels": "off",
"no-lone-blocks": "warn",
"no-loop-func": "error",
"no-multi-spaces": "warn",
"no-multi-str": "error",
"no-native-reassign": "error",
"no-new": "warn",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-octal": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-process-env": "off",
"no-proto": "error",
"no-redeclare": "error",
"no-return-assign": "off",
"arrow-parens": ["warn", "always", { "requireForBlockBody": false }],
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-throw-literal": "error",
"no-unused-expressions": "warn",
"no-void": "error",
"no-with": "error",
"radix": "off",
"vars-on-top": "off",
"wrap-iife": "error",
"yoda": "warn",
"strict": "off",
"no-catch-shadow": "error",
"no-delete-var": "error",
"no-label-var": "error",
"no-shadow": "warn",
"no-shadow-restricted-names": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-multi-assign": "warn",
"no-undefined": "error",
"no-unused-vars": ["warn", { "args": "none", "ignoreRestSiblings": true }],
"no-use-before-define": [
"error",
{ "functions": false, "classes": true, "variables": true }
],
"no-restricted-properties": "warn",
"no-restricted-syntax": "warn",
"brace-style": "off",
"camelcase": "warn",
"comma-spacing": ["warn", { "before": false, "after": true }],
"comma-style": ["warn", "last"],
"consistent-this": ["off", "_this"],
"eol-last": "warn",
"func-names": "off",
"func-style": ["warn", "declaration", { "allowArrowFunctions": true }],
"key-spacing": ["warn", { "beforeColon": false, "afterColon": true }],
"max-nested-callbacks": ["warn", 5],
"new-cap": ["warn", { "newIsCap": true, "capIsNew": false }],
"new-parens": "warn",
"newline-after-var": "off",
"no-array-constructor": "off",
"no-inline-comments": "off",
"no-lonely-if": "warn",
"no-mixed-spaces-and-tabs": "warn",
"no-multiple-empty-lines": ["warn", { "max": 2 }],
"no-nested-ternary": "warn",
"no-new-object": "off",
"no-spaced-func": "warn",
"no-ternary": "off",
"no-trailing-spaces": "warn",
"no-underscore-dangle": "off",
"no-extra-parens": "off",
"padding-line-between-statements": "off",
"one-var": ["warn", "never"],
"operator-assignment": ["off", "never"],
"class-methods-use-this": "off",
"padded-blocks": ["off", "never"],
"lines-between-class-members": ["warn", "always"],
"quote-props": ["warn", "as-needed"],
"quotes": ["off", "single"],
"semi": ["warn", "always"],
"semi-spacing": ["warn", { "before": false, "after": true }],
"sort-vars": "off",
"keyword-spacing": ["warn", { "before": true, "after": true }],
"space-before-blocks": ["warn", "always"],
"function-paren-newline": "off",
"space-before-function-paren": ["warn", { "anonymous": "never", "named": "never" }],
"object-curly-spacing": ["warn", "always"],
"array-bracket-spacing": ["warn", "never"],
"computed-property-spacing": ["warn", "never"],
"space-in-parens": ["warn", "never"],
"space-infix-ops": "warn",
"space-unary-ops": ["warn", { "words": true, "nonwords": false }],
"spaced-comment": ["warn", "always"],
"wrap-regex": "off",
"no-var": "error",
"generator-star-spacing": ["error", "before"],
"max-depth": ["warn", 4],
"max-len": ["off", 80, 2],
"max-params": ["off", 99],
"max-statements": "off",
"no-bitwise": "off",
"no-plusplus": "off",
"react/display-name": "off",
"react/jsx-tag-spacing": "warn",
"jsx-quotes": ["warn", "prefer-double"],
"react/jsx-no-undef": "error",
"react/jsx-sort-props": "off",
"react/jsx-uses-react": "error",
"react/prefer-stateless-function": "warn",
"react/jsx-uses-vars": "error",
"react/jsx-no-bind": "error",
"react/no-did-mount-set-state": "warn",
"react/no-will-update-set-state": "warn",
"react/no-did-update-set-state": "warn",
"react/no-multi-comp": "off",
"react/no-unknown-property": "warn",
"react/prop-types": "off",
"react/react-in-jsx-scope": "error",
"react/self-closing-comp": "warn",
"react/jsx-wrap-multilines": "warn",
"react/no-array-index-key": "warn",
"react/no-unescaped-entities": "warn",
"react/sort-comp": "off",
"jsx-a11y/no-static-element-interactions": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"react/jsx-one-expression-per-line": "off",
"jsx-a11y/anchor-is-valid": "off",
"jsx-a11y/alt-text": "warn",
"jsx-a11y/label-has-for": [
"warn",
{
"required": {
"some": ["nesting", "id"]
}
}
],
"jsx-a11y/img-redundant-alt": "warn",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/anchor-has-content": "off",
"jsx-a11y/label-has-associated-control": "warn",
"jsx-a11y/mouse-events-have-key-events": "off",
"jsx-a11y/interactive-supports-focus": "off",
"jsx-a11y/no-distracting-elements": "warn",
"jsx-a11y/heading-has-content": "warn",
"jsx-a11y/html-has-lang": "warn",
"jsx-a11y/href-no-hash": "off",
"react/jsx-filename-extension": "off",
"jsx-a11y/no-noninteractive-tabindex": "warn",
"jsx-a11y/media-has-caption": "off"
}
}

46
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,46 @@
---
name: 🐛 Bug Report
about: Create a report to help improve this plugin
---
<!--
Hello 👋 Thank you for submitting an issue.
-->
## Bug report
### Describe the bug
A clear and concise description of what the bug is.
### Steps to reproduce the behavior
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
### Expected behavior
A clear and concise description of what you expected to happen.
### Screenshots
If applicable, add screenshots to help explain your problem.
### Code snippets
If applicable, add code samples to help explain your problem.
### System
- Node.js version: <!-- Please ensure you are using the Node LTS version (v12 / v14) -->
- NPM version:
- Strapi version:
- Plugin version:
- Database:
- Operating system:
### Additional context
Add any other context about the problem here.

View File

@ -0,0 +1,26 @@
---
name: 🚀 Feature Request
about: Suggest an idea to help make this plugin even better!
---
<!--
Hello 👋 Thank you for submitting a feature request.
-->
## Feature request
### Summary
Quick summary what's this feature request about.
### Why is it needed?
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
### Suggested solution(s)
A clear and concise description of what you want to happen.
### Related issue(s)/PR(s)
Let us know if this is related to any issue/pull request.

26
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,26 @@
<!--
Hello 👋 Thank you for submitting a pull request.
To help us merge your PR, make sure to follow the instructions below:
- Create or update the documentation.
- Create or update the tests.
- Refer to the issue you are closing in the PR description - fix #issue
- Specify if the PR is in WIP (work in progress) state or ready to be merged
-->
### What does it do?
Describe the technical changes you did.
### Why is it needed?
Describe the issue you are solving.
### How to test it?
Provide information about the environment and the path to verify the behaviour.
### Related issue(s)/PR(s)
Let us know if this is related to any issue/pull request

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 164 KiB

52
.github/workflows/deploy-docs.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: Deploy Docs
on:
workflow_dispatch:
release:
types: [published]
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment:
name: docs.pluginpal.io
url: https://docs.pluginpal.io/config-sync
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker
uses: actions/setup-node@v4
with:
node-version: '14'
- name: Build a Docker image
run: |
cd docs
docker build \
-t docs-config-sync:latest .
docker save -o ../docs-config-sync-latest.tar docs-config-sync:latest
- name: Transfer the Docker image to the Dokku server
uses: appleboy/scp-action@v0.1.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_CI_USERNAME }}
password: ${{ secrets.SSH_CI_PASSWORD }}
source: docs-config-sync-latest.tar
target: /var/lib/dokku/data/storage/docs/docker-images
- name: Deploy the Dokku app based on the Docker image
uses: appleboy/ssh-action@v0.1.10
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_CI_USERNAME }}
password: ${{ secrets.SSH_CI_PASSWORD }}
script_stop: true
script: |
sudo docker load -i /var/lib/dokku/data/storage/docs/docker-images/docs-config-sync-latest.tar
DOCS_CONFIG_SYNC_LATEST_IMAGE=$(sudo docker images --format "{{.ID}}" docs-config-sync:latest)
sudo docker tag docs-config-sync:latest docs-config-sync:$DOCS_CONFIG_SYNC_LATEST_IMAGE
dokku git:from-image docs-config-sync docs-config-sync:$DOCS_CONFIG_SYNC_LATEST_IMAGE
sudo docker system prune --all --force

55
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: Publish to NPM
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
always-auth: true
node-version: 18
cache: 'yarn'
registry-url: 'https://registry.npmjs.org/'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build the plugin
run: yarn build
- name: Get the release tag version
id: get_version
run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
- name: Extract pre-release tag if any
id: extract_tag
run: |
VERSION="${{ steps.get_version.outputs.VERSION }}"
if [[ $VERSION == *-* ]]; then
# Extract everything between hyphen and last period (or end of string)
PRETAG=$(echo $VERSION | sed -E 's/.*-([^.]+).*/\1/')
echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT
echo "NPM_TAG=$PRETAG" >> $GITHUB_OUTPUT
else
echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT
echo "NPM_TAG=latest" >> $GITHUB_OUTPUT
fi
- name: Get source branch
id: get_branch
run: |
RELEASE_COMMIT=$(git rev-list -n 1 ${{ steps.get_version.outputs.VERSION }})
SOURCE_BRANCH=$(git branch -r --contains $RELEASE_COMMIT | grep -v HEAD | head -n 1 | sed 's/.*origin\///')
echo "SOURCE_BRANCH=$SOURCE_BRANCH" >> $GITHUB_OUTPUT
- name: Set package version
run: yarn version --new-version "${{ steps.get_version.outputs.VERSION }}" --no-git-tag-version
- name: Publish package
run: yarn publish --access public --tag ${{ steps.extract_tag.outputs.NPM_TAG }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Push version bump
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'chore: Bump version to ${{ steps.get_version.outputs.VERSION }}'
file_pattern: 'package.json'
branch: master

79
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,79 @@
name: Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
- develop
- beta
jobs:
lint:
name: 'lint'
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Run eslint
run: yarn run eslint
test:
name: 'test'
needs: [lint]
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install dependencies plugin
run: yarn --no-lockfile --unsafe-perm
- name: Push the package to yalc
run: yarn build
- name: Add yalc package to the playground
run: yarn playground:yalc-add
- name: Install dependencies playground
run: cd playground && yarn install --unsafe-perm
- name: Build playground
run: yarn playground:build
# - name: Run unit tests
# run: yarn test:unit
- name: Run integration tests
run: yarn run -s test:integration
- name: Run end-to-end tests
uses: cypress-io/github-action@v6
with:
start: yarn playground:start
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to `warn`
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-videos
path: cypress/videos
if-no-files-found: ignore # 'warn' or 'error' are also available, defaults to `warn`
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
token: ${{ secrets.CODECOV }}
flags: unit
verbose: true
fail_ci_if_error: true

11
.gitignore vendored
View File

@ -3,10 +3,19 @@ coverage
node_modules
stats.json
package-lock.json
yarn.lock
files
# Cruft
.DS_Store
npm-debug.log
.idea
# Production build
build
dist
bundle
# Cypress
cypress/screenshots/
cypress/videos/
cypress/downloads/

128
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[@boazpoolman](https://twitter.com/boazpoolman) on twitter.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

90
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,90 @@
# Contributing
We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project.
## Development Workflow
This plugin provides a local development instance of Strapi to develop it's features. We call this instance `playground` and it can be found in the playground folder in the root of the project. For that reason it is not needed to have your own Strapi instance running to work on this plugin. Just clone the repo and you're ready to go!
#### 1. Fork the [repository](https://github.com/pluginpal/strapi-plugin-config-sync)
[Go to the repository](https://github.com/pluginpal/strapi-plugin-config-sync) and fork it to your own GitHub account.
#### 2. Clone the forked repository
```bash
git clone git@github.com:YOUR_USERNAME/strapi-plugin-config-sync.git
```
#### 3. Install the dependencies
Go to the folder and install the dependencies
```bash
cd strapi-plugin-config-sync && yarn install
```
#### 4. Install the playground dependencies
Run this in the root of the repository
```bash
yarn playground:install
```
#### 5. Run the compiler of the plugin
We use `yalc` to publish the package to a local registry. Run the following command o watch for changes and push to `yalc` every time a change is made:
```bash
yarn develop
```
#### 6. Start the playground instance
Leave the watcher running, open up a new terminal window and browse back to the root of the plugin repo. Run the following command:
```bash
yarn playground:develop
```
This will start the playground instance that will have the plugin installed from the `yalc` registry. Browse to http://localhost:1337 and create a test admin user to log in to the playground.
#### 7. Start your contribution!
You can now start working on your contribution. If you had trouble setting up this testing environment please feel free to report an issue on Github.
### Commit message convention
We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
- `fix`: bug fixes, e.g. fix crash due to deprecated method.
- `feat`: new features, e.g. add new method to the module.
- `refactor`: code refactor, e.g. migrate from class components to hooks.
- `docs`: changes into documentation, e.g. add usage example for the module..
- `test`: adding or updating tests, eg add integration tests using detox.
- `chore`: tooling changes, e.g. change CI config.
### Linting and tests
[ESLint](https://eslint.org/)
We use [ESLint](https://eslint.org/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing.
### Scripts
The `package.json` file contains various scripts for common tasks:
- `yarn eslint`: lint files with ESLint.
- `yarn eslint:fix`: auto-fix ESLint issues.
- `yarn test:integration`: run integration tests with Jest.
### Sending a pull request
When you're sending a pull request:
- Prefer small pull requests focused on one change.
- Verify that linters and tests are passing.
- Review the documentation to make sure it looks good.
- Follow the pull request template when opening a pull request.
- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue.

156
README.md
View File

@ -1,103 +1,105 @@
# Strapi Plugin Config Sync
<div align="center">
<h1>Strapi config-sync plugin</h1>
<p style="margin-top: 0;">This plugin is a multi-purpose tool to manage your Strapi database records through JSON files. Mostly used to version controlconfig data for automated deployment, automated tests and data sharing for collaboration purposes.</p>
A lot of configuration of your Strapi project is stored in the database. Like core_store, user permissions, user roles & webhooks. Things you might want to have the same on all environments. But when you update them locally, you will have to manually update them on all other environments too.
<a href="https://docs.pluginpal.io/config-sync">Read the documentation</a>
<p>
<a href="https://www.npmjs.org/package/strapi-plugin-config-sync">
<img src="https://img.shields.io/npm/v/strapi-plugin-config-sync/latest.svg" alt="NPM Version" />
</a>
<a href="https://www.npmjs.org/package/strapi-plugin-config-sync">
<img src="https://img.shields.io/npm/dm/strapi-plugin-config-sync" alt="Monthly download on NPM" />
</a>
<a href="https://codecov.io/gh/boazpoolman/strapi-plugin-config-sync">
<img src="https://img.shields.io/github/actions/workflow/status/boazpoolman/strapi-plugin-config-sync/tests.yml?branch=master" alt="CI build status" />
</a>
<a href="https://codecov.io/gh/boazpoolman/strapi-plugin-config-sync">
<img src="https://codecov.io/gh/boazpoolman/strapi-plugin-config-sync/coverage.svg?branch=master" alt="codecov.io" />
</a>
</p>
</div>
That's where this plugin comes in to play. It allows you to export these configs as individual JSON files for each config, and write them somewhere in your project. With the configs written in your filesystem you can keep track of them through version control (git), and easily pull and import them across environments.
## ✨ Features
Importing, exporting and keeping track of config changes is done in the admin page of the plugin.
- **CLI** - `config-sync` CLI for syncing the config from the command line
- **GUI** - Settings page for syncing the config in Strapi admin
- **Partial sync** - Import or export only specific portions of config
- **Custom types** - Include your custom collection types in the sync process
- **Import on bootstrap** - Easy automated deployment with `importOnBootstrap`
- **Exclusion** - Exclude single config entries or all entries of a given type
- **Diff viewer** - A git-style diff viewer to inspect the config changes
**THIS PLUGIN IS NOT STABLE**
## ⏳ Getting started
**PLEASE USE WITH CARE**
[Read the Getting Started tutorial](https://docs.pluginpal.io/config-sync) or follow the steps below:
<img src=".github/config-diff.png" alt="Strapi config-sync changes" />
```bash
# using yarn
yarn add strapi-plugin-config-sync
## Installation
Use `npm` or `yarn` to install and build the plugin.
yarn add strapi-plugin-config-sync
yarn build
yarn develop
Add the export path to the `watchIgnoreFiles` list in `config/server.js`.
# using npm
npm install strapi-plugin-config-sync --save
```
Add the export path to the `watchIgnoreFiles` list in the `config/admin.js` file.
This way your app won't reload when you export the config in development.
##### `config/server.js`:
##### `config/admin.js`:
```
module.exports = ({ env }) => ({
// ...
watchIgnoreFiles: [
'**/config/sync/**',
],
});
```
admin: {
auth: {
// ...
},
watchIgnoreFiles: [
'**/config-sync/files/**',
],
},
After successful installation you have to rebuild the admin UI so it'll include this plugin. To rebuild and restart Strapi run:
```bash
# using yarn
yarn build
yarn develop
## Settings
The settings of the plugin can be overridden in the `config/plugins.js` file.
In the example below you can see how, and also what the default settings are.
# using npm
npm run build
npm run develop
```
##### `config/plugins.js`:
module.exports = ({ env }) => ({
// ...
'config-sync': {
destination: "extensions/config-sync/files/",
minify: false,
importOnBootstrap: false,
include: [
"core-store",
"role-permissions"
],
exclude: [
"core-store.plugin_users-permissions_grant"
]
},
// ...
});
The **Config Sync** plugin should now appear in the **Settings** section of your Strapi app.
| Property | Type | Description |
| -------- | ---- | ----------- |
| destination | string | The path for reading and writing the sync files. |
| minify | bool | When enabled all the exported JSON files will be minified. |
| 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 | Configs types you want to include in the syncing process. Allowed values: `core-store`, `role-permissions`, `webhooks`. |
| 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. |
To start tracking your config changes you have to make the first export. This will dump all your configuration data to the `/config/sync` directory. You can export either through [the CLI](https://docs.pluginpal.io/config-sync/cli) or [Strapi admin panel](https://docs.pluginpal.io/config-sync/admin-gui)
## Naming convention
All the config files written in the file destination have the same naming convention. It goes as follows:
Enjoy 🎉
[config-type].[config-name].json
## 📓 Documentation
- `config-type` - Corresponds to the value in from the include setting.
- `config-name` - The unique identifier of the config.
- For `core-store` config this is the `key` value.
- For `role-permissions` config this is the `type` value.
- For `webhooks` config this is the `id` value
See our dedicated [repository](https://github.com/pluginpal/docs) for all of PluginPal's documentation, or view the Config Sync documentation live:
## TODOs
- ~~Exporting of user roles & permissions~~
- ~~Exporting of webhooks~~
- ~~Specify which tables you want to track in the plugin configurations~~
- Exporting of EE roles & permissions
- Add partial import/export functionality
- Add CLI commands for importing/exporting
- ~~Track config deletions~~
- [Config Sync documentation](https://docs.pluginpal.io/config-sync)
## 🤝 Contributing
Feel free to fork and make a pull request of this plugin. All the input is welcome!
## ⭐️ Show your support
Give a star if this project helped you.
## Credits
Shout out to [@ScottAgirs](https://github.com/ScottAgirs) for making [strapi-plugin-migrate](https://github.com/ijsto/strapi-plugin-migrate) as it was a big help while making the config-sync plugin.
## Resources
- [MIT License](LICENSE.md)
## Links
## 🔗 Links
- [PluginPal marketplace](https://www.pluginpal.io/plugin/config-sync)
- [NPM package](https://www.npmjs.com/package/strapi-plugin-config-sync)
- [GitHub repository](https://github.com/boazpoolman/strapi-plugin-config-sync)
- [Strapi marketplace](https://market.strapi.io/plugins/strapi-plugin-config-sync)
## 🌎 Community support
- For general help using Strapi, please refer to [the official Strapi documentation](https://strapi.io/documentation/).
- For support with this plugin you can DM me in the Strapi Discord [channel](https://discord.strapi.io/).
## 📝 Resources
- [MIT License](https://github.com/pluginpal/strapi-plugin-config-sync/blob/master/LICENSE.md)

View File

@ -1,49 +0,0 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { useDispatch } from 'react-redux';
import { isEmpty } from 'lodash';
import { Button } from '@buffetjs/core';
import ConfirmModal from '../ConfirmModal';
import { exportAllConfig, importAllConfig } from '../../state/actions/Config';
const ActionButtons = ({ diff }) => {
const dispatch = useDispatch();
const [modalIsOpen, setModalIsOpen] = useState(false);
const [actionType, setActionType] = useState('');
const closeModal = () => {
setActionType('');
setModalIsOpen(false);
};
const openModal = (type) => {
setActionType(type);
setModalIsOpen(true);
};
return (
<ActionButtonsStyling>
<Button disabled={isEmpty(diff.diff)} color="primary" label="Import" onClick={() => openModal('import')} />
<Button disabled={isEmpty(diff.diff)} color="primary" label="Export" onClick={() => openModal('export')} />
{!isEmpty(diff.diff) && (
<h4 style={{ display: 'inline' }}>{Object.keys(diff.diff).length} {Object.keys(diff.diff).length === 1 ? "config change" : "config changes"}</h4>
)}
<ConfirmModal
isOpen={modalIsOpen}
onClose={closeModal}
type={actionType}
onSubmit={() => actionType === 'import' ? dispatch(importAllConfig()) : dispatch(exportAllConfig())}
/>
</ActionButtonsStyling>
);
}
const ActionButtonsStyling = styled.div`
padding: 10px 0 20px 0;
> button {
margin-right: 10px;
}
`;
export default ActionButtons;

View File

@ -0,0 +1,61 @@
import React from 'react';
import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux';
import isEmpty from 'lodash/isEmpty';
import { Button, Typography } from '@strapi/design-system';
import { Map } from 'immutable';
import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { useIntl } from 'react-intl';
import ConfirmModal from '../ConfirmModal';
import { exportAllConfig, importAllConfig, downloadZip } from '../../state/actions/Config';
const ActionButtons = () => {
const { post, get } = getFetchClient();
const dispatch = useDispatch();
const { toggleNotification } = useNotification();
const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS();
const { formatMessage } = useIntl();
return (
<ActionButtonsStyling>
<ConfirmModal
type="import"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button>
)}
onSubmit={(force) => dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get))}
/>
<ConfirmModal
type="export"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button>
)}
onSubmit={(force) => dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
/>
{!isEmpty(partialDiff) && (
<Typography variant="epsilon">{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</Typography>
)}
<Button onClick={() => dispatch(downloadZip(toggleNotification, formatMessage, post, get))}>{formatMessage({ id: 'config-sync.Buttons.DownloadConfig' })}</Button>
</ActionButtonsStyling>
);
};
const ActionButtonsStyling = styled.div`
padding: 10px 0 20px 0;
display: flex;
align-items: center;
> button {
margin-right: 10px;
}
> button:last-of-type {
margin-left: auto;
}
`;
export default ActionButtons;

View File

@ -1,49 +0,0 @@
import React from 'react';
import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer';
import { AttributeIcon } from '@buffetjs/core';
import {
HeaderModal,
HeaderModalTitle,
Modal,
ModalBody,
ModalFooter,
} from 'strapi-helper-plugin';
const ConfigDiff = ({ isOpen, onClose, onToggle, oldValue, newValue, configName }) => {
return (
<Modal
isOpen={isOpen}
onClosed={onClose}
onToggle={onToggle}
>
<HeaderModal>
<section style={{ alignItems: 'center' }}>
<AttributeIcon type='enum' />
<HeaderModalTitle style={{ marginLeft: 15 }}>Config changes for {configName}</HeaderModalTitle>
</section>
</HeaderModal>
<ModalBody style={{
paddingTop: '0.5rem',
paddingBottom: '3rem'
}}>
<div className="container-fluid">
<section style={{ marginTop: 20 }}>
<ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)}
splitView={true}
compareMethod={DiffMethod.WORDS}
/>
</section>
</div>
</ModalBody>
<ModalFooter>
<section style={{ alignItems: 'center' }}>
</section>
</ModalFooter>
</Modal>
);
}
export default ConfigDiff;

View File

@ -0,0 +1,64 @@
import React from 'react';
import RDV, { DiffMethod } from 'react-diff-viewer-continued';
import { useIntl } from 'react-intl';
/**
* An issue with the diff-viewer library causes a difference in the way the library is exported.
* Depending on whether the library is loaded through the browser or through the server, the default export may or may not be present.
* This causes issues with SSR and the way the library is imported.
*
* Below a workaround to fix this issue.
*
* @see https://github.com/Aeolun/react-diff-viewer-continued/issues/43
*/
let ReactDiffViewer;
if (typeof RDV.default !== 'undefined') {
ReactDiffViewer = RDV.default;
} else {
ReactDiffViewer = RDV;
}
import {
Modal,
Grid,
Typography,
} from '@strapi/design-system';
const ConfigDiff = ({ oldValue, newValue, configName, trigger }) => {
const { formatMessage } = useIntl();
return (
<Modal.Root>
<Modal.Trigger>
{trigger}
</Modal.Trigger>
<Modal.Content>
<Modal.Header>
<Typography variant="omega" fontWeight="bold" textColor="neutral800">
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
</Typography>
</Modal.Header>
<Modal.Body>
<Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<Grid.Item col={6}>
<Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
</Grid.Item>
<Grid.Item col={6}>
<Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</Grid.Item>
</Grid.Root>
<Typography variant="pi">
<ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)}
splitView
compareMethod={DiffMethod.WORDS}
/>
</Typography>
</Modal.Body>
</Modal.Content>
</Modal.Root>
);
};
export default ConfigDiff;

View File

@ -1,52 +0,0 @@
import React from 'react';
import styled from 'styled-components';
const CustomRow = ({ row }) => {
const { config_name, config_type, state, onClick } = row;
return (
<tr onClick={() => onClick(config_type, config_name)}>
<td>
<p>{config_name}</p>
</td>
<td>
<p>{config_type}</p>
</td>
<td>
<p style={stateStyle(state)}>{state}</p>
</td>
</tr>
);
};
const stateStyle = (state) => {
let style = {
display: 'inline-flex',
padding: '0 10px',
borderRadius: '12px',
height: '24px',
alignItems: 'center',
fontWeight: '500',
};
if (state === 'Only in DB') {
style.backgroundColor = '#cbf2d7';
style.color = '#1b522b';
}
if (state === 'Only in sync dir') {
style.backgroundColor = '#f0cac7';
style.color = '#3d302f';
}
if (state === 'Different') {
style.backgroundColor = '#e8e6b7';
style.color = '#4a4934';
}
return style;
};
export default CustomRow

View File

@ -0,0 +1,65 @@
import React from 'react';
import { Tr, Td, Checkbox, Typography } from '@strapi/design-system';
const CustomRow = ({ row, checked, updateValue, ...props }) => {
const { configName, configType, state, onClick } = row;
const stateStyle = (stateStr) => {
const style = {
display: 'inline-flex',
padding: '0 10px',
borderRadius: '12px',
height: '24px',
alignItems: 'center',
fontWeight: '500',
};
if (stateStr === 'Only in DB') {
style.backgroundColor = '#cbf2d7';
style.color = '#1b522b';
}
if (stateStr === 'Only in sync dir') {
style.backgroundColor = '#f0cac7';
style.color = '#3d302f';
}
if (stateStr === 'Different') {
style.backgroundColor = '#e8e6b7';
style.color = '#4a4934';
}
return style;
};
return (
<Tr
{...props}
onClick={(e) => {
if (e.target.type !== 'checkbox') {
onClick(configType, configName);
}
}}
style={{ cursor: 'pointer' }}
>
<Td>
<Checkbox
aria-label={`Select ${configName}`}
checked={checked}
onCheckedChange={updateValue}
/>
</Td>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega">{configName}</Typography>
</Td>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega">{configType}</Typography>
</Td>
<Td onClick={(e) => props.onClick(e)}>
<Typography variant="omega" style={stateStyle(state)}>{state}</Typography>
</Td>
</Tr>
);
};
export default CustomRow;

View File

@ -1,108 +0,0 @@
import React, { useState, useEffect } from 'react';
import { Table } from '@buffetjs/core';
import { isEmpty } from 'lodash';
import ConfigDiff from '../ConfigDiff';
import FirstExport from '../FirstExport';
import ConfigListRow from './ConfigListRow';
const headers = [
{
name: 'Config name',
value: 'config_name',
},
{
name: 'Config type',
value: 'config_type',
},
{
name: 'State',
value: 'state',
},
];
const ConfigList = ({ diff, isLoading }) => {
const [openModal, setOpenModal] = useState(false);
const [originalConfig, setOriginalConfig] = useState({});
const [newConfig, setNewConfig] = useState({});
const [configName, setConfigName] = useState('');
const [rows, setRows] = useState([]);
const getConfigState = (configName) => {
if (
diff.fileConfig[configName] &&
diff.databaseConfig[configName]
) {
return 'Different'
} else if (
diff.fileConfig[configName] &&
!diff.databaseConfig[configName]
) {
return 'Only in sync dir'
} else if (
!diff.fileConfig[configName] &&
diff.databaseConfig[configName]
) {
return 'Only in DB'
}
};
useEffect(() => {
if (isEmpty(diff.diff)) {
setRows([]);
return;
}
let formattedRows = [];
Object.keys(diff.diff).map((configName) => {
const type = configName.split('.')[0]; // Grab the first part of the filename.
const name = configName.split(/\.(.+)/)[1]; // Grab the rest of the filename minus the file extension.
formattedRows.push({
config_name: name,
config_type: type,
state: getConfigState(configName),
onClick: (config_type, config_name) => {
setOriginalConfig(diff.fileConfig[`${config_type}.${config_name}`]);
setNewConfig(diff.databaseConfig[`${config_type}.${config_name}`]);
setConfigName(`${config_type}.${config_name}`);
setOpenModal(true);
}
});
});
setRows(formattedRows);
}, [diff]);
const closeModal = () => {
setOriginalConfig({});
setNewConfig({});
setConfigName('');
setOpenModal(false);
};
if (!isLoading && !isEmpty(diff.message)) {
return <FirstExport />
}
return (
<div>
<ConfigDiff
isOpen={openModal}
oldValue={originalConfig}
newValue={newConfig}
onClose={closeModal}
onToggle={closeModal}
configName={configName}
/>
<Table
headers={headers}
customRow={ConfigListRow}
rows={!isLoading ? rows : []}
isLoading={isLoading}
tableEmptyText="No config changes. You are up to date!"
/>
</div>
);
}
export default ConfigList;

View File

@ -0,0 +1,157 @@
import React, { useState, useEffect } from 'react';
import { useIntl } from 'react-intl';
import { isEmpty } from 'lodash';
import { useDispatch } from 'react-redux';
import {
Table,
Thead,
Tbody,
Tr,
Th,
Typography,
Checkbox,
Loader,
} from '@strapi/design-system';
import ConfigDiff from '../ConfigDiff';
import FirstExport from '../FirstExport';
import NoChanges from '../NoChanges';
import ConfigListRow from './ConfigListRow';
import { setConfigPartialDiffInState } from '../../state/actions/Config';
const ConfigList = ({ diff, isLoading }) => {
const [originalConfig, setOriginalConfig] = useState({});
const [newConfig, setNewConfig] = useState({});
const [cName, setCname] = useState('');
const [rows, setRows] = useState([]);
const [checkedItems, setCheckedItems] = useState([]);
const dispatch = useDispatch();
const { formatMessage } = useIntl();
const getConfigState = (configName) => {
if (
diff.fileConfig[configName]
&& diff.databaseConfig[configName]
) {
return formatMessage({ id: 'config-sync.ConfigList.Different' });
} else if (
diff.fileConfig[configName]
&& !diff.databaseConfig[configName]
) {
return formatMessage({ id: 'config-sync.ConfigList.OnlyDir' });
} else if (
!diff.fileConfig[configName]
&& diff.databaseConfig[configName]
) {
return formatMessage({ id: 'config-sync.ConfigList.OnlyDB' });
}
};
useEffect(() => {
if (isEmpty(diff.diff)) {
setRows([]);
return;
}
const formattedRows = [];
const newCheckedItems = [];
Object.keys(diff.diff).map((name) => {
const type = name.split('.')[0]; // Grab the first part of the filename.
const formattedName = name.split(/\.(.+)/)[1]; // Grab the rest of the filename minus the file extension.
newCheckedItems.push(true);
formattedRows.push({
configName: formattedName,
configType: type,
state: getConfigState(name),
onClick: (configType, configName) => {
setOriginalConfig(diff.fileConfig[`${configType}.${configName}`]);
setNewConfig(diff.databaseConfig[`${configType}.${configName}`]);
setCname(`${configType}.${configName}`);
},
});
});
setCheckedItems(newCheckedItems);
setRows(formattedRows);
}, [diff]);
useEffect(() => {
const newPartialDiff = [];
checkedItems.map((item, index) => {
if (item && rows[index]) newPartialDiff.push(`${rows[index].configType}.${rows[index].configName}`);
});
dispatch(setConfigPartialDiffInState(newPartialDiff));
}, [checkedItems]);
if (isLoading) {
return (
<div style={{ textAlign: 'center', marginTop: 40 }}>
<Loader>{formatMessage({ id: 'config-sync.ConfigList.Loading' })}</Loader>
</div>
);
}
if (!isLoading && !isEmpty(diff.message)) {
return <FirstExport />;
}
if (!isLoading && isEmpty(diff.diff)) {
return <NoChanges />;
}
const allChecked = checkedItems && checkedItems.every(Boolean);
const isIndeterminate = checkedItems.some(Boolean) && !allChecked;
return (
<div>
<Table colCount={4} rowCount={rows.length + 1}>
<Thead>
<Tr>
<Th>
<Checkbox
aria-label={formatMessage({ id: 'config-sync.ConfigList.SelectAll' })}
checked={isIndeterminate ? "indeterminate" : allChecked}
onCheckedChange={(value) => setCheckedItems(checkedItems.map(() => value))}
/>
</Th>
<Th>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigName' })}</Typography>
</Th>
<Th>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.ConfigType' })}</Typography>
</Th>
<Th>
<Typography variant="sigma">{formatMessage({ id: 'config-sync.ConfigList.State' })}</Typography>
</Th>
</Tr>
</Thead>
<Tbody>
{rows.map((row, index) => (
<ConfigDiff
key={row.configName}
oldValue={originalConfig}
newValue={newConfig}
configName={cName}
trigger={(
<ConfigListRow
row={row}
checked={checkedItems[index]}
updateValue={() => {
checkedItems[index] = !checkedItems[index];
setCheckedItems([...checkedItems]);
}}
/>
)}
/>
))}
</Tbody>
</Table>
</div>
);
};
export default ConfigList;

View File

@ -1,34 +0,0 @@
import React from 'react';
import {
ModalConfirm,
} from 'strapi-helper-plugin';
import getTrad from '../../helpers/getTrad';
const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
if (!isOpen) return null;
return (
<ModalConfirm
confirmButtonLabel={{
id: getTrad(`popUpWarning.button.${type}`),
}}
isOpen={isOpen}
toggle={onClose}
onClosed={onClose}
onConfirm={() => {
onClose();
onSubmit();
}}
type="success"
content={{
id: getTrad(`popUpWarning.warning.${type}`),
values: {
br: () => <br />,
},
}}
/>
);
}
export default ConfirmModal;

View File

@ -0,0 +1,80 @@
import React, { useState } from 'react';
import { useIntl } from 'react-intl';
import { useSelector } from 'react-redux';
import {
Dialog,
Flex,
Typography,
Button,
Checkbox,
Divider,
Box,
Field,
} from '@strapi/design-system';
import { WarningCircle } from '@strapi/icons';
const ConfirmModal = ({ onClose, onSubmit, type, trigger }) => {
const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false));
const [force, setForce] = useState(false);
const { formatMessage } = useIntl();
return (
<Dialog.Root>
<Dialog.Trigger>
{trigger}
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>{formatMessage({ id: "config-sync.popUpWarning.Confirmation" })}</Dialog.Header>
<Dialog.Body>
<WarningCircle fill="danger600" width="32px" height="32px" />
<Flex size={2}>
<Flex justifyContent="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}_2` })}
</Typography>
</Flex>
</Flex>
{(soft && type === 'import') && (
<Box width="100%">
<Divider marginTop={4} />
<Box paddingTop={6}>
<Field.Root hint="Check this to ignore the soft setting.">
<Checkbox
onValueChange={(value) => setForce(value)}
value={force}
name="force"
>
{formatMessage({ id: 'config-sync.popUpWarning.force' })}
</Checkbox>
<Field.Hint />
</Field.Root>
</Box>
</Box>
)}
</Dialog.Body>
<Dialog.Footer>
<Dialog.Cancel>
<Button fullWidth variant="tertiary">
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button>
</Dialog.Cancel>
<Dialog.Action>
<Button
fullWidth
variant="secondary"
onClick={() => {
onSubmit(force);
}}
>
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button>
</Dialog.Action>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
);
};
export default ConfirmModal;

View File

@ -1,24 +0,0 @@
import styled from 'styled-components';
const ContainerFluid = styled.div`
padding: 18px 30px;
> div:first-child {
max-height: 33px;
}
.buttonOutline {
height: 30px;
padding: 0 15px;
border: 1px solid #dfe0e1;
font-weight: 500;
font-size: 13px;
&:before {
margin-right: 10px;
content: '\f08e';
font-family: 'FontAwesome';
font-size: 10px;
}
}
`;
export default ContainerFluid;

View File

@ -1,33 +0,0 @@
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { Button } from '@buffetjs/core';
import { exportAllConfig } from '../../state/actions/Config';
import ConfirmModal from '../ConfirmModal';
const FirstExport = () => {
const dispatch = useDispatch();
const [modalIsOpen, setModalIsOpen] = useState(false);
return (
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
textAlign: 'center',
height: '300px',
}}>
<ConfirmModal
isOpen={modalIsOpen}
onClose={() => setModalIsOpen(false)}
type={'export'}
onSubmit={() => dispatch(exportAllConfig())}
/>
<h3>Looks like this is your first time using config-sync for this project.</h3>
<p>Make the initial export!</p>
<Button color="primary" onClick={() => setModalIsOpen(true)}>Initial export</Button>
</div>
);
}
export default FirstExport;

View File

@ -0,0 +1,37 @@
import React from 'react';
import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';
import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { Button, EmptyStateLayout } from '@strapi/design-system';
import { EmptyDocuments } from '@strapi/icons/symbols';
import { exportAllConfig } from '../../state/actions/Config';
import ConfirmModal from '../ConfirmModal';
const FirstExport = () => {
const { post, get } = getFetchClient();
const { toggleNotification } = useNotification();
const dispatch = useDispatch();
const { formatMessage } = useIntl();
return (
<div>
<EmptyStateLayout
content={formatMessage({ id: 'config-sync.FirstExport.Message' })}
action={(
<ConfirmModal
type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
trigger={(
<Button>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>
)}
/>
)}
icon={<EmptyDocuments width={160} />}
/>
</div>
);
};
export default FirstExport;

View File

@ -1,26 +0,0 @@
/*
*
* HeaderComponent
*
*/
import React, { memo } from 'react';
import { Header } from '@buffetjs/custom';
import { useGlobalContext } from 'strapi-helper-plugin';
const HeaderComponent = () => {
const { formatMessage } = useGlobalContext();
const headerProps = {
title: {
label: formatMessage({ id: 'config-sync.Header.Title' }),
},
content: formatMessage({ id: 'config-sync.Header.Description' }),
};
return (
<Header {...headerProps} />
);
};
export default memo(HeaderComponent);

View File

@ -0,0 +1,26 @@
/*
*
* HeaderComponent
*
*/
import React, { memo } from 'react';
import { useIntl } from 'react-intl';
import { Layouts } from '@strapi/admin/strapi-admin';
import { Box } from '@strapi/design-system';
const HeaderComponent = () => {
const { formatMessage } = useIntl();
return (
<Box background="neutral100">
<Layouts.Header
title={formatMessage({ id: 'config-sync.Header.Title' })}
subtitle={formatMessage({ id: 'config-sync.Header.Description' })}
/>
</Box>
);
};
export default memo(HeaderComponent);

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

@ -1 +1 @@
export const __DEBUG__ = strapi.env === 'development';
export const __DEBUG__ = true; // TODO: set actual env.

0
admin/src/config/logger.js Executable file → Normal file
View File

View File

@ -7,20 +7,21 @@
import React from 'react';
import { Provider } from 'react-redux';
import ContainerFluid from '../../components/Container';
import Header from '../../components/Header';
import { Page } from '@strapi/strapi/admin';
import pluginPermissions from '../../permissions';
import Header from '../../components/Header';
import { store } from "../../helpers/configureStore";
import ConfigPage from '../ConfigPage';
const App = () => {
return (
<Provider store={store}>
<ContainerFluid>
<Page.Protect permissions={pluginPermissions.settings}>
<Provider store={store}>
<Header />
<ConfigPage />
</ContainerFluid>
</Provider>
</Provider>
</Page.Protect>
);
};

View File

@ -1,26 +0,0 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Map } from 'immutable';
import { getAllConfigDiff } from '../../state/actions/Config';
import ConfigList from '../../components/ConfigList';
import ActionButtons from '../../components/ActionButtons';
const ConfigPage = () => {
const dispatch = useDispatch();
const isLoading = useSelector((state) => state.getIn(['config', 'isLoading'], Map({})));
const configDiff = useSelector((state) => state.getIn(['config', 'configDiff'], Map({})));
useEffect(() => {
dispatch(getAllConfigDiff());
}, []);
return (
<div>
<ActionButtons diff={configDiff.toJS()} />
<ConfigList isLoading={isLoading} diff={configDiff.toJS()} />
</div>
);
}
export default ConfigPage;

View File

@ -0,0 +1,49 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Map } from 'immutable';
import {
Box,
Alert,
Typography,
} from '@strapi/design-system';
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 ConfigList from '../../components/ConfigList';
import ActionButtons from '../../components/ActionButtons';
const ConfigPage = () => {
const { toggleNotification } = useNotification();
const { get } = getFetchClient();
const { formatMessage } = useIntl();
const dispatch = useDispatch();
const isLoading = useSelector((state) => state.getIn(['config', 'isLoading'], Map({})));
const configDiff = useSelector((state) => state.getIn(['config', 'configDiff'], Map({})));
const appEnv = useSelector((state) => state.getIn(['config', 'appEnv', 'env']));
useEffect(() => {
dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
dispatch(getAppEnv(toggleNotification, formatMessage, get));
}, []);
return (
<Layouts.Content paddingBottom={8}>
{appEnv === 'production' && (
<Box paddingBottom={4}>
<Alert variant="danger">
<Typography variant="omega" fontWeight="bold">You&apos;re in the production environment</Typography><br />
Please be careful when syncing your config in production.<br />
Make sure you are not overriding critical config changes on import.
</Alert>
</Box>
)}
<ActionButtons />
<ConfigList isLoading={isLoading} diff={configDiff.toJS()} />
</Layouts.Content>
);
};
export default ConfigPage;

View File

@ -0,0 +1,9 @@
export function b64toBlob(dataURI, type) {
const byteString = atob(dataURI);
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type });
}

View File

@ -1,14 +1,12 @@
import { createStore, applyMiddleware, compose } from 'redux';
import { createLogger } from 'redux-logger';
import thunkMiddleware from 'redux-thunk';
import { Map } from 'immutable';
import rootReducer from '../state/reducers';
import loggerConfig from '../config/logger';
import { __DEBUG__ } from '../config/constants';
const configureStore = () => {
let initialStoreState = Map();
const initialStoreState = Map();
const enhancers = [];
const middlewares = [
@ -27,30 +25,12 @@ const configureStore = () => {
if (devtools) {
console.info('[setup] ✓ Enabling Redux DevTools Extension');
}
console.info('[setup] ✓ Enabling state logger');
const loggerMiddleware = createLogger({
level: 'info',
collapsed: true,
stateTransformer: (state) => state.toJS(),
predicate: (getState, action) => {
const state = getState();
const showBlacklisted = state.getIn(['debug', 'logs', 'blacklisted']);
if (loggerConfig.blacklist.indexOf(action.type) !== -1 && !showBlacklisted) {
return false;
}
return state.getIn(['debug', 'logs', 'enabled']);
},
});
middlewares.push(loggerMiddleware);
}
const composedEnhancers = devtools || compose;
const storeEnhancers = composedEnhancers(
applyMiddleware(...middlewares),
...enhancers
...enhancers,
);
const store = createStore(

View File

@ -1,5 +1,5 @@
import pluginId from './pluginId';
const getTrad = id => `${pluginId}.${id}`;
const getTrad = (id) => `${pluginId}.${id}`;
export default getTrad;

View File

@ -1,7 +1,8 @@
const pluginPkg = require('../../../package.json');
import pluginPkg from '../../../package.json';
const pluginId = pluginPkg.name.replace(
/^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 };

74
admin/src/index.cy.jsx Normal file
View File

@ -0,0 +1,74 @@
// <reference types="cypress" />
describe('Config Sync', () => {
beforeEach(() => {
cy.task('deleteFolder', 'playground/config/sync');
});
it('Check the config diff', () => {
cy.login();
cy.navigateToInterface();
cy.initialExport();
cy.makeConfigChanges();
cy.navigateToInterface();
cy.get('tbody tr').contains('plugin_users-permissions_advanced').click();
cy.contains('"unique_email": true,');
cy.contains('"unique_email": false,');
});
it('Download the config as zip', () => {
cy.login();
cy.navigateToInterface();
cy.initialExport();
cy.intercept({
method: 'GET',
url: '/config-sync/zip',
}).as('getConfigZip');
cy.get('button').contains('Download Config').click();
cy.wait('@getConfigZip').then((interception) => {
const configZipResponse = interception.response.body;
const downloadsFolder = Cypress.config('downloadsFolder');
cy.readFile(`${downloadsFolder}/${configZipResponse.name.replaceAll(':', '_')}`).should('exist');
});
});
it('Partial import & export', () => {
cy.login();
cy.navigateToInterface();
cy.initialExport();
cy.makeConfigChanges();
cy.navigateToInterface();
cy.get('button[aria-label="Select all entries"]').click();
cy.intercept({
method: 'POST',
url: '/config-sync/import',
}).as('importConfig');
cy.get('button[aria-label="Select plugin_upload_settings"]').click();
cy.get('button').contains('Import').click();
cy.get('button').contains('Yes, import').click();
cy.wait('@importConfig').its('response.statusCode').should('equal', 200);
cy.contains('plugin_users-permissions_advanced');
cy.contains('plugin_users-permissions_email');
cy.intercept({
method: 'POST',
url: '/config-sync/export',
}).as('exportConfig');
cy.get('button[aria-label="Select plugin_users-permissions_advanced"]').click();
cy.get('button').contains('Export').click();
cy.get('button').contains('Yes, export').click();
cy.wait('@exportConfig').its('response.statusCode').should('equal', 200);
cy.contains('plugin_users-permissions_email');
});
});

View File

@ -1,53 +1,65 @@
import React from 'react';
import pluginPkg from '../../package.json';
import pluginId from './helpers/pluginId';
import App from './containers/App';
import Initializer from './containers/Initializer';
import trads from './translations';
import { prefixPluginTranslations } from './helpers/prefixPluginTranslations';
import pluginPermissions from './permissions';
// import pluginIcon from './components/PluginIcon';
// import getTrad from './helpers/getTrad';
function Comp(props) {
return <App {...props} />;
}
const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
const { name } = pluginPkg.strapi;
export default strapi => {
const pluginDescription =
pluginPkg.strapi.description || pluginPkg.description;
export default {
register(app) {
app.registerPlugin({
description: pluginDescription,
id: pluginId,
isReady: true,
isRequired: pluginPkg.strapi.required || false,
name,
});
const icon = pluginPkg.strapi.icon;
const name = pluginPkg.strapi.name;
const plugin = {
icon,
name,
destination: `/plugins/${pluginId}`,
blockerComponent: null,
blockerComponentProps: {},
description: pluginDescription,
id: pluginId,
initializer: Initializer,
injectedComponents: [],
isReady: false,
layout: null,
leftMenuLinks: [],
leftMenuSections: [],
mainComponent: Comp,
name: pluginPkg.strapi.name,
preventComponentRendering: false,
trads,
menu: {
pluginsSectionLinks: [
app.createSettingSection(
{
id: pluginId,
intlLabel: {
id: `${pluginId}.plugin.name`,
defaultMessage: 'Config Sync',
},
},
[
{
destination: `/plugins/${pluginId}`, // Endpoint of the link
icon,
name,
label: {
id: `${pluginId}.plugin.name`, // Refers to a i18n
defaultMessage: 'Config Sync',
intlLabel: {
id: `${pluginId}.Settings.Tool.Title`,
defaultMessage: 'Interface',
},
id: 'config-sync-page',
to: `${pluginId}`,
Component: () => import('./containers/App'),
permissions: pluginPermissions['settings'],
},
],
},
};
);
},
bootstrap(app) {},
async registerTrads({ locales }) {
const importedTrads = await Promise.all(
locales.map((locale) => {
return import(`./translations/${locale}.json`)
.then(({ default: data }) => {
return {
data: prefixPluginTranslations(data, pluginId),
locale,
};
})
.catch(() => {
return {
data: {},
locale,
};
});
}),
);
return strapi.registerPlugin(plugin);
return Promise.resolve(importedTrads);
},
};

10
admin/src/permissions.js Normal file
View File

@ -0,0 +1,10 @@
const pluginPermissions = {
// This permission regards the main component (App) and is used to tell
// If the plugin link should be displayed in the menu
// And also if the plugin is accessible. This use case is found when a user types the url of the
// plugin directly in the browser
'menu-link': [{ action: 'plugin::config-sync.menu-link', subject: null }],
settings: [{ action: 'plugin::config-sync.settings.read', subject: null }],
};
export default pluginPermissions;

View File

@ -3,22 +3,22 @@
* Main actions
*
*/
import { saveAs } from 'file-saver';
import { b64toBlob } from '../../helpers/blob';
import { request } from 'strapi-helper-plugin';
import { Map } from 'immutable';
export function getAllConfigDiff() {
export function getAllConfigDiff(toggleNotification, formatMessage, get) {
return async function(dispatch) {
dispatch(setLoadingState(true));
try {
const configDiff = await request('/config-sync/diff', { method: 'GET' });
dispatch(setConfigDiffInState(configDiff));
const configDiff = await get('/config-sync/diff');
dispatch(setConfigPartialDiffInState([]));
dispatch(setConfigDiffInState(configDiff.data));
dispatch(setLoadingState(false));
} catch(err) {
strapi.notification.error('notification.error');
} catch (err) {
toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false));
}
}
};
}
export const SET_CONFIG_DIFF_IN_STATE = 'SET_CONFIG_DIFF_IN_STATE';
@ -29,36 +29,62 @@ export function setConfigDiffInState(config) {
};
}
export function exportAllConfig() {
return async function(dispatch) {
dispatch(setLoadingState(true));
try {
const { message } = await request('/config-sync/export', { method: 'GET' });
dispatch(setConfigDiffInState(Map({})));
strapi.notification.success(message);
dispatch(setLoadingState(false));
} catch(err) {
strapi.notification.error('notification.error');
dispatch(setLoadingState(false));
}
}
export const SET_CONFIG_PARTIAL_DIFF_IN_STATE = 'SET_CONFIG_PARTIAL_DIFF_IN_STATE';
export function setConfigPartialDiffInState(config) {
return {
type: SET_CONFIG_PARTIAL_DIFF_IN_STATE,
config,
};
}
export function importAllConfig() {
export function exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get) {
return async function(dispatch) {
dispatch(setLoadingState(true));
try {
const { message } = await request('/config-sync/import', { method: 'GET' });
dispatch(setConfigDiffInState(Map({})));
strapi.notification.success(message);
const response = await post('/config-sync/export', partialDiff);
toggleNotification({ type: 'success', message: response.data.message });
dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
dispatch(setLoadingState(false));
} catch(err) {
strapi.notification.error('notification.error');
} catch (err) {
toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false));
}
}
};
}
export function downloadZip(toggleNotification, formatMessage, post, get) {
return async function(dispatch) {
dispatch(setLoadingState(true));
try {
const { message, base64Data, name } = (await get('/config-sync/zip')).data;
toggleNotification({ type: 'success', message });
if (base64Data) {
saveAs(b64toBlob(base64Data, 'application/zip'), name, { type: 'application/zip' });
}
dispatch(setLoadingState(false));
} catch (err) {
toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false));
}
};
}
export function importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get) {
return async function(dispatch) {
dispatch(setLoadingState(true));
try {
const response = await post('/config-sync/import', {
force,
config: partialDiff,
});
toggleNotification({ type: 'success', message: response.data.message });
dispatch(getAllConfigDiff(toggleNotification, formatMessage, get));
dispatch(setLoadingState(false));
} catch (err) {
toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
dispatch(setLoadingState(false));
}
};
}
export const SET_LOADING_STATE = 'SET_LOADING_STATE';
@ -67,4 +93,23 @@ export function setLoadingState(value) {
type: SET_LOADING_STATE,
value,
};
}
}
export function getAppEnv(toggleNotification, formatMessage, get) {
return async function(dispatch) {
try {
const envVars = await get('/config-sync/app-env');
dispatch(setAppEnvInState(envVars.data));
} catch (err) {
toggleNotification({ type: 'warning', message: formatMessage({ id: 'notification.error' }) });
}
};
}
export const SET_APP_ENV_IN_STATE = 'SET_APP_ENV_IN_STATE';
export function setAppEnvInState(value) {
return {
type: SET_APP_ENV_IN_STATE,
value,
};
}

View File

@ -4,23 +4,36 @@
*
*/
import { fromJS, Map } from 'immutable';
import { SET_CONFIG_DIFF_IN_STATE, SET_LOADING_STATE } from '../../actions/Config';
import { fromJS, Map, List } from 'immutable';
import {
SET_CONFIG_DIFF_IN_STATE,
SET_CONFIG_PARTIAL_DIFF_IN_STATE,
SET_LOADING_STATE,
SET_APP_ENV_IN_STATE,
} from '../../actions/Config';
const initialState = fromJS({
configDiff: Map({}),
partialDiff: List([]),
isLoading: false,
appEnv: Map({}),
});
export default function configReducer(state = initialState, action) {
switch (action.type) {
case SET_CONFIG_DIFF_IN_STATE:
return state
.update('configDiff', () => fromJS(action.config))
.update('configDiff', () => fromJS(action.config));
case SET_CONFIG_PARTIAL_DIFF_IN_STATE:
return state
.update('partialDiff', () => fromJS(action.config));
case SET_LOADING_STATE:
return state
.update('isLoading', () => fromJS(action.value))
.update('isLoading', () => fromJS(action.value));
case SET_APP_ENV_IN_STATE:
return state
.update('appEnv', () => fromJS(action.value));
default:
return state;
}
}
}

View File

@ -1,11 +1,40 @@
{
"popUpWarning.warning.import": "If you continue all your local config files<br></br>will be imported into the database.",
"popUpWarning.warning.export": "If you continue all your database config<br></br>will be written into config files.",
"popUpWarning.warning.import_1": "If you continue all your local config files",
"popUpWarning.warning.import_2": "will be imported into the database.",
"popUpWarning.warning.export_1": "If you continue all your database config",
"popUpWarning.warning.export_2": "will be written into config files.",
"popUpWarning.button.import": "Yes, import",
"popUpWarning.button.export": "Yes, export",
"popUpWarning.button.cancel": "Cancel",
"popUpWarning.force": "Force",
"popUpWarning.Confirmation": "Confirmation",
"Header.Title": "Config Sync",
"Header.Description": "Manage your database config across environments.",
"ConfigList.Loading": "Loading content...",
"ConfigList.SelectAll": "Select all entries",
"ConfigList.ConfigName": "Config name",
"ConfigList.ConfigType": "Config type",
"ConfigList.State": "State",
"ConfigList.Different": "Different",
"ConfigList.OnlyDir": "Only in sync dir",
"ConfigList.OnlyDB": "Only in DB",
"NoChanges.Message": "No differences between DB and sync directory. You are up-to-date!",
"ConfigDiff.Title": "Config changes for",
"ConfigDiff.SyncDirectory": "Sync directory",
"ConfigDiff.Database": "Database",
"Buttons.Export": "Export",
"Buttons.DownloadConfig": "Download Config",
"Buttons.Import": "Import",
"FirstExport.Message": "Looks like this is your first time using config-sync for this project.",
"FirstExport.Button": "Make the initial export",
"Settings.Tool.Title": "Interface",
"plugin.name": "Config Sync"
}
}

View File

@ -1 +1,39 @@
{}
{
"popUpWarning.warning.import_1": "Si continuas todos tus ficheros de configuración locales",
"popUpWarning.warning.import_2": "se importarán a la base de datos.",
"popUpWarning.warning.export_1": "Si continuas las configuraciones de tu base de datos",
"popUpWarning.warning.export_2": "se escribirán en ficheros de configuración locales.",
"popUpWarning.button.import": "Sí, importar",
"popUpWarning.button.export": "Sí, exportar",
"popUpWarning.button.cancel": "Cancelar",
"popUpWarning.force": "Forzar",
"popUpWarning.Confirmation": "Confirmación",
"Header.Title": "Config Sync",
"Header.Description": "Gestiona las configuraciones de tu base de datos entre diferentes entornos o instancias.",
"ConfigList.Loading": "Cargando contenido...",
"ConfigList.SelectAll": "Seleccionar todas las entradas",
"ConfigList.ConfigName": "Nombre",
"ConfigList.ConfigType": "Tipo",
"ConfigList.State": "Estado",
"ConfigList.Different": "Diferentes",
"ConfigList.OnlyDir": "Sólo en directorio de sincronización",
"ConfigList.OnlyDB": "Sólo en la base de datos",
"NoChanges.Message": "No hay diferencia entre la base de datos y el directorio de sincronización. ¡Estás actualizado!",
"ConfigDiff.Title": "Cambios en la configuración para",
"ConfigDiff.SyncDirectory": "Directorio de sincronización",
"ConfigDiff.Database": "Base de datos",
"Buttons.Import": "Importar",
"Buttons.Export": "Exportar",
"FirstExport.Message": "Parece ser la primera vez que se usa config-sync en este proyecto.",
"FirstExport.Button": "Hacer la exportación inicial",
"Settings.Tool.Title": "Interfaz",
"plugin.name": "Config Sync"
}

5
bin/config-sync Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env node
'use strict';
require('../dist/cli');

4
codecov.yml Normal file
View File

@ -0,0 +1,4 @@
comment:
branches:
- master
- develop

View File

@ -1,12 +0,0 @@
{
"destination": "extensions/config-sync/files/",
"minify": false,
"importOnBootstrap": false,
"include": [
"core-store",
"role-permissions"
],
"exclude": [
"core-store.plugin_users-permissions_grant"
]
}

View File

@ -1,21 +0,0 @@
'use strict';
const fs = require('fs');
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
*
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*
* See more details here: https://strapi.io/documentation/v3.x/concepts/configurations.html#bootstrap
*/
module.exports = async () => {
if (strapi.plugins['config-sync'].config.importOnBootstrap) {
if (fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
await strapi.plugins['config-sync'].services.main.importAllConfig();
}
}
};

View File

@ -1,28 +0,0 @@
{
"routes": [
{
"method": "GET",
"path": "/export",
"handler": "config.exportAll",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/import",
"handler": "config.importAll",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/diff",
"handler": "config.getDiff",
"config": {
"policies": []
}
}
]
}

View File

@ -1,84 +0,0 @@
'use strict';
const fs = require('fs');
const difference = require('../utils/getObjectDiff');
/**
* Main controllers for config import/export.
*/
module.exports = {
/**
* Export all config, from db to filesystem.
*
* @param {object} ctx - Request context object.
* @returns {void}
*/
exportAll: async (ctx) => {
await strapi.plugins['config-sync'].services.main.exportAllConfig();
ctx.send({
message: `Config was successfully exported to ${strapi.plugins['config-sync'].config.destination}.`
});
},
/**
* Import all config, from filesystem to db.
*
* @param {object} ctx - Request context object.
* @returns {void}
*/
importAll: async (ctx) => {
// Check for existance of the config file destination dir.
if (!fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
ctx.send({
message: 'No config files were found.'
});
return;
}
await strapi.plugins['config-sync'].services.main.importAllConfig();
ctx.send({
message: 'Config was successfully imported.'
});
},
/**
* Get config diff between filesystem & db.
*
* @param {object} ctx - Request context object.
* @returns Object with key value pairs of config.
*/
getDiff: async (ctx) => {
// Check for existance of the config file destination dir.
if (!fs.existsSync(strapi.plugins['config-sync'].config.destination)) {
ctx.send({
message: 'No config files were found.'
});
return;
}
const formattedDiff = {
fileConfig: {},
databaseConfig: {},
diff: {}
};
const fileConfig = await strapi.plugins['config-sync'].services.main.getAllConfigFromFiles();
const databaseConfig = await strapi.plugins['config-sync'].services.main.getAllConfigFromDatabase();
const diff = difference(databaseConfig, fileConfig);
formattedDiff.diff = diff;
Object.keys(diff).map((changedConfigName) => {
formattedDiff.fileConfig[changedConfigName] = fileConfig[changedConfigName];
formattedDiff.databaseConfig[changedConfigName] = databaseConfig[changedConfigName];
})
return formattedDiff;
},
};

33
cypress.config.js Normal file
View File

@ -0,0 +1,33 @@
const { defineConfig } = require('cypress');
const fs = require('fs-extra');
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:1337',
specPattern: '**/*.cy.{js,ts,jsx,tsx}',
video: true,
defaultCommandTimeout: 30000,
requestTimeout: 30000,
setupNodeEvents(on, config) {
// implement node event listeners here.
// eslint-disable-next-line global-require
require('cypress-terminal-report/src/installLogsPrinter')(on);
on('task', {
deleteFolder(folderName) {
console.log(`deleting folder ${folderName}`);
return fs.remove(folderName)
.then(() => {
console.log(`folder ${folderName} deleted`);
return null;
})
.catch((err) => {
console.error(`error deleting folder ${folderName}`, err);
throw err;
});
},
});
},
},
});

129
cypress/support/commands.js Normal file
View File

@ -0,0 +1,129 @@
// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
Cypress.Commands.add('login', (path) => {
cy.visit('/');
cy.intercept({
method: 'GET',
url: '/admin/users/me',
}).as('sessionCheck');
cy.intercept({
method: 'GET',
url: '/admin/init',
}).as('adminInit');
// Wait for the initial request to complete.
cy.wait('@adminInit').its('response.statusCode').should('equal', 200);
// Wait for the form to render.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1000);
cy.get('body').then(($body) => {
// Login
if ($body.text().includes('Log in to your Strapi account')) {
cy.get('input[name="email"]').type('johndoe@example.com');
cy.get('input[name="password"]').type('Abc12345678');
cy.get('button[type="submit"]').click();
cy.wait('@sessionCheck').its('response.statusCode').should('equal', 200);
}
// Register
if ($body.text().includes('Credentials are only used to authenticate in Strapi')) {
cy.get('input[name="firstname"]').type('John');
cy.get('input[name="email"]').type('johndoe@example.com');
cy.get('input[name="password"]').type('Abc12345678');
cy.get('input[name="confirmPassword"]').type('Abc12345678');
cy.get('button[type="submit"]').click();
cy.wait('@sessionCheck').its('response.statusCode').should('equal', 200);
}
});
});
Cypress.Commands.add('navigateToInterface', (path) => {
cy.intercept({
method: 'GET',
url: '/config-sync/diff',
}).as('getConfigDiff');
cy.get('a[href="/admin/settings"]').click();
cy.get('a[href="/admin/settings/config-sync"]').click();
cy.wait('@getConfigDiff').its('response.statusCode').should('equal', 200);
});
Cypress.Commands.add('initialExport', (path) => {
cy.intercept({
method: 'POST',
url: '/config-sync/export',
}).as('exportConfig');
cy.get('button').contains('Make the initial export').click();
cy.get('button').contains('Yes, export').click();
cy.wait('@exportConfig').its('response.statusCode').should('equal', 200);
cy.contains('Config was successfully exported to config/sync/.');
});
Cypress.Commands.add('makeConfigChanges', (path) => {
// Change a setting in the UP advanced settings
cy.intercept({
method: 'PUT',
url: '/users-permissions/advanced',
}).as('saveUpAdvanced');
cy.get('a[href="/admin/settings/users-permissions/advanced-settings"]').click();
cy.get('input[name="unique_email"').click();
cy.get('button[type="submit"]').click();
cy.wait('@saveUpAdvanced').its('response.statusCode').should('equal', 200);
// Change a setting in the media library settings
cy.intercept({
method: 'PUT',
url: '/upload/settings',
}).as('saveMediaLibrarySettings');
cy.get('a[href="/admin/settings/media-library"]').click();
cy.get('input[name="responsiveDimensions"').click();
cy.get('button[type="submit"]').click();
cy.wait('@saveMediaLibrarySettings').its('response.statusCode').should('equal', 200);
// Change a setting in the email templates
cy.intercept({
method: 'PUT',
url: '/users-permissions/email-templates',
}).as('saveUpEmailTemplates');
cy.get('a[href="/admin/settings/users-permissions/email-templates"]').click();
cy.get('tbody tr').contains('Reset password').click();
cy.get('input[name="options.response_email"]').clear();
cy.get('input[name="options.response_email"]').type(`${Math.random().toString(36).substring(2, 15)}@example.com`);
cy.get('button[type="submit"]').click();
cy.wait('@saveUpEmailTemplates').its('response.statusCode').should('equal', 200);
});

22
cypress/support/e2e.js Normal file
View File

@ -0,0 +1,22 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
require('cypress-terminal-report/src/installLogsCollector')();
// Alternatively you can use CommonJS syntax:
// require('./commands')

13
dependabot.yml Normal file
View File

@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: daily
ignore:
- dependency-name: '\*'
update-types: ["version-update:semver-patch"]
groups:
strapi:
patterns:
- "@strapi/*"

52
docs/.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: Deploy
on:
workflow_dispatch:
push:
branches:
- main
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment:
name: docs.pluginpal.io
url: https://docs.pluginpal.io
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Docker
uses: actions/setup-node@v3
with:
node-version: '14'
- name: Build a Docker image
run: |
docker build \
-t pluginpal-docs:latest .
docker save -o pluginpal-docs-latest.tar pluginpal-docs:latest
- name: Transfer the Docker image to the Dokku server
uses: appleboy/scp-action@v0.1.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_CI_USERNAME }}
password: ${{ secrets.SSH_CI_PASSWORD }}
source: pluginpal-docs-latest.tar
target: /var/lib/dokku/data/storage/docs/docker-images
- name: Deploy the Dokku app based on the Docker image
uses: appleboy/ssh-action@v0.1.10
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_CI_USERNAME }}
password: ${{ secrets.SSH_CI_PASSWORD }}
script_stop: true
script: |
sudo docker load -i /var/lib/dokku/data/storage/docs/docker-images/pluginpal-docs-latest.tar
DOCS_LATEST_IMAGE=$(sudo docker images --format "{{.ID}}" pluginpal-docs:latest)
sudo docker tag pluginpal-docs:latest pluginpal-docs:$DOCS_LATEST_IMAGE
dokku git:from-image docs pluginpal-docs:$DOCS_LATEST_IMAGE
sudo docker system prune --all --force

20
docs/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
# Dependencies
/node_modules
# Production
/build
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

29
docs/Dockerfile Normal file
View File

@ -0,0 +1,29 @@
# syntax=docker/dockerfile:1
# Stage 1: Base image.
## Start with a base image containing NodeJS so we can build Docusaurus.
FROM node:18-alpine3.18 as base
## Disable colour output from yarn to make logs easier to read.
ENV FORCE_COLOR=0
## Enable corepack.
RUN corepack enable
## Set the working directory to `/opt/docusaurus`.
WORKDIR /opt/docusaurus
# Stage 2b: Production build mode.
FROM base as prod
## Set the working directory to `/opt/docusaurus`.
WORKDIR /opt/docusaurus
## Copy over the source code.
COPY . /opt/docusaurus/
## Install dependencies with `--immutable` to ensure reproducibility.
RUN yarn install
## Build the static site.
RUN yarn build
# Stage 3a: Serve with `docusaurus serve`.
FROM prod as serve
## Expose the port that Docusaurus will run on.
EXPOSE 3000
## Run the production server.
CMD ["yarn", "serve", "--host", "0.0.0.0", "--no-open"]

41
docs/README.md Normal file
View File

@ -0,0 +1,41 @@
# Website
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
### Installation
```
$ yarn
```
### Local Development
```
$ yarn start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ yarn build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true yarn deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> yarn deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

3
docs/babel.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};

View File

@ -0,0 +1,12 @@
---
slug: first-blog-post
title: First Blog Post
authors: [slorber, yangshun]
tags: [hola, docusaurus]
---
Lorem ipsum dolor sit amet...
<!-- truncate -->
...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

View File

@ -0,0 +1,44 @@
---
slug: long-blog-post
title: Long Blog Post
authors: yangshun
tags: [hello, docusaurus]
---
This is the summary of a very long blog post,
Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
<!-- truncate -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

View File

@ -0,0 +1,24 @@
---
slug: mdx-blog-post
title: MDX Blog Post
authors: [slorber]
tags: [docusaurus]
---
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
:::tip
Use the power of React to create interactive blog posts.
:::
{/* truncate */}
For example, use JSX to create an interactive button:
```js
<button onClick={() => alert('button clicked!')}>Click me!</button>
```
<button onClick={() => alert('button clicked!')}>Click me!</button>

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1,29 @@
---
slug: welcome
title: Welcome
authors: [slorber, yangshun]
tags: [facebook, hello, docusaurus]
---
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
Here are a few tips you might find useful.
<!-- truncate -->
Simply add Markdown files (or folders) to the `blog` directory.
Regular blog authors can be added to `authors.yml`.
The blog post date can be extracted from filenames, such as:
- `2019-05-30-welcome.md`
- `2019-05-30-welcome/index.md`
A blog post folder can be convenient to co-locate blog post images:
![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
The blog supports tags as well!
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.

23
docs/blog/authors.yml Normal file
View File

@ -0,0 +1,23 @@
yangshun:
name: Yangshun Tay
title: Front End Engineer @ Facebook
url: https://github.com/yangshun
image_url: https://github.com/yangshun.png
page: true
socials:
x: yangshunz
github: yangshun
slorber:
name: Sébastien Lorber
title: Docusaurus maintainer
url: https://sebastienlorber.com
image_url: https://github.com/slorber.png
page:
# customize the url of the author page at /blog/authors/<permalink>
permalink: '/all-sebastien-lorber-articles'
socials:
x: sebastienlorber
linkedin: sebastienlorber
github: slorber
newsletter: https://thisweekinreact.com

19
docs/blog/tags.yml Normal file
View File

@ -0,0 +1,19 @@
facebook:
label: Facebook
permalink: /facebook
description: Facebook tag description
hello:
label: Hello
permalink: /hello
description: Hello tag description
docusaurus:
label: Docusaurus
permalink: /docusaurus
description: Docusaurus tag description
hola:
label: Hola
permalink: /hola
description: Hola tag description

View File

@ -0,0 +1,30 @@
---
sidebar_label: 'Plugin config types'
displayed_sidebar: configSyncSidebar
slug: /api/plugin-config-types
---
# Plugin config types
When you're writing a plugin, which registers a content type, you might want to consider that content type as a config type as defined in the Config Sync specification.
## Register a config type programatically
You can register a config type by adding some code to the register function of your plugin.
```md title="register.js"
// Register the config type when using the config-sync plugin.
if (strapi.plugin('config-sync')) {
if (!strapi.plugin('config-sync').pluginTypes) {
strapi.plugin('config-sync').pluginTypes = [];
}
strapi.plugin('config-sync').pluginTypes.push({
configName: 'url-pattern',
queryString: 'plugin::webtools.url-pattern',
uid: 'code',
});
}
```
If you want to read more about what the different values of a config type actually mean please read the in depth [custom types](/config-types#custom-types) docs

View File

@ -0,0 +1,16 @@
---
sidebar_label: 'Custom types'
displayed_sidebar: configSyncSidebar
slug: /configuration/custom-types
---
# 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](/config-types#custom-types) documentation.
| Name | Details |
| ---- | ------- |
| Key | `customTypes` |
| Required | false |
| Type | array |
| Default | `[]` |

View File

@ -0,0 +1,16 @@
---
sidebar_label: 'Excluded config'
displayed_sidebar: configSyncSidebar
slug: /configuration/excluded-config
---
# 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.
| Name | Details |
| ---- | ------- |
| Key | `excludedConfig` |
| Required | false |
| Type | array |
| Default | `['core-store.plugin_users-permissions_grant', 'core-store.plugin_upload_metrics', 'core-store.strapi_content_types_schema', 'core-store.ee_information',]` |

View File

@ -0,0 +1,22 @@
---
sidebar_label: 'Excluded types'
displayed_sidebar: configSyncSidebar
slug: /configuration/excluded-types
---
# 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']
```
| Name | Details |
| ---- | ------- |
| Key | `excludedTypes` |
| Required | false |
| Type | array |
| Default | `[]` |

View File

@ -0,0 +1,20 @@
---
sidebar_label: 'Import on bootstrap'
displayed_sidebar: configSyncSidebar
slug: /configuration/import-on-bootstrap
---
# Import on bootstrap
Allows you to let the config be imported automaticly when strapi is bootstrapping (on `strapi start`).
:::danger
This setting can't be used locally and should be handled very carefully as it can unintendedly overwrite the changes in your database. **PLEASE USE WITH CARE**.
:::
| Name | Details |
| ---- | ------- |
| Key | `importOnBootstrap` |
| Required | false |
| Type | bool |
| Default | `false` |

View File

@ -0,0 +1,32 @@
---
sidebar_label: 'Introduction'
displayed_sidebar: configSyncSidebar
slug: /configuration
---
# 🔧 Configuration
The settings of the plugin can be overridden in the `config/plugins.js` file.
In the example below you can see how, and also what the default settings are.
```md title="config/plugins.js"
module.exports = ({ env }) => ({
// ...
'config-sync': {
enabled: true,
config: {
syncDir: "config/sync/",
minify: false,
soft: false,
importOnBootstrap: false,
customTypes: [],
excludedTypes: [],
excludedConfig: [
"core-store.plugin_users-permissions_grant",
"core-store.plugin_upload_metrics",
"core-store.strapi_content_types_schema",
"core-store.ee_information",
],
},
},
});
```

View File

@ -0,0 +1,16 @@
---
sidebar_label: 'Minify'
displayed_sidebar: configSyncSidebar
slug: /configuration/minify
---
# Minify
When enabled all the exported JSON files will be minified.
| Name | Details |
| ---- | ------- |
| Key | `minify` |
| Required | false |
| Type | bool |
| Default | `false` |

View File

@ -0,0 +1,16 @@
---
sidebar_label: 'Soft'
displayed_sidebar: configSyncSidebar
slug: /configuration/soft
---
# Soft
When enabled the import action will be limited to only create new entries. Entries to be deleted, or updated will be skipped from the import process and will remain in it's original state.
| Name | Details |
| ---- | ------- |
| Key | `soft` |
| Required | false |
| Type | bool |
| Default | `false` |

View File

@ -0,0 +1,16 @@
---
sidebar_label: 'Sync dir'
displayed_sidebar: configSyncSidebar
slug: /configuration/sync-dir
---
# Sync dir
The path for reading and writing the sync files.
| Name | Details |
| ---- | ------- |
| Key | `syncDir` |
| Required | true |
| Type | string |
| Default | `config/sync/` |

View File

@ -0,0 +1,13 @@
---
sidebar_label: 'Admin GUI'
displayed_sidebar: configSyncSidebar
slug: /admin-gui
---
# 🖥️ Admin panel (GUI)
This plugin ships with a React app which can be accessed from the settings page in Strapi admin panel. On this page you can pretty much do the same as you can from the CLI. You can import, export and see the difference between the config as found in the sync directory, and the config as found in the database.
**Pro tip:**
By clicking on one of the items in the diff table you can see the exact difference between sync dir and database in a git-style diff viewer.
![Config diff in admin](/img/assets/admin-diff-viewer.png)

View File

@ -0,0 +1,138 @@
---
sidebar_label: 'CLI'
displayed_sidebar: configSyncSidebar
slug: /cli
---
# 🔌 Command line interface (CLI)
Add the `config-sync` command as a script to the `package.json` of your Strapi project:
```
"scripts": {
// ...
"cs": "config-sync"
},
```
You can now run all the `config-sync` commands like this:
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn cs --help
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm run cs -- --help
```
</TabItem>
</Tabs>
## ⬆️ Import ⬇️ Export
> _Command:_ `import` _Alias:_ `i`
>
> _Command:_ `export` _Alias:_ `e`
These commands are used to sync the config in your Strapi project.
_Example:_
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn cs import
yarn cs export
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm run cs import
npm run cs export
```
</TabItem>
</Tabs>
:::info
When you're using `npm` to run these commands, please note that you need an extra `--` to forward the flags to the script.
More information about this topic can be found on the <a href="https://docs.npmjs.com/cli/commands/npm-run-script">NPM documentation</a>.
Example:
```
npm run cs import -- --yes
```
:::
### Flag: `-y`, `--yes`
Use this flag to skip the confirm prompt and go straight to syncing the config.
```bash
[command] --yes
```
### Flag: `-t`, `--type`
Use this flag to specify the type of config you want to sync.
```bash
[command] --type user-role
```
### Flag: `-p`, `--partial`
Use this flag to sync a specific set of configs by giving the CLI a comma-separated string of config names.
```bash
[command] --partial user-role.public,i18n-locale.en
```
### Flag: `-f`, `--force`
If you're using the soft setting to gracefully import config, you can use this flag to ignore the setting for the current command and forcefully import all changes anyway.
```bash
[command] --force
```
## ↔️ Diff
> _Command:_ `diff` | _Alias:_ `d`
This command is used to see the difference between the config as found in the sync directory, and the config as found in the database.
_Example:_
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn cs diff
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm run cs diff
```
</TabItem>
</Tabs>
### Argument: `<single>`
Add a single config name as the argument of the `diff` command to see the difference of that single file in a git-style diff viewer.
_Example:_
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn cs diff user-role.public
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm run cs diff user-role.public
```
</TabItem>
</Tabs>

View File

@ -0,0 +1,125 @@
---
sidebar_label: 'Config Types'
displayed_sidebar: configSyncSidebar
slug: /config-types
---
# 🚀 Config types
By default the plugin will track 4 (official) types.
To track your own custom types you can register them by setting some plugin config.
## Default types
These 4 types are by default registered in the sync process.
### Admin role
> Config name: `admin-role` | UID: `code` | Query string: `admin::role`
### User role
> 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: `i18n-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.
_Read more about the `config/plugins.js` file [here](/configuration)._
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._
### 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. Therefore 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.
If you do not have a single unique value, you can also pass in an array of keys for a combined uid key. This is for example the case for all content types which use i18n features (An example config would be `uid: ['productId', 'locale']`).
##### Key: `uid`
> `required:` YES | `type:` string | string[]
### Relations
The relations array specifies the relations you want to include in the sync process.
This feature is used to sync the relations between `roles` and `permissions`. See https://github.com/boazpoolman/strapi-plugin-config-sync/blob/master/server/config/types.js#L16.
Example:
```
{
configName: 'admin-role',
queryString: 'admin::role',
uid: 'code',
relations: [{
queryString: 'admin::permission',
relationName: 'permissions',
parentName: 'role',
relationSortFields: ['action', 'subject'],
}],
},
```
##### Key: `relations`
> `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
### 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

View File

@ -0,0 +1,68 @@
---
sidebar_label: 'Installation'
displayed_sidebar: configSyncSidebar
slug: /
---
# ⏳ Installation
:::prerequisites
Complete installation requirements are the exact same as for Strapi itself and can be found in the Strapi documentation.
**Supported Strapi versions:**
Strapi v5 use `strapi-plugin-config-sync@^3`
Strapi v4 use `strapi-plugin-config-sync@^1`
:::
Install the plugin in your Strapi project.
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn add strapi-plugin-config-sync
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm install strapi-plugin-config-sync --save
```
</TabItem>
</Tabs>
Add the export path to the `watchIgnoreFiles` list in the `config/admin.js` file.
This way your app won't reload when you export the config in development.
```md title="config/admin.js"
module.exports = ({ env }) => ({
// ...
watchIgnoreFiles: [
'**/config/sync/**',
],
});
```
After successful installation you have to rebuild the admin UI so it'll include this plugin. To rebuild and restart Strapi run:
<Tabs groupId="yarn-npm">
<TabItem value="yarn" label="Yarn">
```
yarn build
yarn develop
```
</TabItem>
<TabItem value="npm" label="NPM">
```
npm run build
npm run develop
```
</TabItem>
</Tabs>
The **Config Sync** plugin should now appear in the **Settings** section of your Strapi app.
To start tracking your config changes you have to make the first export. This will dump all your configuration data to the `/config/sync` directory. You can export either through [the CLI](/cli) or [Strapi admin panel](/admin-gui)
Enjoy 🎉

View File

@ -0,0 +1,22 @@
---
sidebar_label: 'Motivation'
displayed_sidebar: configSyncSidebar
slug: /motivation
---
# 💡 Motivation
In Strapi we come across what I would call config types. These are models of which the records are stored in our database, just like content types. Though the big difference here is that your code often relies on the database records of these types.
Having said that, it makes sense that these records can be exported, added to git, and be migrated across environments. This way we can make sure we have all the data our code relies on, on each environment.
Examples of these types are:
- Admin roles _(admin::role)_
- User roles _(plugin::users-permissions.role)_
- Admin settings _(strapi::core-store)_
- I18n locale _(plugin::i18n.locale)_
This plugin gives you the tools to sync this data. You can export the data as JSON files on one env, and import them on every other env. By writing this data as JSON files you can easily track them in your version control system (git).
_With great power comes great responsibility - Uncle Ben_

View File

@ -0,0 +1,13 @@
---
sidebar_label: 'Naming convention'
displayed_sidebar: configSyncSidebar
slug: /naming-convention
---
# 🔍 Naming convention
All the config files written in the sync directory have the same naming convention. It goes as follows:
[config-type].[identifier].json
- `config-type` - Corresponds to the `configName` of the config type.
- `identifier` - Corresponds to the value of the `uid` field of the config type.

View File

@ -0,0 +1,33 @@
---
sidebar_label: 'Workflow'
displayed_sidebar: configSyncSidebar
slug: /workflow
---
# ⌨️ Usage / Workflow
This plugin works best when you use `git` for the version control of your Strapi project.
_The following workflows are assuming you're using `git`._
### Intro
All database records tracked with this plugin will be exported to JSON files. Once exported each change to the file or the record will be tracked. Meaning you can now do one of two things:
- Change the file(s), and run an import. You have now imported from filesystem -> database.
- Change the record(s), and run an export. You have now exported from database -> filesystem.
### Local development
When building a new feature locally for your Strapi project you'd use the following workflow:
- Build the feature.
- Export the config.
- Commit and push the files to git.
### Deployment
When deploying the newly created feature - to either a server, or a co-worker's machine - you'd use the following workflow:
- Pull the latest file changes to the environment.
- (Re)start your Strapi instance.
- Import the config.
## Production deployment
The production deployment will be the same as a regular deployment. You just have to be careful before running the import. Ideally making sure the are no open changes before you pull the new code to the environment.

View File

@ -0,0 +1,18 @@
---
sidebar_label: 'Generic update'
displayed_sidebar: configSyncSidebar
slug: /upgrading/generic-update
---
# Updating Config Sync
We are always working to make Config Sync better by fixing bugs and introducing new features. These changes will be released as minor or patch versions as defined in the Semantic Versioning specification.
## Bump a minor/patch version
When you're updating Config Sync you'll have to follow these steps:
1. Make sure there are no config changes before starting. Either export or import all staged changes.
2. Update the version of the `strapi-plugin-config-sync` package in your `package.json` using your package manager of choice (yarn/npm/pnpm)
3. After you've bumped the version make sure to export any new changes that are now shown. It is possible that new configs are introduced, or old ones are updated/removed.
4. You're now ready to push these changes an commit them to your source control!

147
docs/docusaurus.config.ts Normal file
View File

@ -0,0 +1,147 @@
import {themes as prismThemes} from 'prism-react-renderer';
import type {Config} from '@docusaurus/types';
import type * as Preset from '@docusaurus/preset-classic';
const config: Config = {
title: 'Strapi Config Sync',
tagline: "Documentation for the config-sync plugin for Strapi",
favicon: 'img/favicon.jpg',
plugins: [
'docusaurus-plugin-sass',
],
// Set the production url of your site here
url: 'https://docs.pluginpal.io',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/config-sync/',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'pluginpal', // Usually your GitHub org/user name.
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
// Even if you don't use internationalization, you can use this field to set
// useful metadata like html lang. For example, if your site is Chinese, you
// may want to replace "en" with "zh-Hans".
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
// themes: ['@docusaurus/theme-live-codeblock', '@docusaurus/theme-mermaid'],
presets: [
[
'classic',
{
docs: {
routeBasePath: '/',
sidebarPath: './sidebars.ts',
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl:
'https://github.com/pluginpal/strapi-plugin-config-sync/tree/master/docs',
admonitions: {
keywords: [
// Admonitions defaults
'note',
'tip',
'info',
'caution',
'danger',
// Admonitions custom
'callout',
'prerequisites',
'strapi',
'warning',
],
},
},
blog: false,
sitemap: {
lastmod: 'date',
changefreq: 'weekly',
priority: 0.6,
// ignorePatterns: ['/tags/**'],
filename: 'sitemap.xml',
createSitemapItems: async (params) => {
const {defaultCreateSitemapItems, ...rest} = params;
const items = await defaultCreateSitemapItems(rest);
return items;
},
},
theme: {
customCss: './src/scss/__index.scss',
},
} satisfies Preset.Options,
],
],
themeConfig: {
// Replace with your project's social card
// image: 'img/docusaurus-social-card.jpg',
navbar: {
title: 'Strapi Config Sync',
logo: {
alt: 'Config Sync logo',
src: 'img/logo.png',
},
items: [
{
href: 'https://github.com/pluginpal/strapi-plugin-config-sync',
label: 'GitHub',
position: 'right',
},
],
},
footer: {
style: 'dark',
links: [
{
title: 'Community',
items: [
{
label: 'Discord',
href: 'https://discord.com/invite/strapi',
},
{
label: 'Forum',
href: 'https://forum.strapi.io/',
},
],
},
{
title: 'More',
items: [
{
label: 'Website',
href: 'https://www.pluginpal.io',
},
{
label: 'GitHub',
href: 'https://github.com/pluginpal',
},
],
},
],
},
algolia: {
appId: 'ADLP623G89',
apiKey: '8f91ceaf54e8e8db14479fd79a420a8c',
indexName: 'pluginpal',
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
} satisfies Preset.ThemeConfig,
};
export default config;

54
docs/package.json Normal file
View File

@ -0,0 +1,54 @@
{
"name": "pluginpal-docs",
"version": "0.0.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "3.5.2",
"@docusaurus/plugin-sitemap": "^3.5.2",
"@docusaurus/preset-classic": "3.5.2",
"@docusaurus/theme-live-codeblock": "^3.5.2",
"@docusaurus/theme-mermaid": "^3.5.2",
"@docusaurus/theme-search-algolia": "^3.5.2",
"@mdx-js/react": "^3.0.0",
"classnames": "^2.5.1",
"clsx": "^2.0.0",
"docusaurus-plugin-sass": "^0.2.5",
"prism-react-renderer": "^2.3.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sass": "^1.78.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.5.2",
"@docusaurus/tsconfig": "3.5.2",
"@docusaurus/types": "3.5.2",
"typescript": "~5.5.2"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 3 chrome version",
"last 3 firefox version",
"last 5 safari version"
]
},
"engines": {
"node": ">=18.0"
}
}

69
docs/sidebars.ts Normal file
View File

@ -0,0 +1,69 @@
/**
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
// tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
// But you can create a sidebar manually
configSyncSidebar: [
{
type: "category",
collapsed: false,
label: "🚀 Getting Started",
items: [
"getting-started/installation",
"getting-started/motivation",
"getting-started/cli",
"getting-started/admin-gui",
"getting-started/config-types",
"getting-started/workflow",
"getting-started/naming-convention",
// "dev-docs/usage-information",
],
},
{
type: "category",
collapsed: false,
label: "⚙️ Configuration",
items: [
"configuration/introduction",
"configuration/sync-dir",
"configuration/minify",
"configuration/import-on-bootstrap",
"configuration/custom-types",
"configuration/soft",
"configuration/excluded-types",
"configuration/excluded-config",
],
},
{
type: "category",
collapsed: false,
label: "📦 API",
items: [
"api/plugin-config-types",
],
},
{
type: "category",
collapsed: false,
label: "♻️ Upgrading",
items: [
"upgrading/generic-update",
],
},
],
};
module.exports = sidebars;

View File

@ -0,0 +1,18 @@
import React from 'react'
import clsx from 'clsx'
export default function ApiCall({
children,
noSideBySide = false,
}) {
return (
<div
className={clsx(
'api-call',
(noSideBySide && 'api-call--no-side-by-side'),
)}
>
{children}
</div>
);
}

View File

@ -0,0 +1,121 @@
import React from 'react';
import clsx from 'clsx';
export default function Badge({
children,
className,
link = '',
noLink = false,
variant = '',
...rest
}) {
const variantNormalized = variant.toLowerCase().replace(/\W/g, '');
return (
<span
className={clsx(
'badge',
'badge--feature',
(variantNormalized && `badge--${variantNormalized.toLowerCase()}`),
)}
{...rest}
>
{(noLink || !link) ? (
<>
{variant}
</>
) : (
<a className="badge__link" href={link}>
{variant}
</a>
)}
{children}
</span>
);
}
export function AlphaBadge(props) {
return (
<Badge
variant="Alpha"
{...props}
/>
);
}
export function BetaBadge(props) {
return (
<Badge
variant="Beta"
{...props}
/>
);
}
export function FutureBadge(props) {
return (
<Badge
variant="Future"
link="/dev-docs/configurations/features"
{...props}
/>
);
}
export function EnterpriseBadge(props) {
return (
<Badge
variant="Enterprise"
link="https://strapi.io/pricing-self-hosted"
{...props}
/>
);
}
export function CloudProBadge(props) {
return (
<Badge
variant="Strapi Cloud Pro"
link="https://strapi.io/pricing-cloud"
{...props}
/>
);
}
export function CloudTeamBadge(props) {
return (
<Badge
variant="Strapi Cloud Team"
link="https://strapi.io/pricing-cloud"
{...props}
/>
);
}
export function CloudDevBadge(props) {
return (
<Badge
variant="Strapi Cloud Dev"
link="https://strapi.io/pricing-cloud"
{...props}
/>
);
}
export function NewBadge(props) {
return (
<Badge
variant="New ✨"
{...props}
/>
);
}
export function UpdatedBadge(props) {
return (
<Badge
variant="Updated ️🖌"
{...props}
/>
);
}

View File

@ -0,0 +1,40 @@
import clsx from 'clsx';
import React from 'react';
import Link from '@docusaurus/Link';
import styles from './button.module.scss';
export function Button({
href,
to,
children,
className,
decorative,
size = '',
variant = 'primary',
...rest
}) {
const ButtonElement = (to ? Link : (href ? 'a' : 'button'));
return (
<ButtonElement
{...rest}
{...(!href ? {} : { href, target: '_blank' })}
{...(!to ? {} : { to })}
className={clsx(
'button',
(variant && styles[`button--${variant}`]),
(size && styles[`button--${size}`]),
styles.button,
styles[variant],
className,
)}
>
{children}
{decorative && (
<span className={styles.button__decorative}>
{decorative}
</span>
)}
</ButtonElement>
);
}

View File

@ -0,0 +1,96 @@
/** Component: Button */
@import '../../scss/_mixins.scss';
.button {
--strapi-button-background-color: var(--strapi-primary-600);
--strapi-button-border-color: var(--strapi-primary-600);
--strapi-button-border-radius: 4px;
--strapi-button-box-shadow: 0 0 0 transparent;
--strapi-button-color: #fff;
--strapi-button-font-size: 12px;
--strapi-button-font-weight: 600;
--strapi-button-line-height: 16px;
--strapi-button-position: relative;
--strapi-button-py: 7px;
--strapi-button-px: 15px;
--strapi-button-transition-property: color, background, border-color, box-shadow;
--strapi-button-hover-background-color: var(--strapi-primary-700);
--strapi-button-hover-border-color: var(--strapi-primary-700);
--strapi-button-hover-box-shadow: 0px 9px 10px rgba(44, 56, 148, 0.2475);
--strapi-button-hover-color: #fff;
--ifm-button-color: var(--strapi-button-color);
--ifm-button-background-color: var(--strapi-button-background-color);
--ifm-button-border-color: var(--strapi-button-border-color);
--ifm-button-border-radius: var(--strapi-button-border-radius);
--ifm-button-font-weight: var(--strapi-button-font-weight);
--ifm-button-padding-horizontal: var(--strapi-button-px);
--ifm-button-padding-vertical: var(--strapi-button-py);
--ifm-button-size-multiplier: 1;
--ifm-color-primary-darker: var(--strapi-primary-200);
--ifm-link-hover-color: var(--strapi-button-color);
--ifm-link-hover-decoration: none;
position: var(--strapi-button-position);
font-size: var(--strapi-button-font-size);
line-height: var(--strapi-button-line-height);
box-shadow: var(--strapi-button-box-shadow);
transition-property: var(--strapi-button-transition-property);
&__decorative {
position: absolute;
font-size: 32px;
line-height: 32px;
bottom: -16px;
right: -8px;
}
&:not(:disabled),
&:not([aria-disabled="true"]) {
&:focus, &:hover {
--strapi-button-box-shadow: var(--strapi-button-hover-box-shadow);
--strapi-button-background-color: var(--strapi-button-hover-background-color);
--strapi-button-border-color: var(--strapi-button-hover-border-color);
--strapi-button-color: var(--strapi-button-hover-color);
}
}
/** Sizes */
&--huge {
--strapi-button-border-radius: 6px;
--strapi-button-font-size: 15px;
--strapi-button-line-height: 23px;
--strapi-button-py: 11px;
--strapi-button-px: 71px;
}
/** Variants */
&--secondary {
--strapi-button-background-color: #f0f0ff;
--strapi-button-border-color: #d9d8ff;
--strapi-button-color: var(--strapi-primary-600);
--strapi-button-hover-background-color: var(--strapi-neutral-0);
--strapi-button-hover-border-color: #d9d8ff;
--strapi-button-hover-box-shadow: none;
--strapi-button-hover-color: var(--strapi-primary-600);
}
}
/** Dark mode */
@include dark {
.button {
/** Dark mode Variants */
&--secondary {
--strapi-button-background-color: var(--strapi-neutral-100);
--strapi-button-border-color: var(--strapi-neutral-200);
--strapi-button-hover-background-color: var(--strapi-neutral-0);
--strapi-button-hover-border-color: var(--strapi-neutral-200);
}
}
}

View File

@ -0,0 +1,107 @@
import React from 'react';
import clsx from 'clsx';
import Link from '@docusaurus/Link';
import styles from './card.module.scss';
import IconArrow from '@site/static/img/assets/icons/arrow-right.svg';
export function CardTitle({
as,
children,
className,
withArrow,
...rest
}) {
const TitleElement = (as || 'h3');
return (
<TitleElement
className={clsx(
styles.card__title,
className,
)}
{...rest}
>
{children}
{withArrow && (
<span className={styles.card__title__arrow}>
<IconArrow />
</span>
)}
</TitleElement>
);
}
export function CardDescription({
as,
className,
...rest
}) {
const DescriptionElement = (as || 'div');
return (
<DescriptionElement
className={clsx(
styles.card__description,
className,
)}
{...rest}
/>
);
}
export function CardImgBg({
className,
...rest
}) {
return (
<img
className={clsx(
styles['card__img-bg'],
className,
)}
{...rest}
/>
);
}
export function CardImg({
className,
...rest
}) {
return (
<img
className={clsx(
styles['card__img'],
className,
)}
{...rest}
/>
);
}
export function Card({
className,
href,
isContentDelimited,
to,
variant,
...rest
}) {
const asCallToAction = !!(href || to);
const CardElement = (to ? Link : (href ? 'a' : 'div'));
return (
<CardElement
{...(!href ? {} : { href, target: '_blank' })}
{...(!to ? {} : { to })}
className={clsx(
styles.card,
(asCallToAction && styles['card--cta']),
(isContentDelimited && styles['card--content-delimited']),
(variant && styles[`card--${variant}`]),
className,
)}
{...rest}
/>
);
}

View File

@ -0,0 +1,182 @@
/** Component: Card */
@import '../../scss/_mixins.scss';
:root {
--strapi-card-background: var(--strapi-neutral-0);
--strapi-card-border-color: #EDEDFF;
--strapi-card-border-radius: 10px;
--strapi-card-box-shadow: 0 0 0 transparent;
--strapi-card-content-delimited: 395px;
--strapi-card-img-border-width: 5px;
--strapi-card-img-border-radius: 5px 5px 0 0;
--strapi-card-img-bg-scale: 1;
--strapi-card-justify-content: center;
--strapi-card-position: relative;
--strapi-card-overflow: hidden;
--strapi-card-text-align: center;
--strapi-card-gap: var(--strapi-spacing-2);
--strapi-card-px: var(--strapi-spacing-6);
--strapi-card-py: var(--strapi-spacing-6);
--strapi-card-title-arrow-left: var(--strapi-card-gap);
--strapi-card-title-color: #1D1B84;
--strapi-card-title-font-size: 17px;
--strapi-card-title-font-weight: 700;
--strapi-card-title-line-height: 26px;
--strapi-card-description-color: #4E6294;
--strapi-card-description-font-size: 15px;
--strapi-card-description-line-height: 24px;
--strapi-card-hover-border-color: #D6D6FF;
--strapi-card-hover-img-bg-scale: 1.15;
}
.card {
position: var(--strapi-card-position);
overflow: var(--strapi-card-overflow);
background: var(--strapi-card-background);
border-radius: var(--strapi-card-border-radius);
border: 1px solid var(--strapi-card-border-color);
box-shadow: var(--strapi-card-box-shadow);
display: flex;
flex-direction: column;
gap: var(--strapi-card-gap);
align-items: stretch;
justify-content: var(--strapi-card-justify-content);
text-align: var(--strapi-card-text-align);
padding: var(--strapi-card-py) var(--strapi-card-px);
transition: all 0.2s ease;
&:focus, &:hover {
--strapi-card-border-color: var(--strapi-card-hover-border-color);
--strapi-card-title-arrow-left: var(--strapi-spacing-3);
--strapi-card-img-bg-scale: var(--strapi-card-hover-img-bg-scale);
}
&__title {
display: block;
color: var(--strapi-card-title-color);
font-size: var(--strapi-card-title-font-size);
font-weight: var(--strapi-card-title-font-weight);
line-height: var(--strapi-card-title-line-height);
margin: 0;
&:after {
content: none;
}
&__arrow {
display: inline-block;
line-height: 0;
margin-left: var(--strapi-card-title-arrow-left);
transition: margin-left 0.1s ease;
}
}
&__description {
--ifm-link-color: var(--strapi-card-description-color);
--ifm-link-decoration: underline;
color: var(--strapi-card-description-color);
opacity: 0.8;
font-size: var(--strapi-card-description-font-size);
line-height: var(--strapi-card-description-line-height);
}
&__img {
border-bottom: none;
box-shadow: 0 1px 10px 0 #7A78B61A;
}
&--cta {
--ifm-link-color: currentColor;
--strapi-card-background:
linear-gradient(
310deg,
rgba(168, 166, 255, 0.15) 1.16%,
rgba(226, 225, 255, 0.15) 69.23%
),
#FFFFFF
;
--strapi-card-text-align: left;
--strapi-card-gap: var(--strapi-spacing-2);
--strapi-card-title-font-size: 21px;
--strapi-card-title-font-weight: 600;
--strapi-card-title-line-height: 28px;
--ifm-link-decoration: none;
--ifm-link-hover-decoration: none;
}
&--content-delimited {
.card {
&__title,
&__description {
width: 100%;
max-width: var(--strapi-card-content-delimited);
margin-right: auto;
margin-left: auto;
}
}
}
}
/** Responsive */
@include medium-up {
:root {
--strapi-card-px: var(--strapi-spacing-8);
--strapi-card-py: var(--strapi-spacing-9);
}
.card {
&__title {
&__arrow {
transition: margin-left 0.2s ease;
will-change: margin-left;
}
}
&:focus, &:hover {
&.card--cta {
--strapi-card-border-color: #D6D6FF;
--strapi-card-box-shadow: 0px 1px 4px rgba(33, 33, 52, 0.1);
}
}
&--cta {
transition: all 0.2s ease;
will-change: border-color, box-shadow, color;
.card {
&__img {
transition: all 0.2s ease;
will-change: border-radius, transform;
transform:
scale(var(--strapi-card-img-scale, 1))
translate(var(--strapi-card-img-translate, '0, 0'))
;
}
}
}
}
}
/** Dark mode */
@include dark {
--strapi-card-border-color: var(--strapi-neutral-150);
--strapi-card-title-color: var(--strapi-netral-1000);
--strapi-card-description-color: var(--strapi-netral-1000);
--strapi-card-img-border-color: rgba(255, 255, 255, 0.5);
--strapi-card-hover-border-color: #49494D;
.card {
&--cta {
--strapi-card-background: var(--strapi-neutral-0);
&:focus, &:hover {
--strapi-card-border-color: #49494D;
--strapi-card-color: var(--strapi-neutral-1000);
--ifm-link-hover-color: var(--strapi-neutral-1000);
}
}
}
}

View File

@ -0,0 +1,15 @@
import React from 'react';
import clsx from 'clsx';
import styles from './container.module.scss';
export function Container({ className, ...rest }) {
return (
<div
className={clsx(
styles.container,
className,
)}
{...rest}
/>
);
}

View File

@ -0,0 +1,18 @@
/** Component: Container */
:root {
--strapi-container-px: var(--ifm-spacing-horizontal);
--strapi-container-mw: calc(863px + calc(var(--strapi-container-px) * 2));
}
.container {
display: flex;
flex-direction: column;
align-items: stretch;
margin-right: auto;
margin-left: auto;
padding-right: var(--strapi-container-px);
padding-left: var(--strapi-container-px);
max-width: var(--strapi-container-mw);
width: 100%;
}

View File

@ -0,0 +1,32 @@
import React from 'react'
import classNames from 'classnames';
export default function CustomDocCard(props) {
const { title, description, link, emoji, small = false } = props;
const linkClasses = classNames({
card: true,
cardContainer: true,
'padding--lg': !small,
'padding--md': small,
});
const cardClasses = classNames({
'custom-doc-card': true,
'margin-bottom--lg': !small,
'margin-bottom--sm': small,
'custom-doc-card--small': small,
});
return (
<article className={ cardClasses }>
<a className={ linkClasses }
href={ link }
>
<h2 className="text--truncate cardTitle" title={title}>
{emoji ? emoji : '📄️'} {title}
</h2>
<p className="text--truncate cardDescription" title={ description }>
{description}
</p>
</a>
</article>
);
}

View File

@ -0,0 +1,9 @@
import React from 'react';
export default function CustomDocCardsWrapper({ children }) {
return (
<div className="custom-cards-wrapper">
{children}
</div>
);
}

Some files were not shown because too many files have changed in this diff Show More