@jungvonmatt/contentful-migrations 6.2.5 → 7.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 +22 -11
- package/cli.js +314 -171
- package/index.d.ts +9 -9
- package/lib/backend.js +155 -107
- package/lib/content.js +5 -5
- package/lib/contentful.js +90 -43
- package/lib/diff.js +46 -32
- package/lib/helpers/locale.d.ts +3 -3
- package/lib/helpers/validation.d.ts +94 -15
- package/lib/helpers/validation.js +4 -4
- package/lib/migration.js +68 -51
- package/package.json +54 -117
- package/lib/helpers/validation.test.js +0 -381
- package/lib/helpers/validation.utils.test.js +0 -45
package/lib/migration.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const
|
|
3
|
-
const path = require(
|
|
4
|
-
const { stripIndent } = require(
|
|
5
|
-
const runMigration = require(
|
|
1
|
+
const fs = require("fs-extra");
|
|
2
|
+
const { format: oxfmt } = require("oxfmt");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { stripIndent } = require("common-tags");
|
|
5
|
+
const { runMigration } = require("contentful-migration");
|
|
6
6
|
const {
|
|
7
7
|
getContentTypes,
|
|
8
8
|
generateMigrationScript,
|
|
9
|
-
} = require(
|
|
10
|
-
const pc = require(
|
|
11
|
-
const { getEnvironment, getOrganizationId } = require(
|
|
9
|
+
} = require("contentful-cli/dist/lib/cmds/space_cmds/generate_cmds/migration");
|
|
10
|
+
const pc = require("picocolors");
|
|
11
|
+
const { getEnvironment, getOrganizationId } = require("./contentful");
|
|
12
12
|
|
|
13
|
-
const { confirm, STATE_SUCCESS, STATE_FAILURE } = require(
|
|
13
|
+
const { confirm, STATE_SUCCESS, STATE_FAILURE } = require("./config");
|
|
14
14
|
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
storeMigration,
|
|
17
|
+
getNewMigrations,
|
|
18
|
+
getVersionFromFile,
|
|
19
|
+
} = require("./backend");
|
|
16
20
|
|
|
17
21
|
const migrationHeader = stripIndent`/* eslint-env node */
|
|
18
22
|
const { withHelpers } = require('@jungvonmatt/contentful-migrations');
|
|
@@ -33,42 +37,30 @@ const migrationHeader = stripIndent`/* eslint-env node */
|
|
|
33
37
|
const createMigration = async (config) => {
|
|
34
38
|
let module = false;
|
|
35
39
|
try {
|
|
36
|
-
const { readPackageUp } = await import(
|
|
40
|
+
const { readPackageUp } = await import("read-package-up");
|
|
37
41
|
const data = await readPackageUp();
|
|
38
|
-
module = data?.packageJson?.type ===
|
|
42
|
+
module = data?.packageJson?.type === "module";
|
|
39
43
|
} catch (err) {
|
|
40
44
|
console.log(err);
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
const { directory } = config || {};
|
|
44
48
|
const timestamp = Date.now();
|
|
45
|
-
const filename = path.join(
|
|
49
|
+
const filename = path.join(
|
|
50
|
+
directory,
|
|
51
|
+
`${timestamp}-migration.${module ? "cjs" : "js"}`,
|
|
52
|
+
);
|
|
46
53
|
const content = stripIndent`${migrationHeader}
|
|
47
54
|
// Add your migration code here
|
|
48
55
|
})`;
|
|
49
56
|
|
|
50
|
-
await fs.outputFile(filename, await format(filename, content
|
|
57
|
+
await fs.outputFile(filename, await format(filename, content));
|
|
51
58
|
console.log(`Generated new migration file to ${pc.green(filename)}`);
|
|
52
59
|
};
|
|
53
60
|
|
|
54
|
-
const format = async (file, content
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return prettier.format(content, {
|
|
58
|
-
parser: 'babel',
|
|
59
|
-
...prettierOptions,
|
|
60
|
-
});
|
|
61
|
-
} catch (error) {
|
|
62
|
-
if (config?.verbose) {
|
|
63
|
-
console.log(pc.red('Error resolving prettier config. Using default settings.'));
|
|
64
|
-
console.log();
|
|
65
|
-
console.log(error);
|
|
66
|
-
console.log();
|
|
67
|
-
}
|
|
68
|
-
return prettier.format(content, {
|
|
69
|
-
parser: 'babel',
|
|
70
|
-
});
|
|
71
|
-
}
|
|
61
|
+
const format = async (file, content) => {
|
|
62
|
+
const { code } = await oxfmt(file, content, { singleQuote: true });
|
|
63
|
+
return code;
|
|
72
64
|
};
|
|
73
65
|
|
|
74
66
|
/**
|
|
@@ -80,51 +72,56 @@ const fetchMigration = async (config) => {
|
|
|
80
72
|
const client = await getEnvironment(config);
|
|
81
73
|
let module = false;
|
|
82
74
|
try {
|
|
83
|
-
const { readPackageUp } = await import(
|
|
75
|
+
const { readPackageUp } = await import("read-package-up");
|
|
84
76
|
const data = await readPackageUp();
|
|
85
|
-
module = data?.packageJson?.type ===
|
|
77
|
+
module = data?.packageJson?.type === "module";
|
|
86
78
|
} catch (err) {
|
|
87
79
|
console.log(err);
|
|
88
80
|
}
|
|
89
81
|
|
|
90
82
|
let timestamp = Date.now();
|
|
91
83
|
const contentTypes = contentType
|
|
92
|
-
? (
|
|
84
|
+
? (
|
|
85
|
+
await Promise.all(contentType.map((ct) => getContentTypes(client, ct)))
|
|
86
|
+
).flat()
|
|
93
87
|
: await getContentTypes(client);
|
|
94
88
|
|
|
95
89
|
const promises = contentTypes.map(async (entry) => {
|
|
96
|
-
const filename = path.join(
|
|
90
|
+
const filename = path.join(
|
|
91
|
+
directory,
|
|
92
|
+
`${timestamp++}-create-${entry.sys.id}-migration.${module ? "cjs" : "js"}`,
|
|
93
|
+
);
|
|
97
94
|
|
|
98
95
|
const content = await generateMigrationScript(client, [entry]);
|
|
99
96
|
// Fetch migration script generated by contentful
|
|
100
97
|
let modifiedContent = content.toString();
|
|
101
98
|
// Modify migration script to use our helpers
|
|
102
|
-
const testDefaultValueRegex = /(defaultValue\({\s*)[
|
|
99
|
+
const testDefaultValueRegex = /(defaultValue\({\s*)[^:]+([^)]+)/g;
|
|
103
100
|
if (testDefaultValueRegex.test(modifiedContent)) {
|
|
104
101
|
modifiedContent = content
|
|
105
102
|
.toString()
|
|
106
103
|
// Add call to utils.getDefaultLocale() to the top
|
|
107
104
|
.replace(
|
|
108
|
-
|
|
105
|
+
"module.exports = function (migration) {",
|
|
109
106
|
`
|
|
110
107
|
${migrationHeader}
|
|
111
108
|
const defaultLocale = await helpers.locale.getDefaultLocale();
|
|
112
|
-
|
|
109
|
+
`,
|
|
113
110
|
)
|
|
114
111
|
// Replace the default locale with defaultLocale.code so that the migration
|
|
115
112
|
// still works as expected when the locale is changed in contentful
|
|
116
|
-
.replace(testDefaultValueRegex,
|
|
113
|
+
.replace(testDefaultValueRegex, "$1[defaultLocale.code]$2")
|
|
117
114
|
// Add a closing parentheses as we wrap the migration function.
|
|
118
|
-
.replace(/};\s*$/g,
|
|
115
|
+
.replace(/};\s*$/g, "});");
|
|
119
116
|
} else {
|
|
120
117
|
// If we don't have a default value we just wrap the migration function with our withHelpers wrapper
|
|
121
118
|
modifiedContent = content
|
|
122
119
|
.toString()
|
|
123
|
-
.replace(
|
|
124
|
-
.replace(/};\s*$/g,
|
|
120
|
+
.replace("module.exports = function (migration) {", migrationHeader)
|
|
121
|
+
.replace(/};\s*$/g, "});");
|
|
125
122
|
}
|
|
126
123
|
|
|
127
|
-
await fs.outputFile(filename, await format(filename, modifiedContent
|
|
124
|
+
await fs.outputFile(filename, await format(filename, modifiedContent));
|
|
128
125
|
console.log(`Generated new migration file to ${pc.green(filename)}`);
|
|
129
126
|
});
|
|
130
127
|
|
|
@@ -143,7 +140,13 @@ const executeMigration = async (file, config) => {
|
|
|
143
140
|
const environmentId = client.sys.id;
|
|
144
141
|
const organizationId = await getOrganizationId(config);
|
|
145
142
|
const name = path.basename(file);
|
|
146
|
-
const
|
|
143
|
+
const version = getVersionFromFile(file);
|
|
144
|
+
if (!version) {
|
|
145
|
+
console.error(
|
|
146
|
+
`Invalid migration file name "${name}". Must start with a timestamp.`,
|
|
147
|
+
);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
147
150
|
|
|
148
151
|
const options = {
|
|
149
152
|
filePath: path.resolve(file),
|
|
@@ -159,7 +162,9 @@ const executeMigration = async (file, config) => {
|
|
|
159
162
|
options.host = config.host;
|
|
160
163
|
}
|
|
161
164
|
|
|
162
|
-
console.log(
|
|
165
|
+
console.log(
|
|
166
|
+
`\nRun migration ${pc.green(version)} in environment ${pc.green(environmentId)}`,
|
|
167
|
+
);
|
|
163
168
|
const proceed = await confirm(config);
|
|
164
169
|
if (!proceed) {
|
|
165
170
|
return;
|
|
@@ -168,8 +173,13 @@ const executeMigration = async (file, config) => {
|
|
|
168
173
|
await runMigration(options);
|
|
169
174
|
await storeMigration({ version, name, state: STATE_SUCCESS }, config);
|
|
170
175
|
} catch (error) {
|
|
171
|
-
const message = (error.errors || [error])
|
|
172
|
-
|
|
176
|
+
const message = (error.errors || [error])
|
|
177
|
+
.map((error) => error.message)
|
|
178
|
+
.join("\n");
|
|
179
|
+
await storeMigration(
|
|
180
|
+
{ version, name, state: STATE_FAILURE, message },
|
|
181
|
+
config,
|
|
182
|
+
);
|
|
173
183
|
|
|
174
184
|
throw error;
|
|
175
185
|
}
|
|
@@ -193,8 +203,15 @@ const runMigrations = async (config) => {
|
|
|
193
203
|
console.log(error.message);
|
|
194
204
|
throw error;
|
|
195
205
|
}
|
|
196
|
-
console.log(
|
|
197
|
-
|
|
206
|
+
console.log(
|
|
207
|
+
`Found ${pc.green(migrations.length)} unexecuted migrations in environment ${pc.green(environmentId)}`,
|
|
208
|
+
);
|
|
209
|
+
if (config?.verbose) {
|
|
210
|
+
for (const migration of migrations) {
|
|
211
|
+
console.log(` ${pc.green(migration)}`);
|
|
212
|
+
}
|
|
213
|
+
console.log();
|
|
214
|
+
}
|
|
198
215
|
const proceed = migrations.length === 0 || (await confirm(config));
|
|
199
216
|
if (!proceed) {
|
|
200
217
|
return;
|
|
@@ -210,7 +227,7 @@ const runMigrations = async (config) => {
|
|
|
210
227
|
}
|
|
211
228
|
}
|
|
212
229
|
|
|
213
|
-
console.log(pc.green(
|
|
230
|
+
console.log(pc.green("\nAll done"), "🚀");
|
|
214
231
|
};
|
|
215
232
|
|
|
216
233
|
module.exports.fetchMigration = fetchMigration;
|
package/package.json
CHANGED
|
@@ -1,153 +1,90 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jungvonmatt/contentful-migrations",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Helper to handle migrations in contentful",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"cli.js",
|
|
10
|
-
"lib"
|
|
5
|
+
"keywords": [
|
|
6
|
+
"content-type",
|
|
7
|
+
"contentful",
|
|
8
|
+
"migration"
|
|
11
9
|
],
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"contentful-migrations": "cli.js",
|
|
15
|
-
"migrations": "cli.js"
|
|
16
|
-
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"author": "Ben Zörb <benjamin.zoerb@jvm.de>",
|
|
17
12
|
"repository": {
|
|
18
13
|
"type": "git",
|
|
19
14
|
"url": "git+https://github.com/jungvonmatt/contentful-migrations.git"
|
|
20
15
|
},
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"node": ">=18"
|
|
16
|
+
"bin": {
|
|
17
|
+
"contentful-migrations": "cli.js",
|
|
18
|
+
"migrations": "cli.js"
|
|
25
19
|
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
20
|
+
"files": [
|
|
21
|
+
"index.d.ts",
|
|
22
|
+
"index.js",
|
|
23
|
+
"cli.js",
|
|
24
|
+
"lib",
|
|
25
|
+
"!lib/**/*.test.js"
|
|
30
26
|
],
|
|
27
|
+
"main": "index.js",
|
|
28
|
+
"typings": "index.d.ts",
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@contentful/rich-text-plain-text-renderer": "^17.1
|
|
33
|
-
"@jungvonmatt/contentful-config": "^
|
|
34
|
-
"array.prototype.flatmap": "^1.3.3",
|
|
33
|
+
"@contentful/rich-text-plain-text-renderer": "^17.2.1",
|
|
34
|
+
"@jungvonmatt/contentful-config": "^5.0.1",
|
|
35
35
|
"ascii-tree": "^0.3.0",
|
|
36
36
|
"cli-progress": "^3.12.0",
|
|
37
|
-
"commander": "^
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
38
|
"common-tags": "^1.8.2",
|
|
39
|
-
"contentful-cli": "^
|
|
40
|
-
"contentful-import": "^
|
|
41
|
-
"contentful-management": "^
|
|
42
|
-
"contentful-migration": "^
|
|
43
|
-
"
|
|
44
|
-
"diff": "^5.1.0",
|
|
39
|
+
"contentful-cli": "^4.0.1",
|
|
40
|
+
"contentful-import": "^10.0.5",
|
|
41
|
+
"contentful-management": "^12.5.0",
|
|
42
|
+
"contentful-migration": "^5.0.0",
|
|
43
|
+
"diff": "^9.0.0",
|
|
45
44
|
"enquirer": "^2.4.1",
|
|
46
|
-
"fs-extra": "^
|
|
47
|
-
"globby": "^12.0.2",
|
|
45
|
+
"fs-extra": "^11.3.5",
|
|
48
46
|
"markdown-table": "^3.0.4",
|
|
49
47
|
"merge-options": "^3.0.4",
|
|
48
|
+
"microdiff": "^1.5.0",
|
|
50
49
|
"mustache": "^4.2.0",
|
|
51
|
-
"node-
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
50
|
+
"node-object-hash": "^3.1.1",
|
|
51
|
+
"oxfmt": "^0.50.0",
|
|
52
|
+
"package-up": "^5.0.0",
|
|
53
|
+
"picocolors": "^1.1.1",
|
|
54
|
+
"read-package-up": "^12.0.0",
|
|
55
|
+
"tinyglobby": "^0.2.16"
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
|
-
"@
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"jest": "^27.5.1",
|
|
65
|
-
"jest-sonar-reporter": "^2.0.0",
|
|
66
|
-
"lint-staged": "^12.1.2"
|
|
67
|
-
},
|
|
68
|
-
"publishConfig": {
|
|
69
|
-
"access": "public"
|
|
70
|
-
},
|
|
71
|
-
"prettier": {
|
|
72
|
-
"singleQuote": true,
|
|
73
|
-
"printWidth": 120
|
|
58
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
59
|
+
"husky": "^9.1.7",
|
|
60
|
+
"lint-staged": "^17.0.5",
|
|
61
|
+
"oxlint": "^1.65.0",
|
|
62
|
+
"vitest": "^4.1.6"
|
|
74
63
|
},
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
],
|
|
79
|
-
"plugins": [
|
|
80
|
-
"prettier"
|
|
81
|
-
],
|
|
82
|
-
"rules": {
|
|
83
|
-
"prettier/prettier": "error"
|
|
84
|
-
},
|
|
85
|
-
"extends": [
|
|
86
|
-
"prettier"
|
|
87
|
-
],
|
|
88
|
-
"parser": "@babel/eslint-parser",
|
|
89
|
-
"parserOptions": {
|
|
90
|
-
"requireConfigFile": false,
|
|
91
|
-
"allowImportExportEverywhere": true,
|
|
92
|
-
"ecmaFeatures": {
|
|
93
|
-
"ecmaVersion": 2017,
|
|
94
|
-
"impliedStrict": true
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
"env": {
|
|
98
|
-
"node": true
|
|
64
|
+
"husky": {
|
|
65
|
+
"hooks": {
|
|
66
|
+
"pre-commit": "lint-staged"
|
|
99
67
|
}
|
|
100
68
|
},
|
|
101
69
|
"lint-staged": {
|
|
102
70
|
"*.{js,jsx,ts,tsx}": [
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
],
|
|
106
|
-
"*.md": [
|
|
107
|
-
"prettier --write"
|
|
71
|
+
"oxfmt",
|
|
72
|
+
"oxlint --fix"
|
|
108
73
|
]
|
|
109
74
|
},
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"coverageDirectory": "<rootDir>/__coverage__/",
|
|
113
|
-
"collectCoverageFrom": [
|
|
114
|
-
"<rootDir>/lib/*/**"
|
|
115
|
-
],
|
|
116
|
-
"roots": [
|
|
117
|
-
"<rootDir>/lib/"
|
|
118
|
-
],
|
|
119
|
-
"moduleFileExtensions": [
|
|
120
|
-
"js"
|
|
121
|
-
],
|
|
122
|
-
"testRegex": "/lib/.*\\.test.js$",
|
|
123
|
-
"moduleDirectories": [
|
|
124
|
-
"node_modules"
|
|
125
|
-
],
|
|
126
|
-
"globals": {
|
|
127
|
-
"DEVELOPMENT": false
|
|
128
|
-
},
|
|
129
|
-
"reporters": [
|
|
130
|
-
"default"
|
|
131
|
-
]
|
|
132
|
-
},
|
|
133
|
-
"husky": {
|
|
134
|
-
"hooks": {
|
|
135
|
-
"pre-commit": "lint-staged"
|
|
136
|
-
}
|
|
75
|
+
"engines": {
|
|
76
|
+
"node": ">=22"
|
|
137
77
|
},
|
|
138
78
|
"migrations": {
|
|
139
79
|
"storage": "content",
|
|
140
80
|
"migrationContentTypeId": "contentful-migrations",
|
|
141
81
|
"directory": "migrations"
|
|
142
82
|
},
|
|
143
|
-
"jestSonar": {
|
|
144
|
-
"reportPath": "__coverage__",
|
|
145
|
-
"reportFile": "test-report.xml",
|
|
146
|
-
"indent": 2
|
|
147
|
-
},
|
|
148
83
|
"scripts": {
|
|
149
|
-
"test": "
|
|
150
|
-
"lint": "
|
|
151
|
-
"fix-lint": "
|
|
84
|
+
"test": "vitest run --coverage && pnpm run lint",
|
|
85
|
+
"lint": "oxlint",
|
|
86
|
+
"fix-lint": "oxlint --fix",
|
|
87
|
+
"fmt": "oxfmt",
|
|
88
|
+
"fmt:check": "oxfmt --check"
|
|
152
89
|
}
|
|
153
90
|
}
|