storyblok 3.10.5 → 3.12.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.
@@ -0,0 +1,8 @@
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'
@@ -0,0 +1,14 @@
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/README.md CHANGED
@@ -33,24 +33,26 @@ $ storyblok select
33
33
  Download your space's components schema as json. This command will download 2 files: 1 for the components and 1 for the presets.
34
34
 
35
35
  ```sh
36
- $ storyblok pull-components --space <SPACE_ID>
36
+ $ storyblok pull-components --space <SPACE_ID> --region <REGION>
37
37
  ```
38
38
 
39
39
  #### Options
40
40
 
41
41
  * `space`: your space id
42
+ * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
42
43
 
43
44
  ### push-components
44
45
 
45
46
  Push your components file to your/another space
46
47
 
47
48
  ```sh
48
- $ storyblok push-components <SOURCE> --space <SPACE_ID> --presets-source <PRESETS_SOURCE>
49
+ $ storyblok push-components <SOURCE> --space <SPACE_ID> --region <REGION> --presets-source <PRESETS_SOURCE>
49
50
  ```
50
51
 
51
52
  #### Parameters
52
53
 
53
54
  * `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.
54
56
 
55
57
  Using an **URL**
56
58
 
@@ -67,6 +69,7 @@ $ storyblok push-components ./components.json --space 67819
67
69
  #### Options
68
70
 
69
71
  * `space`: your space id
72
+ * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
70
73
  * `presets-source` (optional): it can be a URL or path to JSON file with the presets
71
74
 
72
75
  #### Examples
@@ -96,6 +99,7 @@ $ storyblok sync --type <COMMAND> --source <SPACE_ID> --target <SPACE_ID>
96
99
  * `type`: describe the command type to execute. Can be: `folders`, `components`, `stories`, `datasources` or `roles`. It's possible pass multiple types separated by comma (`,`).
97
100
  * `source`: the source space to use to sync
98
101
  * `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.
99
103
 
100
104
  #### Examples
101
105
 
@@ -138,12 +142,14 @@ Create a migration file (with the name `change_<COMPONENT>_<FIELD>.js`) inside t
138
142
  ```sh
139
143
  $ storyblok generate-migration --space <SPACE_ID> --component <COMPONENT_NAME> --field <FIELD>
140
144
  ```
145
+ It's important to note that the `component` and `field` parameters are required and must be spelled exactly as they are in Storyblok. You can check the exact name by looking at the `Block library` inside your space.
141
146
 
142
147
  #### Options
143
148
 
144
149
  * `space`: space where the component is
145
150
  * `component`: component name. It needs to be a valid component
146
151
  * `field`: name of field
152
+ * `region`: your space region (default: `eu`). If your space was created under US region, you should use `us` instead.
147
153
 
148
154
  ### run-migration
149
155
 
@@ -170,6 +176,7 @@ $ storyblok run-migration --publish published --space 1234 --component article -
170
176
  * `published`: only publish stories that already are published and don't have unpublished changes
171
177
  * `published-with-changes`: publish stories that are published and have unpublished changes
172
178
  * `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.
173
180
 
174
181
  ### rollback-migration
175
182
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storyblok",
3
- "version": "3.10.5",
3
+ "version": "3.12.0",
4
4
  "description": "A simple CLI to start Storyblok from your command line.",
5
5
  "keywords": [
6
6
  "storyblok",
@@ -37,7 +37,7 @@
37
37
  "open": "^6.0.0",
38
38
  "p-series": "^2.1.0",
39
39
  "path": "^0.12.7",
40
- "storyblok-js-client": "^3.3.1",
40
+ "storyblok-js-client": "^4.5.6",
41
41
  "update-notifier": "^5.1.0",
42
42
  "xml-js": "^1.6.11"
43
43
  },
package/src/cli.js CHANGED
@@ -13,7 +13,7 @@ const pkg = require('../package.json')
13
13
 
14
14
  const tasks = require('./tasks')
15
15
  const { getQuestions, lastStep, api, creds } = require('./utils')
16
- const { SYNC_TYPES } = require('./constants')
16
+ const { SYNC_TYPES, COMMANDS } = require('./constants')
17
17
 
18
18
  clear()
19
19
  console.log(chalk.cyan(figlet.textSync('Storyblok')))
@@ -37,7 +37,7 @@ program
37
37
 
38
38
  // login
39
39
  program
40
- .command('login')
40
+ .command(COMMANDS.LOGIN)
41
41
  .description('Login to the Storyblok cli')
42
42
  .action(async () => {
43
43
  if (api.isAuthorized()) {
@@ -56,7 +56,7 @@ program
56
56
 
57
57
  // logout
58
58
  program
59
- .command('logout')
59
+ .command(COMMANDS.LOGOUT)
60
60
  .description('Logout from the Storyblok cli')
61
61
  .action(async () => {
62
62
  try {
@@ -71,9 +71,10 @@ program
71
71
 
72
72
  // pull-components
73
73
  program
74
- .command('pull-components')
74
+ .command(COMMANDS.PULL_COMPONENTS)
75
+ .option('-r, --region [value]', 'region', 'eu')
75
76
  .description("Download your space's components schema as json")
76
- .action(async () => {
77
+ .action(async (source) => {
77
78
  console.log(`${chalk.blue('-')} Executing pull-components task`)
78
79
  const space = program.space
79
80
  if (!space) {
@@ -86,18 +87,23 @@ program
86
87
  await api.processLogin()
87
88
  }
88
89
 
90
+ const { region } = source
91
+ if (program.args.length > 0) {
92
+ api.setRegion(region)
93
+ }
94
+
89
95
  api.setSpaceId(space)
90
96
  await tasks.pullComponents(api, { space })
91
97
  } catch (e) {
92
- console.log(chalk.red('X') + ' An error occurred when executing the pull-components task: ' + e.message)
93
- process.exit(1)
98
+ errorHandler(e, COMMANDS.PULL_COMPONENTS)
94
99
  }
95
100
  })
96
101
 
97
102
  // push-components
98
103
  program
99
- .command('push-components <source>')
104
+ .command(COMMANDS.PUSH_COMPONENTS + ' <source>')
100
105
  .option('-p, --presets-source <presetsSource>', 'Path to presets file')
106
+ .option('-r, --region [value]', 'region', 'eu')
101
107
  .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")
102
108
  .action(async (source, options) => {
103
109
  console.log(`${chalk.blue('-')} Executing push-components task`)
@@ -113,17 +119,22 @@ program
113
119
  if (!api.isAuthorized()) {
114
120
  await api.processLogin()
115
121
  }
122
+
123
+ const { region } = options
124
+ if (program.args.length > 0) {
125
+ api.setRegion(region)
126
+ }
127
+
116
128
  api.setSpaceId(space)
117
129
  await tasks.pushComponents(api, { source, presetsSource })
118
130
  } catch (e) {
119
- console.log(chalk.red('X') + ' An error occurred when executing the push-components task: ' + e.message)
120
- process.exit(1)
131
+ errorHandler(e, COMMANDS.PUSH_COMPONENTS)
121
132
  }
122
133
  })
123
134
 
124
135
  // scaffold
125
136
  program
126
- .command('scaffold <name>')
137
+ .command(COMMANDS.SCAFFOLD + ' <name>')
127
138
  .description('Scaffold <name> component')
128
139
  .action(async (name) => {
129
140
  console.log(`${chalk.blue('-')} Scaffolding a component\n`)
@@ -146,7 +157,7 @@ program
146
157
 
147
158
  // select
148
159
  program
149
- .command('select')
160
+ .command(COMMANDS.SELECT)
150
161
  .description('Usage to kickstart a boilerplate, fieldtype or theme')
151
162
  .action(async () => {
152
163
  console.log(`${chalk.blue('-')} Select a boilerplate, fieldtype or theme to initialize\n`)
@@ -164,36 +175,40 @@ program
164
175
 
165
176
  // sync
166
177
  program
167
- .command('sync')
178
+ .command(COMMANDS.SYNC)
168
179
  .description('Sync schemas, roles, folders and stories between spaces')
169
180
  .requiredOption('--type <TYPE>', 'Define what will be sync. Can be components, folders, stories, datasources or roles')
170
181
  .requiredOption('--source <SPACE_ID>', 'Source space id')
171
182
  .requiredOption('--target <SPACE_ID>', 'Target space id')
183
+ .option('-r, --region [value]', 'region', 'eu')
172
184
  .action(async (options) => {
173
185
  console.log(`${chalk.blue('-')} Sync data between spaces\n`)
174
186
 
175
- const {
176
- type,
177
- source,
178
- target
179
- } = options
180
-
181
187
  try {
182
- const _types = type.split(',') || []
188
+ if (!api.isAuthorized()) {
189
+ await api.processLogin()
190
+ }
191
+
192
+ const {
193
+ type,
194
+ source,
195
+ target,
196
+ region
197
+ } = options
198
+
199
+ api.setRegion(region)
183
200
 
201
+ const _types = type.split(',') || []
184
202
  _types.forEach(_type => {
185
203
  if (!SYNC_TYPES.includes(_type)) {
186
204
  throw new Error(`The type ${_type} is not valid`)
187
205
  }
188
206
  })
189
207
 
190
- if (!api.isAuthorized()) {
191
- await api.processLogin()
192
- }
193
-
194
208
  const token = creds.get().token || null
195
209
 
196
210
  await tasks.sync(_types, {
211
+ api,
197
212
  token,
198
213
  source,
199
214
  target
@@ -201,14 +216,13 @@ program
201
216
 
202
217
  console.log('\n' + chalk.green('✓') + ' Sync data between spaces successfully completed')
203
218
  } catch (e) {
204
- console.error(chalk.red('X') + ' An error ocurred when syncing spaces: ' + e.message)
205
- process.exit(1)
219
+ errorHandler(e, COMMANDS.SYNC)
206
220
  }
207
221
  })
208
222
 
209
223
  // quickstart
210
224
  program
211
- .command('quickstart')
225
+ .command(COMMANDS.QUICKSTART)
212
226
  .description('Start a project quickly')
213
227
  .action(async () => {
214
228
  try {
@@ -223,13 +237,14 @@ program
223
237
  })
224
238
 
225
239
  program
226
- .command('generate-migration')
240
+ .command(COMMANDS.GENERATE_MIGRATION)
227
241
  .description('Generate a content migration file')
242
+ .option('-r, --region [value]', 'region', 'eu')
228
243
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
229
244
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
230
245
  .action(async (options) => {
231
- const field = options.field || ''
232
- const component = options.component || ''
246
+ const { field = '' } = options
247
+ const { component = '' } = options
233
248
 
234
249
  const space = program.space
235
250
  if (!space) {
@@ -244,6 +259,9 @@ program
244
259
  await api.processLogin()
245
260
  }
246
261
 
262
+ const { region } = options
263
+ api.setRegion(region)
264
+
247
265
  api.setSpaceId(space)
248
266
  await tasks.generateMigration(api, component, field)
249
267
  } catch (e) {
@@ -253,10 +271,11 @@ program
253
271
  })
254
272
 
255
273
  program
256
- .command('run-migration')
274
+ .command(COMMANDS.RUN_MIGRATION)
257
275
  .description('Run a migration file')
258
276
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
259
277
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
278
+ .option('-r, --region [value]', 'region', 'eu')
260
279
  .option('--dryrun', 'Do not update the story content')
261
280
  .option('--publish <PUBLISH_OPTION>', 'Publish the content. It can be: all, published or published-with-changes')
262
281
  .option('--publish-languages <LANGUAGES>', 'Publish specific languages')
@@ -304,7 +323,7 @@ program
304
323
  })
305
324
 
306
325
  program
307
- .command('rollback-migration')
326
+ .command(COMMANDS.ROLLBACK_MIGRATION)
308
327
  .description('Rollback-migration a migration file')
309
328
  .requiredOption('-c, --component <COMPONENT_NAME>', 'Name of the component')
310
329
  .requiredOption('-f, --field <FIELD_NAME>', 'Name of the component field')
@@ -333,7 +352,7 @@ program
333
352
 
334
353
  // list spaces
335
354
  program
336
- .command('spaces')
355
+ .command(COMMANDS.SPACES)
337
356
  .description('List all spaces of the logged account')
338
357
  .action(async () => {
339
358
  try {
@@ -350,7 +369,7 @@ program
350
369
 
351
370
  // import data
352
371
  program
353
- .command('import')
372
+ .command(COMMANDS.IMPORT)
354
373
  .description('Import data from other systems and relational databases.')
355
374
  .requiredOption('-f, --file <FILE_NAME>', 'Name of the file')
356
375
  .requiredOption('-t, --type <TYPE>', 'Type of the content')
@@ -386,3 +405,12 @@ program.parse(process.argv)
386
405
  if (program.rawArgs.length <= 2) {
387
406
  program.help()
388
407
  }
408
+
409
+ function errorHandler (e, command) {
410
+ 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.')
412
+ } else {
413
+ console.log(chalk.red('X') + ' An error occurred when executing the ' + command + ' task: ' + e || e.message)
414
+ }
415
+ process.exit(1)
416
+ }
package/src/constants.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const API_URL = 'https://api.storyblok.com/v1/'
2
+ const US_API_URL = 'https://api-us.storyblok.com/v1/'
2
3
  const LOGIN_URL = `${API_URL}users/login`
3
4
  const SIGNUP_URL = `${API_URL}users/signup`
4
5
 
@@ -10,9 +11,27 @@ const SYNC_TYPES = [
10
11
  'datasources'
11
12
  ]
12
13
 
14
+ const COMMANDS = {
15
+ GENERATE_MIGRATION: 'generate-migration',
16
+ IMPORT: 'import',
17
+ LOGIN: 'login',
18
+ LOGOUT: 'logout',
19
+ PULL_COMPONENTS: 'pull-components',
20
+ PUSH_COMPONENTS: 'push-components',
21
+ QUICKSTART: 'quickstart',
22
+ ROLLBACK_MIGRATION: 'rollback-migration',
23
+ RUN_MIGRATION: 'run-migration',
24
+ SCAFFOLD: 'scaffold',
25
+ SELECT: 'select',
26
+ SPACES: 'spaces',
27
+ SYNC: 'sync'
28
+ }
29
+
13
30
  module.exports = {
14
31
  LOGIN_URL,
15
32
  SIGNUP_URL,
16
33
  API_URL,
17
- SYNC_TYPES
34
+ SYNC_TYPES,
35
+ US_API_URL,
36
+ COMMANDS
18
37
  }
@@ -103,7 +103,7 @@ const push = async (api, components, presets = []) => {
103
103
  if (schema) {
104
104
  Object.keys(schema).forEach(field => {
105
105
  if (schema[field].component_group_whitelist) {
106
- schema[field].component_group_whitelist = schema[field].component_group_whitelist.map(uuid =>
106
+ schema[field].component_group_whitelist = schema[field].component_group_whitelist.map(uuid =>
107
107
  getGroupByUuid(componentsGroups, uuid) ? getGroupByUuid(componentsGroups, uuid).uuid : uuid
108
108
  )
109
109
  }
package/src/tasks/sync.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const pSeries = require('p-series')
2
2
  const chalk = require('chalk')
3
- const StoryblokClient = require('storyblok-js-client')
4
3
  const SyncComponents = require('./sync-commands/components')
5
4
  const SyncDatasources = require('./sync-commands/datasources')
6
5
  const { capitalize } = require('../utils')
@@ -10,13 +9,12 @@ const SyncSpaces = {
10
9
  sourceComponents: [],
11
10
 
12
11
  init (options) {
12
+ const { api } = options
13
13
  console.log(chalk.green('✓') + ' Loading options')
14
14
  this.sourceSpaceId = options.source
15
15
  this.targetSpaceId = options.target
16
16
  this.oauthToken = options.token
17
- this.client = new StoryblokClient({
18
- oauthToken: options.token
19
- }, options.api)
17
+ this.client = api.getClient()
20
18
  },
21
19
 
22
20
  async getStoryWithTranslatedSlugs (sourceStory, targetStory) {
package/src/utils/api.js CHANGED
@@ -5,16 +5,21 @@ 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 } = require('../constants')
8
+ const { LOGIN_URL, SIGNUP_URL, API_URL, US_API_URL } = require('../constants')
9
9
 
10
10
  module.exports = {
11
11
  accessToken: '',
12
+ oauthToken: '',
12
13
  spaceId: null,
14
+ region: 'eu',
13
15
 
14
16
  getClient () {
17
+ const apiURL = this.region === 'us' ? US_API_URL : API_URL
15
18
  return new Storyblok({
16
- oauthToken: this.accessToken
17
- }, API_URL)
19
+ accessToken: this.accessToken,
20
+ oauthToken: this.oauthToken,
21
+ region: this.region
22
+ }, apiURL)
18
23
  },
19
24
 
20
25
  getPath (path) {
@@ -70,7 +75,7 @@ module.exports = {
70
75
  persistCredentials (email, data) {
71
76
  const token = this.extractToken(data)
72
77
  if (token) {
73
- this.accessToken = token
78
+ this.oauthToken = token
74
79
  creds.set(email, token)
75
80
 
76
81
  return Promise.resolve(data)
@@ -115,7 +120,7 @@ module.exports = {
115
120
  })
116
121
  .then(response => {
117
122
  const token = this.extractToken(response)
118
- this.accessToken = token
123
+ this.oauthToken = token
119
124
  creds.set(email, token)
120
125
 
121
126
  return Promise.resolve(true)
@@ -127,7 +132,7 @@ module.exports = {
127
132
  const { token } = creds.get() || {}
128
133
 
129
134
  if (token) {
130
- this.accessToken = token
135
+ this.oauthToken = token
131
136
  return true
132
137
  }
133
138
 
@@ -138,6 +143,10 @@ module.exports = {
138
143
  this.spaceId = spaceId
139
144
  },
140
145
 
146
+ setRegion (region) {
147
+ this.region = region
148
+ },
149
+
141
150
  getPresets () {
142
151
  const client = this.getClient()
143
152
 
@@ -99,7 +99,7 @@ const FAKE_PRESETS = {
99
99
  title: 'A default hero title',
100
100
  subtitle: 'A default hero subtitle',
101
101
  component: 'hero',
102
- image: 'https://a.storyblok.com/f/002/bd78c087d1/screen-shot.png',
102
+ image: 'https://a.storyblok.com/f/002/bd78c087d1/screen-shot.png'
103
103
  },
104
104
  component_id: 3, // from FAKE_COMPONENTS 'hero'
105
105
  space_id: '000000',
@@ -221,6 +221,9 @@ describe('testing syncComponents', () => {
221
221
  const _types = ['components']
222
222
 
223
223
  return sync(_types, {
224
+ api: {
225
+ getClient: jest.fn(() => ({}))
226
+ },
224
227
  token: TOKEN_TEST,
225
228
  source: SOURCE_SPACE_TEST,
226
229
  target: TARGET_SPACE_TEST
@@ -291,7 +294,7 @@ describe('testing syncComponents', () => {
291
294
  title: 'A default hero title',
292
295
  subtitle: 'A default hero subtitle',
293
296
  component: 'hero',
294
- image: 'https://a.storyblok.com/f/002/bd78c087d1/screen-shot.png',
297
+ image: 'https://a.storyblok.com/f/002/bd78c087d1/screen-shot.png'
295
298
  },
296
299
  component_id: 3, // from FAKE_COMPONENTS 'hero'
297
300
  space_id: '000000',