storyblok 3.14.0 → 3.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,12 @@
1
1
  ---
2
2
  name: Bug report
3
- about: Create a report to help us improve Storyblok
3
+ about: Create a report to help us improve the CLI
4
4
  title: ''
5
5
  labels: bug
6
6
  assignees: ''
7
7
 
8
8
  ---
9
9
 
10
- **The issue occurs while working with:** (check one with "x")
11
- - [ ] *app.storyblok.com (CMS - Interface)*
12
- - [ ] *api.storyblok.com (CMS - Content Delivery API)*
13
- - [ ] *mapi.storyblok.com (CMS - Management API)*
14
- - [ ] *a.storyblok.com (CMS - Image Service)*
15
- - [ ] *storyblok.com (Website)*
16
- - [ ] *Other:* <!-- => If you've got an issue with on of our boilerplates or themes - please create an issue in the specific repo -->
17
10
 
18
11
  **Current behavior:**
19
12
  <!-- Describe how the bug manifests. -->
@@ -0,0 +1,23 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - uses: actions/setup-node@v3
14
+ with:
15
+ node-version: 16
16
+ cache: 'yarn'
17
+ - name: Install dependencies
18
+ run: yarn
19
+ - name: Release
20
+ env:
21
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22
+ NPM_TOKEN: ${{ secrets.NPM_PUBLISH }}
23
+ run: npx semantic-release
package/README.md CHANGED
@@ -10,9 +10,13 @@ You found an issue?<br>Tell us about it - <a href="https://github.com/storyblok/
10
10
  [![GitHub issues](https://img.shields.io/github/issues/storyblok/storyblok.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok/issues?q=is%3Aopen+is%3Aissue)
11
11
  [![GitHub closed issues](https://img.shields.io/github/issues-closed/storyblok/storyblok.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok/issues?q=is%3Aissue+is%3Aclosed)
12
12
 
13
+ ## BREAKING CHANGE
14
+
15
+ We added the `region` option upon login. If you are using the CLI, please `logout` and `login` again providing your user region.
16
+
13
17
  ## Installation
14
18
 
15
- Make sure you've node `>= 9.11.0` installed.
19
+ Make sure you have Node `>= 9.11.0` installed.
16
20
 
17
21
  ```sh
18
22
  $ npm i storyblok -g
@@ -28,6 +32,18 @@ Usage to kickstart a boilerplate, fieldtype or theme
28
32
  $ storyblok select
29
33
  ```
30
34
 
35
+ ### pull-languages
36
+
37
+ Download your space's languages schema as json. This command will download 1 file.
38
+
39
+ ```sh
40
+ $ storyblok pull-languages --space <SPACE_ID>
41
+ ```
42
+
43
+ #### Options
44
+
45
+ * `space`: your space id
46
+
31
47
  ### pull-components
32
48
 
33
49
  Download your space's components schema as json. This command will download 2 files: 1 for the components and 1 for the presets.
@@ -39,7 +55,6 @@ $ storyblok pull-components --space <SPACE_ID> --region <REGION>
39
55
  #### Options
40
56
 
41
57
  * `space`: your space id
42
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
43
58
 
44
59
  ### push-components
45
60
 
@@ -52,7 +67,6 @@ $ storyblok push-components <SOURCE> --space <SPACE_ID> --region <REGION> --pres
52
67
  #### Parameters
53
68
 
54
69
  * `source`: can be a URL or path to JSON file.
55
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
56
70
 
57
71
  Using an **URL**
58
72
 
@@ -69,7 +83,6 @@ $ storyblok push-components ./components.json --space 67819
69
83
  #### Options
70
84
 
71
85
  * `space`: your space id
72
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
73
86
  * `presets-source` (optional): it can be a URL or path to JSON file with the presets
74
87
 
75
88
  #### Examples
@@ -86,6 +99,65 @@ Using a **path** to file
86
99
  $ storyblok push-components ./components.json --presets-source ./presets.json --space 67819
87
100
  ```
88
101
 
102
+ ### delete-component
103
+
104
+ Delete a single component on your space.
105
+
106
+ ```sh
107
+ storyblok delete-component <component> --space <SPACE_ID>
108
+ ```
109
+
110
+ #### Parameters
111
+ * `component`: The name or id of the component
112
+
113
+ #### Options
114
+ * `space_id`: the space where the command should be executed.
115
+
116
+ #### Examples
117
+
118
+ Delete a component on your space.
119
+ ```sh
120
+ storyblok delete-component 111111 --space 67819
121
+ ```
122
+
123
+ ```sh
124
+ storyblok delete-component teaser --space 67819
125
+ ```
126
+
127
+ ### delete-components
128
+
129
+ Delete all components from your Space that occur in your Local JSON.
130
+ Or delete those components on your Space that do not appear in the JSON. (`--reverse`)
131
+
132
+ ```sh
133
+ storyblok delete-components <SOURCE> --space <SPACE_ID>
134
+ ```
135
+
136
+ #### Parameters
137
+ * `source`: can be a URL or path to JSON file.
138
+
139
+ #### Options
140
+ * `space_id`: the space where the command should be executed.
141
+ * `reverse`: When passed as an argument, deletes only those components on your space that do not appear in the JSON.
142
+ * `dryrun`: when passed as an argument, does not perform any changes on the given space.
143
+
144
+ #### Examples
145
+
146
+ Delete all components on a certain space that occur in your local JSON.
147
+ ```sh
148
+ storyblok delete-components ./components.json --space 67819
149
+ ```
150
+
151
+ Delete only those components which do not occur in your local json from your space.
152
+ ```sh
153
+ storyblok delete-components ./components.json --space 67819 --reverse
154
+ ```
155
+
156
+ To see the result in your console output but to not perform the command on your space, use the `--dryrun` argument.
157
+ ```sh
158
+ storyblok delete-components ./components.json --space 67819 --reverse --dryrun
159
+ ```
160
+
89
161
  ### sync
90
162
 
91
163
  Sync components, folder, roles, datasources or stories between spaces
@@ -99,7 +171,6 @@ $ storyblok sync --type <COMMAND> --source <SPACE_ID> --target <SPACE_ID>
99
171
  * `type`: describe the command type to execute. Can be: `folders`, `components`, `stories`, `datasources` or `roles`. It's possible pass multiple types separated by comma (`,`).
100
172
  * `source`: the source space to use to sync
101
173
  * `target`: the target space to use to sync
102
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
103
174
 
104
175
  #### Examples
105
176
 
@@ -134,6 +205,19 @@ Login to the Storyblok cli
134
205
  ```sh
135
206
  $ storyblok login
136
207
  ```
208
+ #### Options
209
+
210
+ * `email`: your user's email address
211
+ * `password`: your user's password
212
+ * `region`: your user's region (default: `eu`). You can use `us`, `cn` or `eu`. This region will be used for the other cli's commands.
213
+
214
+ ### user
215
+
216
+ Get the currently logged in user
217
+
218
+ ```sh
219
+ $ storyblok user
220
+ ```
137
221
 
138
222
  ### generate-migration
139
223
 
@@ -149,7 +233,6 @@ It's important to note that the `component` and `field` parameters are required
149
233
  * `space`: space where the component is
150
234
  * `component`: component name. It needs to be a valid component
151
235
  * `field`: name of field
152
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
153
236
 
154
237
  ### run-migration
155
238
 
@@ -176,7 +259,6 @@ $ storyblok run-migration --publish published --space 1234 --component article -
176
259
  * `published`: only publish stories that already are published and don't have unpublished changes
177
260
  * `published-with-changes`: publish stories that are published and have unpublished changes
178
261
  * `publish-languages` (optional): publish specific languages. You can publish more than one language at a time by separating the languages by `,`
179
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
180
262
 
181
263
  ### rollback-migration
182
264
 
@@ -196,6 +278,7 @@ $ storyblok rollback-migration --space 1234 --component Product --field title
196
278
 
197
279
  ### spaces
198
280
 
281
+
199
282
  List all spaces of the logged account
200
283
 
201
284
  ```sh
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "storyblok",
3
- "version": "3.14.0",
3
+ "version": "3.16.0",
4
4
  "description": "A simple CLI to start Storyblok from your command line.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/storyblok/storyblok-cli.git"
8
+ },
5
9
  "keywords": [
6
10
  "storyblok",
7
11
  "cli",
@@ -55,5 +59,10 @@
55
59
  "eslint-plugin-promise": "^4.2.1",
56
60
  "eslint-plugin-standard": "^4.0.1",
57
61
  "jest": "^26.1.0"
62
+ },
63
+ "release": {
64
+ "branches": [
65
+ "master"
66
+ ]
58
67
  }
59
68
  }
@@ -0,0 +1,29 @@
1
+ <!--- Please provide a general summary of your changes in the title above -->
2
+
3
+ ## Pull request type
4
+
5
+ Jira Link: [INT-](url)
6
+
7
+ <!-- Please try to limit your pull request to one type, submit multiple pull requests if needed.
8
+
9
+ Please check the type of change your PR introduces:-->
10
+
11
+ - [ ] Bugfix
12
+ - [ ] Feature
13
+ - [ ] Code style update (formatting, renaming)
14
+ - [ ] Refactoring (no functional changes, no api changes)
15
+ - [ ] Other (please describe):
16
+
17
+ ## How to test this PR
18
+
19
+ <!-- Please provide the steps on how to test this PR. -->
20
+
21
+ ## What is the new behavior?
22
+
23
+ <!-- Please describe the behavior or changes that are being added by this PR. -->
24
+
25
+ -
26
+ -
27
+ -
28
+
29
+ ## Other information
package/src/cli.js CHANGED
@@ -39,7 +39,7 @@ program
39
39
  program
40
40
  .command(COMMANDS.LOGIN)
41
41
  .description('Login to the Storyblok cli')
42
- .action(async () => {
42
+ .action(async (options) => {
43
43
  if (api.isAuthorized()) {
44
44
  console.log(chalk.green('✓') + ' The user has been already logged. If you want to change the logged user, you must logout and login again')
45
45
  return
@@ -54,6 +54,24 @@ program
54
54
  }
55
55
  })
56
56
 
57
+ // getUser
58
+ program
59
+ .command('user')
60
+ .description('Get the currently logged in user')
61
+ .action(async () => {
62
+ if (api.isAuthorized()) {
63
+ try {
64
+ const user = await api.getUser()
65
+ console.log(chalk.green('✓') + ` Hi ${user.friendly_name}, you current logged in with: ${creds.get().email}`)
66
+ } catch (e) {
67
+ console.log(chalk.red('X') + ` Please check if your current region matches your user's region: ${e.message}.`)
68
+ } finally {
69
+ process.exit(0)
70
+ }
71
+ }
72
+ console.log(chalk.red('X') + ' There is currently no user logged.')
73
+ })
74
+
57
75
  // logout
58
76
  program
59
77
  .command(COMMANDS.LOGOUT)
@@ -69,12 +87,36 @@ program
69
87
  }
70
88
  })
71
89
 
90
+ // pull-languages
91
+ program
92
+ .command('pull-languages')
93
+ .description("Download your space's languages schema as json")
94
+ .action(async () => {
95
+ console.log(`${chalk.blue('-')} Executing pull-languages task`)
96
+ const space = program.space
97
+ if (!space) {
98
+ console.log(chalk.red('X') + ' Please provide the space as argument --space YOUR_SPACE_ID.')
99
+ process.exit(0)
100
+ }
101
+
102
+ try {
103
+ if (!api.isAuthorized()) {
104
+ await api.processLogin()
105
+ }
106
+
107
+ api.setSpaceId(space)
108
+ await tasks.pullLanguages(api, { space })
109
+ } catch (e) {
110
+ console.log(chalk.red('X') + ' An error occurred when executing the pull-languages task: ' + e.message)
111
+ process.exit(1)
112
+ }
113
+ })
114
+
72
115
  // pull-components
73
116
  program
74
117
  .command(COMMANDS.PULL_COMPONENTS)
75
- .option('-r, --region [value]', 'region', 'eu')
76
118
  .description("Download your space's components schema as json")
77
- .action(async (source) => {
119
+ .action(async () => {
78
120
  console.log(`${chalk.blue('-')} Executing pull-components task`)
79
121
  const space = program.space
80
122
  if (!space) {
@@ -87,11 +129,6 @@ program
87
129
  await api.processLogin()
88
130
  }
89
131
 
90
- const { region } = source
91
- if (program.args.length > 0) {
92
- api.setRegion(region)
93
- }
94
-
95
132
  api.setSpaceId(space)
96
133
  await tasks.pullComponents(api, { space })
97
134
  } catch (e) {
@@ -103,7 +140,6 @@ program
103
140
  program
104
141
  .command(COMMANDS.PUSH_COMPONENTS + ' <source>')
105
142
  .option('-p, --presets-source <presetsSource>', 'Path to presets file')
106
- .option('-r, --region [value]', 'region', 'eu')
107
143
  .description("Download your space's components schema as json. The source parameter can be a URL to your JSON file or a path to it")
108
144
  .action(async (source, options) => {
109
145
  console.log(`${chalk.blue('-')} Executing push-components task`)
@@ -120,11 +156,6 @@ program
120
156
  await api.processLogin()
121
157
  }
122
158
 
123
- const { region } = options
124
- if (program.args.length > 0) {
125
- api.setRegion(region)
126
- }
127
-
128
159
  api.setSpaceId(space)
129
160
  await tasks.pushComponents(api, { source, presetsSource })
130
161
  } catch (e) {
@@ -132,6 +163,56 @@ program
132
163
  }
133
164
  })
134
165
 
166
+ // delete-component
167
+ program
168
+ .command('delete-component <component>')
169
+ .description('Delete a single component on your space.')
170
+ .action(async (component) => {
171
+ console.log(`${chalk.blue('-')} Executing delete-component task`)
172
+ const space = program.space
173
+ if (!space) {
174
+ console.log(chalk.red('X') + ' Please provide the space as argument --space YOUR_SPACE_ID.')
175
+ process.exit(0)
176
+ }
177
+ try {
178
+ if (!api.isAuthorized()) {
179
+ await api.processLogin()
180
+ }
181
+
182
+ api.setSpaceId(space)
183
+ await tasks.deleteComponent(api, { comp: component })
184
+ } catch (e) {
185
+ console.log(chalk.red('X') + ' An error occurred when executing the delete-component task: ' + e.message)
186
+ process.exit(1)
187
+ }
188
+ })
189
+
190
+ // delete-components
191
+ program
192
+ .command('delete-components <source>')
193
+ .description('Delete all components in your space that occur in your source file.')
194
+ .option('-r, --reverse', 'Delete all components in your space that do not appear in your source.', false)
195
+ .option('--dryrun', 'Does not perform any delete changes on your space.')
196
+ .action(async (source, options) => {
197
+ console.log(`${chalk.blue('-')} Executing delete-components task`)
198
+ const space = program.space
199
+ if (!space) {
200
+ console.log(chalk.red('X') + ' Please provide the space as argument --space YOUR_SPACE_ID.')
201
+ process.exit(0)
202
+ }
203
+ try {
204
+ if (!api.isAuthorized()) {
205
+ await api.processLogin()
206
+ }
207
+
208
+ api.setSpaceId(space)
209
+ await tasks.deleteComponents(api, { source, dryRun: !!options.dryrun, reversed: !!options.reverse })
210
+ } catch (e) {
211
+ console.log(chalk.red('X') + ' An error occurred when executing the delete-component task: ' + e.message)
212
+ process.exit(1)
213
+ }
214
+ })
215
+
135
216
  // scaffold
136
217
  program
137
218
  .command(COMMANDS.SCAFFOLD + ' <name>')
@@ -180,7 +261,6 @@ program
180
261
  .requiredOption('--type <TYPE>', 'Define what will be sync. Can be components, folders, stories, datasources or roles')
181
262
  .requiredOption('--source <SPACE_ID>', 'Source space id')
182
263
  .requiredOption('--target <SPACE_ID>', 'Target space id')
183
- .option('-r, --region [value]', 'region', 'eu')
184
264
  .action(async (options) => {
185
265
  console.log(`${chalk.blue('-')} Sync data between spaces\n`)
186
266
 
@@ -192,12 +272,9 @@ program
192
272
  const {
193
273
  type,
194
274
  source,
195
- target,
196
- region
275
+ target
197
276
  } = options
198
277
 
199
- api.setRegion(region)
200
-
201
278
  const _types = type.split(',') || []
202
279
  _types.forEach(_type => {
203
280
  if (!SYNC_TYPES.includes(_type)) {
@@ -226,6 +303,10 @@ program
226
303
  .description('Start a project quickly')
227
304
  .action(async () => {
228
305
  try {
306
+ if (!api.isAuthorized()) {
307
+ await api.processLogin()
308
+ }
309
+
229
310
  const space = program.space
230
311
  const questions = getQuestions('quickstart', { space }, api)
231
312
  const answers = await inquirer.prompt(questions)
@@ -239,7 +320,6 @@ program
239
320
  program
240
321
  .command(COMMANDS.GENERATE_MIGRATION)
241
322
  .description('Generate a content migration file')
242
- .option('-r, --region [value]', 'region', 'eu')
243
323
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
244
324
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
245
325
  .action(async (options) => {
@@ -259,9 +339,6 @@ program
259
339
  await api.processLogin()
260
340
  }
261
341
 
262
- const { region } = options
263
- api.setRegion(region)
264
-
265
342
  api.setSpaceId(space)
266
343
  await tasks.generateMigration(api, component, field)
267
344
  } catch (e) {
@@ -275,7 +352,6 @@ program
275
352
  .description('Run a migration file')
276
353
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
277
354
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
278
- .option('-r, --region [value]', 'region', 'eu')
279
355
  .option('--dryrun', 'Do not update the story content')
280
356
  .option('--publish <PUBLISH_OPTION>', 'Publish the content. It can be: all, published or published-with-changes')
281
357
  .option('--publish-languages <LANGUAGES>', 'Publish specific languages')
@@ -362,7 +438,7 @@ program
362
438
 
363
439
  await tasks.listSpaces(api)
364
440
  } catch (e) {
365
- console.log(chalk.red('X') + ' An error ocurred to listing sapces : ' + e.message)
441
+ console.log(chalk.red('X') + ' An error ocurred to listing spaces: ' + e.message)
366
442
  process.exit(1)
367
443
  }
368
444
  })
@@ -408,7 +484,7 @@ if (program.rawArgs.length <= 2) {
408
484
 
409
485
  function errorHandler (e, command) {
410
486
  if (/404/.test(e.message)) {
411
- console.log(chalk.yellow('/!\\') + ' If your space was created under US region, you must provide the region as argument --region us. Otherwise, you can use the default --region eu or omit this flag.')
487
+ console.log(chalk.yellow('/!\\') + ' If your space was created under US or CN region, you must provide the region us or cn upon login.')
412
488
  } else {
413
489
  console.log(chalk.red('X') + ' An error occurred when executing the ' + command + ' task: ' + e || e.message)
414
490
  }
package/src/constants.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const API_URL = 'https://api.storyblok.com/v1/'
2
2
  const US_API_URL = 'https://api-us.storyblok.com/v1/'
3
+ const CN_API_URL = 'https://api.storyblokchina.cn/v1/'
3
4
  const LOGIN_URL = `${API_URL}users/login`
4
5
  const SIGNUP_URL = `${API_URL}users/signup`
5
6
 
@@ -33,5 +34,6 @@ module.exports = {
33
34
  API_URL,
34
35
  SYNC_TYPES,
35
36
  US_API_URL,
37
+ CN_API_URL,
36
38
  COMMANDS
37
39
  }
@@ -0,0 +1,32 @@
1
+ const chalk = require('chalk')
2
+ const { getComponentsFromName } = require('./migrations/utils')
3
+
4
+ /**
5
+ *
6
+ * @param api {Object}
7
+ * @param comp {String | Number}
8
+ * @param dryrun {Boolean}
9
+ * @returns {Promise<void>}
10
+ */
11
+ const deleteComponent = async (api, { comp, dryrun = false }) => {
12
+ try {
13
+ let component
14
+ if (!isNaN(comp)) {
15
+ const { data } = await api.get(`components/${comp}`)
16
+ component = data.component
17
+ } else {
18
+ component = await getComponentsFromName(api, comp)
19
+ }
20
+ if (Object.keys(component).length === 0) {
21
+ return Promise.reject(new Error(`Component ${comp} not found.`))
22
+ }
23
+ if (!dryrun) {
24
+ await api.delete(`components/${component.id}`)
25
+ }
26
+ console.log(chalk.green('✓') + ' Component ' + chalk.blue(component.name) + ' deleted.')
27
+ } catch (e) {
28
+ console.error(`${chalk.red('X')} An error occurred in delete-component task.`)
29
+ return Promise.reject(new Error(e))
30
+ }
31
+ }
32
+ module.exports = deleteComponent
@@ -0,0 +1,92 @@
1
+ const chalk = require('chalk')
2
+ const axios = require('axios')
3
+ const fs = require('fs')
4
+ const deleteComponent = require('./delete-component')
5
+
6
+ const isUrl = source => source.indexOf('http') === 0
7
+
8
+ /**
9
+ * Get the data from a local or remote JSON file
10
+ * @param {string} source the local path or remote url of the file
11
+ * @returns {Promise<Object>} return the data from the source or an error
12
+ */
13
+ const getDataFromSource = async (source) => {
14
+ if (!source) {
15
+ return {}
16
+ }
17
+
18
+ try {
19
+ if (isUrl(source)) {
20
+ return (await axios.get(source)).data
21
+ } else {
22
+ return JSON.parse(fs.readFileSync(source, 'utf8'))
23
+ }
24
+ } catch (err) {
25
+ console.error(`${chalk.red('X')} Can not load json file from ${source}`)
26
+ return Promise.reject(err)
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Delete all components from your Space that occur in your Local JSON.
32
+ * @param api {Object}
33
+ * @param source {String}
34
+ * @param reversed {Boolean} Or delete those components on your Space that do not appear in the JSON.
35
+ * @param dryRun {Boolean}
36
+ * @returns {Promise<void>}
37
+ */
38
+ const deleteComponents = async (api, { source, reversed = false, dryRun = false }) => {
39
+ try {
40
+ const sourceComponents = (await getDataFromSource(source)).components || []
41
+ if (!reversed) {
42
+ return deleteAllComponents(api, sourceComponents, dryRun)
43
+ }
44
+ const spaceComponents = await api.getComponents()
45
+ return deleteComponentsReversed(api, sourceComponents, spaceComponents, dryRun)
46
+ } catch (e) {
47
+ console.error(`${chalk.red('X')} Can not delete with invalid json - please provide a valid json file`)
48
+ return Promise.reject(new Error('Can not delete with invalid json - please provide a valid json file'))
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Delete all given components
54
+ * @param api {Object}
55
+ * @param components {Object[]}
56
+ * @param dryrun {Boolean}
57
+ * @returns {Promise<void>}
58
+ */
59
+ const deleteAllComponents = async (api, components, dryrun) => {
60
+ for (const c of components) {
61
+ await deleteComponentAndSkip(api, c, dryrun)
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Delete all components which do not appear in components but in the space components
67
+ * @param api {Object}
68
+ * @param components {Object[]}
69
+ * @param spaceComponents {Object[]}
70
+ * @param dryrun {Boolean}
71
+ * @returns {Promise<void>}
72
+ */
73
+ const deleteComponentsReversed = async (api, components, spaceComponents, dryrun) => {
74
+ const unifiedComps = components.concat([...spaceComponents])
75
+ const toDelete = unifiedComps
76
+ .filter((value, index, self) =>
77
+ self.findIndex((o, i) => o.id === value.id && i !== index) < 0)
78
+ console.log(chalk.blue('-') + ' Deleting all components which do not appear in the given source.')
79
+ for (const c of toDelete) {
80
+ await deleteComponentAndSkip(api, c, dryrun)
81
+ }
82
+ }
83
+
84
+ const deleteComponentAndSkip = async (api, c, dryrun) => {
85
+ try {
86
+ return await deleteComponent(api, { comp: c.id, dryrun: dryrun })
87
+ } catch (e) {
88
+ console.log(chalk.red('-') + ' Error deleting component ' + chalk.blue(c.name) + '! Skipped...')
89
+ }
90
+ }
91
+
92
+ module.exports = deleteComponents
@@ -3,10 +3,13 @@ module.exports = {
3
3
  scaffold: require('./scaffold'),
4
4
  quickstart: require('./quickstart'),
5
5
  pullComponents: require('./pull-components'),
6
+ pullLanguages: require('./pull-languages'),
6
7
  pushComponents: require('./push-components'),
7
8
  generateMigration: require('./migrations/generate'),
8
9
  runMigration: require('./migrations/run'),
9
10
  rollbackMigration: require('./migrations/rollback'),
10
11
  listSpaces: require('./list-spaces'),
11
- importFiles: require('./import/import')
12
+ importFiles: require('./import/import'),
13
+ deleteComponent: require('./delete-component'),
14
+ deleteComponents: require('./delete-components')
12
15
  }
@@ -91,7 +91,7 @@ const runMigration = async (api, component, field, options = {}) => {
91
91
  const storyData = await api.getSingleStory(story.id)
92
92
  const oldContent = cloneDeep(storyData.content)
93
93
 
94
- await processMigration(storyData.content, component, migrationFn)
94
+ await processMigration(storyData.content, component, migrationFn, story.full_slug)
95
95
 
96
96
  const isChangeContent = !isEqual(oldContent, storyData.content)
97
97