storyblok 3.15.0 → 3.16.1

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
@@ -3,16 +3,18 @@
3
3
  <p align="center">A simple CLI for scaffolding <a href="https://www.storyblok.com" target="_blank">Storyblok</a> projects and fieldtypes.</p>
4
4
  </p>
5
5
 
6
- You found an issue?<br>Tell us about it - <a href="https://github.com/storyblok/storyblok/issues/new">open an issue</a> or look if it was <a href="https://github.com/storyblok/storyblok/issues/">already reported</a>.
7
-
8
6
  [![npm](https://img.shields.io/npm/v/storyblok.svg)](https://www.npmjs.com/package/storyblok)
9
7
  [![npm](https://img.shields.io/npm/dt/storyblok.svg)](ttps://img.shields.io/npm/dt/storyblok.svg)
10
8
  [![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
9
  [![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
10
 
11
+ ## BREAKING CHANGE
12
+
13
+ We added the `region` option upon login. If you are using the CLI, please `logout` and `login` again providing your user region.
14
+
13
15
  ## Installation
14
16
 
15
- Make sure you've node `>= 9.11.0` installed.
17
+ Make sure you have Node `>= 9.11.0` installed.
16
18
 
17
19
  ```sh
18
20
  $ npm i storyblok -g
@@ -51,7 +53,6 @@ $ storyblok pull-components --space <SPACE_ID> --region <REGION>
51
53
  #### Options
52
54
 
53
55
  * `space`: your space id
54
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
55
56
 
56
57
  ### push-components
57
58
 
@@ -64,7 +65,6 @@ $ storyblok push-components <SOURCE> --space <SPACE_ID> --region <REGION> --pres
64
65
  #### Parameters
65
66
 
66
67
  * `source`: can be a URL or path to JSON file.
67
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
68
68
 
69
69
  Using an **URL**
70
70
 
@@ -81,7 +81,6 @@ $ storyblok push-components ./components.json --space 67819
81
81
  #### Options
82
82
 
83
83
  * `space`: your space id
84
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
85
84
  * `presets-source` (optional): it can be a URL or path to JSON file with the presets
86
85
 
87
86
  #### Examples
@@ -98,6 +97,65 @@ Using a **path** to file
98
97
  $ storyblok push-components ./components.json --presets-source ./presets.json --space 67819
99
98
  ```
100
99
 
100
+ ### delete-component
101
+
102
+ Delete a single component on your space.
103
+
104
+ ```sh
105
+ storyblok delete-component <component> --space <SPACE_ID>
106
+ ```
107
+
108
+ #### Parameters
109
+ * `component`: The name or id of the component
110
+
111
+ #### Options
112
+ * `space_id`: the space where the command should be executed.
113
+
114
+ #### Examples
115
+
116
+ Delete a component on your space.
117
+ ```sh
118
+ storyblok delete-component 111111 --space 67819
119
+ ```
120
+
121
+ ```sh
122
+ storyblok delete-component teaser --space 67819
123
+ ```
124
+
125
+ ### delete-components
126
+
127
+ Delete all components from your Space that occur in your Local JSON.
128
+ Or delete those components on your Space that do not appear in the JSON. (`--reverse`)
129
+
130
+ ```sh
131
+ storyblok delete-components <SOURCE> --space <SPACE_ID>
132
+ ```
133
+
134
+ #### Parameters
135
+ * `source`: can be a URL or path to JSON file.
136
+
137
+ #### Options
138
+ * `space_id`: the space where the command should be executed.
139
+ * `reverse`: When passed as an argument, deletes only those components on your space that do not appear in the JSON.
140
+ * `dryrun`: when passed as an argument, does not perform any changes on the given space.
141
+
142
+ #### Examples
143
+
144
+ Delete all components on a certain space that occur in your local JSON.
145
+ ```sh
146
+ storyblok delete-components ./components.json --space 67819
147
+ ```
148
+
149
+ Delete only those components which do not occur in your local json from your space.
150
+ ```sh
151
+ storyblok delete-components ./components.json --space 67819 --reverse
152
+ ```
153
+
154
+ To see the result in your console output but to not perform the command on your space, use the `--dryrun` argument.
155
+ ```sh
156
+ storyblok delete-components ./components.json --space 67819 --reverse --dryrun
157
+ ```
158
+
101
159
  ### sync
102
160
 
103
161
  Sync components, folder, roles, datasources or stories between spaces
@@ -111,7 +169,6 @@ $ storyblok sync --type <COMMAND> --source <SPACE_ID> --target <SPACE_ID>
111
169
  * `type`: describe the command type to execute. Can be: `folders`, `components`, `stories`, `datasources` or `roles`. It's possible pass multiple types separated by comma (`,`).
112
170
  * `source`: the source space to use to sync
113
171
  * `target`: the target space to use to sync
114
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
115
172
 
116
173
  #### Examples
117
174
 
@@ -146,6 +203,19 @@ Login to the Storyblok cli
146
203
  ```sh
147
204
  $ storyblok login
148
205
  ```
206
+ #### Options
207
+
208
+ * `email`: your user's email address
209
+ * `password`: your user's password
210
+ * `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.
211
+
212
+ ### user
213
+
214
+ Get the currently logged in user
215
+
216
+ ```sh
217
+ $ storyblok user
218
+ ```
149
219
 
150
220
  ### generate-migration
151
221
 
@@ -161,7 +231,6 @@ It's important to note that the `component` and `field` parameters are required
161
231
  * `space`: space where the component is
162
232
  * `component`: component name. It needs to be a valid component
163
233
  * `field`: name of field
164
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
165
234
 
166
235
  ### run-migration
167
236
 
@@ -188,7 +257,6 @@ $ storyblok run-migration --publish published --space 1234 --component article -
188
257
  * `published`: only publish stories that already are published and don't have unpublished changes
189
258
  * `published-with-changes`: publish stories that are published and have unpublished changes
190
259
  * `publish-languages` (optional): publish specific languages. You can publish more than one language at a time by separating the languages by `,`
191
- * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
192
260
 
193
261
  ### rollback-migration
194
262
 
@@ -208,6 +276,7 @@ $ storyblok rollback-migration --space 1234 --component Product --field title
208
276
 
209
277
  ### spaces
210
278
 
279
+
211
280
  List all spaces of the logged account
212
281
 
213
282
  ```sh
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "storyblok",
3
- "version": "3.15.0",
3
+ "version": "3.16.1",
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)
@@ -97,9 +115,8 @@ program
97
115
  // pull-components
98
116
  program
99
117
  .command(COMMANDS.PULL_COMPONENTS)
100
- .option('-r, --region [value]', 'region', 'eu')
101
118
  .description("Download your space's components schema as json")
102
- .action(async (source) => {
119
+ .action(async () => {
103
120
  console.log(`${chalk.blue('-')} Executing pull-components task`)
104
121
  const space = program.space
105
122
  if (!space) {
@@ -112,11 +129,6 @@ program
112
129
  await api.processLogin()
113
130
  }
114
131
 
115
- const { region } = source
116
- if (program.args.length > 0) {
117
- api.setRegion(region)
118
- }
119
-
120
132
  api.setSpaceId(space)
121
133
  await tasks.pullComponents(api, { space })
122
134
  } catch (e) {
@@ -128,7 +140,6 @@ program
128
140
  program
129
141
  .command(COMMANDS.PUSH_COMPONENTS + ' <source>')
130
142
  .option('-p, --presets-source <presetsSource>', 'Path to presets file')
131
- .option('-r, --region [value]', 'region', 'eu')
132
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")
133
144
  .action(async (source, options) => {
134
145
  console.log(`${chalk.blue('-')} Executing push-components task`)
@@ -145,11 +156,6 @@ program
145
156
  await api.processLogin()
146
157
  }
147
158
 
148
- const { region } = options
149
- if (program.args.length > 0) {
150
- api.setRegion(region)
151
- }
152
-
153
159
  api.setSpaceId(space)
154
160
  await tasks.pushComponents(api, { source, presetsSource })
155
161
  } catch (e) {
@@ -157,6 +163,56 @@ program
157
163
  }
158
164
  })
159
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
+
160
216
  // scaffold
161
217
  program
162
218
  .command(COMMANDS.SCAFFOLD + ' <name>')
@@ -205,7 +261,6 @@ program
205
261
  .requiredOption('--type <TYPE>', 'Define what will be sync. Can be components, folders, stories, datasources or roles')
206
262
  .requiredOption('--source <SPACE_ID>', 'Source space id')
207
263
  .requiredOption('--target <SPACE_ID>', 'Target space id')
208
- .option('-r, --region [value]', 'region', 'eu')
209
264
  .action(async (options) => {
210
265
  console.log(`${chalk.blue('-')} Sync data between spaces\n`)
211
266
 
@@ -217,12 +272,9 @@ program
217
272
  const {
218
273
  type,
219
274
  source,
220
- target,
221
- region
275
+ target
222
276
  } = options
223
277
 
224
- api.setRegion(region)
225
-
226
278
  const _types = type.split(',') || []
227
279
  _types.forEach(_type => {
228
280
  if (!SYNC_TYPES.includes(_type)) {
@@ -251,6 +303,10 @@ program
251
303
  .description('Start a project quickly')
252
304
  .action(async () => {
253
305
  try {
306
+ if (!api.isAuthorized()) {
307
+ await api.processLogin()
308
+ }
309
+
254
310
  const space = program.space
255
311
  const questions = getQuestions('quickstart', { space }, api)
256
312
  const answers = await inquirer.prompt(questions)
@@ -264,7 +320,6 @@ program
264
320
  program
265
321
  .command(COMMANDS.GENERATE_MIGRATION)
266
322
  .description('Generate a content migration file')
267
- .option('-r, --region [value]', 'region', 'eu')
268
323
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
269
324
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
270
325
  .action(async (options) => {
@@ -284,9 +339,6 @@ program
284
339
  await api.processLogin()
285
340
  }
286
341
 
287
- const { region } = options
288
- api.setRegion(region)
289
-
290
342
  api.setSpaceId(space)
291
343
  await tasks.generateMigration(api, component, field)
292
344
  } catch (e) {
@@ -300,7 +352,6 @@ program
300
352
  .description('Run a migration file')
301
353
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
302
354
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
303
- .option('-r, --region [value]', 'region', 'eu')
304
355
  .option('--dryrun', 'Do not update the story content')
305
356
  .option('--publish <PUBLISH_OPTION>', 'Publish the content. It can be: all, published or published-with-changes')
306
357
  .option('--publish-languages <LANGUAGES>', 'Publish specific languages')
@@ -387,7 +438,7 @@ program
387
438
 
388
439
  await tasks.listSpaces(api)
389
440
  } catch (e) {
390
- 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)
391
442
  process.exit(1)
392
443
  }
393
444
  })
@@ -433,7 +484,7 @@ if (program.rawArgs.length <= 2) {
433
484
 
434
485
  function errorHandler (e, command) {
435
486
  if (/404/.test(e.message)) {
436
- 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.')
437
488
  } else {
438
489
  console.log(chalk.red('X') + ' An error occurred when executing the ' + command + ' task: ' + e || e.message)
439
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
@@ -9,5 +9,7 @@ module.exports = {
9
9
  runMigration: require('./migrations/run'),
10
10
  rollbackMigration: require('./migrations/rollback'),
11
11
  listSpaces: require('./list-spaces'),
12
- importFiles: require('./import/import')
12
+ importFiles: require('./import/import'),
13
+ deleteComponent: require('./delete-component'),
14
+ deleteComponents: require('./delete-components')
13
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
 
@@ -186,9 +186,10 @@ const showMigrationChanges = (path, value, oldValue) => {
186
186
  * @param {Object} content component structure from Storyblok
187
187
  * @param {String} component name of the component that is processing
188
188
  * @param {Function} migrationFn the migration function defined by user
189
+ * @param {String} storyFullSlug the full slug of the containing story
189
190
  * @return {Promise<Boolean>}
190
191
  */
191
- const processMigration = async (content = {}, component = '', migrationFn) => {
192
+ const processMigration = async (content = {}, component = '', migrationFn, storyFullSlug) => {
192
193
  // I'm processing the component that I want
193
194
  if (content.component === component) {
194
195
  const watchedContent = onChange(
@@ -196,7 +197,7 @@ const processMigration = async (content = {}, component = '', migrationFn) => {
196
197
  showMigrationChanges
197
198
  )
198
199
 
199
- await migrationFn(watchedContent)
200
+ await migrationFn(watchedContent, storyFullSlug)
200
201
  }
201
202
 
202
203
  for (const key in content) {
@@ -205,7 +206,7 @@ const processMigration = async (content = {}, component = '', migrationFn) => {
205
206
  if (isArray(value)) {
206
207
  try {
207
208
  await Promise.all(
208
- value.map(_item => processMigration(_item, component, migrationFn))
209
+ value.map(_item => processMigration(_item, component, migrationFn, storyFullSlug))
209
210
  )
210
211
  } catch (e) {
211
212
  console.error(e)
@@ -214,7 +215,7 @@ const processMigration = async (content = {}, component = '', migrationFn) => {
214
215
 
215
216
  if (isPlainObject(value) && has(value, 'component')) {
216
217
  try {
217
- await processMigration(value, component, migrationFn)
218
+ await processMigration(value, component, migrationFn, storyFullSlug)
218
219
  } catch (e) {
219
220
  console.error(e)
220
221
  }
@@ -223,7 +224,7 @@ const processMigration = async (content = {}, component = '', migrationFn) => {
223
224
  if (isPlainObject(value) && value.type === 'doc' && value.content) {
224
225
  value.content.filter(item => item.type === 'blok').forEach(async (item) => {
225
226
  try {
226
- await processMigration(item.attrs.body, component, migrationFn)
227
+ await processMigration(item.attrs.body, component, migrationFn, storyFullSlug)
227
228
  } catch (e) {
228
229
  console.error(e)
229
230
  }
@@ -1,6 +1,6 @@
1
1
  const chalk = require('chalk')
2
- const StoryblokClient = require('storyblok-js-client')
3
2
  const { findByProperty } = require('../../utils')
3
+ const api = require('../../utils/api')
4
4
 
5
5
  class SyncComponentGroups {
6
6
  /**
@@ -14,9 +14,7 @@ class SyncComponentGroups {
14
14
  this.sourceComponentGroups = []
15
15
  this.targetComponentGroups = []
16
16
 
17
- this.client = new StoryblokClient({
18
- oauthToken: options.oauthToken
19
- })
17
+ this.client = api.getClient()
20
18
  }
21
19
 
22
20
  async init () {
@@ -1,9 +1,9 @@
1
1
  const chalk = require('chalk')
2
- const StoryblokClient = require('storyblok-js-client')
3
2
  const { find } = require('lodash')
4
3
  const SyncComponentGroups = require('./component-groups')
5
4
  const { findByProperty } = require('../../utils')
6
5
  const PresetsLib = require('../../utils/presets-lib')
6
+ const api = require('../../utils/api')
7
7
 
8
8
  class SyncComponents {
9
9
  /**
@@ -16,9 +16,7 @@ class SyncComponents {
16
16
  this.sourceSpaceId = options.sourceSpaceId
17
17
  this.targetSpaceId = options.targetSpaceId
18
18
  this.oauthToken = options.oauthToken
19
- this.client = new StoryblokClient({
20
- oauthToken: options.oauthToken
21
- })
19
+ this.client = api.getClient()
22
20
  this.presetsLib = new PresetsLib({ oauthToken: options.oauthToken, targetSpaceId: this.targetSpaceId })
23
21
  }
24
22
 
package/src/utils/api.js CHANGED
@@ -5,21 +5,22 @@ const inquirer = require('inquirer')
5
5
 
6
6
  const creds = require('./creds')
7
7
  const getQuestions = require('./get-questions')
8
- const { LOGIN_URL, SIGNUP_URL, API_URL, US_API_URL } = require('../constants')
8
+ const { SIGNUP_URL, API_URL, US_API_URL, CN_API_URL } = require('../constants')
9
9
 
10
10
  module.exports = {
11
11
  accessToken: '',
12
12
  oauthToken: '',
13
13
  spaceId: null,
14
- region: 'eu',
14
+ region: '',
15
15
 
16
16
  getClient () {
17
- const apiURL = this.region === 'us' ? US_API_URL : API_URL
17
+ const { region } = creds.get()
18
+
18
19
  return new Storyblok({
19
20
  accessToken: this.accessToken,
20
21
  oauthToken: this.oauthToken,
21
22
  region: this.region
22
- }, apiURL)
23
+ }, this.apiSwitcher(region))
23
24
  },
24
25
 
25
26
  getPath (path) {
@@ -30,9 +31,9 @@ module.exports = {
30
31
  return path
31
32
  },
32
33
 
33
- async login (email, password) {
34
+ async login (email, password, region) {
34
35
  try {
35
- const response = await axios.post(LOGIN_URL, {
36
+ const response = await axios.post(`${this.apiSwitcher(region)}users/login`, {
36
37
  email: email,
37
38
  password: password
38
39
  })
@@ -57,26 +58,41 @@ module.exports = {
57
58
 
58
59
  const { otp_attempt: code } = await inquirer.prompt(questions)
59
60
 
60
- const newResponse = await axios.post(LOGIN_URL, {
61
+ const newResponse = await axios.post(`${this.apiSwitcher(region)}users/login`, {
61
62
  email: email,
62
63
  password: password,
63
64
  otp_attempt: code
64
65
  })
65
66
 
66
- return this.persistCredentials(email, newResponse.data || {})
67
+ return this.persistCredentials(email, newResponse.data || {}, region)
67
68
  }
68
69
 
69
- return this.persistCredentials(email, data)
70
+ return this.persistCredentials(email, data, region)
70
71
  } catch (e) {
71
72
  return Promise.reject(e)
72
73
  }
73
74
  },
74
75
 
75
- persistCredentials (email, data) {
76
+ async getUser () {
77
+ const { region } = creds.get()
78
+
79
+ try {
80
+ const { data } = await axios.get(`${this.apiSwitcher(this.region ? this.region : region)}users/me`, {
81
+ headers: {
82
+ Authorization: this.oauthToken
83
+ }
84
+ })
85
+ return data.user
86
+ } catch (e) {
87
+ return Promise.reject(e)
88
+ }
89
+ },
90
+
91
+ persistCredentials (email, data, region = 'eu') {
76
92
  const token = this.extractToken(data)
77
93
  if (token) {
78
94
  this.oauthToken = token
79
- creds.set(email, token)
95
+ creds.set(email, token, region)
80
96
 
81
97
  return Promise.resolve(data)
82
98
  }
@@ -86,9 +102,9 @@ module.exports = {
86
102
  async processLogin () {
87
103
  try {
88
104
  const questions = getQuestions('login')
89
- const { email, password } = await inquirer.prompt(questions)
105
+ const { email, password, region } = await inquirer.prompt(questions)
90
106
 
91
- const data = await this.login(email, password)
107
+ const data = await this.login(email, password, region)
92
108
 
93
109
  console.log(chalk.green('✓') + ' Log in successfully! Token has been added to .netrc file.')
94
110
 
@@ -109,19 +125,23 @@ module.exports = {
109
125
  return data.access_token
110
126
  },
111
127
 
112
- logout () {
128
+ logout (unauthorized) {
129
+ if (creds.get().email && unauthorized) {
130
+ console.log(chalk.red('X') + ' Your login seems to be expired, we logged you out. Please log back in again.')
131
+ }
113
132
  creds.set(null)
114
133
  },
115
134
 
116
- signup (email, password) {
135
+ signup (email, password, region = 'eu') {
117
136
  return axios.post(SIGNUP_URL, {
118
137
  email: email,
119
- password: password
138
+ password: password,
139
+ region
120
140
  })
121
141
  .then(response => {
122
142
  const token = this.extractToken(response)
123
143
  this.oauthToken = token
124
- creds.set(email, token)
144
+ creds.set(email, token, region)
125
145
 
126
146
  return Promise.resolve(true)
127
147
  })
@@ -130,7 +150,6 @@ module.exports = {
130
150
 
131
151
  isAuthorized () {
132
152
  const { token } = creds.get() || {}
133
-
134
153
  if (token) {
135
154
  this.oauthToken = token
136
155
  return true
@@ -226,5 +245,15 @@ module.exports = {
226
245
  .get('spaces/', {})
227
246
  .then(res => res.data.spaces || [])
228
247
  .catch(err => Promise.reject(err))
248
+ },
249
+
250
+ apiSwitcher (region) {
251
+ const apiList = {
252
+ us: US_API_URL,
253
+ cn: CN_API_URL,
254
+ eu: API_URL
255
+ }
256
+
257
+ return region ? apiList[region] : apiList[this.region]
229
258
  }
230
259
  }
@@ -25,31 +25,34 @@ const getNrcFile = () => {
25
25
  const get = function () {
26
26
  const obj = getNrcFile()
27
27
 
28
- if (process.env.STORYBLOK_LOGIN && process.env.STORYBLOK_TOKEN) {
28
+ if (process.env.STORYBLOK_LOGIN && process.env.STORYBLOK_TOKEN && process.env.STORYBLOK_REGION) {
29
29
  return {
30
30
  email: process.env.STORYBLOK_LOGIN,
31
- token: process.env.STORYBLOK_TOKEN
31
+ token: process.env.STORYBLOK_TOKEN,
32
+ region: process.env.STORYBLOK_REGION
32
33
  }
33
34
  }
34
35
 
35
- if (process.env.TRAVIS_STORYBLOK_LOGIN && process.env.TRAVIS_STORYBLOK_TOKEN) {
36
+ if (process.env.TRAVIS_STORYBLOK_LOGIN && process.env.TRAVIS_STORYBLOK_TOKEN && process.env.TRAVIS_STORYBLOK_REGION) {
36
37
  return {
37
38
  email: process.env.TRAVIS_STORYBLOK_LOGIN,
38
- token: process.env.TRAVIS_STORYBLOK_TOKEN
39
+ token: process.env.TRAVIS_STORYBLOK_TOKEN,
40
+ region: process.env.TRAVIS_STORYBLOK_REGION
39
41
  }
40
42
  }
41
43
 
42
44
  if (Object.hasOwnProperty.call(obj, host)) {
43
45
  return {
44
46
  email: obj[host].login,
45
- token: obj[host].password
47
+ token: obj[host].password,
48
+ region: obj[host].region
46
49
  }
47
50
  }
48
51
 
49
52
  return null
50
53
  }
51
54
 
52
- const set = function (email, token) {
55
+ const set = function (email, token, region) {
53
56
  const file = getFile()
54
57
  let obj = {}
55
58
 
@@ -66,7 +69,8 @@ const set = function (email, token) {
66
69
  } else {
67
70
  obj[host] = {
68
71
  login: email,
69
- password: token
72
+ password: token,
73
+ region
70
74
  }
71
75
  fs.writeFileSync(file, netrc.format(obj) + os.EOL)
72
76
  return get()
@@ -128,6 +128,19 @@ const getOptions = (subCommand, argv = {}, api = {}) => {
128
128
 
129
129
  return 'Please enter a valid password:'
130
130
  }
131
+ },
132
+ {
133
+ type: 'input',
134
+ name: 'region',
135
+ message: 'Enter your user\'s region (us, eu or cn):',
136
+ validate: function (value) {
137
+ const flagList = ['us', 'cn', 'eu']
138
+ if (flagList.indexOf(value) > -1) {
139
+ return true
140
+ }
141
+
142
+ return 'Please enter a valid region: us, eu or cn'
143
+ }
131
144
  }
132
145
  ]
133
146
  }
@@ -1,8 +1,8 @@
1
1
  const chalk = require('chalk')
2
- const StoryblokClient = require('storyblok-js-client')
3
2
  const FormData = require('form-data')
4
3
  const axios = require('axios')
5
4
  const { last } = require('lodash')
5
+ const api = require('./api')
6
6
 
7
7
  class PresetsLib {
8
8
  /**
@@ -10,9 +10,7 @@ class PresetsLib {
10
10
  */
11
11
  constructor (options) {
12
12
  this.oauthToken = options.oauthToken
13
- this.client = new StoryblokClient({
14
- oauthToken: options.oauthToken
15
- })
13
+ this.client = api.getClient()
16
14
  this.targetSpaceId = options.targetSpaceId
17
15
  }
18
16
 
@@ -1,6 +1,7 @@
1
1
  const EMAIL_TEST = 'test@storyblok.com'
2
2
  const PASSWORD_TEST = 'test'
3
3
  const TOKEN_TEST = 'storyblok1234'
4
+ const REGION_TEST = 'eu'
4
5
 
5
6
  // use functions to always returns "new" data
6
7
  const FAKE_COMPONENTS = () => [
@@ -255,5 +256,6 @@ module.exports = {
255
256
  PASSWORD_TEST,
256
257
  FAKE_COMPONENTS,
257
258
  FAKE_SPACES,
258
- FAKE_SPACE_OPTIONS
259
+ FAKE_SPACE_OPTIONS,
260
+ REGION_TEST
259
261
  }
@@ -0,0 +1,53 @@
1
+ const deleteComponent = require('../../src/tasks/delete-component')
2
+ const { FAKE_COMPONENTS } = require('../constants')
3
+
4
+ describe('testing deleteComponent', () => {
5
+ it('api.deleteComponent name', () => {
6
+ const api = {
7
+ getComponents: jest.fn(() => Promise.resolve(FAKE_COMPONENTS())),
8
+ delete: jest.fn(() => Promise.resolve())
9
+ }
10
+ return deleteComponent(api, { comp: 'teaser' }).then(() => {
11
+ expect(api.delete.mock.calls.length).toBe(1)
12
+ })
13
+ })
14
+ it('api.deleteComponent id', () => {
15
+ const comp = FAKE_COMPONENTS()[0]
16
+ const api = {
17
+ get: jest.fn(() => Promise.resolve({ data: { component: comp } })),
18
+ delete: jest.fn(() => Promise.resolve())
19
+ }
20
+ return deleteComponent(api, { comp: 0 }).then(() => {
21
+ expect(api.get.mock.calls.length).toBe(1)
22
+ expect(api.delete.mock.calls.length).toBe(1)
23
+ })
24
+ })
25
+ it('api.deleteComponent name dryrun', () => {
26
+ const api = {
27
+ getComponents: jest.fn(() => Promise.resolve(FAKE_COMPONENTS())),
28
+ delete: jest.fn(() => Promise.resolve())
29
+ }
30
+ return deleteComponent(api, { comp: 'teaser', dryrun: true }).then(() => {
31
+ expect(api.delete.mock.calls.length).toBe(0)
32
+ })
33
+ })
34
+ it('api.deleteComponent not found', () => {
35
+ const api = {
36
+ getComponents: jest.fn(() => Promise.resolve(FAKE_COMPONENTS())),
37
+ delete: jest.fn(() => Promise.resolve())
38
+ }
39
+ return expect(deleteComponent(api, { comp: 'not a fake component' }).then(() => {
40
+ expect(api.delete.mock.calls.length).toBe(0)
41
+ })).rejects.toThrow('Component not a fake component not found.')
42
+ })
43
+ it('api.deleteComponent not found by id', () => {
44
+ const api = {
45
+ get: jest.fn(() => Promise.reject(new Error('Not Found'))),
46
+ delete: jest.fn(() => Promise.resolve())
47
+ }
48
+ return expect(deleteComponent(api, { comp: 1 }).then(() => {
49
+ expect(api.get.mock.calls.length).toBe(1)
50
+ expect(api.delete.mock.calls.length).toBe(0)
51
+ })).rejects.toThrow('Not Found')
52
+ })
53
+ })
@@ -0,0 +1,93 @@
1
+ const deleteComponents = require('../../src/tasks/delete-components')
2
+ const { FAKE_COMPONENTS } = require('../constants')
3
+ const fs = require('fs')
4
+ jest.mock('fs')
5
+
6
+ afterEach(() => {
7
+ jest.clearAllMocks()
8
+ })
9
+
10
+ describe('testing deleteComponents', () => {
11
+ it('api.deleteComponents', () => {
12
+ const source = 'components.js'
13
+ const components = FAKE_COMPONENTS()
14
+ const spy = jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({
15
+ components
16
+ }))
17
+ const api = {
18
+ get: jest.fn((path) => {
19
+ const id = path.split('/')[1]
20
+ return Promise.resolve({ data: { component: components[id] } })
21
+ }),
22
+ delete: jest.fn(() => Promise.resolve())
23
+ }
24
+ return deleteComponents(api, { source, reversed: false }).then(() => {
25
+ expect(spy.mock.calls.length).toBe(1)
26
+ expect(api.delete.mock.calls.length).toBe(components.length)
27
+ })
28
+ })
29
+ it('api.deleteComponents reverse', () => {
30
+ const source = 'components.js'
31
+ const components = FAKE_COMPONENTS()
32
+ const spy = jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({
33
+ components
34
+ }))
35
+ const api = {
36
+ get: jest.fn((path) => {
37
+ const id = path.split('/')[1]
38
+ return Promise.resolve({ data: { component: components[id] } })
39
+ }),
40
+ getComponents: jest.fn(() => {
41
+ const copy = [...components]
42
+ copy.splice(3, 1)
43
+ return copy
44
+ }),
45
+ delete: jest.fn(() => Promise.resolve())
46
+ }
47
+ return deleteComponents(api, { source, reversed: true }).then(() => {
48
+ expect(spy.mock.calls.length).toBe(1)
49
+ expect(api.delete.mock.calls.length).toBe(1)
50
+ })
51
+ })
52
+ it('api.deleteComponents --dryrun', () => {
53
+ const source = 'components.js'
54
+ const components = FAKE_COMPONENTS()
55
+ const spy = jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({
56
+ components
57
+ }))
58
+ const api = {
59
+ get: jest.fn((path) => {
60
+ const id = path.split('/')[1]
61
+ return Promise.resolve({ data: { component: components[id] } })
62
+ }),
63
+ delete: jest.fn(() => Promise.resolve())
64
+ }
65
+ return deleteComponents(api, { source, reversed: false, dryRun: true }).then(() => {
66
+ expect(spy.mock.calls.length).toBe(1)
67
+ expect(api.delete.mock.calls.length).toBe(0)
68
+ })
69
+ })
70
+ it('api.deleteComponents reverse --dryrun', () => {
71
+ const source = 'components.js'
72
+ const components = FAKE_COMPONENTS()
73
+ const spy = jest.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({
74
+ components
75
+ }))
76
+ const api = {
77
+ get: jest.fn((path) => {
78
+ const id = path.split('/')[1]
79
+ return Promise.resolve({ data: { component: components[id] } })
80
+ }),
81
+ getComponents: jest.fn(() => {
82
+ const copy = [...components]
83
+ copy.splice(3, 1)
84
+ return copy
85
+ }),
86
+ delete: jest.fn(() => Promise.resolve())
87
+ }
88
+ return deleteComponents(api, { source, reversed: true, dryRun: true }).then(() => {
89
+ expect(spy.mock.calls.length).toBe(1)
90
+ expect(api.delete.mock.calls.length).toBe(0)
91
+ })
92
+ })
93
+ })
@@ -1,6 +1,6 @@
1
1
  const api = require('../../src/utils/api')
2
2
  const creds = require('../../src/utils/creds')
3
- const { EMAIL_TEST, TOKEN_TEST, PASSWORD_TEST } = require('../constants')
3
+ const { EMAIL_TEST, TOKEN_TEST, PASSWORD_TEST, REGION_TEST } = require('../constants')
4
4
 
5
5
  jest.mock('axios')
6
6
 
@@ -19,7 +19,8 @@ describe('api.login() method', () => {
19
19
 
20
20
  expect(creds.get()).toEqual({
21
21
  email: EMAIL_TEST,
22
- token: TOKEN_TEST
22
+ token: TOKEN_TEST,
23
+ region: REGION_TEST
23
24
  })
24
25
  } catch (e) {
25
26
  console.error(e)
@@ -28,7 +29,7 @@ describe('api.login() method', () => {
28
29
 
29
30
  it('when login is incorrect, the .netrc file is not populated and throw a reject message', async () => {
30
31
  try {
31
- await api.login(EMAIL_TEST, '1234')
32
+ await api.login(EMAIL_TEST, '1234', REGION_TEST)
32
33
  } catch (e) {
33
34
  expect(e.message).toBe('Incorrect access')
34
35
  }
@@ -1,28 +0,0 @@
1
- ---
2
- name: Feature request
3
- about: Suggest an idea for Storyblok
4
- title: ''
5
- labels: enhancement
6
- assignees: ''
7
-
8
- ---
9
-
10
- **The feature would affect:** (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
- - [ ] *Other* <!-- => If you've got an issue with on of our boilerplates or themes - please create an issue in the specific repo -->
16
-
17
-
18
- **Is your feature request related to a problem? Please describe.**
19
- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
20
-
21
- **Describe the solution you'd like**
22
- A clear and concise description of what you want to happen.
23
-
24
- **Describe alternatives you've considered**
25
- A clear and concise description of any alternative solutions or features you've considered.
26
-
27
- **Additional context**
28
- Add any other context or screenshots about the feature request here.
@@ -1,10 +0,0 @@
1
- ---
2
- name: Question
3
- about: Ask a question related to Storyblok
4
- title: ''
5
- labels: question
6
- assignees: ''
7
-
8
- ---
9
-
10
- Is your feature request related to a problem? Please describe.
@@ -1,31 +0,0 @@
1
- **The issue occurs while working with:** (check one with "x")
2
- - [ ] *app.storyblok.com (CMS - Interface)*
3
- - [ ] *api.storyblok.com (CMS - Content Delivery API)*
4
- - [ ] *mapi.storyblok.com (CMS - Management API)*
5
- - [ ] *capi.storyblok.com (Commerce - API)*
6
- - [ ] *Commerce - Interface*
7
- - [ ] *Other* <!-- => If you've got an issue with on of our boilerplates or themes - please create an issue in the specific repo -->
8
-
9
- **I'm submitting a ...** (check one with "x")
10
- - [ ] bug report
11
- - [ ] feature request
12
- - [ ] question
13
-
14
- **Current behavior:**
15
- <!-- Describe how the bug manifests. -->
16
-
17
- **Expected behavior:**
18
- <!-- Describe what the behavior would be without the bug. -->
19
-
20
- **Steps to reproduce:**
21
- <!-- If you are able to illustrate the bug or feature request with an example, please provide steps to reproduce and if possible also a demo.-->
22
-
23
- **Related code:**
24
-
25
- ```
26
- insert any relevant code here
27
- ```
28
-
29
- **Other information:**
30
- <!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
31
-
@@ -1,8 +0,0 @@
1
- app.storyblok:
2
- - '[x] *app.storyblok.com'
3
- api.storyblok:
4
- - '[x] *api.storyblok.com'
5
- mapi.storyblok:
6
- - '[x] *mapi.storyblok.com'
7
- capi.storyblok:
8
- - '[x] *capi.storyblok.com'
@@ -1,14 +0,0 @@
1
- name: "Issue Labeler"
2
- on:
3
- issues:
4
- types: [opened]
5
-
6
- jobs:
7
- triage:
8
- runs-on: ubuntu-latest
9
- steps:
10
- - uses: github/issue-labeler@v2.5
11
- with:
12
- repo-token: "${{ secrets.GITHUB_TOKEN }}"
13
- configuration-path: .github/labeler.yml
14
- enable-versioned-regex: 0
package/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - 14
4
- after_success:
5
- - npx semantic-release