storyblok-backup 0.4.1 → 0.6.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/.env.example +2 -2
- package/README.md +57 -52
- package/bin/{storyblok-restore.mjs → storyblok-backup-restore.mjs} +17 -4
- package/bin/storyblok-backup.mjs +47 -29
- package/package.json +2 -2
package/.env.example
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
STORYBLOK_OAUTH_TOKEN=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
|
|
2
|
-
STORYBLOK_SPACE_ID=123456
|
|
1
|
+
STORYBLOK_OAUTH_TOKEN=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
|
|
2
|
+
STORYBLOK_SPACE_ID=123456
|
|
3
3
|
STORYBLOK_REGION=eu
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
A npx CLI tool to create a full backup of a space of the [Storyblok CMS](https://www.storyblok.com).
|
|
7
7
|
|
|
8
|
-
A restore tool to restore (create or update) resources is also included.
|
|
8
|
+
A limited restore tool to restore (create or update) single resources is also included. A full restore-tool is available in a separate package: [netgen/storyblok-restore](https://github.com/netgen/storyblok-restore)
|
|
9
9
|
|
|
10
10
|
The backup script will fetch the following resources of a Storyblok space using the Management API and archive them in a zip file:
|
|
11
11
|
|
|
@@ -38,6 +38,8 @@ The restore script is able to individually restore the resources from the backup
|
|
|
38
38
|
- Workflow stage changes: No update possible.
|
|
39
39
|
- Access Tokens: Creating access tokens from backup makes no sense, since it will result in a new token-string.
|
|
40
40
|
|
|
41
|
+
For a much more feature-rich full restore-tool see [netgen/storyblok-restore](https://github.com/netgen/storyblok-restore).
|
|
42
|
+
|
|
41
43
|
## Table of contents
|
|
42
44
|
|
|
43
45
|
- [Installation](#installation)
|
|
@@ -83,51 +85,52 @@ Call `npx storyblok-backup` with the following options:
|
|
|
83
85
|
#### Backup options
|
|
84
86
|
|
|
85
87
|
```text
|
|
86
|
-
--token <token>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
--space <space_id>
|
|
91
|
-
|
|
92
|
-
--region <region>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
--types <types>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
--
|
|
123
|
-
--
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
--
|
|
127
|
-
--zip
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
--
|
|
88
|
+
--token <token> (required) Personal OAuth access token created
|
|
89
|
+
in the account settings of a Stoyblok user.
|
|
90
|
+
(NOT the Access Token of a Space!)
|
|
91
|
+
Alternatively, you can set the STORYBLOK_OAUTH_TOKEN environment variable.
|
|
92
|
+
--space <space_id> (required) ID of the space to backup
|
|
93
|
+
Alternatively, you can set the STORYBLOK_SPACE_ID environment variable.
|
|
94
|
+
--region <region> Region of the space. Possible values are:
|
|
95
|
+
- 'eu' (default): EU
|
|
96
|
+
- 'us': US
|
|
97
|
+
- 'ap': Australia
|
|
98
|
+
- 'ca': Canada
|
|
99
|
+
- 'cn': China
|
|
100
|
+
Alternatively, you can set the STORYBLOK_REGION environment variable.
|
|
101
|
+
--types <types> Comma separated list of resource-types to backup (default=all).
|
|
102
|
+
Possible values are:
|
|
103
|
+
- 'stories'
|
|
104
|
+
- 'collaborators'
|
|
105
|
+
- 'components'
|
|
106
|
+
- 'component-groups'
|
|
107
|
+
- 'assets'
|
|
108
|
+
- 'asset-folders'
|
|
109
|
+
- 'internal-tags'
|
|
110
|
+
- 'datasources'
|
|
111
|
+
- 'space'
|
|
112
|
+
- 'space-roles'
|
|
113
|
+
- 'tasks'
|
|
114
|
+
- 'activities'
|
|
115
|
+
- 'presets'
|
|
116
|
+
- 'field-types'
|
|
117
|
+
- 'webhooks'
|
|
118
|
+
- 'workflow-stages'
|
|
119
|
+
- 'workflow-stage-changes'
|
|
120
|
+
- 'workflows'
|
|
121
|
+
- 'releases'
|
|
122
|
+
- 'pipeline-branches'
|
|
123
|
+
- 'access-tokens'
|
|
124
|
+
--omit-types <types> Comma separated list of resource-types to omit.
|
|
125
|
+
--with-asset-files Downloads all files (assets) of the space (default=false).
|
|
126
|
+
--output-dir <dir> Directory to write the backup to (default=./.output)
|
|
127
|
+
(ATTENTION: Will fail if the directory already exists!)
|
|
128
|
+
--force Force deletion and recreation of existing output directory.
|
|
129
|
+
--create-zip Create a zip file of the backup (default=false).
|
|
130
|
+
--zip-prefix <dir> Prefix for the zip file. (default='backup').
|
|
131
|
+
(The suffix will automatically be the current date.)
|
|
132
|
+
--verbose Will show detailed output for every file written.
|
|
133
|
+
--help Show this help
|
|
131
134
|
```
|
|
132
135
|
|
|
133
136
|
OAuth token, space-id and region can be set via environment variables. You can also use a `.env` file in your project root for this (see `.env.example`).
|
|
@@ -160,7 +163,7 @@ This will create the folder `./my-dir/backup`, fetch all resources (incl. the or
|
|
|
160
163
|
|
|
161
164
|
#### Continuous backup integration examples
|
|
162
165
|
|
|
163
|
-
You can use this script to create periodic backups of Storyblok spaces using GitHub Actions and artifacts, or commit each content change to a git repository
|
|
166
|
+
You can use this script to create periodic backups of Storyblok spaces using GitHub Actions and artifacts, or commit each content change to a git repository using Storyblok's webhooks.
|
|
164
167
|
|
|
165
168
|
##### Example for a GitHub workflow for a complete backup as an artifact
|
|
166
169
|
|
|
@@ -225,7 +228,7 @@ Also keep in mind, that there is a limit on artifact storage and runner minutes
|
|
|
225
228
|
|
|
226
229
|
##### Example for a GitHub workflow for an incremental git-commit-based backup
|
|
227
230
|
|
|
228
|
-
The following workflow should run via webhook on every relevant change (e.g.publish) in Storyblok. It creates a new current backup (excl. asset files) and commits them to the current repository in the `backup` folder. This enables an incremental git-commit-based backup of all Storyblok-content.
|
|
231
|
+
The following workflow should run via webhook on every relevant change (e.g.publish) in Storyblok. It creates a new current backup (excl. asset files and resources of types access-tokens, activities and workflow-stage-changes) and commits them to the current repository in the `backup` folder. This enables an incremental git-commit-based backup of all Storyblok-content.
|
|
229
232
|
|
|
230
233
|
```yaml
|
|
231
234
|
name: Incremental Repository Backup
|
|
@@ -256,7 +259,7 @@ jobs:
|
|
|
256
259
|
env:
|
|
257
260
|
STORYBLOK_OAUTH_TOKEN: ${{ secrets.STORYBLOK_OAUTH_TOKEN }}
|
|
258
261
|
STORYBLOK_SPACE_ID: ${{ secrets.STORYBLOK_SPACE_ID }}
|
|
259
|
-
run: npx storyblok-backup
|
|
262
|
+
run: npx storyblok-backup --omit-types "access-tokens,activities,workflow-stage-changes"
|
|
260
263
|
|
|
261
264
|
- name: Copy files into repository
|
|
262
265
|
run: |
|
|
@@ -281,9 +284,11 @@ A webhook to the URL `https://api.github.com/repos/{owner}/{repo}/dispatches` mu
|
|
|
281
284
|
|
|
282
285
|
### Restore
|
|
283
286
|
|
|
287
|
+
(NOTE: The included restore functionality is limited to restoring only single documents, and not full spaces. For a much more feature-rich full restore-tool see [netgen/storyblok-restore](https://github.com/netgen/storyblok-restore).)
|
|
288
|
+
|
|
284
289
|
Make sure to install the package first (see [Installation](#installation)).
|
|
285
290
|
|
|
286
|
-
Call `npx storyblok-restore` with the following options:
|
|
291
|
+
Call `npx storyblok-backup-restore` with the following options:
|
|
287
292
|
|
|
288
293
|
#### Restore options
|
|
289
294
|
|
|
@@ -338,7 +343,7 @@ Call `npx storyblok-restore` with the following options:
|
|
|
338
343
|
#### Minimal restore example
|
|
339
344
|
|
|
340
345
|
```shell
|
|
341
|
-
npx storyblok-restore --token 1234567890abcdef --space 12345 --type story --file ./.output/backup/123456789.json
|
|
346
|
+
npx storyblok-backup-restore --token 1234567890abcdef --space 12345 --type story --file ./.output/backup/123456789.json
|
|
342
347
|
```
|
|
343
348
|
|
|
344
349
|
This will restore the story from the stated file by updating it.
|
|
@@ -346,7 +351,7 @@ This will restore the story from the stated file by updating it.
|
|
|
346
351
|
#### Maximal restore example
|
|
347
352
|
|
|
348
353
|
```shell
|
|
349
|
-
npx storyblok-restore \
|
|
354
|
+
npx storyblok-backup-restore \
|
|
350
355
|
--token 1234567890abcdef \
|
|
351
356
|
--space 12345 \
|
|
352
357
|
--region ap \
|
|
@@ -8,7 +8,7 @@ import dotenvx from '@dotenvx/dotenvx'
|
|
|
8
8
|
|
|
9
9
|
const startTime = performance.now()
|
|
10
10
|
|
|
11
|
-
dotenvx.config({ quiet: true })
|
|
11
|
+
dotenvx.config({ quiet: true, ignore: ['MISSING_ENV_FILE'] })
|
|
12
12
|
|
|
13
13
|
const resourceTypes = [
|
|
14
14
|
'story',
|
|
@@ -37,7 +37,7 @@ const args = minimist(process.argv.slice(2))
|
|
|
37
37
|
|
|
38
38
|
if ('help' in args) {
|
|
39
39
|
console.log(`USAGE
|
|
40
|
-
$ npx storyblok-restore
|
|
40
|
+
$ npx storyblok-backup-restore
|
|
41
41
|
|
|
42
42
|
OPTIONS
|
|
43
43
|
--token <token> (required) Personal OAuth access token created
|
|
@@ -69,10 +69,10 @@ OPTIONS
|
|
|
69
69
|
--help Show this help
|
|
70
70
|
|
|
71
71
|
MINIMAL EXAMPLE
|
|
72
|
-
$ npx storyblok-restore --token 1234567890abcdef --space 12345 --type story --file ./.output/backup/123456789.json
|
|
72
|
+
$ npx storyblok-backup-restore --token 1234567890abcdef --space 12345 --type story --file ./.output/backup/123456789.json
|
|
73
73
|
|
|
74
74
|
MAXIMAL EXAMPLE
|
|
75
|
-
$ npx storyblok-restore \\
|
|
75
|
+
$ npx storyblok-backup-restore \\
|
|
76
76
|
--token 1234567890abcdef \\
|
|
77
77
|
--space 12345 \\
|
|
78
78
|
--region ap \\
|
|
@@ -154,6 +154,19 @@ if (propagate && args.type !== 'story') {
|
|
|
154
154
|
process.exit(1)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
// Output General information
|
|
158
|
+
console.log('')
|
|
159
|
+
console.log(`Restoring backup in space ${spaceId}:`)
|
|
160
|
+
console.log(`- resource type: ${args.type}`)
|
|
161
|
+
console.log(`- file: ${args.file}`)
|
|
162
|
+
if ('id' in args) {
|
|
163
|
+
console.log(`- datasource id: ${args.id}`)
|
|
164
|
+
}
|
|
165
|
+
console.log(`- mode: ${'create' in args ? 'create' : 'update'}`)
|
|
166
|
+
console.log(`- publish: ${'publish' in args ? 'yes' : 'no'}`)
|
|
167
|
+
console.log(`- propagate: ${'propagate' in args ? 'yes' : 'no'}`)
|
|
168
|
+
console.log('')
|
|
169
|
+
|
|
157
170
|
// Init Management API
|
|
158
171
|
const StoryblokMAPI = new StoryblokClient({
|
|
159
172
|
oauthToken: oauthToken,
|
package/bin/storyblok-backup.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import dotenvx from '@dotenvx/dotenvx'
|
|
|
11
11
|
|
|
12
12
|
const startTime = performance.now()
|
|
13
13
|
|
|
14
|
-
dotenvx.config({ quiet: true })
|
|
14
|
+
dotenvx.config({ quiet: true, ignore: ['MISSING_ENV_FILE'] })
|
|
15
15
|
|
|
16
16
|
let resourceTypes = [
|
|
17
17
|
'stories',
|
|
@@ -44,31 +44,32 @@ if ('help' in args) {
|
|
|
44
44
|
$ npx storyblok-backup
|
|
45
45
|
|
|
46
46
|
OPTIONS
|
|
47
|
-
--token <token>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
--space <space_id>
|
|
52
|
-
|
|
53
|
-
--region <region>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
--types <types>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
--
|
|
64
|
-
--
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
--
|
|
68
|
-
--zip
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
--
|
|
47
|
+
--token <token> (required) Personal OAuth access token created
|
|
48
|
+
in the account settings of a Stoyblok user.
|
|
49
|
+
(NOT the Access Token of a Space!)
|
|
50
|
+
Alternatively, you can set the STORYBLOK_OAUTH_TOKEN environment variable.
|
|
51
|
+
--space <space_id> (required) ID of the space to backup
|
|
52
|
+
Alternatively, you can set the STORYBLOK_SPACE_ID environment variable.
|
|
53
|
+
--region <region> Region of the space. Possible values are:
|
|
54
|
+
- 'eu' (default): EU
|
|
55
|
+
- 'us': US
|
|
56
|
+
- 'ap': Australia
|
|
57
|
+
- 'ca': Canada
|
|
58
|
+
- 'cn': China
|
|
59
|
+
Alternatively, you can set the STORYBLOK_REGION environment variable.
|
|
60
|
+
--types <types> Comma separated list of resource-types to backup (default=all).
|
|
61
|
+
Possible values are:
|
|
62
|
+
- '${resourceTypes.join("'\n - '")}'
|
|
63
|
+
--omit-types <types> Comma separated list of resource-types to omit.
|
|
64
|
+
--with-asset-files Downloads all files (assets) of the space (default=false).
|
|
65
|
+
--output-dir <dir> Directory to write the backup to (default=./.output)
|
|
66
|
+
(ATTENTION: Will fail if the directory already exists!)
|
|
67
|
+
--force Force deletion and recreation of existing output directory.
|
|
68
|
+
--create-zip Create a zip file of the backup (default=false).
|
|
69
|
+
--zip-prefix <dir> Prefix for the zip file. (default='backup').
|
|
70
|
+
(The suffix will automatically be the current date.)
|
|
71
|
+
--verbose Will show detailed output for every file written.
|
|
72
|
+
--help Show this help
|
|
72
73
|
|
|
73
74
|
MINIMAL EXAMPLE
|
|
74
75
|
$ npx storyblok-backup --token 1234567890abcdef --space 12345
|
|
@@ -79,6 +80,7 @@ MAXIMAL EXAMPLE
|
|
|
79
80
|
--space 12345 \\
|
|
80
81
|
--region ap \\
|
|
81
82
|
--types "stories,components" \\
|
|
83
|
+
--omit-types "activities" \\
|
|
82
84
|
--with-asset-files \\
|
|
83
85
|
--output-dir ./my-dir \\
|
|
84
86
|
--force \\
|
|
@@ -128,6 +130,11 @@ if ('types' in args) {
|
|
|
128
130
|
resourceTypes = typesToBackup
|
|
129
131
|
}
|
|
130
132
|
|
|
133
|
+
if ('omit-types' in args) {
|
|
134
|
+
const typesToOmit = args['omit-types'].split(',')
|
|
135
|
+
resourceTypes = resourceTypes.filter((type) => !typesToOmit.includes(type))
|
|
136
|
+
}
|
|
137
|
+
|
|
131
138
|
const verbose = 'verbose' in args
|
|
132
139
|
|
|
133
140
|
const outputDir = args['output-dir'] || './.output'
|
|
@@ -156,11 +163,17 @@ const fileName =
|
|
|
156
163
|
|
|
157
164
|
const filePath = `${outputDir}/${fileName}`
|
|
158
165
|
|
|
166
|
+
// Output General information
|
|
167
|
+
console.log('')
|
|
159
168
|
console.log(`Creating backup for space ${spaceId}:`)
|
|
160
|
-
console.log(
|
|
169
|
+
console.log(`- output dir: ${outputDir}`)
|
|
161
170
|
if ('create-zip' in args) {
|
|
162
|
-
console.log(
|
|
171
|
+
console.log(`- output zip: ${filePath}`)
|
|
163
172
|
}
|
|
173
|
+
console.log(`- resource types: ${resourceTypes.join(', ')}`)
|
|
174
|
+
console.log(`- with asset files: ${'with-asset-files' in args ? 'yes' : 'no'}`)
|
|
175
|
+
console.log(`- force output folder: ${'force' in args ? 'yes' : 'no'}`)
|
|
176
|
+
console.log('')
|
|
164
177
|
|
|
165
178
|
// Init Management API
|
|
166
179
|
const StoryblokMAPI = new StoryblokClient({
|
|
@@ -179,6 +192,11 @@ resourceTypes.forEach(
|
|
|
179
192
|
(resource) => resource === 'space' || fs.mkdirSync(`${backupDir}/${resource}`)
|
|
180
193
|
)
|
|
181
194
|
|
|
195
|
+
// Create separate directory for asset-files
|
|
196
|
+
if (resourceTypes.includes('assets') && 'with-asset-files' in args) {
|
|
197
|
+
fs.mkdirSync(`${backupDir}/asset-files`)
|
|
198
|
+
}
|
|
199
|
+
|
|
182
200
|
// Function to perform a default fetch
|
|
183
201
|
const defaultFetch = async (endpoint, type, fileField, fileFieldObject) => {
|
|
184
202
|
if (resourceTypes.includes(type)) {
|
|
@@ -282,7 +300,7 @@ if (resourceTypes.includes('assets')) {
|
|
|
282
300
|
if ('with-asset-files' in args) {
|
|
283
301
|
const fileExtension = asset.filename.split('.').at(-1)
|
|
284
302
|
const fileName = asset.id + '.' + fileExtension
|
|
285
|
-
await downloadFile('
|
|
303
|
+
await downloadFile('asset-files', fileName, asset.filename)
|
|
286
304
|
}
|
|
287
305
|
}
|
|
288
306
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "storyblok-backup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "npx CLI tool to create a full backup of a Storyblok space and restore single resources from it.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"upgrade": "npx npm-check-updates -i -u && pnpm install",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
15
|
"storyblok-backup": "bin/storyblok-backup.mjs",
|
|
16
|
-
"storyblok-restore": "bin/storyblok-restore.mjs"
|
|
16
|
+
"storyblok-backup-restore": "bin/storyblok-backup-restore.mjs"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|