@jungvonmatt/contentful-migrations 5.6.1 → 6.0.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/README.md +52 -18
- package/cli.js +122 -61
- package/lib/config.js +53 -143
- package/lib/content.js +2 -2
- package/lib/contentful.js +3 -4
- package/lib/helpers/validation.d.ts +26 -3
- package/lib/helpers/validation.js +113 -23
- package/lib/helpers/validation.test.js +212 -2
- package/lib/migration.js +7 -3
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -28,22 +28,26 @@ This initializes migrations and stores the config values in the `package.json` o
|
|
|
28
28
|
|
|
29
29
|
The default configuration file name is `.migrationsrc`. But since we use [cosmiconfig](https://github.com/davidtheclark/cosmiconfig#cosmiconfig) you can also use the other supported config file formats and name patterns like `migrationsrc.json` or `migrations.config.js`.
|
|
30
30
|
|
|
31
|
-
You can also use any config file path by adding the `-f <path/to/confg>` or `--config-file <path/to/config>` command line argument. The extensions `.json`, `.yaml`, `.yml`, `.js`, or `.cjs` are supported.
|
|
31
|
+
You can also use any config file path by adding the `-f <path/to/confg>` or `--config-file <path/to/config>` command line argument. The extensions `.json`, `.yaml`, `.yml`, `.js`, `.ts`, `.mjs`, or `.cjs` are supported.
|
|
32
32
|
|
|
33
33
|
By specifying the config file path you can use multiple config files for different environments or spaces in your project.
|
|
34
34
|
|
|
35
35
|
#### Configuration values
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
37
|
+
All configuration values can also be set via environment variables
|
|
38
|
+
|
|
39
|
+
| Name | Environment Variable | Default | Description |
|
|
40
|
+
| ---------------------- | ------------------------------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
41
|
+
| managementToken | `CONTENTFUL_MANAGEMENT_TOKEN` | `undefined` | Contentful Management Token. Just run `npx contentful login` and you're done. |
|
|
42
|
+
| -accessToken- | | `undefined` | Not supported anymore. Please use `managementToken` instead. |
|
|
43
|
+
| spaceId | `CONTENTFUL_SPACE_ID` | `undefined` | Contentful Space id. Will fallback to `process.env.CONTENTFUL_SPACE_ID` if not set. |
|
|
44
|
+
| environmentId | `CONTENTFUL_ENVIRONMENT_ID` | `undefined` | Contentful Environment id. Will fallback to `process.env.CONTENTFUL_ENVIRONMENT_ID` if not set.<br/>If neither `environmentId` nor `CONTENTFUL_ENVIRONMENT_ID` is available we search for environment whose id matches the current git branch |
|
|
45
|
+
| host | `CONTENTFUL_HOST` | `undefined` | Allows configuring the Contentful CLI for EU usage. Will fallback to the global contentful config in your `.contentfulrc.json` |
|
|
46
|
+
| requestBatchSize | `CONTENTFUL_MIGRATIONS_REQUEST_BATCH_SIZE` | `undefined` | The batch size used for loading data from contentful. Contentful uses a default of 100. Use a smaller value when you get `Response size too big` errors (for example caused by very large rich text fields). Be aware that contentful migrations might hide the response size error and only print `The provided space does not exist or you do not have access` |
|
|
47
|
+
| storage | `CONTENTFUL_MIGRATIONS_STORAGE` | `undefined` | We need to keep a hint to the executed migrations inside Contentful. You can choose between **content\* and **tag**. <br/><br/>**Content** will add a new content type to your Contentful environment and stores the state of every migration as content entry (recommended approach) <br/>**tag\*\* Will only store the latest version inside a tag. You need to preserve the right order yourself. When you add a new migration with an older version number it will not be executed. |
|
|
48
|
+
| fieldId | `'CONTENTFUL_MIGRATIONS_FIELD_ID'` | `'migration'` | Id of the tag where the migration version is stored (only used with storage `tag`) |
|
|
49
|
+
| migrationContentTypeId | `CONTENTFUL_MIGRATIONS_CONTENT_TYPE_ID` | `'contentful-migrations'` | Id of the migration content-type (only used with storage `content`) |
|
|
50
|
+
| directory | `CONTENTFUL_MIGRATIONS_DIRECTORY` | `'./migrations'` | Directory where the migration files are stored |
|
|
47
51
|
|
|
48
52
|
<br/>
|
|
49
53
|
<br/>
|
|
@@ -86,7 +90,7 @@ npx migrations generate
|
|
|
86
90
|
|
|
87
91
|
Sometimes you may not want to start a migration from scratch. You can create a new Content type in the [contentful web app](https://www.contentful.com/help/content-modelling-basics/) and import it using the `fetch` command.
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
_When you want to use the contentful web app to configure your content types you should do so in a separate environment because the migration will fail if the content-type is already present at the time you run the migration script_
|
|
90
94
|
|
|
91
95
|
```bash
|
|
92
96
|
# Generate migration scripts for all content types from the current environment
|
|
@@ -126,7 +130,7 @@ npx migrations execute <path/to/migration.js> -e <environment-id>
|
|
|
126
130
|
## Managing the migration versions stored in contentful
|
|
127
131
|
|
|
128
132
|
Sometimes you may need to manually mark a migration as migrated or not. You can use the `version` command for this.
|
|
129
|
-
|
|
133
|
+
_Use caution when using the version command. If you delete a version from the table and then run the migrate command, that migration version will be executed again._
|
|
130
134
|
|
|
131
135
|
**This command is only available when using the content storage**
|
|
132
136
|
|
|
@@ -177,8 +181,8 @@ npx migrations doc -e <environment> -p <path/to/docs>
|
|
|
177
181
|
`--template`: Use a custom template for docs. `.js` with default export or `.mustache` is allowed<br/>
|
|
178
182
|
`--extension`: Use a custom file extension (default is `.md`)<br/>
|
|
179
183
|
|
|
180
|
-
|
|
181
184
|
## Migration helpers
|
|
185
|
+
|
|
182
186
|
We provide you with a few smaller migration helpers. There aren't many at the moment, but there may be more in the future.
|
|
183
187
|
|
|
184
188
|
To use the helpers you just need to wrap your migration with the provided `withHelpers` function which makes the helpers available as 3rd parameter
|
|
@@ -204,7 +208,7 @@ module.exports = withHelpers(async (migration, context, helpers) => {
|
|
|
204
208
|
|
|
205
209
|
// Add or remove values from "in" validations without knowing all the other elements in the array
|
|
206
210
|
await helpers.validation.addInValues('contentTypeId', 'fieldId', ['value']); // add at the end
|
|
207
|
-
await helpers.validation.addInValues('contentTypeId', 'fieldId', ['value'], { mode: 'sorted'}); // add and sort
|
|
211
|
+
await helpers.validation.addInValues('contentTypeId', 'fieldId', ['value'], { mode: 'sorted' }); // add and sort
|
|
208
212
|
await helpers.validation.removeInValues('contentTypeId', 'fieldId', ['value']);
|
|
209
213
|
await helpers.validation.modifyInValues('contentTypeId', 'fieldId', (existing) => {
|
|
210
214
|
const result = existing.filter((value) => value.startsWith('prefix')); // keep values with prefix
|
|
@@ -212,6 +216,37 @@ module.exports = withHelpers(async (migration, context, helpers) => {
|
|
|
212
216
|
return result; // possible duplicate values are removed afterwards
|
|
213
217
|
});
|
|
214
218
|
|
|
219
|
+
// Add or remove enabled marks for a rich text field without knowing all the active marks
|
|
220
|
+
// See: https://github.com/contentful/rich-text/blob/master/packages/rich-text-types/src/marks.ts
|
|
221
|
+
await helpers.validation.richText.addEnabledMarksValues('contentTypeId', 'fieldId', ['bold']);
|
|
222
|
+
await helpers.validation.richText.removeEnabledMarksValues('contentTypeId', 'fieldId', ['underline']);
|
|
223
|
+
await helpers.validation.richText.modifyEnabledMarksValues('contentTypeId', 'fieldId', (existing) => {
|
|
224
|
+
const result = existing.filter((value) => value !== 'code'); // keep values with prefix
|
|
225
|
+
result.push('italic'); // and add one
|
|
226
|
+
return result; // possible duplicate values are removed afterwards
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Add or remove enabled node types for a rich text field without knowing all the active node types
|
|
230
|
+
// See https://github.com/contentful/rich-text/blob/master/packages/rich-text-types/src/blocks.ts
|
|
231
|
+
// and https://github.com/contentful/rich-text/blob/master/packages/rich-text-types/src/inlines.ts
|
|
232
|
+
await helpers.validation.richText.addEnabledNodeTypeValues('contentTypeId', 'fieldId', ['blockquote']);
|
|
233
|
+
await helpers.validation.richText.removeEnabledNodeTypeValues('contentTypeId', 'fieldId', ['hyperlink']);
|
|
234
|
+
await helpers.validation.richText.modifyEnabledNodeTypeValues('contentTypeId', 'fieldId', (existing) => {
|
|
235
|
+
const result = existing.filter((value) => !value.startsWith('heading-')); // filter out headings like 'heading-1'
|
|
236
|
+
result.push('quote'); // and add one
|
|
237
|
+
return result; // possible duplicate values are removed afterwards
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Add or remove embedded or linked content types for a rich text field without knowing all the allowed content types
|
|
241
|
+
// The possible node types are 'entry-hyperlink', 'embedded-entry-block' and 'embedded-entry-inline'.
|
|
242
|
+
await helpers.validation.richText.addNodeContentTypeValues('contentTypeId', 'fieldId', 'embedded-entry-block', ['a-content-type']);
|
|
243
|
+
await helpers.validation.richText.removeNodeContentTypeValues('contentTypeId', 'fieldId', 'embedded-entry-inline', ['a-content-type']);
|
|
244
|
+
await helpers.validation.richText.modifyNodeContentTypeValues('contentTypeId', 'fieldId', 'entry-hyperlink', (existing) => {
|
|
245
|
+
const result = existing.filter((value) => value.startsWith('t-')); // filter out content types that not start with 't-'
|
|
246
|
+
result.push('t-article'); // and add one
|
|
247
|
+
return result; // possible duplicate values are removed afterwards
|
|
248
|
+
});
|
|
249
|
+
|
|
215
250
|
});
|
|
216
251
|
```
|
|
217
252
|
|
|
@@ -221,11 +256,10 @@ Of course. We appreciate all of our [contributors](https://github.com/jungvonmat
|
|
|
221
256
|
welcome contributions to improve the project further. If you're uncertain whether an addition should be made, feel
|
|
222
257
|
free to open up an issue and we can discuss it.
|
|
223
258
|
|
|
224
|
-
|
|
225
|
-
|
|
226
259
|
## Contributors
|
|
260
|
+
|
|
227
261
|
<a href="https://github.com/jungvonmatt/contentful-migrations/graphs/contributors">
|
|
228
|
-
<img src="https://contrib.rocks/image?repo=jungvonmatt/contentful-migrations" />
|
|
262
|
+
<img alt="Contributor profile pictures" src="https://contrib.rocks/image?repo=jungvonmatt/contentful-migrations" />
|
|
229
263
|
</a>
|
|
230
264
|
|
|
231
265
|
[npm-url]: https://www.npmjs.com/package/@jungvonmatt/contentful-migrations
|
package/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ const { versionDelete, versionAdd } = require('./lib/version');
|
|
|
13
13
|
const { transferContent } = require('./lib/content');
|
|
14
14
|
const { createOfflineDocs } = require('./lib/doc');
|
|
15
15
|
const { createEnvironment, removeEnvironment, resetEnvironment } = require('./lib/environment');
|
|
16
|
-
const { getConfig,
|
|
16
|
+
const { getConfig, confirm, STORAGE_CONTENT, STORAGE_TAG } = require('./lib/config');
|
|
17
17
|
const pkg = require('./package.json');
|
|
18
18
|
|
|
19
19
|
require('dotenv').config();
|
|
@@ -23,7 +23,7 @@ const parseArgs = (cmd) => {
|
|
|
23
23
|
const directory = cmd.path || parent.path;
|
|
24
24
|
return {
|
|
25
25
|
...cmd,
|
|
26
|
-
configFile: cmd.
|
|
26
|
+
configFile: cmd.config,
|
|
27
27
|
environment: cmd.env || parent.env,
|
|
28
28
|
directory: directory ? path.resolve(directory) : undefined,
|
|
29
29
|
sourceEnvironmentId: cmd.sourceEnvironmentId || parent.sourceEnvironmentId,
|
|
@@ -59,36 +59,52 @@ const program = new Command();
|
|
|
59
59
|
program.version(pkg.version);
|
|
60
60
|
program
|
|
61
61
|
.command('init')
|
|
62
|
+
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
63
|
+
.option('--host <host>', 'Management API host')
|
|
64
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
65
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
62
66
|
.description('Initialize contentful-migrations')
|
|
63
67
|
.action(
|
|
64
68
|
actionRunner(async (cmd) => {
|
|
65
|
-
const config = await getConfig(parseArgs(cmd || {})
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
70
|
+
'managementToken',
|
|
71
|
+
'spaceId',
|
|
72
|
+
'environmentId',
|
|
73
|
+
'storage',
|
|
74
|
+
'fieldId',
|
|
75
|
+
'migrationContentTypeId',
|
|
76
|
+
'directory',
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
const { managementToken, accessToken, environmentId, spaceId, ...rest } = config;
|
|
68
80
|
|
|
69
|
-
if (
|
|
70
|
-
await initializeContentModel(
|
|
71
|
-
await migrateToContentStorage(
|
|
81
|
+
if (config.storage === STORAGE_CONTENT) {
|
|
82
|
+
await initializeContentModel(config);
|
|
83
|
+
await migrateToContentStorage(config);
|
|
72
84
|
}
|
|
73
|
-
if (
|
|
74
|
-
await migrateToTagStorage(
|
|
85
|
+
if (config.storage === STORAGE_TAG) {
|
|
86
|
+
await migrateToTagStorage(config);
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
if (!process.env.CONTENTFUL_SPACE_ID) {
|
|
78
90
|
rest.spaceId = spaceId;
|
|
79
91
|
}
|
|
80
92
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
const storeConfig = await confirm({ message: 'Do you want to store the configuration?' });
|
|
94
|
+
|
|
95
|
+
if (storeConfig) {
|
|
96
|
+
// try to store in package.json
|
|
97
|
+
const { pkgUp } = await import('pkg-up');
|
|
98
|
+
const localPkg = await pkgUp();
|
|
99
|
+
if (localPkg) {
|
|
100
|
+
const packageJson = await fs.readJson(localPkg);
|
|
101
|
+
rest.directory = path.relative(path.dirname(localPkg), rest.directory);
|
|
102
|
+
packageJson.migrations = rest;
|
|
103
|
+
await fs.outputJson(localPkg, packageJson, { spaces: 2 });
|
|
104
|
+
} else {
|
|
105
|
+
// store in .migrationsrc if no package.json is available
|
|
106
|
+
await fs.outputJson(path.join(process.cwd(), '.migrationsrc'), rest, { spaces: 2 });
|
|
107
|
+
}
|
|
92
108
|
}
|
|
93
109
|
})
|
|
94
110
|
);
|
|
@@ -99,14 +115,20 @@ program
|
|
|
99
115
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
100
116
|
.option('-c, --content-type <content-type...>', 'Specify content-types')
|
|
101
117
|
.option('-p, --path <path/to/migrations>', 'Change the path where the migrations are saved')
|
|
102
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
103
118
|
.option('-v, --verbose', 'Verbosity')
|
|
119
|
+
.option('--host <host>', 'Management API host')
|
|
120
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
121
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
104
122
|
.description('Generate a new Contentful migration from content type')
|
|
105
123
|
.action(
|
|
106
124
|
actionRunner(async (cmd) => {
|
|
107
|
-
const config = await getConfig(parseArgs(cmd || {})
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
126
|
+
'managementToken',
|
|
127
|
+
'spaceId',
|
|
128
|
+
'environmentId',
|
|
129
|
+
'directory',
|
|
130
|
+
]);
|
|
131
|
+
await fetchMigration({ ...config, contentType: cmd.contentType });
|
|
110
132
|
})
|
|
111
133
|
);
|
|
112
134
|
|
|
@@ -115,14 +137,20 @@ program
|
|
|
115
137
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
116
138
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
117
139
|
.option('-p, --path <path/to/migrations>', 'Change the path where the migrations are saved')
|
|
118
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
119
140
|
.option('-v, --verbose', 'Verbosity')
|
|
141
|
+
.option('--host <host>', 'Management API host')
|
|
142
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
143
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
120
144
|
.description('Generate a new Contentful migration')
|
|
121
145
|
.action(
|
|
122
146
|
actionRunner(async (cmd) => {
|
|
123
|
-
const config = await getConfig(parseArgs(cmd || {})
|
|
124
|
-
|
|
125
|
-
|
|
147
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
148
|
+
'managementToken',
|
|
149
|
+
'spaceId',
|
|
150
|
+
'environmentId',
|
|
151
|
+
'directory',
|
|
152
|
+
]);
|
|
153
|
+
await createMigration(config);
|
|
126
154
|
})
|
|
127
155
|
);
|
|
128
156
|
|
|
@@ -131,24 +159,33 @@ program
|
|
|
131
159
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
132
160
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
133
161
|
.option('-p, --path <path/to/migrations>', 'Change the path where the migrations are stored')
|
|
134
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
135
162
|
.option('-v, --verbose', 'Verbosity')
|
|
136
163
|
.option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
|
|
164
|
+
.option('--host <host>', 'Management API host')
|
|
165
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
166
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
137
167
|
.option('--bail', 'Abort execution after first failed migration (default: true)', true)
|
|
138
168
|
.option('--no-bail', 'Ignore failed migrations')
|
|
139
169
|
.description('Execute all unexecuted migrations available.')
|
|
140
170
|
.action(
|
|
141
171
|
actionRunner(async (cmd) => {
|
|
142
|
-
const config = await getConfig(parseArgs(cmd || {})
|
|
143
|
-
|
|
172
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
173
|
+
'managementToken',
|
|
174
|
+
'spaceId',
|
|
175
|
+
'environmentId',
|
|
176
|
+
'storage',
|
|
177
|
+
'fieldId',
|
|
178
|
+
'migrationContentTypeId',
|
|
179
|
+
'directory',
|
|
180
|
+
]);
|
|
144
181
|
|
|
145
|
-
const { missingStorageModel } =
|
|
182
|
+
const { missingStorageModel } = config;
|
|
146
183
|
if (missingStorageModel) {
|
|
147
184
|
console.error(pc.red('\nError:'), `Missing migration content type. Run ${pc.cyan('npx migrations init')}`);
|
|
148
185
|
process.exit(1);
|
|
149
186
|
}
|
|
150
187
|
|
|
151
|
-
await runMigrations(
|
|
188
|
+
await runMigrations(config);
|
|
152
189
|
}, false)
|
|
153
190
|
);
|
|
154
191
|
|
|
@@ -156,22 +193,30 @@ program
|
|
|
156
193
|
.command('execute <file>')
|
|
157
194
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
158
195
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
159
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
160
196
|
.option('-v, --verbose', 'Verbosity')
|
|
161
197
|
.option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
|
|
198
|
+
.option('--host <host>', 'Management API host')
|
|
199
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
200
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
162
201
|
.description('Execute a single migration.')
|
|
163
202
|
.action(
|
|
164
203
|
actionRunner(async (file, options) => {
|
|
165
|
-
const config = await getConfig(parseArgs(
|
|
166
|
-
|
|
204
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
205
|
+
'managementToken',
|
|
206
|
+
'spaceId',
|
|
207
|
+
'environmentId',
|
|
208
|
+
'storage',
|
|
209
|
+
'fieldId',
|
|
210
|
+
'migrationContentTypeId',
|
|
211
|
+
'directory',
|
|
212
|
+
]);
|
|
167
213
|
|
|
168
|
-
const { missingStorageModel } =
|
|
214
|
+
const { missingStorageModel } = config;
|
|
169
215
|
if (missingStorageModel) {
|
|
170
216
|
console.error(pc.red('\nError:'), `Missing migration content type. Run ${pc.cyan('npx migrations init')}`);
|
|
171
217
|
process.exit(1);
|
|
172
218
|
}
|
|
173
|
-
|
|
174
|
-
await executeMigration(path.resolve(file), verified);
|
|
219
|
+
await executeMigration(path.resolve(file), config);
|
|
175
220
|
}, false)
|
|
176
221
|
);
|
|
177
222
|
|
|
@@ -179,31 +224,40 @@ program
|
|
|
179
224
|
.command('version <file>')
|
|
180
225
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
181
226
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
182
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
183
227
|
.option('-v, --verbose', 'Verbosity')
|
|
228
|
+
.option('--host <host>', 'Management API host')
|
|
229
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
184
230
|
.option('--add', 'Mark migration as migrated')
|
|
185
231
|
.option('--remove', 'Delete migration entry in Contentful')
|
|
232
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
186
233
|
.description('Manually mark a migration as migrated or not. (Only available with the Content-model storage)')
|
|
187
234
|
.action(
|
|
188
235
|
actionRunner(async (file, options) => {
|
|
189
236
|
const { remove, add } = options;
|
|
190
|
-
const config = await getConfig(parseArgs(
|
|
191
|
-
|
|
237
|
+
const config = await getConfig(parseArgs(cmd || {}), [
|
|
238
|
+
'managementToken',
|
|
239
|
+
'spaceId',
|
|
240
|
+
'environmentId',
|
|
241
|
+
'storage',
|
|
242
|
+
'fieldId',
|
|
243
|
+
'migrationContentTypeId',
|
|
244
|
+
'directory',
|
|
245
|
+
]);
|
|
192
246
|
|
|
193
|
-
const { missingStorageModel } =
|
|
247
|
+
const { missingStorageModel } = config;
|
|
194
248
|
if (missingStorageModel) {
|
|
195
249
|
console.error(pc.red('\nError:'), `Missing migration content type. Run ${pc.cyan('npx migrations init')}`);
|
|
196
250
|
process.exit(1);
|
|
197
251
|
}
|
|
198
252
|
|
|
199
|
-
const { storage } =
|
|
253
|
+
const { storage } = config || {};
|
|
200
254
|
if (storage === STORAGE_TAG) {
|
|
201
255
|
throw new Error('The version command is not available for the "tag" storage');
|
|
202
256
|
}
|
|
203
257
|
if (remove) {
|
|
204
|
-
await versionDelete(file,
|
|
258
|
+
await versionDelete(file, config);
|
|
205
259
|
} else if (add) {
|
|
206
|
-
await versionAdd(file,
|
|
260
|
+
await versionAdd(file, config);
|
|
207
261
|
}
|
|
208
262
|
}, true)
|
|
209
263
|
);
|
|
@@ -211,29 +265,34 @@ program
|
|
|
211
265
|
program
|
|
212
266
|
.command('environment <environment-id>')
|
|
213
267
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
214
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
215
268
|
.option('-v, --verbose', 'Verbosity')
|
|
269
|
+
.option('--host <host>', 'Management API host')
|
|
270
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
216
271
|
.option('--create', 'Create new contentful environment')
|
|
217
272
|
.option('--remove', 'Delete contentful environment')
|
|
218
273
|
.option('--reset', 'Reset contentful environment')
|
|
219
274
|
.option('--source-environment-id <environment-id>', 'Set the source environment to clone new environment from')
|
|
275
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
220
276
|
.description('Add or remove a contentful environment for migrations')
|
|
221
277
|
.action(
|
|
222
278
|
actionRunner(async (environmentId, options) => {
|
|
223
279
|
const { remove, create, reset } = options;
|
|
224
|
-
const config = await getConfig(parseArgs({ ...(options || {}), environmentId })
|
|
225
|
-
|
|
280
|
+
const config = await getConfig(parseArgs({ ...(options || {}), environmentId }), [
|
|
281
|
+
'managementToken',
|
|
282
|
+
'spaceId',
|
|
283
|
+
'environmentId',
|
|
284
|
+
]);
|
|
226
285
|
|
|
227
286
|
if (create) {
|
|
228
|
-
return createEnvironment(environmentId,
|
|
287
|
+
return createEnvironment(environmentId, config);
|
|
229
288
|
}
|
|
230
289
|
|
|
231
290
|
if (remove) {
|
|
232
|
-
return removeEnvironment(environmentId,
|
|
291
|
+
return removeEnvironment(environmentId, config);
|
|
233
292
|
}
|
|
234
293
|
|
|
235
294
|
if (reset) {
|
|
236
|
-
return resetEnvironment(environmentId,
|
|
295
|
+
return resetEnvironment(environmentId, config);
|
|
237
296
|
}
|
|
238
297
|
}, true)
|
|
239
298
|
);
|
|
@@ -243,16 +302,17 @@ program
|
|
|
243
302
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
244
303
|
.option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
|
|
245
304
|
.option('-p, --path <path/to/docs>', 'Change the path where the docs are stored')
|
|
246
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
247
305
|
.option('-v, --verbose', 'Verbosity')
|
|
248
306
|
.option('-t, --template <path/to/template>', 'Use custom template for docs')
|
|
307
|
+
.option('--host <host>', 'Management API host')
|
|
308
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
249
309
|
.option('--extension <file-extension>', 'Use custom file extension (default is `md`)')
|
|
310
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
250
311
|
.description('Generate offline docs from content-types')
|
|
251
312
|
.action(
|
|
252
313
|
actionRunner(async (cmd) => {
|
|
253
|
-
const config = await getConfig(parseArgs(cmd || {}));
|
|
254
|
-
|
|
255
|
-
await createOfflineDocs(verified);
|
|
314
|
+
const config = await getConfig(parseArgs(cmd || {}), ['managementToken', 'spaceId', 'environmentId']);
|
|
315
|
+
await createOfflineDocs(config);
|
|
256
316
|
}, true)
|
|
257
317
|
);
|
|
258
318
|
|
|
@@ -262,20 +322,21 @@ program
|
|
|
262
322
|
.requiredOption('--dest-environment-id <environment-id>', 'Set the Contentful destination environment (to)')
|
|
263
323
|
.option('-s, --space-id <space-id>', 'Contentful space id')
|
|
264
324
|
.option('-c, --content-type <content-type>', 'Specify content-type')
|
|
265
|
-
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
266
325
|
.option('-v, --verbose', 'Verbosity')
|
|
267
326
|
.option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
|
|
327
|
+
.option('--host <host>', 'Management API host')
|
|
328
|
+
.option('--config <path/to/config>', 'Config file path (disables auto detect)')
|
|
268
329
|
.option('--diff', 'Manually choose skip/overwrite for every conflict')
|
|
269
330
|
.option('--force', 'No manual diffing. Overwrites all conflicting entries/assets')
|
|
270
331
|
.description('Transfer content from source environment to destination environment')
|
|
332
|
+
.option('--cwd <directory>', 'Working directory. Defaults to process.cwd()')
|
|
271
333
|
.action(
|
|
272
334
|
actionRunner(async (cmd) => {
|
|
273
|
-
const config = await getConfig(parseArgs(cmd || {}));
|
|
274
|
-
const verified = await askMissing({ ...config, environmentId: 'not-used' });
|
|
335
|
+
const config = await getConfig(parseArgs(cmd || {}), ['managementToken', 'spaceId', 'storage']);
|
|
275
336
|
|
|
276
337
|
// run migrations on destination environment
|
|
277
338
|
await transferContent({
|
|
278
|
-
...
|
|
339
|
+
...config,
|
|
279
340
|
contentType: cmd.contentType || '',
|
|
280
341
|
forceOverwrite: cmd.force || false,
|
|
281
342
|
diffConflicts: cmd.diff || false,
|