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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -8
- package/.github/workflows/release.yml +23 -0
- package/README.md +90 -7
- package/package.json +10 -1
- package/pull_request_template.md +29 -0
- package/src/cli.js +102 -26
- package/src/constants.js +2 -0
- package/src/tasks/delete-component.js +32 -0
- package/src/tasks/delete-components.js +92 -0
- package/src/tasks/index.js +4 -1
- package/src/tasks/migrations/run.js +1 -1
- package/src/tasks/migrations/utils.js +6 -5
- package/src/tasks/pull-languages.js +39 -0
- package/src/utils/api.js +56 -18
- package/src/utils/creds.js +11 -7
- package/src/utils/get-questions.js +13 -0
- package/tests/constants.js +23 -1
- package/tests/units/delete-component.spec.js +53 -0
- package/tests/units/delete-components.spec.js +93 -0
- package/tests/units/login.spec.js +4 -3
- package/tests/units/pull-languages.spec.js +62 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -28
- package/.github/ISSUE_TEMPLATE/question.md +0 -10
- package/.github/ISSUE_TEMPLATE.md +0 -31
- package/.github/labeler.yml +0 -8
- package/.github/workflows/issue-label.yml +0 -14
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Bug report
|
|
3
|
-
about: Create a report to help us improve
|
|
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
|
[](https://github.com/storyblok/storyblok/issues?q=is%3Aopen+is%3Aissue)
|
|
11
11
|
[](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
|
|
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.
|
|
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 (
|
|
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
|
|
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
|
|
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
|
package/src/tasks/index.js
CHANGED
|
@@ -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
|
|